U
    b,                     @   sP  d Z ddlmZmZmZ zddlmZmZ W n$ ek
rP   ddl	mZmZ Y nX 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 d	dlmZmZ d	dl m!Z!m"Z"m#Z# d	dl$m%Z%m&Z& d	dl'm(Z( d	dl)m*Z* d	dl+m,Z, ee-Z.ddddddddddddd d!gZ/d"Z0d#Z1G d$d de2Z3G d%d de3Z4e4Z5G d&d de3Z6e6Z7G d'd de3Z8G d(d de3Z9G d)d de3Z:G d*d de3Z;G d+d de3Z<G d,d- d-e<Z=G d.d  d e3Z>G d/d! d!e3Z?G d0d1 d1e@ZAG d2d deAd3ZBG d4d deBZCG d5d6 d6e2ZDG d7d8 d8eZEd9S ):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}'


    )absolute_importdivisionprint_function)MappingSequence)datetime)reduce)JSONEncoderdumpsloads)	getLogger)Enum   )NULL   )isoparse)
frozendict)AttrDictmake_immutable)integer_types
isiterableodict)RaiseValidationError)find_or_raise)DumpEncoder)	maybecallEntityImmutableEntityFieldBooleanField	BoolFieldIntegerFieldIntFieldNumberFieldStringField	DateField	EnumField	ListFieldMapFieldComposableFieldZ__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                   @   s   e Zd ZdZdZedddddddfddZed	d
 Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zedd Zedd Zedd  Zed!d" Zed#d$ Zed%d& Zed'd( Zed)d* ZdS )+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   TNF c	           	   	   C   s   || _ || _|| _|| _|| _|| _|| _|tkr:t| _n6t	|rF|n| 
d d || _| d | 
d d t| tj| _t jd7  _d S 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aliasesr+   r+   2lib/python3.8/site-packages/conda/auxlib/entity.py__init__w  s    zField.__init__c                 C   s.   z| j W S  tk
r(   td  Y nX d S )NzYThe name attribute has not been set for this field. Call set_name at class creation time.)_nameAttributeErrorlogerrorr:   r+   r+   rC   name  s
    
z
Field.namec                 C   s
   || _ | S N)rE   )r:   rJ   r+   r+   rC   set_name  s    zField.set_namec                 C   s   z*|d krt |t| j }n|j| j }W n^ tk
rP   td tdY n: tk
r   | jt	krztd
| jn
t| j}Y nX |d kr| jstd
| j| |||S )Nz3The name attribute has not been set for this field.z A value for {0} has not been setzThe {0} field has been deleted.)getattrKEY_OVERRIDES_MAPrJ   __dict__rF   rG   rH   KeyErrorr;   r   formatr   r@   unboxr:   instanceinstance_typevalr+   r+   rC   __get__  s    

zField.__get__c                 C   s@   | j r|jrtd| j| || ||j||j| j< d S )NThe {0} field is immutable.)	rA   _initdrF   rQ   rJ   r7   r6   	__class__rO   r:   rT   rV   r+   r+   rC   __set__  s    zField.__set__c                 C   s^   | j r|jrtd| jn<| jr6td| jn$| jsJd |j| j< n|j| jd  d S )NrX   z0The {0} field is required and cannot be deleted.)	rA   rY   rF   rQ   rJ   r<   r@   rO   pop)r:   rT   r+   r+   rC   
__delete__  s    zField.__delete__c                 C   s   |S rK   r+   rS   r+   r+   rC   r6     s    z	Field.boxc                 C   s   |S rK   r+   rS   r+   r+   rC   rR     s    zField.unboxc                 C   s   |S rK   r+   rS   r+   r+   rC   dump  s    z
Field.dumpc                 C   s^   t || jr$| jdks | |r$|S |tkr6| js6|S |dkrH| jrH|S tt| dd|dS )zj

        Returns:
            True: if val is valid

        Raises:
            ValidationError
        NrJ   zundefined name)
