3
]ð]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
Z
ddl
mZmZmZ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dlmZ dd	lmZ dd
lmZ ddlm Z  ddl!m"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dl/m0Z0 ej1ej2ej3ej4ej5ej6dœZ7e8dddgƒZ9G dd„ dƒZ:G dd„ dƒZ;G dd„ deƒZ<e<e;j=d�Z>e>Z?e<e;j@d�ZAe<e;jBd�ZCe<de:jDdd�ZEdd „ ZFd!d"„ ZGe?fd#d$„ZHe?fd%d&„ZIe?fd'd(„ZJd)d*„ ZKd+d,„ ZLd-d.„ ZMd/d0„ ZNd1d2„ ZOd3d4„ ZPd5d6„ ZQd7d8„ ZRd9d:„ ZSd;d<„ ZTd=d>„ ZUd?d@„ ZVdAdB„ ZWdCdD„ ZXdEdF„ ZYdGdH„ ZZdIdJ„ Z[dKdL„ Z\dMdN„ Z]e?fdOdP„Z^dS )Qaá  Tools for using Python's :mod:`json` module with BSON documents.

This module provides two helper methods `dumps` and `loads` that wrap the
native :mod:`json` methods and provide explicit BSON conversion to and from
JSON. :class:`~bson.json_util.JSONOptions` provides a way to control how JSON
is emitted and parsed, with the default being the legacy PyMongo format.
:mod:`~bson.json_util` can also generate Canonical or Relaxed `Extended JSON`_
when :const:`CANONICAL_JSON_OPTIONS` or :const:`RELAXED_JSON_OPTIONS` is
provided, respectively.

.. _Extended JSON: https://github.com/mongodb/specifications/blob/master/source/extended-json.rst

Example usage (deserialization):

.. doctest::

   >>> from bson.json_util import loads
   >>> loads('[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$scope": {}, "$code": "function x() { return 1; }"}}, {"bin": {"$type": "80", "$binary": "AQIDBA=="}}]')
   [{u'foo': [1, 2]}, {u'bar': {u'hello': u'world'}}, {u'code': Code('function x() { return 1; }', {})}, {u'bin': Binary('...', 128)}]

Example usage (serialization):

.. doctest::

   >>> from bson import Binary, Code
   >>> from bson.json_util import dumps
   >>> dumps([{'foo': [1, 2]},
   ...        {'bar': {'hello': 'world'}},
   ...        {'code': Code("function x() { return 1; }", {})},
   ...        {'bin': Binary(b"")}])
   '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }", "$scope": {}}}, {"bin": {"$binary": "AQIDBA==", "$type": "00"}}]'

Example usage (with :const:`CANONICAL_JSON_OPTIONS`):

.. doctest::

   >>> from bson import Binary, Code
   >>> from bson.json_util import dumps, CANONICAL_JSON_OPTIONS
   >>> dumps([{'foo': [1, 2]},
   ...        {'bar': {'hello': 'world'}},
   ...        {'code': Code("function x() { return 1; }")},
   ...        {'bin': Binary(b"")}],
   ...       json_options=CANONICAL_JSON_OPTIONS)
   '[{"foo": [{"$numberInt": "1"}, {"$numberInt": "2"}]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]'

Example usage (with :const:`RELAXED_JSON_OPTIONS`):

.. doctest::

   >>> from bson import Binary, Code
   >>> from bson.json_util import dumps, RELAXED_JSON_OPTIONS
   >>> dumps([{'foo': [1, 2]},
   ...        {'bar': {'hello': 'world'}},
   ...        {'code': Code("function x() { return 1; }")},
   ...        {'bin': Binary(b"")}],
   ...       json_options=RELAXED_JSON_OPTIONS)
   '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]'

