
    wBfx                        d Z ddlmZ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 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 d
dlmZ d
dlmZmZ d
dlm Z  d
dl!m"Z" d
dl#m$Z$ 	 ddl%m&Z&m%Z% ddl%m'Z( ddl%m)Z* e e(       vr
 e*ed        [([* ee/      Z0g dZ1dZ2dZ3 G d d      Z4 G d de4      Z5e5Z6 G d  d!e4      Z7e7Z8 G d" d#e4      Z9 G d$ d%e4      Z: G d& d'e4      Z; G d( d)e4      Z< G d* d+e4      Z= G d, d-e=      Z> G d. d/e4      Z? G d0 d1e4      Z@ G d2 d3eA      ZB G d4 d5eB6      ZC G d7 d8eC      ZD G d9 d:      ZE G d; d<e
      ZFy=# e+$ r ddl,m%Z% ddl-m.Z& Y w xY w)>a  
This module provides serializable, validatable, type-enforcing domain objects and data
transfer objects. It has many of the same motivations as the python
`Marshmallow <http://marshmallow.readthedocs.org/en/latest/why.html>`_ package. It is most
similar to `Schematics <http://schematics.readthedocs.io/>`_.

========
Tutorial
========

Chapter 1: Entity and Field Basics
----------------------------------

    >>> class Color(Enum):
    ...     blue = 0
    ...     black = 1
    ...     red = 2
    >>> class Car(Entity):
    ...     weight = NumberField(required=False)
    ...     wheels = IntField(default=4, validation=lambda x: 3 <= x <= 4)
    ...     color = EnumField(Color)

    >>> # create a new car object
    >>> car = Car(color=Color.blue, weight=4242.46)
    >>> car
    Car(weight=4242.46, color=0)

    >>> # it has 4 wheels, all by default
    >>> car.wheels
    4

    >>> # but a car can't have 5 wheels!
    >>> #  the `validation=` field is a simple callable that returns a
    >>> #  boolean based on validity
    >>> car.wheels = 5
    Traceback (most recent call last):
    ValidationError: Invalid value 5 for wheels

    >>> # we can call .dump() on car, and just get back a standard
    >>> #  python dict actually, it's an ordereddict to match attribute
    >>> #  declaration order
    >>> type(car.dump())
    <class '...OrderedDict'>
    >>> car.dump()
    OrderedDict([('weight', 4242.46), ('wheels', 4), ('color', 0)])

    >>> # and json too (note the order!)
    >>> car.json()
    '{"weight": 4242.46, "wheels": 4, "color": 0}'

    >>> # green cars aren't allowed
    >>> car.color = "green"
    Traceback (most recent call last):
    ValidationError: 'green' is not a valid Color

    >>> # but black cars are!
    >>> car.color = "black"
    >>> car.color
    <Color.black: 1>

    >>> # car.color really is an enum, promise
    >>> type(car.color)
    <enum 'Color'>

    >>> # enum assignment can be with any of (and preferentially)
    >>> #   (1) an enum literal,
    >>> #   (2) a valid enum value, or
    >>> #   (3) a valid enum name
    >>> car.color = Color.blue; car.color.value
    0
    >>> car.color = 1; car.color.name
    'black'

    >>> # let's do a round-trip marshalling of this thing
    >>> same_car = Car.from_json(car.json())  # or equally Car.from_json(json.dumps(car.dump()))
    >>> same_car == car
    True

    >>> # actually, they're two different instances
    >>> same_car is not car
    True

    >>> # this works too
    >>> cloned_car = Car(**car.dump())
    >>> cloned_car == car
    True

    >>> # while we're at it, these are all equivalent too
    >>> car == Car.from_objects(car)
    True
    >>> car == Car.from_objects({"weight": 4242.46, "wheels": 4, "color": 1})
    True
    >>> car == Car.from_json('{"weight": 4242.46, "color": 1}')
    True

    >>> # .from_objects() even lets you stack and combine objects
    >>> class DumbClass:
    ...     color = 0
    ...     wheels = 3
    >>> Car.from_objects(DumbClass(), dict(weight=2222, color=1))
    Car(weight=2222, wheels=3, color=0)
    >>> # and also pass kwargs that override properties pulled
    >>> #  off any objects
    >>> Car.from_objects(DumbClass(), {'weight': 2222, 'color': 1}, color=2, weight=33)
    Car(weight=33, wheels=3, color=2)


Chapter 2: Entity and Field Composition
---------------------------------------

    >>> # now let's get fancy
    >>> # a ComposableField "nests" another valid Entity
    >>> # a ListField's first argument is a "generic" type,
    >>> #   which can be a valid Entity, any python primitive
    >>> #   type, or a list of Entities/types
    >>> class Fleet(Entity):
    ...     boss_car = ComposableField(Car)
    ...     cars = ListField(Car)

    >>> # here's our fleet of company cars
    >>> company_fleet = Fleet(boss_car=Car(color='red'), cars=[car, same_car, cloned_car])
    >>> company_fleet.pretty_json()  #doctest: +SKIP
    {
      "boss_car": {
        "wheels": 4
        "color": 2,
      },
      "cars": [
        {
          "weight": 4242.46,
          "wheels": 4
          "color": 1,
        },
        {
          "weight": 4242.46,
          "wheels": 4
          "color": 1,
        },
        {
          "weight": 4242.46,
          "wheels": 4
          "color": 1,
        }
      ]
    }

    >>> # the boss' car is red of course (and it's still an Enum)
    >>> company_fleet.boss_car.color.name
    'red'

    >>> # and there are three cars left for the employees
    >>> len(company_fleet.cars)
    3


Chapter 3: Immutability
-----------------------

    >>> class ImmutableCar(ImmutableEntity):
    ...     wheels = IntField(default=4, validation=lambda x: 3 <= x <= 4)
    ...     color = EnumField(Color)
    >>> icar = ImmutableCar.from_objects({'wheels': 3, 'color': 'blue'})
    >>> icar
    ImmutableCar(wheels=3, color=0)

    >>> icar.wheels = 4
    Traceback (most recent call last):
    AttributeError: Assignment not allowed. ImmutableCar is immutable.

    >>> class FixedWheelCar(Entity):
    ...     wheels = IntField(default=4, immutable=True)
    ...     color = EnumField(Color)
    >>> fwcar = FixedWheelCar.from_objects(icar)
    >>> fwcar.json()
    '{"wheels": 3, "color": 0}'

    >>> # repainting the car is easy
    >>> fwcar.color = Color.red
    >>> fwcar.color.name
    'red'

    >>> # can't really change the number of wheels though
    >>> fwcar.wheels = 18
    Traceback (most recent call last):
    AttributeError: The wheels field is immutable.


Chapter X: The del and null Weeds
---------------------------------

    >>> old_date = lambda: isoparse('1982-02-17')
    >>> class CarBattery(Entity):
    ...     # NOTE: default value can be a callable!
    ...     first_charge = DateField(required=False)  # default=None, nullable=False
    ...     latest_charge = DateField(default=old_date, nullable=True)  # required=True
    ...     expiration = DateField(default=old_date, required=False, nullable=False)

    >>> # starting point
    >>> battery = CarBattery()
    >>> battery
    CarBattery()
    >>> battery.json()
    '{"latest_charge": "1982-02-17T00:00:00", "expiration": "1982-02-17T00:00:00"}'

    >>> # first_charge is not assigned a default value. Once one is assigned, it can be deleted,
    >>> #   but it can't be made null.
    >>> battery.first_charge = isoparse('2016-03-23')
    >>> battery
    CarBattery(first_charge=datetime.datetime(2016, 3, 23, 0, 0))
    >>> battery.first_charge = None
    Traceback (most recent call last):
    ValidationError: Value for first_charge not given or invalid.
    >>> del battery.first_charge
    >>> battery
    CarBattery()

    >>> # latest_charge can be null, but it can't be deleted. The default value is a callable.
    >>> del battery.latest_charge
    Traceback (most recent call last):
    AttributeError: The latest_charge field is required and cannot be deleted.
    >>> battery.latest_charge = None
    >>> battery.json()
    '{"latest_charge": null, "expiration": "1982-02-17T00:00:00"}'

    >>> # expiration is assigned by default, can't be made null, but can be deleted.
    >>> battery.expiration
    datetime.datetime(1982, 2, 17, 0, 0)
    >>> battery.expiration = None
    Traceback (most recent call last):
    ValidationError: Value for expiration not given or invalid.
    >>> del battery.expiration
    >>> battery.json()
    '{"latest_charge": null}'


    )MappingSequence)datetime)Enum)reduce)JSONEncoderdumpsloads)	getLogger)Path)isoparse   )NULL)
