U
    d                     @   s  U 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mZm	Z	m
Z
mZmZmZmZmZmZ ddlmZmZmZmZ ddlmZ ddl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/m0Z0m1Z1 ddl2m3Z3 ddl4m5Z5 ej6ej7ej8ej9ej:ej;dZ<G dd dZ=G dd dZ>G dd deZ?e?e>j@dZAe?eBd< e?e>jCdZDe?eBd< e?e>jEdZFe?eBd< eFZGe?eBd< eeeeHddd ZIeeHeJeKf eeed!d"d#ZLeGfee?ed$d%d&ZMeGfeeeHef  e?ed'd(d)ZNeGfe
eHef e?ed*d+d,ZOeed-d.d/ZPee?eeejQf d0d1d2ZReeSe?eeejQf d3d4d5ZTee?eeejQf d0d6d7ZUee?eeejQf d0d8d9ZVee?eejef d0d:d;ZWee,d-d<d=ZXeeHd-d>d?ZYeed-d@dAZZee.d-dBdCZ[ee"d-dDdEZ\eed-dFdGZ]eeSd-dHdIZ^ee&d-dJdKZ_ee`d-dLdMZaee$d-dNdOZbee*d-dPdQZcee(d-dRdSZdeJeSe?ed3dTdUZeeGfee?ed$dVdWZfdS )XaO  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 Relaxed Extended JSON format.
:mod:`~bson.json_util` can also generate Canonical or legacy `Extended JSON`_
when :const:`CANONICAL_JSON_OPTIONS` or :const:`LEGACY_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=="}}]'
   ... )
   [{'foo': [1, 2]}, {'bar': {'hello': 'world'}}, {'code': Code('function x() { return 1; }', {})}, {'bin': Binary(b'...', 128)}]

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

.. 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; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "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:`LEGACY_JSON_OPTIONS`):

.. doctest::

   >>> from bson import Binary, Code
   >>> from bson.json_util import dumps, LEGACY_JSON_OPTIONS
   >>> dumps(
   ...     [
   ...         {"foo": [1, 2]},
   ...         {"bar": {"hello": "world"}},
   ...         {"code": Code("function x() { return 1; }", {})},
   ...         {"bin": Binary(b"")},
   ...     ],
   ...     json_options=LEGACY_JSON_OPTIONS,
   ... )
   '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }", "$scope": {}}}, {"bin": {"$binary": "AQIDBA==", "$type": "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`.
    N)	AnyDictMappingOptionalSequenceTupleTypeUnioncast)ALL_UUID_SUBTYPESUUID_SUBTYPEBinaryUuidRepresentation)Code)CodecOptionsDatetimeConversion)EPOCH_AWARE
DatetimeMS_datetime_to_millis_max_datetime_ms_millis_to_datetime)DBRef)
Decimal128)Int64)MaxKey)MinKey)ObjectId)Regex)RE_TYPESON)	Timestamp)utc)ilmsuxc                   @   s   e Zd ZdZdZdZdS )DatetimeRepresentationr         N)__name__
__module____qualname__LEGACY
NUMBERLONGISO8601 r1   r1   2/tmp/pip-unpacked-wheel-oblwsawz/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	CANONICALr1   r1   r1   r2   r3      s   r3   c                
       s   e Zd ZU eed< eed< eed< eed< eed fddZdddej	fe