Alternatively, you can manually pass the `default` to :func:`json.dumps`.
It won't handle :class:`~bson.binary.Binary` and :class:`~bson.code.Code`
instances (as they are extended strings you can't provide custom defaults),
but it will be faster as there is less recursion.

.. note::
   If your application does not need the flexibility offered by
   :class:`JSONOptions` and spends a large amount of time in the `json_util`
   module, look to
   `python-bsonjs <https://pypi.python.org/pypi/python-bsonjs>`_ for a nice
   performance improvement. `python-bsonjs` is a fast BSON to MongoDB
   Extended JSON converter for Python built on top of
   `libbson <https://github.com/mongodb/libbson>`_. `python-bsonjs` works best
   with PyMongo when using :class:`~bson.raw_bson.RawBSONDocument`.

.. versionchanged:: 2.8
   The output format for :class:`~bson.timestamp.Timestamp` has changed from
   '{"t": <int>, "i": <int>}' to '{"$timestamp": {"t": <int>, "i": <int>}}'.
   This new format will be decoded to an instance of
   :class:`~bson.timestamp.Timestamp`. The old format will continue to be
   decoded to a python dict as before. Encoding to the old format is no longer
   supported as it was never correct and loses type information.
   Added support for $numberLong and $undefined - new in MongoDB 2.6 - and
   parsing $date in ISO-8601 format.

.. versionchanged:: 2.7
   Preserves order when rendering SON, Timestamp, Code, Binary, and DBRef
   instances.

.. versionchanged:: 2.3
   Added dumps and loads helpers to automatically handle conversion to and
   from json and supports :class:`~bson.binary.Binary` and
   :class:`~bson.code.Code`
é    N)ÚConfigurationError)ÚEPOCH_AWAREÚEPOCH_NAIVEÚRE_TYPEÚSON)ÚBinaryÚJAVA_LEGACYÚCSHARP_LEGACYÚOLD_UUID_SUBTYPEÚUUID_SUBTYPE)ÚCode)ÚCodecOptions)ÚDBRef)Ú
Decimal128)ÚInt64)ÚMaxKey)ÚMinKey)ÚObjectId)ÚPY3Ú	iteritemsÚinteger_typesÚstring_typeÚ	text_type)ÚRegex)Ú	Timestamp)Úutc)ÚiÚlÚmÚsÚuÚxz$idz$refz$dbc               @   s   e Zd ZdZdZdZdS )ÚDatetimeRepresentationr   é   é   N)Ú__name__Ú
__module__Ú__qualname__ÚLEGACYÚ
NUMBERLONGÚISO8601© r+   r+   ú1/tmp/pip-build-20mum3z4/pymongo/bson/json_util.pyr"   –   s   
r"   c               @   s   e Zd ZdZdZdZdS )ÚJSONModer   r#   r$   N)r%   r&   r'   r(   ÚRELAXEDÚ	CANONICALr+   r+   r+   r,   r-   º   s   r-   c                   s:   e Zd ZdZdejdejf‡ fdd„	Z‡ fdd„Z‡  Z	S )ÚJSONOptionsa*  Encapsulates JSON options for :func:`dumps` and :func:`loads`.

    :Parameters:
      - `strict_number_long`: If ``True``, :class:`~bson.int64.Int64` objects
        are encoded to MongoDB Extended JSON's *Strict mode* type
        `NumberLong`, ie ``'{"$numberLong": "<number>" }'``. Otherwise they
        will be encoded as an `int`. Defaults to ``False``.
      - `datetime_representation`: The representation to use when encoding
        instances of :class:`datetime.datetime`. Defaults to
        :const:`~DatetimeRepresentation.LEGACY`.
      - `strict_uuid`: If ``True``, :class:`uuid.UUID` object are encoded to
        MongoDB Extended JSON's *Strict mode* type `Binary`. Otherwise it
        will be encoded as ``'{"$uuid": "<hex>" }'``. Defaults to ``False``.
      - `json_mode`: The :class:`JSONMode` to use when encoding BSON types to
        Extended JSON. Defaults to :const:`~JSONMode.LEGACY`.
      - `document_class`: BSON documents returned by :func:`loads` will be
        decoded to an instance of this class. Must be a subclass of
        :class:`collections.MutableMapping`. Defaults to :class:`dict`.
      - `uuid_representation`: The BSON representation to use when encoding
        and decoding instances of :class:`uuid.UUID`. Defaults to
        :const:`~bson.binary.PYTHON_LEGACY`.
      - `tz_aware`: If ``True``, MongoDB Extended JSON's *Strict mode* type
        `Date` will be decoded to timezone aware instances of
        :class:`datetime.datetime`. Otherwise they will be naive. Defaults
        to ``True``.
      - `tzinfo`: A :class:`datetime.tzinfo` subclass that specifies the
        timezone from which :class:`~datetime.datetime` objects should be
        decoded. Defaults to :const:`~bson.tz_util.utc`.
      - `args`: arguments to :class:`~bson.codec_options.CodecOptions`
      - `kwargs`: arguments to :class:`~bson.codec_options.CodecOptions`

    .. seealso:: The specification for Relaxed and Canonical `Extended JSON`_.

    .. versionadded:: 3.4

    .. versionchanged:: 3.5
       Accepts the optional parameter `json_mode`.

    Fc                sØ   |j ddƒ|d< |d r(|j dtƒ|d< |tjtjtjfkrDtdƒ‚tt| ƒj	| f|ž|Ž}|t
