3
]ð]¡$  ã               @   s    d Z ddlZddlZddlZddlZddlZddlZddlZddlm	Z	 ddl
mZ ddlmZmZmZmZ ddlmZ dZdd	„ Zd
d„ ZG dd„ deƒZdS )zXTools for working with MongoDB `ObjectIds
<http://dochub.mongodb.org/core/objectids>`_.
é    N)ÚSystemRandom)Ú	InvalidId)ÚPY3Úbytes_from_hexÚstring_typeÚ	text_type)Úutciÿÿÿ c             C   s   t d|  ƒ‚d S )NzS%r is not a valid ObjectId, it must be a 12-byte input or a 24-character hex string)r   )Úoid© r
   ú0/tmp/pip-build-20mum3z4/pymongo/bson/objectid.pyÚ_raise_invalid_id%   s    r   c               C   s
   t jdƒS )z+Get the 5-byte random field of an ObjectId.é   )ÚosÚurandomr
   r
   r
   r   Ú_random_bytes+   s    r   c               @   sê   e Zd ZdZejƒ Zeƒ jde	ƒZ
ejƒ Zeƒ Zd,ZdZd-dd„Zedd	„ ƒZed
d„ ƒZedd„ ƒZdd„ Zdd„ Zedd„ ƒZedd„ ƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z d d!„ Z!d"d#„ Z"d$d%„ Z#d&d'„ Z$d(d)„ Z%d*d+„ Z&dS ).ÚObjectIdzA MongoDB ObjectId.
    r   Ú__idé   Nc             C   s>   |dkr| j ƒ  n(t|tƒr0t|ƒdkr0|| _n
| j|ƒ dS )a  Initialize a new ObjectId.

        An ObjectId is a 12-byte unique identifier consisting of:

          - a 4-byte value representing the seconds since the Unix epoch,
          - a 5-byte random value,
          - a 3-byte counter, starting with a random value.

        By default, ``ObjectId()`` creates a new unique identifier. The
        optional parameter `oid` can be an :class:`ObjectId`, or any 12
        :class:`bytes` or, in Python 2, any 12-character :class:`str`.

        For example, the 12 bytes b'foo-bar-quux' do not follow the ObjectId
        specification but they are acceptable input::

          >>> ObjectId(b'foo-bar-quux')
          ObjectId('666f6f2d6261722d71757578')

        `oid` can also be a :class:`unicode` or :class:`str` of 24 hex digits::

          >>> ObjectId('0123456789ab0123456789ab')
          ObjectId('0123456789ab0123456789ab')
          >>>
          >>> # A u-prefixed unicode literal:
          >>> ObjectId(u'0123456789ab0123456789ab')
          ObjectId('0123456789ab0123456789ab')

        Raises :class:`~bson.errors.InvalidId` if `oid` is not 12 bytes nor
        24 hex digits, or :class:`TypeError` if `oid` is not an accepted type.

        :Parameters:
          - `oid` (optional): a valid ObjectId.

        .. mongodoc:: objectids

        .. versionchanged:: 3.8
           :class:`~bson.objectid.ObjectId` now implements the `ObjectID
           specification version 0.2
           <https://github.com/mongodb/specifications/blob/master/source/
           objectid.rst>`_.
        Né   )Ú_ObjectId__generateÚ
isinstanceÚbytesÚlenÚ_ObjectId__idÚ_ObjectId__validate)Úselfr	   r
   r
   r   Ú__init__?   s
    *
zObjectId.__init__c             C   sB   |j ƒ dk	r||j ƒ  }tj|jƒ ƒ}tjdt|ƒƒd }| |ƒS )a^  Create a dummy ObjectId instance with a specific generation time.

        This method is useful for doing range queries on a field
        containing :class:`ObjectId` instances.

        .. warning::
           It is not safe to insert a document containing an ObjectId
           generated using this method. This method deliberately
           eliminates the uniqueness guarantee that ObjectIds
           generally provide. ObjectIds generated with this method
           should be used exclusively in queries.

        `generation_time` will be converted to UTC. Naive datetime
        instances will be treated as though they already contain UTC.

        An example using this helper to get documents where ``"_id"``
        was generated before January 1, 2010 would be:

        >>> gen_time = datetime.datetime(2010, 1, 1)
        >>> dummy_id = ObjectId.from_datetime(gen_time)
        >>> result = collection.find({"_id": {"$lt": dummy_id}})

        :Parameters:
          - `generation_time`: :class:`~datetime.datetime` to be used
            as the generation time for the resulting ObjectId.
        Nz>Is           )Ú	utcoffsetÚcalendarÚtimegmÚ	timetupleÚstructÚpackÚint)ÚclsÚgeneration_timeÚ	timestampr	   r
   r
   r   Úfrom_datetimep   s    zObjectId.from_datetimec             C   s2   |sdS yt |ƒ dS  ttfk