isiterableodict)AttrDict)RaiseValidationError)find_or_raise)DumpEncoder)	maybecall)
deepfreeze
frozendict)getFreezeConversionMap)registerc                     | S N xs    3lib/python3.12/site-packages/conda/auxlib/entity.py<lambda>r"     s    1        )r   )make_immutable)EntityImmutableEntityFieldBooleanField	BoolFieldIntegerFieldIntFieldNumberFieldStringField	DateField	EnumField	ListFieldMapFieldComposableField__key_overrides__a  

Current deficiencies to schematics:
  - no get_mock_object method
  - no context-dependent serialization or MultilingualStringType
  - name = StringType(serialized_name='person_name', alternate_names=['human_name'])
  - name = StringType(serialize_when_none=False)
  - more flexible validation error messages
  - field validation can depend on other fields
  - 'roles' containing denylists for .dump() and .json()
    __roles__ = {
        EntityRole.registered_name: Denylist('field1', 'field2'),
        EntityRole.another_registered_name: Allowlist('field3', 'field4'),
    }


TODO:
  - alternate field names
  - add dump_if_null field option
  - add help/description parameter to Field
  - consider leveraging slots
  - collect all validation errors before raising
  - Allow returning string error message for validation instead of False
  - profile and optimize
  - use boltons instead of dateutil
  - correctly implement copy and deepcopy on fields and Entity, DictSafeMixin
    http://stackoverflow.com/questions/1500718/what-is-the-right-way-to-override-the-copy-deepcopy-operations-on-an-object-in-p