jt
jt
jfkrxtdƒ‚||_|jt
jkr d|_tj|_d|_n4|jt
jkrÂd|_tj|_d|_n||_||_||_|S )NÚtz_awareTÚtzinfoznJSONOptions.datetime_representation must be one of LEGACY, NUMBERLONG, or ISO8601 from DatetimeRepresentation.zQJSONOptions.json_mode must be one of LEGACY, RELAXED, or CANONICAL from JSONMode.F)Úgetr   r"   r(   r)   r*   r   Úsuperr0   Ú__new__r-   r.   r/   Ú	json_modeÚstrict_number_longÚdatetime_representationÚstrict_uuid)Úclsr7   r8   r9   r6   ÚargsÚkwargsÚself)Ú	__class__r+   r,   r5     s6    

zJSONOptions.__new__c                s$   d| j | j| j| jtt| ƒjƒ f S )NzSstrict_number_long=%r, datetime_representation=%r, strict_uuid=%r, json_mode=%r, %s)r7   r8   r9   r6   r4   r0   Ú_arguments_repr)r=   )r>   r+   r,   r?   1  s    zJSONOptions._arguments_repr)
r%   r&   r'   Ú__doc__r"   r(   r-   r5   r?   Ú__classcell__r+   r+   )r>   r,   r0   å   s
   '!r0   )r6   T)r7   r8   r9   c             O   s$   |j dtƒ}tjt| |ƒf|ž|ŽS )aW  Helper function that wraps :func:`json.dumps`.

    Recursive function that handles all BSON types including
    :class:`~bson.binary.Binary` and :class:`~bson.code.Code`.

    :Parameters:
      - `json_options`: A :class:`JSONOptions` instance used to modify the
        encoding of MongoDB Extended JSON types. Defaults to
        :const:`DEFAULT_JSON_OPTIONS`.

    .. versionchanged:: 3.4
       Accepts optional parameter `json_options`. See :class:`JSONOptions`.

    .. versionchanged:: 2.7
       Preserves order when rendering SON, Timestamp, Code, Binary, and DBRef
       instances.
    Újson_options)ÚpopÚDEFAULT_JSON_OPTIONSÚjsonÚdumpsÚ_json_convert)Úobjr;   r<   rB   r+   r+   r,   rF   l  s    rF   c                s.   |j dtƒ‰ ‡ fdd„|d< tj| f|ž|ŽS )a  Helper function that wraps :func:`json.loads`.

    Automatically passes the object_hook for BSON type conversion.

    Raises ``TypeError``, ``ValueError``, ``KeyError``, or
    :exc:`~bson.errors.InvalidId` on invalid MongoDB Extended JSON.

    :Parameters:
      - `json_options`: A :class:`JSONOptions` instance used to modify the
        decoding of MongoDB Extended JSON types. Defaults to
        :const:`DEFAULT_JSON_OPTIONS`.

    .. versionchanged:: 3.5
       Parses Relaxed and Canonical Extended JSON as well as PyMongo's legacy
       format. Now raises ``TypeError`` or ``ValueError`` when parsing JSON
       type wrappers with values of the wrong type or any extra keys.

    .. versionchanged:: 3.4
       Accepts optional parameter `json_options`. See :class:`JSONOptions`.
    rB   c                s
   t | ˆ ƒS )N)Úobject_pairs_hook)Úpairs)rB   r+   r,   Ú<lambda>˜  s   zloads.<locals>.<lambda>rI   )rC   rD   rE   Úloads)r   r;   r<   r+   )rB   r,   rL   ‚  s    rL   c                s‚   t | dƒst | dƒr.t‡ fdd„t| ƒD ƒƒS t | dƒr^t| ttfƒ r^t‡ fdd„| D ƒƒS y