isinstance_typer.   r   r<   r@   r   rM   r[   r+   r+   rC   r7     s    
 zField.validatec                 C   s   | j S rK   )r-   rI   r+   r+   rC   r<     s    zField.requiredc                 C   s   | j S rK   )ra   rI   r+   r+   rC   type  s    z
Field.typec                 C   s   | j S rK   )r4   rI   r+   r+   rC   r;     s    zField.defaultc                 C   s   | j S rK   )r/   rI   r+   r+   rC   r>     s    zField.in_dumpc                 C   s   | j S rK   )r0   rI   r+   r+   rC   r?     s    zField.default_in_dumpc                 C   s   | j S rK   )is_nullablerI   r+   r+   rC   r@     s    zField.nullablec                 C   s   | j S rK   )r1   rI   r+   r+   rC   rc     s    zField.is_nullablec                 C   s   | j S rK   )r2   rI   r+   r+   rC   rA     s    zField.immutable)__name__
__module____qualname____doc__r8   r   rD   propertyrJ   rL   rW   r\   r^   r6   rR   r_   r7   r<   rb   r;   r>   r?   r@   rc   rA   r+   r+   r+   rC   r   c  sF       









c                   @   s   e Zd ZeZdd ZdS )r    c                 C   s   |d krd S t |S rK   )boolrS   r+   r+   rC   r6     s    zBooleanField.boxN)rd   re   rf   ri   ra   r6   r+   r+   r+   rC   r      s   c                   @   s   e Zd ZeZdS )r"   N)rd   re   rf   r   ra   r+   r+   r+   rC   r"   	  s   c                   @   s   e Zd Zeeef ZdS )r$   N)rd   re   rf   r   floatcomplexra   r+   r+   r+   rC   r$     s   c                   @   s   e Zd ZeZdd ZdS )r%   c                 C   s   t |tjrt|S |S rK   )r`   r$   ra   strrS   r+   r+   rC   r6     s    zStringField.boxN)rd   re   rf   rl   ra   r6   r+   r+   r+   rC   r%     s   c                   @   s    e Zd ZeZdd Zdd ZdS )r&   c              
   C   sL   zt |trt|n|W S  tk
rF } zt||dW 5 d }~X Y nX d S Nmsg)r`   rl   r   
ValueErrorr   )r:   rT   rU   rV   er+   r+   rC   r6     s    zDateField.boxc                 C   s   |d krd S |  S rK   )Z	isoformatrS   r+   r+   rC   r_   $  s    zDateField.dumpN)rd   re   rf   r   ra   r6   r_   r+   r+   r+   rC   r&     s   c                       s>   e Zd Zedddddddf fdd	Zdd Zd	d
 Z  ZS )r'   TNFr+   c
           
   
      s>   t |tstd dd|| _tt| ||||||||	 d S )Nz&enum_class must be an instance of Enumrn   )
issubclassr   r   ra   superr'   rD   )
r:   
enum_classr;   r<   r=   r>   r?   r@   rA   rB   rZ   r+   rC   rD   *  s    
    zEnumField.__init__c                 C   sv   |d krd S z|  |W S  tk