Optional Field Properties:
  - validation = None
  - default = None
  - required = True
  - in_dump = True
  - nullable = False

Behaviors:
  - Nullable is a "hard" setting, in that the value is either always or never allowed to be None.
  - What happens then if required=False and nullable=False?
      - The object can be init'd without a value (though not with a None value).
        getattr throws AttributeError
      - Any assignment must be not None.


  - Setting a value to None doesn't "unset" a value.  (That's what del is for.)  And you can't
    del a value if required=True, nullable=False, default=None.

  - If a field is not required, del does *not* "unmask" the default value.  Instead, del
    removes the value from the object entirely.  To get back the default value, need to recreate
    the object.  Entity.from_objects(old_object)


  - Disabling in_dump is a "hard" setting, in that with it disabled the field will never get
    dumped.  With it enabled, the field may or may not be dumped depending on its value and other
    settings.

  - Required is a "hard" setting, in that if True, a valid value or default must be provided. None
    is only a valid value or default if nullable is True.

  - In general, nullable means that None is a valid value.
    - getattr returns None instead of raising Attribute error
    - If in_dump, field is given with null value.
    - If default is not None, assigning None clears a previous assignment. Future getattrs return
      the default value.
    - What does nullable mean with default=None and required=True? Does instantiation raise
      an error if assignment not made on init? Can IntField(nullable=True) be init'd?

  - If required=False and nullable=False, field will only be in dump if field!=None.
    Also, getattr raises AttributeError.
  - If required=False and nullable=True, field will be in dump if field==None.

  - If in_dump is True, does default value get dumped:
    - if no assignment, default exists
    - if nullable, and assigned None
  - How does optional validation work with nullable and assigning None?
  - When does gettattr throw AttributeError, and when does it return None?



c                       e Zd ZdZdZedddddddfdZed        Zd	 Z	d
 Z
d Zd Zd Zd Zd Zd Zed        Zed        Zed        Zed        Zed        Zed        Zed        Zed        Zy)r(   a  
    Fields are doing something very similar to boxing and unboxing
    of c#/java primitives.  __set__ should take a "primitive" or "raw" value and create a "boxed"
    or "programmatically usable" value of it.  While __get__ should return the boxed value,
    dump in turn should unbox the value into a primitive or raw value.

    Arguments:
        types_ (primitive literal or type or sequence of types):
        default (any, callable, optional):  If default is callable, it's guaranteed to return a
            valid value at the time of Entity creation.
        required (boolean, optional):
        validation (callable, optional):
        dump (boolean, optional):
    r   TNFr   c	           
         || _         || _        || _        || _        || _        || _        || _        |t        u rt        | _        nQt        |      r|n| j                  d d |      | _        | j                  d | j                  d d t        |                   t        j                  | _        t        xj                  dz  c_        y Nr   )	_required_validation_in_dump_default_in_dump	_nullable
_immutable_aliasesr   _defaultcallableboxvalidater   r(   _order_helper)	selfdefaultrequired
validationin_dumpdefault_in_dumpnullable	immutablealiasess	            r!   __init__zField.__init__  s    !% /!#d? DM'/'8GdhhtTSZ>[DMMM$tYw5G HI"00q r#   c                 b    	 | j                   S # t        $ r t        j                  d        w xY w)NzYThe name attribute has not been set for this field. Call set_name at class creation time.)_nameAttributeErrorlogerrorrD   s    r!   namez
Field.name  s4    	:: 	II > ?	s     .c                     || _         | S r   )rO   )rD   rT   s     r!   set_namezField.set_name  s    
r#   c                    	 |t        |t              | j                     }n|j                  | j                     }|%| j                  st	        d| j                   d      | j                  |||      S # t        $ r! t
        j                  d       t	        d      t        $ rC | j                  t        u rt	        d| j                   d      t        | j                        }Y w xY w)Nz3The name attribute has not been set for this field.zA value for z has not been setThe z field has been deleted.)getattrKEY_OVERRIDES_MAPrT   __dict__rP   rQ   rR   KeyErrorrE   r   r   rJ   unboxrD   instanceinstance_typevals       r!   __get__zField.__get__  s    	.m->?		J''		2 ;t}} 4		{2J!KLLzz(M377  	XIIKL !VWW 	.||t#$|DII;>O%PQQ-		.s   9A5 5A1C)(C)c                     | j                   r%|j                  rt        d| j                   d      | j	                  || j                  ||j                  |            |j                  | j                  <   y )NrX    field is immutable.)rK   _initdrP   rT   rB   rA   	__class__r[   rD   r_   ra   s      r!   __set__zField.__set__  s`    >>hoo 4		{2F!GHH (,}}HHXx1137(
$))$r#   c                 H   | j                   r%|j                  rt        d| j                   d      | j                  rt        d| j                   d      | j
                  sd |j                  | j                  <   y |j                  j                  | j                  d        y )NrX   rd   z) field is required and cannot be deleted.)rK   re   rP   rT   rF   rJ   r[   pop)rD   r_   s     r!   
