U
    d#                     @   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mZmZmZmZ ddlmZ ddlmZ dZeedd	d
ZedddZG dd dZdS )z)Tools for working with MongoDB ObjectIds.    N)SystemRandom)AnyNoReturnOptionalTypeUnion	InvalidId)utci oidreturnc                 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 stringr   )r    r   1/tmp/pip-unpacked-wheel-oblwsawz/bson/objectid.py_raise_invalid_id!   s
    r   r   c                   C   s
   t 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 Ze de	Z
e Ze ZdZdZd2eeed ef  ddddZeed  ejd d	d
dZeed  eedddZeedddZddddZeddddZ e!edddZ"e!ejdddZ#edddZ$eddddZ%eddd Z&edd!d"Z'eed#d$d%Z(eed#d&d'Z)eed#d(d)Z*eed#d*d+Z+eed#d,d-Z,eed#d.d/Z-e.dd0d1Z/dS )3ObjectIdzA MongoDB ObjectId.r   )Z__id   Nr   c                 C   s>   |dkr|    n(t|tr0t|dkr0|| _n
| | dS )ay  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`.

        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:`str` of 24 hex digits::

          >>> ObjectId('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.

        .. seealso:: The MongoDB documentation on  `ObjectIds <http://dochub.mongodb.org/core/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__)clsgeneration_timer   c                 C   sB   |  }|dk	r|| }t| }t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.
        N>Is           )	utcoffsetcalendartimegm	timetuplestructpackint)r"   r#   offset	timestampr   r   r   r   from_datetimeh   s    zObjectId.from_datetime)r"   r   r   c              	   C   s6   |sdS zt | W dS  ttfk
r0   Y dS X dS )zChecks 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_validr   c                 C   s&   t  }|| jkr || _t | _| jS )z1Generate 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 dtt }|t 7 }tj4 |t dtjdd 7 }tjd td  t_W 5 Q R X || _	dS )z'Generate a new value for this ObjectId.r$         N)
r)   r*   r+   timer   r5   	_inc_lock_inc_MAX_COUNTER_VALUEr   r   r   r   r   Z
__generate   s    zObjectId.__generatec              	   C   s~   t |tr|j| _nft |trht|dkr^zt|| _W qf tt	fk
rZ   t
| Y qfX qzt
| ntdt| dS )a  Validate and use the given id for this ObjectId.

        Raises TypeError if id is not an instance of :class:`str`,
        :class:`bytes`, or ObjectId. Raises InvalidId if it is not a
        valid ObjectId.

        :Parameters:
          - `oid`: a valid ObjectId
           z6id must be an instance of (bytes, str, ObjectId), not N)r   r   binaryr   strr   r   fromhexr/   
ValueErrorr   typer   r   r   r   Z
__validate   s    




zObjectId.__validatec                 C   s   | j S )z/12-byte binary representation of this ObjectId.r   r    r   r   r   r=      s    zObjectId.binaryc                 C   s(   t d| jdd d }t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.
        r$   r   r7   )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.
        rB   rC   r   r   r   __getstate__   s    zObjectId.__getstate__)valuer   c                 C   s:   t |tr|d }n|}t |tr0|d| _n|| _dS )z Explicit state set from picklingr   zlatin-1N)r   dictr>   encoder   )r    rH   r   r   r   r   __setstate__   s    


zObjectId.__setstate__c                 C   s   t | j S N)binasciihexlifyr   decoderC   r   r   r   __str__   s    zObjectId.__str__c                 C   s   dt |  dS )Nz
ObjectId('z'))r>   rC   r   r   r   __repr__   s    zObjectId.__repr__)otherr   c                 C   s   t |tr| j|jkS tS rL   r   r   r   r=   NotImplementedr    rR   r   r   r   __eq__   s    
zObjectId.__eq__c                 C   s   t |tr| j|jkS tS rL   rS   rU   r   r   r   __ne__   s    
zObjectId.__ne__c                 C   s   t |tr| j|jk S tS rL   rS   rU   r   r   r   __lt__  s    
zObjectId.__lt__c                 C   s   t |tr| j|jkS tS rL   rS   rU   r   r   r   __le__  s    
zObjectId.__le__c                 C   s   t |tr| j|jkS tS rL   rS   rU   r   r   r   __gt__  s    
zObjectId.__gt__c                 C   s   t |tr| j|jkS tS rL   rS   rU   r   r   r   __ge__  s    
zObjectId.__ge__c                 C   s
   t | jS )z,Get a hash value for this :class:`ObjectId`.)hashr   rC   r   r   r   __hash__  s    zObjectId.__hash__)N)0__name__
__module____qualname____doc__r   r1   r2   r   randintr;   r:   	threadingLockr9   r   r3   	__slots__Z_type_markerr   r   r>   r   r!   classmethodr   rE   r.   r   boolr0   r5   r   r   propertyr=   r#   rG   rK   rP   rQ   rV   rW   rX   rY   rZ   r[   r+   r]   r   r   r   r   r   -   s>    -"r   )ra   rM   r&   rE   r   r)   rc   r8   randomr   typingr   r   r   r   r   Zbson.errorsr	   Zbson.tz_utilr
   r;   r>   r   r   r   r   r   r   r   r   <module>   s   