o
    sDi,                  	   @  sn  d Z ddlm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mZ edjZedjZdZd	Zd
ZdZdZdZdZdZdZee dfZedfZee dfZedfZ ee dfZ!edfZ"eej#eedg ej$ej%ej&gddZ'ej(d"i e') Z*eeje+e,e	e-ee- e-f f Z.G dd deZ/G dd deZ0d#ddZ1d$ddZ2G d d! d!Z3dS )%zHTools for working with the BSON decimal128 type.

.. versionadded:: 3.4
    )annotationsNDecimal)AnySequenceTupleTypeUnion)TypeDecoderTypeEncoderz<Ql            i   i   i"   l          @ l          ` l          p l               )precroundingEminEmaxcapitalsflagstrapsclampc                   @  (   e Zd ZdZedddZdd	d
ZdS )DecimalEncodera  Converts Python :class:`decimal.Decimal` to BSON :class:`Decimal128`.

    For example::
        opts = CodecOptions(type_registry=TypeRegistry([DecimalEncoder()]))
        bson.encode({"d": decimal.Decimal('1.0')}, codec_options=opts)

    .. versionadded:: 4.15
    returnType[Decimal]c                 C     t S Nr   self r   M/home/alumno/antzosa8961/venv/lib/python3.10/site-packages/bson/decimal128.pypython_typeJ      zDecimalEncoder.python_typevaluer   
Decimal128c                 C  s   t |S r   r#   r   r"   r   r   r   transform_pythonN      zDecimalEncoder.transform_pythonN)r   r   )r"   r   r   r#   )__name__
__module____qualname____doc__propertyr    r&   r   r   r   r   r   @   
    	r   c                   @  r   )DecimalDecoderzConverts BSON :class:`Decimal128` to Python :class:`decimal.Decimal`.

    For example::
        opts = CodecOptions(type_registry=TypeRegistry([DecimalDecoder()]))
        bson.decode(data, codec_options=opts)

    .. versionadded:: 4.15
    r   Type[Decimal128]c                 C  r   r   r$   r   r   r   r   	bson_type\   r!   zDecimalDecoder.bson_typer"   r   decimal.Decimalc                 C  s   |  S r   )