__delete__zField.__delete__  s    >>hoo 4		{2F!GHH]] 4		{2[!\]]
 ,0Hdii(!!$))T2r#   c                     |S r   r   r^   s       r!   rA   z	Field.box      
r#   c                     |S r   r   r^   s       r!   r]   zField.unbox  rm   r#   c                     |S r   r   r^   s       r!   dumpz
Field.dump  rm   r#   c                     t        || j                        r| j                  | j                  |      r|S |t        u r| j                  s|S || j
                  r|S t        t        | dd      |      )zj

        Returns:
            True: if val is valid

        Raises:
            ValidationError
        rT   zundefined name)
isinstance_typer9   r   rF   rJ   r   rY   rg   s      r!   rB   zField.validate  si     c4::&D,<,<,DHXHXY\H]JD[J[T]]J!'$8H"I3OOr#   c                     | j                   S r   )r8   rS   s    r!   rF   zField.required      ~~r#   c                     | j                   S r   )rs   rS   s    r!   typez
Field.type  s    zzr#   c                     | j                   S r   )r?   rS   s    r!   rE   zField.default      }}r#   c                     | j                   S r   )r:   rS   s    r!   rH   zField.in_dump  ry   r#   c                     | j                   S r   )r;   rS   s    r!   rI   zField.default_in_dump  s    $$$r#   c                     | j                   S r   )is_nullablerS   s    r!   rJ   zField.nullable  s    r#   c                     | j                   S r   )r<   rS   s    r!   r}   zField.is_nullable   ru   r#   c                     | j                   S r   )r=   rS   s    r!   rK   zField.immutable  s    r#   )__name__
__module____qualname____doc__rC   r   rM   propertyrT   rV   rb   rh   rk   rA   r]   rp   rB   rF   rw   rE   rH   rI   rJ   r}   rK   r   r#   r!   r(   r(   n  s   " M#dtteu^`!$  8&
3P&         % %        r#   r(   c                       e Zd ZeZd Zy)r)   c                      |d S t        |      S r   )boolr^   s       r!   rA   zBooleanField.box  s    {t1S	1r#   N)r   r   r   r   rs   rA   r   r#   r!   r)   r)   	  s    E2r#   r)   c                       e Zd ZeZy)r+   N)r   r   r   intrs   r   r#   r!   r+   r+     s    Er#   r+   c                       e Zd ZeeefZy)r-   N)r   r   r   r   floatcomplexrs   r   r#   r!   r-   r-     s    %!Er#   r-   c                       e Zd ZeZd Zy)r.   c                 P    t        |t        j                        rt        |      S |S r   )rr   r-   rs   strr^   s       r!   rA   zStringField.box!  s     %c;+<+<=s3xF3Fr#   N)r   r   r   r   rs   rA   r   r#   r!   r.   r.     s    EGr#   r.   c                       e Zd ZeZd Zd Zy)r/   c                 z    	 t        |t              rt        |      S |S # t        $ r}t	        ||      d }~ww xY wNmsg)rr   r   r   
ValueErrorr   )rD   r_   r`   ra   es        r!   rA   zDateField.box(  s<    	.$.sC$88C=AcA 	.!#1--	.s     	:5:c                 *    |d S |j                         S r   )	isoformatr^   s       r!   rp   zDateField.dump.  s    {t77r#   N)r   r   r   r   rs   rA   rp   r   r#   r!   r/   r/   %  s    E.8r#   r/   c                   <     e Zd Zedddddddf fd	Zd Zd Z xZS )r0   TNFr   c
           
      z    t        |t              st        d d      || _        t        
|   ||||||||	       y )Nz&enum_class must be an instance of Enumr   )
issubclassr   r   rs   superrM   )rD   
enum_classrE   rF   rG   rH   rI   rJ   rK   rL   rf   s             r!   rM   zEnumField.__init__4  sA    *d+!$,TUU
Xz7OXyZa	
r#   c                     |y 	 | j                  |      S # t        $ r4}	 | j                   |   cY d }~S # t        $ r t        ||      w xY wd }~ww xY wr   )rs   r   r\   r   )rD   r_   r`   ra   e1s        r!   rA   zEnumField.box=  s[    ;	3::c?" 	33zz#& 3%cr223		3s#    	A4AAAAc                 2    |d t         fv rd S |j                  S r   )r   valuer^   s       r!   rp   zEnumField.dumpK  s    tTl*t9		9r#   r   r   r   r   rM   rA   rp   __classcell__rf   s   @r!   r0   r0   2  s%    +/$4teu^`
3:r#   r0   c                   P     e Zd ZeZedddddddf fd	Zd Zd Zd Z	 fd	Z
 xZS )