d  ee ee ee eeed d	 fd
dZed fddZeeef d fddZed dddZ  ZS )JSONOptions	json_modestrict_number_longdatetime_representationstrict_uuid)argskwargsc                    s   t    dS )a  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 :class:`~bson.binary.UuidRepresentation`
            to use when encoding and decoding instances of :class:`uuid.UUID`.
            Defaults to :const:`~bson.binary.UuidRepresentation.UNSPECIFIED`.
          - `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 ``False``.
          - `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`.
          - `datetime_conversion`: Specifies how UTC datetimes should be decoded
            within BSON. Valid options include 'datetime_ms' to return as a
            DatetimeMS, 'datetime' to return as a datetime.datetime and
            raising a ValueError for out-of-range values, 'datetime_auto' to
            return DatetimeMS objects when the underlying datetime is
            out-of-range and 'datetime_clamp' to clamp to the minimum and
            maximum possible datetimes. Defaults to 'datetime'. See
            :ref:`handling-out-of-range-datetimes` for details.
          - `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`_.

        .. versionchanged:: 4.0
           The default for `json_mode` was changed from :const:`JSONMode.LEGACY`
           to :const:`JSONMode.RELAXED`.
           The default for `uuid_representation` was changed from
           :const:`~bson.binary.UuidRepresentation.PYTHON_LEGACY` to
           :const:`~bson.binary.UuidRepresentation.UNSPECIFIED`.

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

        .. versionchanged:: 4.0
           Changed default value of `tz_aware` to False.
        N)super__init__)selfr;   r<   	__class__r1   r2   r>      s    7zJSONOptions.__init__N)clsr8   r9   r:   r7   r;   r<   returnc                    s|  | dd|d< |d r(| dt|d< |tjtjtjd fkrFtdttt	 j
| f||}|tjtjtjfkr|td||_|jtjkr|rtd|d tjfkrtd|dkrtd	d|_tj|_d
|_n|jtjkr4|dkrtd|d tjfkrtd|dkrtd	d
|_tj|_d
|_nDd|_tj|_d|_|d k	rX||_|d k	rh||_|d k	rx||_|S )Ntz_awareF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.z<Cannot specify strict_number_long=True with JSONMode.RELAXEDz_datetime_representation must be DatetimeRepresentation.ISO8601 or omitted with JSONMode.RELAXED)NTz6Cannot specify strict_uuid=False with JSONMode.RELAXEDTz=Cannot specify strict_number_long=False with JSONMode.RELAXEDzbdatetime_representation must be DatetimeRepresentation.NUMBERLONG or omitted with JSONMode.RELAXED)getr!   r(   r.   r/   r0   
ValueErrorr
   r6   r=   __new__r3   r4   r5   r7   r8   r9   r:   )rB   r8   r9   r:   r7   r;   r<   r?   r@   r1   r2   rH     sh    	



zJSONOptions.__new__)rC   c                    s    d | j| j| j| jt  S )Nz[strict_number_long={!r}, datetime_representation={!r}, strict_uuid={!r}, json_mode={!r}, {})formatr8   r9   r:   r7   r=   _arguments_repr)r?   r@   r1   r2   rJ   _  s    zJSONOptions._arguments_reprc                    s*   t   }|| j| j| j| jd |S )Nr8   r9   r:   r7   )r=   _options_dictupdater8   r9   r:   r7   )r?   Zoptions_dictr@   r1   r2   rL   l  s    
zJSONOptions._options_dict)r<   rC   c                 K   s<   |   }dD ]}||t| |||< q|| tf |S )a  
        Make a copy of this JSONOptions, overriding some options::

            >>> from bson.json_util import CANONICAL_JSON_OPTIONS
            >>> CANONICAL_JSON_OPTIONS.tz_aware
            True
            >>> json_options = CANONICAL_JSON_OPTIONS.with_options(tz_aware=False, tzinfo=None)
            >>> json_options.tz_aware
            False

        .. versionadded:: 3.12
        rK   )rL   rF   getattrrM   r6   )r?   r<   optsoptr1   r1   r2   with_optionsy  s
    
zJSONOptions.with_options)r+   r,   r-   int__annotations__boolr   r>   r3   r4   r   r   rH   strrJ   r   rL   rQ   __classcell__r1   r1   r@   r2   r6      s,   
;Cr6   )r7   LEGACY_JSON_OPTIONSCANONICAL_JSON_OPTIONSRELAXED_JSON_OPTIONSDEFAULT_JSON_OPTIONS)objr;   r<   rC   c                 O   s$   | dt}tjt| |f||S )aa  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:: 4.0
       Now outputs MongoDB Relaxed Extended JSON by default (using
       :const:`DEFAULT_JSON_OPTIONS`).

    .. versionchanged:: 3.4
       Accepts optional parameter `json_options`. See :class:`JSONOptions`.
    json_options)poprZ   jsondumps_json_convert)r[   r;   r<   r\   r1   r1   r2   r_     s    r_   )r%   r;   r<   rC   c                    s.   | 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:: 4.0
       Now loads :class:`datetime.datetime` instances as naive by default. To
       load timezone aware instances utilize the `json_options` parameter.
       See :ref:`tz_aware_default_change` for an example.

    .. 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`.
    r\   c                    s
   t |  S N)object_pairs_hook)pairsr\   r1   r2   <lambda>      zloads.<locals>.<lambda>rb   )r]   rZ   r^   loads)r%   r;   r<   r1   rd   r2   rg     s    rg   )r[   r\   rC   c                    sx   t | dr$t fdd|  D S t | drNt| ttfsN fdd| D S zt|  W S  tk
rr   |  Y S X dS )z]Recursive helper method that converts BSON types so they can be
    converted into json.
    itemsc                 3   s    | ]\}}|t | fV  qd S ra   r`   ).0kvrd   r1   r2   	<genexpr>  s     z _json_convert.<locals>.<genexpr>__iter__c                    s   g | ]}t | qS r1   ri   )rj   rl   rd   r1   r2   
<listcomp>  s     z!_json_convert.<locals>.<listcomp>N)hasattrr   rh   
isinstancerU   bytesdefault	TypeError)r[   r\   r1   rd   r2   r`     s    
r`   )rc   r\   rC   c                 C   s   t || |S ra   )object_hookZdocument_class)rc   r\   r1   r1   r2   rb     s    rb   )dctr\   rC   c                 C   s  d| krt | S t| dtrHd| krHt| dttd frHt| S d| krZt| |S d| krjt| S d| krzt| S d| krt	| S d	| krd
| krt
| |S t| |S d| krt| S d| krt| |S d| krd S d| krt| S d| kr| d }t|d |d S d| kr"t| S d| kr4t| S d| krFt| S d| krXt| S d| krjt| S d| kr|t| S | S )N$oid$ref$id$db$date$regex$minKey$maxKey$binary$type$code$uuidz
$undefined$numberLong
$timestamptr"   $numberDecimal
$dbPointer$regularExpression$symbol
$numberInt$numberDouble)_parse_canonical_oidrq   rF   rU   type_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)rv   r\   Ztspr1   r1   r2   ru     sZ    










ru   )docrC   c                 C   sJ   | d }t |ttfs| S d}| ddD ]}|t|dO }q*t||S )Nr|   r   $options )rq   rU   rr   rF   _RE_OPT_TABLEr   )r   patternflagsrP   r1   r1   r2   r   +  s    r   )r   r\   rC   c                 C   sh   t | dkrtd|  t| d ts6td|  |jtjkrVtt	
| d S t	
| d S dS )z*Decode a JSON legacy $uuid to Python UUID.r)   zBad $uuid, extra field(s): r   z$uuid must be a string: N)lenrt   rq   rU   uuid_representationr   UNSPECIFIEDr   	from_uuiduuidUUID)r   r\   r1   r1   r2   r   7  s    r   )datasubtyper\   rC   c                 C   sn   |t krP|j}t| |}|tjkr&|S |tkr6tj}n|tjkrFtj}||S |dkrdt	t
j| S t| |S )Nr   )r   r   r   r   r   r   ZSTANDARDZPYTHON_LEGACYZas_uuidr
   r   r   )r   r   r\   r   Zbinary_valuer1   r1   r2   _binary_or_uuidC  s    



r   c                 C   sh   t | d trd| d  | d< t| d d}|dkrJt| d dd  d}t| d  }t|||S )Nr   %02x   l       r   )rq   rR   base64	b64decodeencoder   )r   r\   r   r   r1   r1   r2   r   X  s    r   c                 C   s   | d }|d }|d }t |ts0td|  t |trFt|dkrTtd|  t|dkrntd|  t| }t|t|d|S )	Nr   r   subTypez!$binary base64 must be a string: r*   z7$binary subType must be a string at most 2 characters: z=$binary must include only "base64" and "subType" components: r   )	rq   rU   rt   r   r   r   r   r   rR   )r   r\   binaryZb64r   r   r1   r1   r2   r   b  s    
r   c                 C   s^  | d }t | dkr"td|  t|trP|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}|d}d}|dkrtt||d d }|d| }tj|dj	|t
d}|r|dkrt |dkrt|dd d
\}}	t|d t|	d  }
nZt |dkrt|dd d t|dd d  }
n"t |dkrt|dd d }
|d dkr|
d9 }
|tj|
d }|jr*|jr||j}|jtjkr&t|S |S |j	dd}|jtjkrLt|S |S tt||S )z3Decode a JSON datetime to python datetime.datetime.r{   r)   zBad $date, extra field(s): ZNi)+-:r   .r   i@B %Y-%m-%dT%H:%M:%S)microsecondrE   r   i  <         r   )secondsrE   )r   rt   rq   rU   rfindrR   floatdatetimestrptimereplacer!   split	timedeltarD   rE   
astimezoneZdatetime_conversionr   ZDATETIME_MSr   r   )r   r\   ZdtmdtoffsetZ	dot_indexr   ZawarehoursminutesZsecsZaware_tzinfo_noner1   r1   r2   r   q  sb    

 *r   c                 C   s&   t | dkrtd|  t| d S )z1Decode a JSON ObjectId to bson.objectid.ObjectId.r)   zBad $oid, extra field(s): rw   )r   rt   r   r   r1   r1   r2   r     s    r   c                 C   s*   | d }t | dkr"td|  t|S )z&Decode a JSON symbol to Python string.r   r)   zBad $symbol, extra field(s): )r   rt   rU   )r   symbolr1   r1   r2   r     s    r   c                 C   s6   | D ]}|dkrt d|  qt| d | ddS )z%Decode a JSON code to bson.code.Code.)r   $scopezBad $code, extra field(s): r   r   )scope)rt   r   rF   )r   keyr1   r1   r2   r     s    r   c                 C   sl   | d }t | dkr"td|  t |dkr<td| |d }t|ts^tdt| t|d |S )	z(Decode a JSON regex to bson.regex.Regex.r   r)   z(Bad $regularExpression, extra field(s): r*   zNBad $regularExpression must include only "pattern"and "options" components: {}optionszCBad $regularExpression options, options must be string, was type %sr   )r   rt   rI   rq   rU   r   r   )r   regexrO   r1   r1   r2   r     s    

r   c                 C   s*   t | d| dfd| ddi| S )z(Decode a JSON DBRef to bson.dbref.DBRef.rx   ry   databaserz   N)r   r]   r   r1   r1   r2   r     s    r   c                 C   s   | d }t | dkr"td|  t|tr| }|jdk	rLtd| t|jtsftd| t |dkrtd| |S td	|  dS )
z9Decode a JSON (deprecated) DBPointer to bson.dbref.DBRef.r   r)   z Bad $dbPointer, extra field(s): Nz!Bad $dbPointer, extra field $db: z)Bad $dbPointer, $id must be an ObjectId: r*   z)Bad $dbPointer, extra field(s) in DBRef: z"Bad $dbPointer, expected a DBRef: )r   rt   rq   r   as_docr   idr   )r   ZdbrefZ	dbref_docr1   r1   r2   r     s    

r   c                 C   sB   | d }t | dkr"td|  t|ts:td|  t|S )z"Decode a JSON int32 to python int.r   r)   z Bad $numberInt, extra field(s): z$numberInt must be string: )r   rt   rq   rU   rR   )r   Zi_strr1   r1   r2   r     s    
r   c                 C   s*   | d }t | dkr"td|  t|S )z(Decode a JSON int64 to bson.int64.Int64.r   r)   z!Bad $numberLong, extra field(s): )r   rt   r   )r   Zl_strr1   r1   r2   r     s    r   c                 C   sB   | d }t | dkr"td|  t|ts:td|  t|S )z%Decode a JSON double to python float.r   r)   z#Bad $numberDouble, extra field(s): z$numberDouble must be string: )r   rt   rq   rU   r   r   Zd_strr1   r1   r2   r     s    
r   c                 C   sB   | d }t | dkr"td|  t|ts:td|  t|S )z7Decode a JSON decimal128 to bson.decimal128.Decimal128.r   r)   z$Bad $numberDecimal, extra field(s): z$numberDecimal must be string: )r   rt   rq   rU   r   r   r1   r1   r2   r     s    
r   c                 C   sJ   t | d tk	s| d dkr*td|  t| dkrDtd|  t S )z,Decode a JSON MinKey to bson.min_key.MinKey.r}   r)   z$minKey value must be 1: Bad $minKey, extra field(s): )r   rR   rt   r   r   r   r1   r1   r2   r     s
    r   c                 C   sH   t | d tk	s| d dkr(td| ft| dkrBtd|  t S )z,Decode a JSON MaxKey to bson.max_key.MaxKey.r~   r)   z$maxKey value must be 1: %sr   )r   rR   rt   r   r   r   r1   r1   r2   r   #  s
    r   c                 C   sT   |j tjkr.tdt|  fdd| fgS dtdt|  fdd| fgiS )Nr   r   r   r   r   )r7   r3   r.   r   r   	b64encodedecode)r   r   r\   r1   r1   r2   _encode_binary,  s
    "  r   c           
      C   s  t | trdt| iS t | tr0t|  |dS t | tjr|jtj	kr| j
sj| jtd} | j
d k	sjt| tkr| j
| }|j|j|jfdkrd}n
| d}t| jd }|rd|f nd	}d
d| d||iS t| }|jtjkrd
|iS d
dt|iiS t | tr|jtj	krPdt|   kr>t krPn nt|  |S |jtjkrnd
tt| iS d
dtt| iiS |jrt | trdt| iS t | tt frd	}| j!t"j#@ r|d7 }| j!t"j$@ r|d7 }| j!t"j%@ r|d7 }| j!t"j&@ r|d7 }| j!t"j'@ r$|d7 }| j!t"j(@ r:|d7 }t | j)trP| j)}n| 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.rddiS t | t/rddiS t | t0rdt-d| j1fd| j2fgiS t | t3r*| j4d kr
d t| iS t-d t| fd!t| j4|fgS t | t5rDt6| | j7|S t | t8r\t6| d|S t | t9j:r|j;rt5j<| |j=d"}t6||j7|S d#| j>iS t | t?rd$t| iS t | t@r| S |j+t,jAkrt | trd%|   krd&k rn nd't| iS dt| iS |j+t,jkrt | tBrtCD| r>d(d)iS tCE| rd| dkrXd*nd+}	d(|	iS |j+t,jAkrd(ttF| iS tGd,|  d S )-Nrw   rd   r   )r   r   r   r   z%zi  z.%03dr   r{   z{}{}{}r   r   r   r"   r#   r$   r%   r&   r'   zutf-8r|   r   r   r   r   r}   r)   r~   r   r   r   r   )r   r   r   i   l        r   r   NaNInfinityz	-Infinityz%r is not JSON serializable)Hrq   r   rU   r   r`   r   r   r9   r(   r0   rE   r   r!   AssertionErrorr   	utcoffsetdaysr   microsecondsstrftimerR   r   rI   r   r.   r   r   rs   Zas_datetimer8   r   r   r   r   re
IGNORECASELOCALE	MULTILINEDOTALLUNICODEVERBOSEr   r   r7   r3   r   r   r   r    timeincr   r   r   r   r   rr   r   r   r:   r   r   hexr   rT   r5   r   mathisnanisinfreprrt   )
r[   r\   offZ	tz_stringZmillisZfracsecsr   r   ZbinvalZrepresentationr1   r1   r2   rs   4  s    


 
 
 
rs   )g__doc__r   r   r^   r   r   r   typingr   r   r   r   r   r   r   r	   r
   Zbson.binaryr   r   r   r   Z	bson.coder   Zbson.codec_optionsr   r   Zbson.datetime_msr   r   r   r   r   Z
bson.dbrefr   Zbson.decimal128r   Z
bson.int64r   Zbson.max_keyr   Zbson.min_keyr   Zbson.objectidr   Z
bson.regexr   Zbson.sonr   r   Zbson.timestampr    Zbson.tz_utilr!   ILMSUXr   r(   r3   r6   r.   rW   rS   r5   rX   r4   rY   rZ   rU   r_   rr   	bytearrayrg   r`   rb   ru   r   r   r   rR   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rs   r1   r1   r1   r2   <module>   s   X,
$+ 1 0
 B


		