t| ˆ ƒS  tk
r|   | S X dS )z]Recursive helper method that converts BSON types so they can be
    converted into json.
    r   Úitemsc             3   s    | ]\}}|t |ˆ ƒfV  qd S )N)rG   )Ú.0ÚkÚv)rB   r+   r,   ú	<genexpr>¢  s   z _json_convert.<locals>.<genexpr>Ú__iter__c             3   s   | ]}t |ˆ ƒV  qd S )N)rG   )rN   rP   )rB   r+   r,   rQ   ¥  s    N)	Úhasattrr   r   Ú
isinstancer   ÚbytesÚlistÚdefaultÚ	TypeError)rH   rB   r+   )rB   r,   rG   �  s    
rG   c             C   s   t |j| ƒ|ƒS )N)Úobject_hookZdocument_class)rJ   rB   r+   r+   r,   rI   ¬  s    rI   c             C   sR  d| krt | ƒS d| kr t| ƒS d| kr2t| |ƒS d| krBt| ƒS d| krRt| ƒS d| krbt| ƒS d| kr†d| kr|t| |ƒS t| |ƒS d	| kr–t| ƒS d
| kr¦t	| ƒS d| kr²d S d| krÂt
| ƒS d| krä| d }t|d |d ƒS d| krôt| ƒS d| k�rt| ƒS d| k�rt| ƒS d| k�r*t| ƒS d| k�r<t| ƒS d| k�rNt| ƒS | S )Nz$oidz$refz$datez$regexz$minKeyz$maxKeyz$binaryz$typez$codez$uuidz
$undefinedz$numberLongz
$timestampÚtr   z$numberDecimalz
$dbPointerz$regularExpressionz$symbolz
$numberIntz$numberDouble)Ú_parse_canonical_oidÚ_parse_canonical_dbrefÚ_parse_canonical_datetimeÚ_parse_legacy_regexÚ_parse_canonical_minkeyÚ_parse_canonical_maxkeyÚ_parse_legacy_binaryÚ_parse_canonical_binaryÚ_parse_canonical_codeÚ_parse_legacy_uuidÚ_parse_canonical_int64r   Ú_parse_canonical_decimal128Ú_parse_canonical_dbpointerÚ_parse_canonical_regexÚ_parse_canonical_symbolÚ_parse_canonical_int32Ú_parse_canonical_double)ÚdctrB   Ztspr+   r+   r,   rY   °  sP    







rY   c             C   sJ   | d }t |tƒr| S d}x$| jddƒD ]}|tj|dƒO }q(W t||ƒS )Nz$regexr   z$optionsÚ )rT   r   r3   Ú_RE_OPT_TABLE)ÚdocÚpatternÚflagsÚoptr+   r+   r,   r^   Ü  s    
r^   c             C   s(   t | ƒdkrtd| f ƒ‚tj| d ƒS )z*Decode a JSON legacy $uuid to Python UUID.r#   zBad $uuid, extra field(s): %sz$uuid)ÚlenrX   ÚuuidÚUUID)ro   r+   r+   r,   rd   è  s    rd   c             C   s~   |t krP|jtkrtj| d�S |jtkrD| dd d… | d dd…  } tj| d�S |tkrdtj| d�S trt|dkrt| S t| |ƒS )N)Úbytes_leé   r#   )rU   r   éÿÿÿÿrx   )	r
   Úuuid_representationr	   rt   ru   r   r   r   r   )ÚdataÚsubtyperB   r+   r+   r,   Ú_binary_or_uuidï  s    