rp } z:z| j | W  W Y &S  tk
r^   t||dY nX W 5 d }~X Y nX d S rm   )ra   rp   rP   r   )r:   rT   rU   rV   Ze1r+   r+   rC   r6   2  s    zEnumField.boxc                 C   s   |d t fkrd S |jS rK   )r   valuerS   r+   r+   rC   r_   @  s    zEnumField.dumprd   re   rf   r   rD   r6   r_   __classcell__r+   r+   ru   rC   r'   (  s       c                       sV   e Zd ZeZedddddddf fdd	Zdd Zd	d
 Zdd Z	 fddZ
  ZS )r(   TNFr+   c
           
   
      s(   || _ tt| ||||||||	 d S rK   )_element_typers   r(   rD   )
r:   Zelement_typer;   r<   r=   r>   r?   r@   rA   rB   ru   r+   rC   rD   G  s        zListField.__init__c                    s   |d krd S t |tr(td| jnht|r|| j t  trbt t	rb| 
 fdd|D S | jrpt|S | 
|S nt|d| jdd S )Nz-Attempted to assign a string to ListField {0}c                 3   s&   | ]}t | r|n f |V  qd S rK   )r`   .0vetr+   rC   	<genexpr>V  s     z ListField.box.<locals>.<genexpr>)Cannot assign a non-iterable value to {0}rn   )r`   rl   r   rQ   rJ   r   ry   rb   rr   r   ra   rA   r   rS   r+   r}   rC   r6   M  s    
zListField.boxc                 C   s   |d kr| j s|  S |S rK   )r@   ra   rS   r+   r+   rC   rR   ]  s    zListField.unboxc                 C   s4   t | jtr,t| jtr,| dd |D S |S d S )Nc                 s   s   | ]}|  V  qd S rK   r_   rz   r+   r+   rC   r   b  s     z!ListField.dump.<locals>.<genexpr>)r`   ry   rb   rr   r   ra   rS   r+   r+   rC   r_   `  s    zListField.dumpc                    s:   t t||}|r6j  fdd|D  |S )Nc                 3   s*   | ]"}t | sttj| V  qd S rK   )r`   r   r   rJ   )r{   Zelr~   r:   r+   rC   r   j  s    
z%ListField.validate.<locals>.<genexpr>)rs   r(   r7   ry   ra   r[   ru   r   rC   r7   f  s
    zListField.validate)rd   re   rf   tuplera   r   rD   r6   rR   r_   r7   rx   r+   r+   ru   rC   r(   D  s       c                   @   s   e Zd ZeZdS )MutableListFieldN)rd   re   rf   listra   r+   r+   r+   rC   r   o  s   r   c                       s:   e Zd ZeZedddddddf fdd	Zdd Z  ZS )	r)   TNFr+   c	           	   
      s"   t t| |||||||| d S rK   )rs   r)   rD   r9   ru   r+   rC   rD   v  s
      zMapField.__init__c                 C   sZ   |d kr|   S t|rBt|}t|ts>t|d| jd|S t|d| jdd S )Nr   rn   )ra   r   r   r`   r   r   rQ   rJ   rS   r+   r+   rC   r6   {  s    
zMapField.box)	rd   re   rf   r   ra   r   rD   r6   rx   r+   r+   ru   rC   r)   s  s       c                       s>   e Zd Zedddddddf fdd	Zdd Zd	d
 Z  ZS )r*   TNFr+   c
           
   
      s(   || _ tt| ||||||||	 d S rK   )ra   rs   r*   rD   )
r:   Zfield_classr;   r<   r=   r>   r?   r@   rA   rB   ru   r+   rC   rD     s       zComposableField.__init__c                 C   s   |d krd S t || jr|S zt|dr6|d|d< W n tk
rL   Y nX t || jrvt || jrj|S | jf |S t |tr| jf |S t |trt |ts| j| S | |S d S )Nr]   r:   Zslf)r`   ra   hasattrr]   rP   r   r   rl   rS   r+   r+   rC   r6     s     


zComposableField.boxc                 C   s   |d krd S |  S rK   r   rS   r+   r+   rC   r_     s    zComposableField.dumprw   r+   r+   ru   rC   r*     s       c                       sL   e Zd Zedd Z fddZ fddZ fddZed	d
 Z	  Z
S )
EntityTypec                 C   s,   zdd | D W S  t k
r&   Y dS X d S )Nc                 S   s"   g | ]}t |tr|tk	r|qS r+   )rr   r   r{   baser+   r+   rC   
<listcomp>  s     
  z6EntityType.__get_entity_subclasses.<locals>.<listcomp>r+   )	NameError)basesr+   r+   rC   Z__get_entity_subclasses  s    z"EntityType.__get_entity_subclassesc                    sn   dd    D }t|rNfdd|D }t fdd|D  t< n