to_decimalr%   r   r   r   transform_bson`   r'   zDecimalDecoder.transform_bsonN)r   r/   )r"   r   r   r1   )r(   r)   r*   r+   r,   r0   r3   r   r   r   r   r.   R   r-   r.   r   decimal.Contextc                  C  s    t  } g | d< tjdi | S )zReturns an instance of :class:`decimal.Context` appropriate
    for working with IEEE-754 128-bit decimal floating point values.
    r   Nr   )_CTX_OPTIONScopydecimalContext)optsr   r   r   create_decimal128_contextd   s   r:   r"   _VALUE_OPTIONSTuple[int, int]c                 C  sl  t t}|| } W d   n1 sw   Y  |  r&|  r$tS tS |  \}}}| 	 rK|r7t
d|  rC|  rAtS tS |  rItS tS tddd |D }| }d}d}ttd|D ]}	|d|	> @ rt|d|	> O }qftd|D ]}	|d|	> @ r|d|	d > O }qz|t }
|d	? dkr|d
@ }|tO }||
d@ d> O }n||
d	> O }|r|tO }||fS )zoConverts a decimal.Decimal to BID (high bits, low bits).

    :param value: An instance of decimal.Decimal
    Nz'NaN with debug payload is not supported c                 S  s   g | ]}t |qS r   )str.0digitr   r   r   
<listcomp>   s    z#_decimal_to_128.<locals>.<listcomp>r   @   r   1   l    i?  /   )r7   localcontext_DEC128_CTXcreate_decimalis_infinite	is_signed_NINF_PINFas_tupleis_nan
ValueErroris_snan_NSNAN_PSNAN_NNAN_PNANintjoin
bit_lengthrangemin_EXPONENT_BIAS_EXPONENT_MASK_SIGN)r"   ctxsigndigitsexponentsignificandrW   highlowibiased_exponentr   r   r   _decimal_to_128m   sB   rf   c                   @  s   e Zd ZdZdZdZd&dd	Zd'ddZed(ddZ	e
d)ddZd*ddZd*ddZd+ddZd,ddZd-d!d"Zd-d#d$Zd%S ).r#   a  BSON Decimal128 type::

      >>> Decimal128(Decimal("0.0005"))
      Decimal128('0.0005')
      >>> Decimal128("0.0005")
      Decimal128('0.0005')
      >>> Decimal128((3474527112516337664, 5))
      Decimal128('0.0005')

    :param value: An instance of :class:`decimal.Decimal`, string, or tuple of
        (high bits, low bits) from Binary Integer Decimal (BID) format.

    .. note:: :class:`~Decimal128` uses an instance of :class:`decimal.Context`
      configured for IEEE-754 Decimal128 when validating parameters.
      Signals like :class:`decimal.InvalidOperation`, :class:`decimal.Inexact`,
      and :class:`decimal.Overflow` are trapped and raised as exceptions::

        >>> Decimal128(".13.1")
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
          ...
        decimal.InvalidOperation: [<class 'decimal.ConversionSyntax'>]
        >>>
        >>> Decimal128("1E-6177")
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
          ...
        decimal.Inexact: [<class 'decimal.Inexact'>]
        >>>
        >>> Decimal128("1E6145")
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
          ...
        decimal.Overflow: [<class 'decimal.Overflow'>, <class 'decimal.Rounded'>]

      To ensure the result of a calculation can always be stored as BSON
      Decimal128 use the context returned by
      :func:`create_decimal128_context`::

        >>> import decimal
        >>> decimal128_ctx = create_decimal128_context()
        >>> with decimal.localcontext(decimal128_ctx) as ctx:
        ...     Decimal128(ctx.create_decimal(".13.3"))
        ...
        Decimal128('NaN')
        >>>
        >>> with decimal.localcontext(decimal128_ctx) as ctx:
        ...     Decimal128(ctx.create_decimal("1E-6177"))
        ...
        Decimal128('0E-6176')
        >>>
        >>> with decimal.localcontext(DECIMAL128_CTX) as ctx:
        ...     Decimal128(ctx.create_decimal("1E6145"))
        ...
        Decimal128('Infinity')

      To match the behavior of MongoDB's Decimal128 implementation
      str(Decimal(value)) may not match str(Decimal128(value)) for NaN values::

        >>> Decimal128(Decimal('NaN'))
        Decimal128('NaN')
        >>> Decimal128(Decimal('-NaN'))
        Decimal128('NaN')
        >>> Decimal128(Decimal('sNaN'))
        Decimal128('NaN')
        >>> Decimal128(Decimal('-sNaN'))
        Decimal128('NaN')

      However, :meth:`~Decimal128.to_decimal` will return the exact value::

        >>> Decimal128(Decimal('NaN')).to_decimal()
        Decimal('NaN')
        >>> Decimal128(Decimal('-NaN')).to_decimal()
        Decimal('-NaN')
        >>> Decimal128(Decimal('sNaN')).to_decimal()
        Decimal('sNaN')
        >>> Decimal128(Decimal('-sNaN')).to_decimal()
        Decimal('-sNaN')

      Two instances of :class:`Decimal128` compare equal if their Binary
      Integer Decimal encodings are equal::

        >>> Decimal128('NaN') == Decimal128('NaN')
        True
        >>> Decimal128('NaN').bid == Decimal128('NaN').bid
        True

      This differs from :class:`decimal.Decimal` comparisons for NaN::

        >>> Decimal('NaN') == Decimal('NaN')
        False
    )__high__low   r"   r;   r   Nonec                 C  sf   t |ttjfrt|\| _| _d S t |ttfr+t	|dkr#t
d|\| _| _d S td|d)N   zYInvalid size for creation of Decimal128 from list or tuple. Must have exactly 2 elements.zCannot convert z to Decimal128)
isinstancer>   r7   r   rf   _Decimal128__high_Decimal128__lowlisttuplelenrO   	TypeErrorr%   r   r   r   __init__   s   zDecimal128.__init__r1   c           
      C  s  | j }| j}|t@ rdnd}|t@ tkrt|ddfS |t@ tkr*t|ddfS |t@ tkr8t|ddfS |t@ tkrN|d@ d? t	 }t|d	|fS |d
@ d? t	 }t
d}d}tdddD ]}||@ d| d> ? ||< |d> }qbd}tdddD ]}||@ d| d> ? ||< |d> }q}d}||@ d? |d< tdd tt|dD }tt}	|	|||fW  d   S 1 sw   Y  dS )z^Returns an instance of :class:`decimal.Decimal` for this
        :class:`Decimal128`.
        r   r   r   NnFl          rE   )r   l          rD                     l          0   c                 s  s    | ]}t |V  qd S r   )rU   r?   r   r   r   	<genexpr>1  s    z(Decimal128.to_decimal.<locals>.<genexpr>bigN)rm   rn   r\   _SNANr7   r   _NAN_INFr[   rZ   	bytearrayrX   rp   r>   rU   
from_bytesrF   rG   rH   )
r   rb   rc   r^   r`   arrmaskrd   r_   r]   r   r   r   r2     s8   