r1   TNFr   c
           
      @    || _         t        
| 	  ||||||||	       y r   )_element_typer   rM   )rD   element_typerE   rF   rG   rH   rI   rJ   rK   rL   rf   s             r!   rM   zListField.__init__R  s*    )Xz7OXyZa	
r#   c                    |y t        |t              rt        d| j                         t	        |      rn| j
                  t        t              r*t        t              r| j                  fd|D              S | j                  rt        |      S | j                  |      S t        |d| j                         )Nz*Attempted to assign a string to ListField c              3   J   K   | ]  }t        |      r|n di |  y wNr   )rr   ).0vets     r!   	<genexpr>z ListField.box.<locals>.<genexpr>c  s%     !S!z!R'8!bg1g"E!S    #&Cannot assign a non-iterable value to r   )rr   r   r   rT   r   r   rw   r   r&   rs   rK   r   )rD   r_   r`   ra   r   s       @r!   rA   zListField.boxY  s    ;S!!<TYYKH  _##B"d#
2v(>zz!Ss!SSS*...z#MdjjoM!A$))M r#   c                 B    || j                   s| j                         S |S r   )rJ   rs   r^   s       r!   r]   zListField.unboxk  s    "{4==tzz|IcIr#   c                     t        | j                  t              r2t        | j                  t              r| j                  d |D              S |S )Nc              3   <   K   | ]  }|j                           y wr   rp   )r   r   s     r!   r   z!ListField.dump.<locals>.<genexpr>p  s     41affh4s   )rr   r   rw   r   r&   rs   r^   s       r!   rp   zListField.dumpn  s<    d(($/Jt?Q?QSY4Z::4444Jr#   c                 ~     t            ||      }|r' j                   j                   fd|D               |S )Nc              3   v   K   | ]0  }t        |      s"t        t        j                  |             2 y wr   )rr   r   r   rT   )r   elr   rD   s     r!   r   z%ListField.validate.<locals>.<genexpr>x  s4      2R(R0 _TYYB?@ 2s   69)r   rB   r   rs   )rD   r_   ra   r   rf   s   `  @r!   rB   zListField.validatet  s?    gx-##BJJ 23 2 2
r#   )r   r   r   tuplers   r   rM   rA   r]   rp   rB   r   r   s   @r!   r1   r1   O  s:    E-1DTteu^`
$J r#   r1   c                       e Zd ZeZy)MutableListFieldN)r   r   r   listrs   r   r#   r!   r   r   }  s    Er#   r   c                   :     e Zd ZeZedddddddf fd	Zd Z xZS )r2   TNFr   c	           
      2    t         	|   ||||||||       y r   )r   rM   )
rD   rE   rF   rG   rH   rI   rJ   rK   rL   rf   s
            r!   rM   zMapField.__init__  s$     	Xz7OXyZa	
r#   c                     || j                         S t        |      r7t        |      }t        |t              st        |d| j                         |S t        |d| j                         )Nr   r   )rs   r   r   rr   r   r   rT   r^   s       r!   rA   zMapField.box  sp    ;::<_S/Cc7+%Edii[Q  J!A$))M r#   )	r   r   r   r   rs   r   rM   rA   r   r   s   @r!   r2   r2     s,    E 
r#   r2   c                   <     e Zd Zedddddddf fd	Zd Zd Z xZS )r3   TNFr   c
           
      @    || _         t        
| 	  ||||||||	       y r   )rs   r   rM   )rD   field_classrE   rF   rG   rH   rI   rJ   rK   rL   rf   s             r!   rM   zComposableField.__init__  s)     
Xz7OXyZa	
r#   c                    |y t        || j                        r|S 	 t        |d      r|j                  d      |d<   t        || j                        r*t        || j                        r|S  | j                  di |S t        |t
              r | j                  di |S t        |t              rt        |t              s | j                  | S | j                  |      S # t        $ r Y w xY w)Nrj   rD   slfr   )rr   rs   hasattrrj   r\   r   r   r   r^   s       r!   rA   zComposableField.box  s    ;c4::&J3&!$CJ #tzz*(djj9sPztzz?PC?PPC)!tzz(C((C*:c33G!tzz3''zz#&  s    C 	C+*C+c                 *    |d S |j                         S r   r   r^   s       r!   rp   zComposableField.dump  s    {t2