r,   dS X dS )z”Checks if a `oid` string is valid or not.

        :Parameters:
          - `oid`: the object id to validate

        .. versionadded:: 2.3
        FTN)r   r   Ú	TypeError)r$   r	   r
   r
   r   Úis_valid“   s    	zObjectId.is_validc             C   s&   t jƒ }|| jkr || _tƒ | _| jS )z:Generate a 5-byte random number once per process.
        )r   ÚgetpidÚ_pidr   Ú_ObjectId__random)r$   Úpidr
   r
   r   Ú_random¥   s
    
zObjectId._randomc             C   sj   t jdttjƒ ƒƒ}|tjƒ 7 }tj�4 |t jdtjƒdd… 7 }tjd td  t_W dQ R X || _	dS )z0Generate a new value for this ObjectId.
        z>Ié   é   N)
r!   r"   r#   Útimer   r.   Ú	_inc_lockÚ_incÚ_MAX_COUNTER_VALUEr   )r   r	   r
   r
   r   Z
__generate¯   s    zObjectId.__generatec             C   s€   t |tƒr|j| _nht |tƒrft|ƒdkr\yt|ƒ| _W qd ttfk
rX   t	|ƒ Y qdX q|t	|ƒ ntdt
jt|ƒf ƒ‚dS )a;  Validate and use the given id for this ObjectId.

        Raises TypeError if id is not an instance of
        (:class:`basestring` (:class:`str` or :class:`bytes`
        in python 3), ObjectId) and InvalidId if it is not a
        valid ObjectId.

        :Parameters:
          - `oid`: a valid ObjectId
        é   z7id must be an instance of (bytes, %s, ObjectId), not %sN)r   r   Úbinaryr   r   r   r   r(   Ú
ValueErrorr   r   Ú__name__Útype)r   r	   r
   r
   r   Z
__validateÀ   s    



zObjectId.__validatec             C   s   | j S )z812-byte binary representation of this ObjectId.
        )r   )r   r
   r
   r   r6   Ú   s    zObjectId.binaryc             C   s(   t jd| jdd… ƒd }tjj|tƒS )a	  A :class:`datetime.datetime` instance representing the time of
        generation for this :class:`ObjectId`.

        The :class:`datetime.datetime` is timezone aware, and
        represents the generation time in UTC. It is precise to the
        second.
        z>Ir   r0   )r!   Úunpackr   ÚdatetimeÚfromtimestampr   )r   r&   r
   r
   r   r%   à   s    	zObjectId.generation_timec             C   s   | j S )zdreturn value of object for pickling.
        needed explicitly because __slots__() defined.
        )r   )r   r
   r
   r   Ú__getstate__ì   s    zObjectId.__getstate__c             C   s>   t |tƒr|d }n|}tr4t |tƒr4|jdƒ| _n|| _dS )z)explicit state set from pickling
        r   zlatin-1N)r   Údictr   r   Úencoder   )r   Úvaluer	   r
   r
   r   Ú__setstate__ò   s    

zObjectId.__setstate__c             C   s    t rtj| jƒjƒ S tj| jƒS )N)r   ÚbinasciiÚhexlifyr   Údecode)r   r
   r
   r   Ú__str__  s    zObjectId.__str__c             C   s   dt | ƒf S )NzObjectId('%s'))Ústr)r   r
   r
   r   Ú__repr__  s    zObjectId.__repr__c             C   s   t |tƒr| j|jkS tS )N)r   r   r   r6   ÚNotImplemented)r   Úotherr
   r
   r   Ú__eq__  s    
zObjectId.__eq__c             C   s   t |tƒr| j|jkS tS )N)r   r   r   r6   rH   )r   rI   r
   r
   r   Ú__ne__  s    
zObjectId.__ne__c             C   s   t |tƒr| j|jk S tS )N)r   r   r   r6   rH   )r   rI   r
   r
   r   Ú__lt__  s    
zObjectId.__lt__c             C   s   t |tƒr| j|jkS tS )N)r   r   r   r6   rH   )r   rI   r
   r
   r   Ú__le__  s    
zObjectId.__le__c             C   s   t |tƒr| j|jkS tS )N)r   r   r   r6   rH   )r   rI   r
   r
   r   Ú__gt__  s    
zObjectId.__gt__c             C   s   t |tƒr| j|jkS tS )N)r   r   r   r6   rH   )r   rI   r
   r
   r   Ú__ge__$  s    
zObjectId.__ge__c             C   s
   t | jƒS )z,Get a hash value for this :class:`ObjectId`.)Úhashr   )r   r
   r
   r   Ú__hash__)  s    zObjectId.__hash__)r   )N)'r8   Ú
__module__Ú__qualname__Ú__doc__r   r*   r+   r   Úrandintr4   r3   Ú	threadingÚLockr2   r   r,   Ú	__slots__Z_type_markerr   Úclassmethodr'   r)   r.   r   r   Úpropertyr6   r%   r=   rA   rE   rG   rJ   rK   rL   rM   rN   rO   rQ   r
   r
   r
   r   r   0   s4   
1#
r   )rT   rB   r   r;   r   r!   rV   r1   Úrandomr   Zbson.errorsr   Zbson.py3compatr   r   r   r   Zbson.tz_utilr   r4   r   r   Úobjectr   r
   r
   r
   r   Ú<module>   s   