r|   c             C   sh   t | d tƒrd| d  | d< t| d dƒ}|dkrJt| d dd … dƒ}tj| d jƒ ƒ}t|||ƒS )Nz$typez%02xé   l   €ÿ é   z$binary)rT   ÚintÚbase64Ú	b64decodeÚencoder|   )ro   rB   r{   rz   r+   r+   r,   ra   þ  s    ra   c             C   s�   | d }|d }|d }t |tƒs0td| f ƒ‚t |tƒ sHt|ƒdkrVtd| f ƒ‚t|ƒdkrptd| f ƒ‚tj|jƒ ƒ}t|t|dƒ|ƒS )	Nz$binaryr€   ÚsubTypez#$binary base64 must be a string: %sr$   z9$binary subType must be a string at most 2 characters: %sz?$binary must include only "base64" and "subType" components: %sr}   )	rT   r   rX   rs   r€   r�   r‚   r|   r   )ro   rB   ÚbinaryZb64r{   rz   r+   r+   r,   rb     s    


rb   c             C   s0  | d }t | ƒdkr"td| f ƒ‚t|tƒ�r |d dkrL|dd… }d}n†|d dkr~|d d
kr~|dd… }|dd… }nT|d dkr¤|dd… }|d d… }n.|d! d"krÊ|dd#… }|d$d… }n|}d}|jdƒ}d}|d%k�rtt||d… ƒd ƒ}|d|… }tjj|dƒj	|t
d�}|�rô|dk�rôt |ƒdk�rt|dd… jd
ƒ\}}	t|ƒd t|	ƒd  }
nZt |ƒdk�r¬t|dd	… ƒd t|d	d… ƒd  }
n"t |ƒd	k�rÎt|dd	… ƒd }
|d dk�rä|
d&9 }
|tj|
d� }|j�r|j�r|j|jƒ}|S |j	dd�S tjt|ƒ|ƒS )'z3Decode a JSON datetime to python datetime.datetime.z$dater#   zBad $date, extra field(s): %sÚZNr~   ú+ú-é   ú:é   rm   Ú.r   i@B z%Y-%m-%dT%H:%M:%S)Úmicrosecondr2   i  é<   )Úseconds)r2   rx   rx   iúÿÿÿ)r†   r‡   éýÿÿÿiúÿÿÿiúÿÿÿéûÿÿÿ)r†   r‡   r�   r�   r�   )r†   r‡   r�   r�   rx   rx   )rs   rX   rT   r   Úrfindr   ÚfloatÚdatetimeÚstrptimeÚreplacer   ÚsplitÚ	timedeltar1   r2   Ú
astimezoneÚbsonZ_millis_to_datetime)ro   rB   ZdtmÚdtÚoffsetZ	dot_indexrŒ   ZawareÚhoursÚminutesZsecsr+   r+   r,   r]     sV    


*r]   c             C   s&   t | ƒdkrtd| f ƒ‚t| d ƒS )z1Decode a JSON ObjectId to bson.objectid.ObjectId.r#   zBad $oid, extra field(s): %sz$oid)rs   rX   r   )ro   r+   r+   r,   r[   T  s    r[   c             C   s*   | d }t | ƒdkr"td| f ƒ‚t|ƒS )z&Decode a JSON symbol to Python string.z$symbolr#   zBad $symbol, extra field(s): %s)rs   rX   r   )ro   Úsymbolr+   r+   r,   ri   [  s    ri   c             C   s:   x"| D ]}|dkrt d| f ƒ‚qW t| d | jdƒd�S )z%Decode a JSON code to bson.code.Code.ú$codeú$scopezBad $code, extra field(s): %s)Úscope)rŸ   r    )rX   r   r3   )ro   Úkeyr+   r+   r,   rc   c  s    
rc   c             C   sN   | d }t | ƒdkr"td| f ƒ‚t |ƒdkr<td| f ƒ‚t|d |d ƒS )z(Decode a JSON regex to bson.regex.Regex.z$regularExpressionr#   z*Bad $regularExpression, extra field(s): %sr$   zNBad $regularExpression must include only "pattern"and "options" components: %srp   Úoptions)rs   rX   r   )ro   Úregexr+   r+   r,   rh   k  s    
rh   c             C   sN   x"| D ]}|j dƒr|tkr| S qW t| jdƒ| jdƒfd| jddƒi| —ŽS )z(Decode a JSON DBRef to bson.dbref.DBRef.ú$z$refz$idÚdatabasez$dbN)Ú
startswithÚ_DBREF_KEYSr   rC   )ro   r¢   r+   r+   r,   r\   v  s
    