$zDecimal128.to_decimalclsr/   bytesc                 C  s\   t |tstdt| t|dkrtd| t|dd d t|dd d fS )zCreate an instance of :class:`Decimal128` from Binary Integer
        Decimal string.

        :param value: 16 byte string (128-bit IEEE 754-2008 decimal floating
            point in Binary Integer Decimal (BID) format).
        z(value must be an instance of bytes, not    zvalue must be exactly 16 bytesr}   Nr   )rl   r   rr   typerq   rO   
_UNPACK_64)r   r"   r   r   r   from_bid6  s
   
,zDecimal128.from_bidc                 C  s   t | jt | j S )z;The Binary Integer Decimal (BID) encoding of this instance.)_PACK_64rn   rm   r   r   r   r   bidD  s   zDecimal128.bidr>   c                 C  s   |   }| r
dS t|S )NNaN)r2   rN   r>   )r   decr   r   r   __str__I  s   zDecimal128.__str__c                 C  s   d| dS )NzDecimal128('z')r   r   r   r   r   __repr__P     zDecimal128.__repr__r<   c                 C  s   |\| _ | _d S r   rm   rn   r%   r   r   r   __setstate__S  s   zDecimal128.__setstate__c                 C  s   | j | jfS r   r   r   r   r   r   __getstate__V  r   zDecimal128.__getstate__otherr   boolc                 C  s   t |tr| j|jkS tS r   )rl   r#   r   NotImplementedr   r   r   r   r   __eq__Y  s   
zDecimal128.__eq__c                 C  s
   | |k S r   r   r   r   r   r   __ne__^  s   
zDecimal128.__ne__N)r"   r;   r   rj   )r   r1   )r   r/   r"   r   r   r#   )r   r   )r   r>   )r"   r<   r   rj   )r   r<   )r   r   r   r   )r(   r)   r*   r+   	__slots___type_markerrs   r2   classmethodr   r,   r   r   r   r   r   r   r   r   r   r   r   r#      s     ]

)




r#   r   )r   r4   )r"   r;   r   r<   )4r+   
__future__r   r7   structr   typingr   r   r   r   r	   bson.codec_optionsr
   r   Structpackr   unpackr   r[   rZ   _EXPONENT_MAX_EXPONENT_MIN_MAX_DIGITSr   r   r   r\   rK   rL   rS   rT   rQ   rR   ROUND_HALF_EVENInvalidOperationOverflowInexactr5   r8   r6   rG   floatr>   rU   r;   r   r.   r:   rf   r#   r   r   r   r   <module>   sP    

	0