a
    Cg                     @   s   d dl Z d dlmZ d dlZd dlmZ d dlmZmZm	Z	m
Z
mZmZ d dlmZ dZG dd deZG d	d
 d
eZG dd dZedddd ZdddZdd ZdS )    N)	lru_cache)FieldDoesNotExist)	DateFieldDateTimeFieldManyToManyFieldManyToManyRelModel	TimeField)datetime_utils__c                   @   s   e Zd ZdS )ManyToManyTraversalErrorN__name__
__module____qualname__ r   r   Q/var/www/lab.imftr.de/x/nb_venv/lib/python3.9/site-packages/modelcluster/utils.pyr      s   r   c                   @   s   e Zd ZdS ) NullRelationshipValueEncounteredNr   r   r   r   r   r      s   r   c                   @   s:   e Zd ZddgZdd ZeedddZedd	 Zd
S )TraversedRelationship
from_modelfieldc                 C   s   || _ || _d S N)r   r   )selfr   r   r   r   r   __init__   s    zTraversedRelationship.__init__)returnc                 C   s   | j jS r   )r   namer   r   r   r   
field_name#   s    z TraversedRelationship.field_namec                 C   s   | j jS r   )r   Ztarget_modelr   r   r   r   to_model'   s    zTraversedRelationship.to_modelN)	r   r   r   	__slots__r   propertystrr   r   r   r   r   r   r      s   r   )maxsizec              	   C   sB  | }g }d}| tD ]}|durt|ttfrJtdj|| ||dnt|ddrn|t	|| |j
}nzt|tr|tjv st|tr|tjv st|tr|tjv rtj| }| } q4n&tdj|jjd |j t||dz|j|}W q ty0   |dr*|j|dd	 j} Y q0 qt||_|S )
a  
    Returns a model field matching the supplied ``name``, which can include
    double-underscores (`'__'`) to indicate relationship traversal - in which
    case, the model field will be lookuped up from the related model.

    Multiple traversals for the same field are supported, but at this
    moment in time, only traversal of many-to-one and one-to-one relationships
    is supported.

    Details of any relationships traversed in order to reach the returned
    field are made available as `field.traversals`. The value is a tuple of
    ``TraversedRelationship`` instances.

    Raises ``FieldDoesNotExist`` if the name cannot be mapped to a model field.
    NzThe lookup '{name}' from {model} cannot be replicated by modelcluster, because the '{field_name}' relationship from {subject_model} is a many-to-many, and traversal is only supported for one-to-one or many-to-one relationships.)r   modelr   subject_modelrelated_modelzVFailed attempting to traverse from {from_field} (a {from_field_type}) to '{to_field}'..)Z
from_fieldZfrom_field_typeZto_fieldZ_id)splitREL_DELIMETER
isinstancer   r   r   formatgetattrappendr   r%   r   r
   #DATETIMEFIELD_TRANSFORM_EXPRESSIONSr   DATEFIELD_TRANSFORM_EXPRESSIONSr	   TIMEFIELD_TRANSFORM_EXPRESSIONSZTRANSFORM_FIELD_TYPESr   _metalabelr   type	get_fieldendswithZtarget_fieldtuple
traversals)r#   r   r$   r7   r   r   Ztransform_field_typer   r   r   get_model_field,   s^    	


r8   Fc                 C   s  | }| }| t}t|ddD ]\}}	t|tjr<|	tjv sht|tjrR|	tjv sht|tj	rz|	tj
v rzt||	}|}
qt||	rt||	}
t|
tr|
}|
du r|t|k r|r dS tdj|t| |jj|	d|
}q|r dS tdj|	t|dq|rt|
dr|
jS |
S )	a  
    Attempts to extract a field value from ``obj`` matching the ``key`` - which,
    can contain double-underscores (`'__'`) to indicate traversal of relationships
    to related objects.

    For keys that specify ``ForeignKey`` or ``OneToOneField`` field values, full
    related objects are returned by default. If only the primary key values are
    required ((.g. when ordering, or using ``values()`` or ``values_list()``)),
    call the function with ``pk_only=True``.

    By default, ``FieldDoesNotExist`` is raised if the key cannot be mapped to
    a model field. Call the function with ``suppress_fielddoesnotexist=True``
    to instead receive a ``None`` value when this occurs.

    By default, ``NullRelationshipValueEncountered`` is raised if a ``None``
    value is encountered while attempting to traverse relationships in order to
    access further fields. Call the function with
    ``suppress_nullrelationshipvalueencountered`` to instead receive a ``None``
    value when this occurs.
       )startNzO'{key}' cannot be reached for {obj} because {model_class}.{field_name} is null.)keyobjZmodel_classr   z.'{name}' is not a valid field name for {model})r   r#   pk)r(   r)   	enumerater*   datetimer
   r.   dater/   timer0   Zderive_from_valuehasattrr,   r   lenr   r+   reprr1   r2   r   r3   r=   )r<   r;   pk_onlysuppress_fielddoesnotexist)suppress_nullrelationshipvalueencounteredsourceZ
latest_objsegmentsisegmentvaluer   r   r   extract_field_valuew   sX    







	rM   c                    s`   t |D ]R  dkr t|  qd} d dkr@d} dd   fdd	}| j||d
 qdS )z
    Sort a list of objects on the given fields. The field list works analogously to
    queryset.order_by(*fields): each field is either a property of the object,
    or is prefixed by '-' (e.g. '-name') to indicate reverse ordering.
    ?Fr   -Tr9   Nc                    s   t |  dddd}|d u|fS )NT)rE   rF   rG   )rM   )itemrL   r;   r   r   get_sort_value   s    z&sort_by_fields.<locals>.get_sort_value)r;   reverse)reversedrandomshufflesort)itemsfieldsrS   rR   r   rQ   r   sort_by_fields   s    
rZ   )FFF)r?   	functoolsr   rU   Zdjango.core.exceptionsr   Zdjango.db.modelsr   r   r   r   r   r	   Zmodelclusterr
   r)   
ValueErrorr   	Exceptionr   r   r8   rM   rZ   r   r   r   r   <module>   s    	
J
G