t  t< tt| | || S )Nc                 s   s*   | ]"\}}t |ts|d s|V  qdS )__N)r`   r   
startswith)r{   keyrv   r+   r+   rC   r     s   
 
z%EntityType.__new__.<locals>.<genexpr>c                    s&   g | ] t  fd dD r qS )c                 3   s    | ]}t |j tV  qd S rK   )r`   rO   getr   r   r   r+   rC   r     s   z0EntityType.__new__.<locals>.<listcomp>.<genexpr>)any)r{   )entity_subclassesr   rC   r     s
    z&EntityType.__new__.<locals>.<listcomp>c                 3   s   | ]}|  |fV  qd S rK   )r]   r{   r   )dctr+   rC   r     s     )itemsr   "_EntityType__get_entity_subclassesdictrN   rs   __new__)ZmcsrJ   r   r   Znon_field_keysZkeys_to_overrideru   )r   r   rC   r     s    

zEntityType.__new__c                    s|   t t| ||| t }dd }tt| D ]*}dd |j D }|	t
||d q0t|| _t| drx|   d S )Nc                 S   s
   | d j S r,   )r8   )xr+   r+   rC   <lambda>      z%EntityType.__init__.<locals>.<lambda>c                 s   s*   | ]"\}}t |tr|||fV  qd S rK   )r`   r   rL   r{   rJ   fieldr+   r+   rC   r     s   
z&EntityType.__init__.<locals>.<genexpr>r   __register__)rs   r   rD   r   reversedrb   mrorO   r   updatesortedr   
__fields__r   r   )clsrJ   r   attrfieldsZ_field_sort_keyZclzZ
clz_fieldsru   r+   rC   rD     s    

zEntityType.__init__c                    s*   t t| j||}t|d| jd |S )N_{0}__initdT)rs   r   __call__setattrrQ   rd   )r   argskwargsrT   ru   r+   rC   r     s    zEntityType.__call__c                 C   s
   | j  S rK   )r   keysr   r+   r+   rC   r     s    zEntityType.fields)rd   re   rf   staticmethodr   r   rD   r   rh   r   rx   r+   r+   ru   rC   r     s   
r   c                   @   s   e Zd Ze ZdZdd Zedd Zedd Z	edd	 Z
d
d Zdd Zedd Zd!ddZd"ddZdd Zedd Zdd Zdd Zedd  ZdS )#r   Fc                    s   | j  D ]\}}zt| | |  W q
 tk
r   t fdd|jD d }|d k	rjt| | |  nP|t| tkrt| |t| t|  n*|jr|j	t
krt|d| jj| dY q
 tk