2r#   r   r   s   @r!   r3   r3     s%    ,04Dteu^`
',3r#   r3   c                   R     e Zd Zed        Z fdZ fdZ fdZed        Z	 xZ
S )
EntityTypec                     	 | D cg c]  }t        |t              s|t        us|  c}S c c}w # t        $ r Y yw xY wr   )r   r&   	NameError)basesbases     r!   __get_entity_subclassesz"EntityType.__get_entity_subclasses  s>    	%*^Tjv.F4W]K]D^^^ 		s    1 ,,,1 1 	==c                 D   d |j                         D        }t        j                  |      }|rL|D cg c]  t        fd|D              r }}|D ci c]  }||j	                  |       c}|t
        <   n	i |t
        <   t        |   | |||      S c c}w c c}w )Nc              3   h   K   | ]*  \  }}t        |t              s|j                  d       s| , yw)__N)rr   r(   
startswith)r   keyr   s      r!   r   z%EntityType.__new__.<locals>.<genexpr>  s1      
UeU+CNN44H 
   02c              3   p   K   | ]-  }t        |j                  j                        t               / y wr   )rr   r[   getr(   )r   r   r   s     r!   r   z%EntityType.__new__.<locals>.<genexpr>  s1      'F+/ (2$--2C2CC2H%'P 'Fs   36)itemsr   "_EntityType__get_entity_subclassesanyrj   rZ   r   __new__)	mcsrT   r   dctnon_field_keysentity_subclassesr   keys_to_overriderf   s	         ` r!   r   zEntityType.__new__  s    
!iik

 '>>uE/=  G#& 'F3D'F $F !$  G  G DT%TCc3773<&7%TC!"%'C!"wsD%55 G &Us   BBc                 \   t         |   |||       t               }d }t        t        j                  |             D ]?  }d |j                  j                         D        }|j                  t        ||             A t        |      | _        t        | d      r| j                          y y )Nc                      | d   j                   S r7   )rC   r   s    r!   r"   z%EntityType.__init__.<locals>.<lambda>  s    AaD$6$6 r#   c              3   h   K   | ]*  \  }}t        |t              r||j                  |      f , y wr   )rr   r(   rV   r   rT   fields      r!   r   z&EntityType.__init__.<locals>.<genexpr>  s4      D%eU+ u~~d+,r   r   __register__)r   rM   r   reversedrw   mror[   r   updatesortedr   
__fields__r   r   )	clsrT   r   attrfields_field_sort_keyclz
clz_fieldsrf   s	           r!   rM   zEntityType.__init__  s    ud+6DHHSM* 	CC#&<<#5#5#7J
 MM&AB	C $F+3' (r#   c                 \    t        |   |i |}t        |d| j                   dd       |S )N___initdT)r   __call__setattrr   )r   argskwargsr_   rf   s       r!   r   zEntityType.__call__  s5    7#T4V4Acll^73T:r#   c                 6    | j                   j                         S r   )r   keysr   s    r!   r   zEntityType.fields  s    ~~""$$r#   )r   r   r   staticmethodr   r   rM   r   r   r   r   r   s   @r!   r   r     s8     6&"
 % %r#   r   c                       e Zd Z e       ZdZd Zed        Zed        Z	ed        Z
d Zd Zed        Zdd
ZddZd Zed        Zd Zd Zed        Zy	)r&   Fc           
      d   | j                   j                         D ]  \  }}	 t        | ||           | j                  s| j!                          y y # t        $ r t	        fd|j
                  D        d       }|t        | ||          n|t        | t              v rt        | |t        | t              |          nP|j                  rD|j                  t        u r2t        |dj                  | j                  j                  |            Y t        $ r |   |j                  r Y w xY w)Nc              3   ,   K   | ]  }|v s|  y wr   r   )r   lsr   s     r!   r   z"Entity.__init__.<locals>.<genexpr>  s     JRR6\bJs   	z,{} requires a {} field. Instantiated with {}r   )r   r   r   r\   nextr>   rY   rZ   rF   rE   r   r   formatrf   r   _lazy_validaterB   )rD   r   r   r   aliass    `   r!   rM   zEntity.__init__  s   ////1 	JCc6#;/	& ""MMO #!  J5>>JDQ$D#ve}5GD*;<<D#wt5F'G'LM^^(=)#VDNN$;$;S&I 
 # #;*enn /=s   AB<D/D/.D/c                     i }t        d |f|z   D              }| j                  j                         D ]   \  }}	 t        |||j                        ||<   "  | di |S # t
        $ r Y 6w xY w)Nc              3   V   K   | ]!  }t        |t              rt        |      n| # y wr   )rr   dictr   )r   os     r!   r   z&Entity.from_objects.<locals>.<genexpr>  s,      E ! ,6a+>HQKAE Es   ')r   )r   r   r   r   r>   rP   )r   objectsoverride_fields	init_varssearch_mapsr   r   s          r!   from_objectszEntity.from_objects  s    	 E'6&87&BE E....0 	JC!.sK!P	#	 Y " s   A	A*)A*c                 $     | di t        |      S r   )