r\   c             C   s–   | d }t | ƒdkr"td| f ƒ‚t|tƒr„|jƒ }|jdk	rLtd|f ƒ‚t|jtƒsftd|f ƒ‚t |ƒdkr€td|f ƒ‚|S td	| f ƒ‚dS )
z9Decode a JSON (deprecated) DBPointer to bson.dbref.DBRef.z
$dbPointerr#   z"Bad $dbPointer, extra field(s): %sNz#Bad $dbPointer, extra field $db: %sz+Bad $dbPointer, $id must be an ObjectId: %sr$   z+Bad $dbPointer, extra field(s) in DBRef: %sz$Bad $dbPointer, expected a DBRef: %s)rs   rX   rT   r   Úas_docr¦   Úidr   )ro   ZdbrefZ	dbref_docr+   r+   r,   rg   €  s     

rg   c             C   sB   | d }t | ƒdkr"td| f ƒ‚t|tƒs:td| f ƒ‚t|ƒS )z"Decode a JSON int32 to python int.z
$numberIntr#   z"Bad $numberInt, extra field(s): %sz$numberInt must be string: %s)rs   rX   rT   r   r   )ro   Zi_strr+   r+   r,   rj   –  s    
rj   c             C   s*   | d }t | ƒdkr"td| f ƒ‚t|ƒS )z(Decode a JSON int64 to bson.int64.Int64.z$numberLongr#   z#Bad $numberLong, extra field(s): %s)rs   rX   r   )ro   Zl_strr+   r+   r,   re      s    re   c             C   sB   | d }t | ƒdkr"td| f ƒ‚t|tƒs:td| f ƒ‚t|ƒS )z%Decode a JSON double to python float.z$numberDoubler#   z%Bad $numberDouble, extra field(s): %sz $numberDouble must be string: %s)rs   rX   rT   r   r’   )ro   Úd_strr+   r+   r,   rk   ¨  s    
rk   c             C   sB   | d }t | ƒdkr"td| f ƒ‚t|tƒs:td| f ƒ‚t|ƒS )z7Decode a JSON decimal128 to bson.decimal128.Decimal128.z$numberDecimalr#   z&Bad $numberDecimal, extra field(s): %sz!$numberDecimal must be string: %s)rs   rX   rT   r   r   )ro   r«   r+   r+   r,   rf   ²  s    
rf   c             C   sJ   t | d ƒtk	s| d dkr*td| f ƒ‚t| ƒdkrDtd| f ƒ‚tƒ S )z,Decode a JSON MinKey to bson.min_key.MinKey.z$minKeyr#   z$minKey value must be 1: %szBad $minKey, extra field(s): %s)Útyper   rX   rs   r   )ro   r+   r+   r,   r_   ¼  s
    r_   c             C   sH   t | d ƒtk	s| d dkr(td| fƒ‚t| ƒdkrBtd| f ƒ‚tƒ S )z,Decode a JSON MaxKey to bson.max_key.MaxKey.z$maxKeyr#   z$maxKey value must be 1: %szBad $minKey, extra field(s): %s)r¬   r   rX   rs   r   )ro   r+   r+   r,   r`   Å  s
    r`   c             C   sT   |j tjkr.tdtj| ƒjƒ fdd| fgƒS dtdtj| ƒjƒ fdd| fgƒiS )Nz$binaryz$typez%02xr€   rƒ   )r6   r-   r(   r   r€   Ú	b64encodeÚdecode)rz   r{   rB   r+   r+   r,   Ú_encode_binaryÎ  s    r¯   c             C   sV  t | tƒrdt| ƒiS t | tƒr0t| jƒ |d�S t | tjƒ� rú|jtj	krÌ| j
s\| jtd�} | tkrÌ| j
j| ƒ}|j|j|jfd,krŠd}n
| jdƒ}t| jd ƒ}|r°d|f nd	}d
d| jdƒ||f iS tj| ƒ}|jtjkrêd
|iS d
dt|ƒiiS |j�rt | tƒ�rdt| ƒiS t | ttfƒ�rd	}| jtj@ �rD|d7 }| jtj@ �rZ|d7 }| jtj @ �rp|d7 }| jtj!@ �r†|d7 }| jtj"@ �rœ|d7 }| jtj#@ �r²|d7 }t | j$t%ƒ�rÈ| j$}n| j$j&dƒ}|j't(jk�röt)d|fd|fgƒS dt)d|fd|fgƒiS t | t*ƒ�r"ddiS t | t+ƒ�r6ddiS t | t,ƒ�r^dt)d| j-fd| j.fgƒiS t | t/ƒ�r¢| j0d k�r‚dt| ƒiS t)dt| ƒfd t| j0|ƒfgƒS t | t1ƒ�r¼t2| | j3|ƒS t4�rÚt | t5ƒ�rÚt2| d|ƒS t | t6j7ƒ�r^|j8�rT| j5}t9}	|j:t;k�r| j<}n:|j:t=k�r8|d!d d-… |d d!d.…  }n|j:t>k�rHt>}	t2||	|ƒS d"| j?iS t | t@ƒ�rvd#t| ƒiS t | tAƒ�r†| S |j't(jBk�rÔt | tCƒ�rÔd0|   k�o´d1k n  �rÈd&t%| ƒiS dt%| ƒiS |j't(jk�rFt | tDƒ�rFtEjF| ƒ�rd'd(iS tEjG| ƒ�r(| dk�rd)nd*}
d'|
iS |j't(jBk�rFd't%tH| ƒƒiS tId+|  ƒ‚d S )2Nz$oid)rB   )r2   r   r…   z%ziè  z.%03drm   z$datez%s%s%sz%Y-%m-%dT%H:%M:%Sz$numberLongr   r   r   r   r    r!   zutf-8z$regexz$optionsz$regularExpressionrp   r£   z$minKeyr#   z$maxKeyz
$timestamprZ   z$codez$scoperw   z$uuidz$numberDecimalr$   é   z
$numberIntz$numberDoubleÚNaNÚInfinityz	-Infinityz%r is not JSON serializable)r   r   r   rx   rx   l        i   €l        )JrT   r   Ústrr   rG   r©   r“   r8   r"   r*   r2   r•   r   r   Ú	utcoffsetÚdaysrŽ   ÚmicrosecondsÚstrftimer   rŒ   r™   Z_datetime_to_millisr(   r7   r   r   r   rq   ÚreÚ
IGNORECASEÚLOCALEÚ	MULTILINEÚDOTALLÚUNICODEÚVERBOSErp   r   r®   r6   r-   r   r   r   r   ÚtimeÚincr   r¡   r   r¯   r{   r   rU   rt   ru   r9   r
   ry   r	   rv   r   r   Úhexr   Úboolr/   r   r’   ÚmathÚisnanÚisinfÚreprrX   )rH   rB   ÚoffZ	tz_stringZmillisZfracsecsrq   rp   rz   r{   Zrepresentationr+   r+   r,   rW   Ø  s¸    






rW   )_r@   r€   r“   rE   rÃ   r¸   Úsysrt   Zpymongo.errorsr   r™   r   r   r   r   Zbson.binaryr   r   r	   r
   r   Z	bson.coder   Zbson.codec_optionsr   Z
bson.dbrefr   Zbson.decimal128r   Z
bson.int64r   Zbson.max_keyr   Zbson.min_keyr   Zbson.objectidr   Zbson.py3compatr   r   r   r   r   Z
bson.regexr   Zbson.timestampr   Zbson.tz_utilr   ÚIÚLÚMÚSÚUÚXrn   Ú	frozensetr¨   r"   r-   r0   r(   ZLEGACY_JSON_OPTIONSrD   r/   ZCANONICAL_JSON_OPTIONSr.   ZRELAXED_JSON_OPTIONSr*   ZSTRICT_JSON_OPTIONSrF   rL   rG   rI   rY   r^   rd   r|   ra   rb   r]   r[   ri   rc   rh   r\   rg   rj   re   rk   rf   r_   r`   r¯   rW   r+   r+   r+   r,   Ú<module>j   s„   
$+W	,
;



		