r    | d k	s|jr Y q
X q
| js|   d S )Nc                 3   s   | ]}| kr|V  qd S rK   r+   )r{   Zlsr   r+   rC   r     s      z"Entity.__init__.<locals>.<genexpr>z/{0} requires a {1} field. Instantiated with {2}rn   )r   r   r   rP   nextr3   rM   rN   r<   r;   r   r   rQ   rZ   rd   _lazy_validater7   )r:   r   r   r   aliasr+   r   rC   rD     s(     
zEntity.__init__c              	   O   sh   t  }tdd |f| D }| j D ]4\}}zt|||j||< W q( tk
rZ   Y q(X q(| f |S )Nc                 s   s$   | ]}t |trt|n|V  qd S rK   )r`   r   r   )r{   or+   r+   rC   r     s   z&Entity.from_objects.<locals>.<genexpr>)r   r   r   r   r   r3   rF   )r   ZobjectsZoverride_fieldsZ	init_varsZsearch_mapsr   r   r+   r+   rC   from_objects  s    zEntity.from_objectsc                 C   s   | f t |S rK   )
json_loads)r   Zjson_strr+   r+   rC   	from_json  s    zEntity.from_jsonc                 C   s
   | f |S rK   r+   )r   Z	data_dictr+   r+   rC   load  s    zEntity.loadc              
      s   z&t  fdddd  j D  W nZ tk
rT } zt|dkrDW 5 d }~X Y n. tk
r } ztd |dW 5 d }~X Y nX d S )Nc                    s
   t  |S rK   rM   )_rJ   rI   r+   rC   r     r   z!Entity.validate.<locals>.<lambda>c                 s   s   | ]\}}|j r|V  qd S rK   )r<   r   r+   r+   rC   r     s      z"Entity.validate.<locals>.<genexpr>z0reduce() of empty sequence with no initial valuern   )r   r   r   	TypeErrorrl   rF   r   )r:   rq   r+   rI   rC   r7     s    
zEntity.validatec                    sX   fddfdd fdd}d  fdd	tj|d
D }djj|S )Nc                    s8   d| krdS zt  |  W dS  tk
r2   Y dS X d S )Nr   FT)rM   rF   r   rI   r+   rC   _valid!  s    
zEntity.__repr__.<locals>._validc                    s&   t  | }t|trt|jS t|S rK   )rM   r`   r   reprrv   )r   rV   rI   r+   rC   _val-  s    
zEntity.__repr__.<locals>._valc                    s    j | }|d k	r|jS dS )N)r   r   r8   )r   r   rI   r+   rC   _sort_helper1  s    z%Entity.__repr__.<locals>._sort_helperz, c                 3   s&   | ]}|rd  | |V  qdS )z{0}={1}N)rQ   r   )r   r   r+   rC   r   5  s   z"Entity.__repr__.<locals>.<genexpr>r   z{0}({1}))joinr   rO   rQ   rZ   rd   )r:   r   Z	kwarg_strr+   )r   r   r:   rC   __repr__   s    zEntity.__repr__c                 C   s   d S rK   r+   r   r+   r+   rC   r   :  s    zEntity.__register__Nc                 K   s   t | f||td|S )N)indent
separatorsr   )
json_dumpsr   r:   r   r   r   r+   r+   rC   json>  s    zEntity.jsonr   ,z: c                 K   s   | j f ||d|S )N)r   r   )r   r   r+   r+   rC   pretty_jsonA  s    zEntity.pretty_jsonc                    s(   t  fdd fdd  D D S )Nc                 3   s@   | ]8\}}|t k	r||jkr"|jr|j|  j|fV  qd S rK   )r   r;   r?   rJ   r_   rZ   )r{   r   rv   rI   r+   rC   r   E  s
    
zEntity.dump.<locals>.<genexpr>c                 3   s    | ]}|t  |jtfV  qd S rK   )rM   rJ   r   r{   r   rI   r+   rC   r   F  s   )r   _Entity__dump_fieldsrI   r+   rI   rC   r_   D  s
    
zEntity.dumpc                 C   s*   d| j kr$tdd | j D | _| jS )NZ__dump_fields_cachec                 s   s   | ]}|j r|V  qd S rK   )r>   r   r+   r+   rC   r   N  s     z'Entity.__dump_fields.<locals>.<genexpr>)rO   r   r   valuesZ_Entity__dump_fields_cacher   r+   r+   rC   Z__dump_fieldsK  s
    