json_loads)r   json_strs     r!   	from_jsonzEntity.from_json'  s    *Z)**r#   c                      | di |S r   r   )r   	data_dicts     r!   loadzEntity.load+  s    Yr#   c                      	 t         fdd  j                  j                         D               y # t        $ r}t	        |      dk(  rY d }~y Y d }~y d }~wt
        $ r}t        d |      d }~ww xY w)Nc                     t        |      S r   rY   )r   rT   rD   s     r!   r"   z!Entity.validate.<locals>.<lambda>3  s    d 3 r#   c              3   @   K   | ]  \  }}|j                   s|  y wr   )rF   r   s      r!   r   z"Entity.validate.<locals>.<genexpr>4  s     S+$ENNS   z0reduce() of empty sequence with no initial valuer   )r   r   r   	TypeErrorr   rP   r   )rD   r   s   ` r!   rB   zEntity.validate/  sf    		/3S)>)>)@S  	1vKK L 	/!$A..	/s    .2 	A1AA1A,,A1c                       fd fd fd}dj                  fdt         j                  |      D              } j                  j                   d| dS )	Nc                 H    d| v ry	 t        |        y# t        $ r Y yw xY w)Nr   FT)rY   rP   )r   rD   s    r!   _validzEntity.__repr__.<locals>._valid=  s3     s{c"! s    	!!c                 |    t        |       }t        |t              rt        |j                        S t        |      S r   )rY   rr   r   reprr   )r   ra   rD   s     r!   _valzEntity.__repr__.<locals>._valI  s/    $$C&0d&;4		?JcJr#   c                 Z    j                   j                  |       }||j                  S dS )N)r   r   rC   )r   r   rD   s     r!   _sort_helperz%Entity.__repr__.<locals>._sort_helperM  s-    OO'',E*/*;5&&CCr#   z, c              3   J   K   | ]  } |      s| d  |         yw)=Nr   )r   r   r  r  s     r!   r   z"Entity.__repr__.<locals>.<genexpr>Q  s.      
%(W]^aWbse1T#YK 
s   ##r   ())joinr   r[   rf   r   )rD   r"  	kwarg_strr  r  s   `  @@r!   __repr__zEntity.__repr__<  s\    
		K	D II 
,24==l,S
 
	 ..))*!I;a88r#   c                      y r   r   r   s    r!   r   zEntity.__register__V  s    r#   Nc                 *    t        | f||t        d|S )N)indent
separatorsr   )
json_dumpsr   rD   r,  r-  r   s       r!   jsonzEntity.jsonZ  s    $`v*+`Y_``r#   c                 ,     | j                   d||d|S )N)r,  r-  r   )r0  r/  s       r!   pretty_jsonzEntity.pretty_json]  s    tyyH:HHHr#   c                 Z     t         fd fd j                         D        D              S )Nc              3      K   | ]R  \  }}|t         urE||j                  u r|j                  r+|j                  |j	                  j
                  |      f T y wr   )r   rE   rI   rT   rp   rf   )r   r   r   rD   s      r!   r   zEntity.dump.<locals>.<genexpr>a  sU      S%T)5EMM3I;@;P;P	 jj%**T4>>5"IJ Ss   AAc              3   X   K   | ]!  }|t        |j                  t              f # y wr   )rY   rT   r   r   r   rD   s     r!   r   zEntity.dump.<locals>.<genexpr>b  s-      *M.3 ,1'$

