
    U-fn                         d Z ddlZddlZddlmZmZ ddlmZmZm	Z	m
Z
 ddlmZ  e	dd          Z G d	 dej        
          ZdS )zJOSE interfaces.    N)MappingSequence)AnyTypeTypeVarUnion)errorsGenericJSONDeSerializableJSONDeSerializable)boundc                   
   e Zd ZdZej        defd            ZdefdZe	ej        de
e         dedefd                        Ze	de
e         deeef         defd	            Zd
edefdZdefdZe	dd defd            ZdS )r   a  Interface for (de)serializable JSON objects.

    Please recall, that standard Python library implements
    :class:`json.JSONEncoder` and :class:`json.JSONDecoder` that perform
    translations based on respective :ref:`conversion tables
    <conversion-table>` that look pretty much like the one below (for
    complete tables see relevant Python documentation):

    .. _conversion-table:

    ======  ======
     JSON   Python
    ======  ======
    object  dict
    ...     ...
    ======  ======

    While the above **conversion table** is about translation of JSON
    documents to/from the basic Python types only,
    :class:`JSONDeSerializable` introduces the following two concepts:

      serialization
        Turning an arbitrary Python object into Python object that can
        be encoded into a JSON document. **Full serialization** produces
        a Python object composed of only basic types as required by the
        :ref:`conversion table <conversion-table>`. **Partial
        serialization** (accomplished by :meth:`to_partial_json`)
        produces a Python object that might also be built from other
        :class:`JSONDeSerializable` objects.

      deserialization
        Turning a decoded Python object (necessarily one of the basic
        types as required by the :ref:`conversion table
        <conversion-table>`) into an arbitrary Python object.

    Serialization produces **serialized object** ("partially serialized
    object" or "fully serialized object" for partial and full
    serialization respectively) and deserialization produces
    **deserialized object**, both usually denoted in the source code as
    ``jobj``.

    Wording in the official Python documentation might be confusing
    after reading the above, but in the light of those definitions, one
    can view :meth:`json.JSONDecoder.decode` as decoder and
    deserializer of basic types, :meth:`json.JSONEncoder.default` as
    serializer of basic types, :meth:`json.JSONEncoder.encode`  as
    serializer and encoder of basic types.

    One could extend :mod:`json` to support arbitrary object
    (de)serialization either by:

      - overriding :meth:`json.JSONDecoder.decode` and
        :meth:`json.JSONEncoder.default` in subclasses

      - or passing ``object_hook`` argument (or ``object_hook_pairs``)
        to :func:`json.load`/:func:`json.loads` or ``default`` argument
        for :func:`json.dump`/:func:`json.dumps`.

    Interestingly, ``default`` is required to perform only partial
    serialization, as :func:`json.dumps` applies ``default``
    recursively. This is the idea behind making :meth:`to_partial_json`
    produce only partial serialization, while providing custom
    :meth:`json_dumps` that dumps with ``default`` set to
    :meth:`json_dump_default`.

    To make further documentation a bit more concrete, please, consider
    the following imaginatory implementation example::

      class Foo(JSONDeSerializable):
          def to_partial_json(self):
              return 'foo'

          @classmethod
          def from_json(cls, jobj):
              return Foo()

      class Bar(JSONDeSerializable):
          def to_partial_json(self):
              return [Foo(), Foo()]

          @classmethod
          def from_json(cls, jobj):
              return Bar()

    returnc                     t                      )a  Partially serialize.

        Following the example, **partial serialization** means the following::

          assert isinstance(Bar().to_partial_json()[0], Foo)
          assert isinstance(Bar().to_partial_json()[1], Foo)

          # in particular...
          assert Bar().to_partial_json() != ['foo', 'foo']

        :raises josepy.errors.SerializationError:
            in case of any serialization error.
        :returns: Partially serializable object.

        )NotImplementedErrorselfs    `/home/cdr/domains/dharristours.com/map/certbot/lib/python3.11/site-packages/josepy/interfaces.pyto_partial_jsonz"JSONDeSerializable.to_partial_jsonc   s    " "###    c                 B    dt           dt           ffd |           S )aD  Fully serialize.

        Again, following the example from before, **full serialization**
        means the following::

          assert Bar().to_json() == ['foo', 'foo']

        :raises josepy.errors.SerializationError:
            in case of any serialization error.
        :returns: Fully serialized object.

        objr   c                    t          | t                    r |                                           S t          | t                    r| S t          | t                    rfd| D             S t          | t
                    rt          fd| D                       S t          | t                    r fd|                                 D             S | S )Nc                 &    g | ]} |          S  r   .0subobj
_serializes     r   
<listcomp>zBJSONDeSerializable.to_json.<locals>._serialize.<locals>.<listcomp>   s#    ===v

6**===r   c              3   .   K   | ]} |          V  d S )Nr   r   s     r   	<genexpr>zAJSONDeSerializable.to_json.<locals>._serialize.<locals>.<genexpr>   s-      BBFZZ//BBBBBBr   c                 @    i | ]\  }} |           |          S r   r   )r   keyvaluer   s      r   
<dictcomp>zBJSONDeSerializable.to_json.<locals>._serialize.<locals>.<dictcomp>   s1    YYYzsE

3E):):YYYr   )	
isinstancer   r   strlistr   tupler   items)r   r   s    r   r   z.JSONDeSerializable.to_json.<locals>._serialize   s    #122 9!z#"5"5"7"7888#s## 
C&& 	========C**  BBBBcBBBBBBC)) YYYYSYY[[YYYY
r   )r   )r   r   s    @r   to_jsonzJSONDeSerializable.to_jsonv   sA    	C 	C 	 	 	 	 	 	  z$r   clsjobjc                      |             S )a  Deserialize a decoded JSON document.

        :param jobj: Python object, composed of only other basic data
            types, as decoded from JSON document. Not necessarily
            :class:`dict` (as decoded from "JSON object" document).

        :raises josepy.errors.DeserializationError:
            if decoding was unsuccessful, e.g. in case of unparseable
            X509 certificate, or wrong padding in JOSE base64 encoded
            string, etc.

        r   )r,   r-   s     r   	from_jsonzJSONDeSerializable.from_json   s    " suur   json_stringc                     	 t          j        |          }n&# t          $ r}t          j        |          d}~ww xY w|                     |          S )z&Deserialize from JSON document string.N)jsonloads
ValueErrorr	   DeserializationErrorr/   )r,   r0   r3   errors       r   
json_loadszJSONDeSerializable.json_loads   sZ    
	5J{++EE 	5 	5 	5-e444	5}}U###s    
:5:kwargsc                 4    t          j        | fd| j        i|S )zsDump to JSON string using proper serializer.

        :returns: JSON document string.
        :rtype: str

        default)r2   dumpsjson_dump_default)r   r8   s     r   
json_dumpszJSONDeSerializable.json_dumps   s$     z$II(>I&IIIr   c                 2    |                      ddd          S )zNDump the object to pretty JSON document string.

        :rtype: str

        T   ),z: )	sort_keysindent
separators)r=   r   s    r   json_dumps_prettyz$JSONDeSerializable.json_dumps_pretty   s     aKPPPr   python_objectc                     t          |t                    r|                                S t          t	          |          dz             )a  Serialize Python object.

        This function is meant to be passed as ``default`` to
        :func:`json.dump` or :func:`json.dumps`. They call
        ``default(python_object)`` only for non-basic Python types, so
        this function necessarily raises :class:`TypeError` if
        ``python_object`` is not an instance of
        :class:`IJSONSerializable`.

        Please read the class docstring for more information.

        z is not JSON serializable)r&   r   r   	TypeErrorrepr)r,   rE   s     r   r<   z$JSONDeSerializable.json_dump_default   sF     m%788 	O 00222D//2MMNNNr   N)__name__
__module____qualname____doc__abcabstractmethodr   r   r+   classmethodr   r
   r/   r   r'   bytesr7   r=   rD   r<   r   r   r   r   r      sx       T Tl 	$ $ $ $ $$         @ t56 c F_     [" $+,$;@e;L$	"$ $ $ [$J3 J3 J J J JQ3 Q Q Q Q O.B Os O O O [O O Or   )	metaclass)rL   rM   r2   collections.abcr   r   typingr   r   r   r   josepyr	   r
   ABCMetar   r   r   r   <module>rV      s      



  - - - - - - - - , , , , , , , , , , , ,      #G$?G[\\\ JO JO JO JO JO3; JO JO JO JO JO JOr   