zEntity.__dump_fieldsc                    s0   j  j krdS dt fddjD S )NFl   "jy c                 3   s&   | ]}t |t  |kV  qd S rK   r   r   otherZrando_defaultr:   r+   rC   r   W  s   z Entity.__eq__.<locals>.<genexpr>)rZ   allr   )r:   r   r+   r   rC   __eq__S  s    zEntity.__eq__c                    s   t  fdd jD S )Nc                 3   s   | ]}t t |d V  qd S rK   )hashrM   r   rI   r+   rC   r   [  s     z"Entity.__hash__.<locals>.<genexpr>)sumr   rI   r+   rI   rC   __hash__Z  s    zEntity.__hash__c                 C   s   t | d| jjd S )Nr   )rM   rQ   rZ   rd   rI   r+   r+   rC   rY   ]  s    zEntity._initd)NN)r   r   )rd   re   rf   r   r   r   rD   classmethodr   r   r   r7   r   r   r   r   r_   r   r   r   rh   rY   r+   r+   r+   rC   r     s,   






)	metaclassc                       s(   e Zd Z fddZ fddZ  ZS )r   c                    s.   | j rtd| jjtt| || d S )Nz)Assignment not allowed. {0} is immutable.)rY   rF   rQ   rZ   rd   rs   r   __setattr__)r:   Z	attributerv   ru   r+   rC   r   d  s
    zImmutableEntity.__setattr__c                    s,   | j rtd| jjtt| | d S )Nz'Deletion not allowed. {0} is immutable.)rY   rF   rQ   rZ   rd   rs   r   __delattr__r:   itemru   r+   rC   r   j  s
    zImmutableEntity.__delattr__)rd   re   rf   r   r   rx   r+   r+   ru   rC   r   b  s   c                   @   s`   e Zd Zdd Zdd Zdd Zddd	Zd
d Zdd Zdd Z	dd Z
dd ZdddZdS )DictSafeMixinc                 C   s
   t | |S rK   r   r   r+   r+   rC   __getitem__s  s    zDictSafeMixin.__getitem__c                 C   s   t | || d S rK   r   )r:   r   rv   r+   r+   rC   __setitem__v  s    zDictSafeMixin.__setitem__c                 C   s   t | | d S rK   )delattrr:   r   r+   r+   rC   __delitem__y  s    zDictSafeMixin.__delitem__Nc                 C   s   t | ||S rK   r   )r:   r   r;   r+   r+   rC   r   |  s    zDictSafeMixin.getc                 C   s@   t | |d }|d krdS | j| }t|ttfr<t|dkS dS )NFr   T)rM   r   r`   r)   r(   len)r:   r   rv   r   r+   r+   rC   __contains__  s    
zDictSafeMixin.__contains__c                 c   s   | j D ]}|| kr|V  qd S rK   )r   r   r+   r+   rC   __iter__  s    
zDictSafeMixin.__iter__c                 c   s(   | j D ]}|| kr|t| |fV  qd S rK   )r   rM   r   r+   r+   rC   r     s    
zDictSafeMixin.itemsc                 C   s   | j f |  S rK   )rZ   r_   rI   r+   r+   rC   copy  s    zDictSafeMixin.copyc                 C   s   || krt | || d S rK   r   )r:   r   Zdefault_valuer+   r+   rC   
setdefault  s    zDictSafeMixin.setdefaultc                 K   sl   |d k	rRz|  D ]\}}|| |< qW n* tk
rP   |D ]\}}|| |< q:Y nX |D ]}|| | |< qVd S rK   )r   rF   )r:   EFkr|   r+   r+   rC   r     s    zDictSafeMixin.update)N)N)rd   re   rf   r   r   r   r   r   r   r   r   r   r   r+   r+   r+   rC   r   q  s   
	r   c                   @   s   e Zd Zdd ZdS )EntityEncoderc                 C   sd   t |dr| S t |dr$| S t |dr6| S t |drH| S t|trX|jS t	| |S )Nr_   __json__to_jsonas_json)
r   r_   r   r   r   r`   r   rv   r	   r;   )r:   objr+   r+   rC   r;     s    




zEntityEncoder.defaultN)rd   re   rf   r;   r+   r+   r+   rC   r     s   r   N)Frg   Z
__future__r   r   r   Zcollections.abcr   r   ImportErrorcollectionsr   	functoolsr   r   r	   r
   r   r   r   Zloggingr   enumr    r   Z_vendor.boltons.timeutilsr   Z_vendor.frozendictr   Z
collectionr   r   compatr   r   r   
exceptionsr   r   Zishr   Zlogzr   Ztype_coercionr   rd   rG   __all__rN   ZNOTESobjectr   r    r!   r"   r#   r$   r%   r&   r'   r(   r   r)   r*   rb   r   r   r   r   r   r+   r+   r+   rC   <module>   sr    m          R +#8}8