D2Q*R *Ms   '*)r   _Entity__dump_fieldsrS   s   `r!   rp   zEntity.dump`  s6     S*M7;7I7I7K*MS S 	Sr#   c                     d| j                   vr/t        d | j                  j                         D              | _        | j                  S )N__dump_fields_cachec              3   :   K   | ]  }|j                   s|  y wr   )rH   )r   r   s     r!   r   z'Entity.__dump_fields.<locals>.<genexpr>j  s      ,emm,s   )r[   r   r   values_Entity__dump_fields_cacher   s    r!   __dump_fieldszEntity.__dump_fieldsg  sC     4&+ ,#&>>#8#8#:, 'C# &&&r#   c                       j                   j                   k7  rydt         fd j                  D              S )NFl   "jy c              3   T   K   | ]  }t        |      t        |      k(   ! y wr   r  )r   r   otherrando_defaultrD   s     r!   r   z Entity.__eq__.<locals>.<genexpr>s  s1      1 46'%P]:^^ 1s   %()rf   allr   )rD   r@  rA  s   ``@r!   __eq__zEntity.__eq__o  s9    >>U__,# 1 $1 1 	1r#   c                 @     t         fd j                  D              S )Nc              3   J   K   | ]  }t        t        |d               y wr   )hashrY   r6  s     r!   r   z"Entity.__hash__.<locals>.<genexpr>w  s     Q4eT23Qr   )sumr   rS   s   `r!   __hash__zEntity.__hash__v  s    QQQQr#   c                 L    t        | d| j                  j                   dd       S )Nr   r   )rY   rf   r   rS   s    r!   re   zEntity._initdy  s%    tq!8!8 9A4HHr#   )NN)r$   ),z: )r   r   r   r   r   r  rM   classmethodr  r  r  rB   r)  r   r0  r2  rp   r7  rC  rH  r   re   r   r#   r!   r&   r&     s    JN. 
  
  + +    /94  aIS ' '1R I Ir#   r&   )	metaclassc                   (     e Zd Z fdZ fdZ xZS )r'   c                     | j                   r#t        d| j                  j                   d      t        |   ||       y )NzAssignment not allowed.  is immutable.)re   rP   rf   r   r   __setattr__)rD   	attributer   rf   s      r!   rP  zImmutableEntity.__setattr__  s?    ;; *4>>+B+B*C>R  	Iu-r#   c                     | j                   r#t        d| j                  j                   d      t        |   |       y )NzDeletion not allowed. rO  )re   rP   rf   r   r   __delattr__)rD   itemrf   s     r!   rS  zImmutableEntity.__delattr__  s8    ;; #9$..:Q:Q9RR`!abbD!r#   )r   r   r   rP  rS  r   r   s   @r!   r'   r'   ~  s    ." "r#   r'   c                   L    e Zd Zd Zd Zd ZddZd Zd Zd Z	d	 Z
d
 ZddZy)DictSafeMixinc                     t        | |      S r   r  )rD   rT  s     r!   __getitem__zDictSafeMixin.__getitem__  s    tT""r#   c                     t        | ||       y r   r   )rD   r   r   s      r!   __setitem__zDictSafeMixin.__setitem__  s    c5!r#   c                     t        | |       y r   )delattrrD   r   s     r!   __delitem__zDictSafeMixin.__delitem__  s    cr#   Nc                     t        | ||      S r   r  )rD   rT  rE   s      r!   r   zDictSafeMixin.get  s    tT7++r#   c                     t        | |d       }|y| j                  |   }t        |t        t        f      rt        |      dkD  S y)NFr   T)rY   r   rr   r2   r1   len)rD   rT  r   r   s       r!   __contains__zDictSafeMixin.__contains__  sF    dD)=%eh	23u:>!r#   c              #   @   K   | j                   D ]  }|| v s|  y wr   )r   r^  s     r!   __iter__zDictSafeMixin.__iter__  s%     ?? 	Cd{		r  c              #   X   K   | j                   D ]  }|| v s|t        | |      f  y wr   )r   rY   r^  s     r!   r   zDictSafeMixin.items  s2     ?? 	.Cd{74---	.s   **c                 B     | j                   di | j                         S r   )rf   rp   rS   s    r!   copyzDictSafeMixin.copy  s    t~~,		,,r#   c                 (    || vrt        | ||       y y r   rZ  )rD   r   default_values      r!   
setdefaultzDictSafeMixin.setdefault  s    d?D#}- r#   c                     |	 |j                         D ]
  \  }}|| |<    	 |D ]
  }||   | |<    y # t        $ r |D ]
  \  }}|| |<    Y *w xY wr   )r   rP   )rD   EFkr   s        r!   r   zDictSafeMixin.update  s{    
 = GGI  DAqDG 
  	AdDG	 "    DAqDG  s   2 AAr   )r   r   r   rX  r[  r_  r   rc  re  r   rh  rk  r   r   r#   r!   rV  rV    s4    #",
.
-.r#   rV  c                       e Zd Zd Zy)EntityEncoderc                 |   t        |d      r|j                         S t        |d      r|j                         S t        |d      r|j                         S t        |d      r|j	                         S t        |t              r|j                  S t        |t              rt        |      S t        j                  | |      S )Nrp   __json__to_jsonas_json)r   rp   rs  rt  ru  rr   r   r   r   r   r   rE   )rD   objs     r!   rE   zEntityEncoder.default  s    388:S*%<<>!S)$;;= S)$;;= T"99T"s8O""4--r#   N)r   r   r   rE   r   r#   r!   rq  rq    s    .r#   rq  N)Gr   collections.abcr   r   r   enumr   	functoolsr   r0  r   r	   r.  r
   r  loggingr   pathlibr   boltons.timeutilsr    r   compatr   r   
collectionr   
exceptionsr   r   ishr   logzr   type_coercionr   r   r   r   _getFreezeConversionMapr   	_registerImportError_vendor.frozendictauxlib.collectionr%   r   rQ   __all__rZ   NOTESr(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r   r2   r3   rw   r   r&   r'   rV  rq  r   r#   r!   <module>r     s  kZ .    F F   &  %   .   $A1L0*,, 	$%
  ( O	dX Xv25 2 	5  "% "G% G
8 
8: ::+ +\y  u  F 3e  3F5% 5%p|Iz |I~"f "5 5p.K .s  A/@As   ()E E)(E)