o
    ޭhpB                     @  s  d dl mZ d dlZd dlZd dlm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 dlmZmZ d dlmZ e	rFd d	lmZ ejd
krRd dlmZ n	G dd deeZedZG dd deZejZejZejZej Z ej!Z!G dd de"Z#G dd dee e#dZ$dS )    )annotationsN)Callable)Enum)TYPE_CHECKINGAnyGenericTypeVarUnionoverload)Term)ConfigurationErrorValidationError)	Validator)Model)      )StrEnumc                   @  s   e Zd ZejZdS )r   N)__name__
__module____qualname__str__str__ r   r   Y/var/www/html/stock_analysis/be/venv/lib/python3.10/site-packages/tortoise/fields/base.pyr      s    
r   VALUEc                   @  s    e Zd ZdZdZdZdZdZdS )OnDeleteCASCADERESTRICTzSET NULLzSET DEFAULTz	NO ACTIONN)r   r   r   r   r   SET_NULLSET_DEFAULT	NO_ACTIONr   r   r   r   r      s    r   c                   @  s   e Zd Zdd	d
ZdS )
_FieldMetanamer   basestuple[type, ...]attrsdictreturntypec                 C  sn   t |dkr/|d tu r/t| ||d f|}t |dkr$|d |_|S t|dd   |_|S t| |||S )N   r      )lenFieldr(   __new__r	   
field_type)mcsr"   r#   r%   clsr   r   r   r-   -   s   z_FieldMeta.__new__N)r"   r   r#   r$   r%   r&   r'   r(   )r   r   r   r-   r   r   r   r   r!   +   s    r!   c                      sD  e Zd ZU dZdZded< dZded< dZded< d	Zded
< d	Z	ded< dZ
ded< dZded< dZded< erXdQ fddZedRddZedSd dZdTd#dZdUd%d&Z													dVdWd4d5ZdXd7d8ZdYd9d:ZdZd;d<Zed[d=d>Zed\d@dAZd]dCdDZd^dEdFZd_dHdIZd`dLdMZdadOdPZ  ZS )br,   a(  
    Base Field type.

    :param source_field: Provide a source_field name if the DB column name needs to be
        something specific instead of generated off the field name.
    :param generated: Is this field DB-generated?
    :param primary_key: Is this field a Primary Key? Can only have a single such field on the Model,
        and if none is specified it will autogenerate a default primary key called ``id``.
    :param null: Is this field nullable?
    :param default: A default value for the field if not specified on Model creation.
        This can also be a callable for dynamic defaults in which case we will call it.
        The default value will not be part of the schema.
    :param unique: Is this field unique?
    :param db_index: Should this field be indexed by itself?
    :param description: Field description. Will also appear in ``Tortoise.describe_model()``
        and as DB comments in the generated DDL.
    :param validators: Validators for this field.

    **Class Attributes:**
    These attributes needs to be defined when defining an actual field type.

    .. attribute:: field_type
        :annotation: type[Any]

        The Python type the field is.
        If adding a type as a mixin, _FieldMeta will automatically set this to that.

    .. attribute:: indexable
        :annotation: bool = True

        Is the field indexable? Set to False if this field can't be indexed reliably.

    .. attribute:: has_db_field
        :annotation: bool = True

        Does this field have a direct corresponding DB column? Or is the field virtualized?

    .. attribute:: skip_to_python_if_native
        :annotation: bool = False

        If the DB driver natively supports this Python type, should we skip it?
        This is for optimization purposes only, where we don't need to force type conversion
        between Python and the DB.

    .. attribute:: allows_generated
        :annotation: bool = False

        Is this field able to be DB-generated?

    .. attribute:: function_cast
        :annotation: Optional[pypika_tortoise.Term] = None

        A casting term that we need to apply in case the DB needs emulation help.

    .. attribute:: SQL_TYPE
        :annotation: str

        The SQL type as a string that the DB will use.

    .. attribute:: GENERATED_SQL
        :annotation: str

        The SQL that instructs the DB to auto-generate this field.
        Required if ``allows_generated`` is ``True``.

    **Per-DB overrides:**

    One can specify per-DB overrides of any of the class attributes,
    or the ``to_db_value`` or ``to_python_value`` methods.

    To do so, specify a inner class in the form of :samp:`class _db__{SQL_DIALECT}:` like so:

    .. code-block:: py3

        class _db_sqlite:
            SQL_TYPE = "VARCHAR(40)"
            skip_to_python_if_native = False

            def function_cast(self, term: Term) -> Term:
                return functions.Cast(term, SqlTypes.NUMERIC)

    Tortoise will then use the overridden attributes/functions for that dialect.
    If you need a dynamic attribute, you can use a property.
    Nz	type[Any]r.   Tbool	indexablehas_db_fieldFskip_to_python_if_nativeallows_generatedzCallable[[Term], Term] | Nonefunction_castr   SQL_TYPEGENERATED_SQLargsr   kwargsr'   Field[VALUE]c                   s   t  | S N)superr-   )r0   r9   r:   	__class__r   r   r-      s   zField.__new__instanceNoneownertype[Model]c                 C     d S r<   r   selfr@   rB   r   r   r   __get__      zField.__get__r   r   c                 C  rD   r<   r   rE   r   r   r   rG      rH   Model | NoneField[VALUE] | VALUEc                 C  rD   r<   r   rE   r   r   r   rG          valuec                 C  rD   r<   r   )rF   r@   rL   r   r   r   __set__   rK   zField.__set__source_field
str | None	generatedprimary_keybool | Nonenulldefaultuniquedb_indexdescriptionmodel
validators!list[Validator | Callable] | Nonec                 K  sR  | dd  }d ur&|d u rtjdtdd |}n||kr&t| jj d| js6|s-|r6t| jj d| dd  }d ur\|d u rOtjdtdd |}n||kr\t| jj d	|rt|rit| jj d
|rtt| jj d|rzd}d}|| _|| _	t
|| _|| _|| _|| _t
|| _d| _|| _d | _|
pg | _|	| _d | _d S )Nindexz4`index` is deprecated, please use `db_index` insteadr*   )
stacklevelz" can't set both db_index and indexz can't be indexedpkz4`pk` is deprecated, please use `primary_key` insteadz" can't set both primary_key and pkz$ can't be both null=True and pk=Truez- can't be both null=True and primary_key=TrueT )popwarningswarnDeprecationWarningr   r?   r   r2   rN   rP   r1   r]   rT   rS   rU   r[   model_field_namerW   	docstringrY   rX   	reference)rF   rN   rP   rQ   rS   rT   rU   rV   rW   rX   rY   r:   r[   r]   r   r   r   __init__   sf   



zField.__init__type[Model] | Modelc                 C  s,   |durt || js| |}| | |S )at  
        Converts from the Python type to the DB type.

        :param value: Current python value in model.
        :param instance: Model class or Model instance provided to look up.

            Due to metacoding, to determine if this is an instance reliably, please do a:

            .. code-block:: py3

                if hasattr(instance, "_saved_in_db"):
        N)
isinstancer.   validate)rF   rL   r@   r   r   r   to_db_value   s   

zField.to_db_valuec                 C  s"   |durt || js| |}|S )zd
        Converts from the DB type to the Python type.

        :param value: Value from DB
        N)rh   r.   )rF   rL   r   r   r   to_python_value   s   
zField.to_python_valuec                 C  sn   | j D ]1}| jr|du rqzt|tr||j n|| W q ty4 } z
t| j d| d}~ww dS )z
        Validate whether given value is valid

        :param value: Value to be validation
        :raises ValidationError: If validator check is not passed
        Nz: )rY   rS   rh   r   rL   r   rc   )rF   rL   vexcr   r   r   ri     s   

zField.validatec                 C  s   | j du o| j o| j S )z
        Returns ``True`` if the field is required to be provided.

        It needs to be non-nullable and not have a default or be DB-generated to be required.
        N)rT   rS   rP   rF   r   r   r   required  s   zField.requiredr&   c                 C  s   i S )z\
        Returns a dict with constraints defined in the Pydantic/JSONSchema format.
        r   rn   r   r   r   constraints"  s   zField.constraintsdict[str, dict]c              	     s   i }t | D ]A}|dsqt| |  j}z | W n	 ty%   Y nw  fddt  D }i ||}dd | D ||dd  < q|S )N_db_c                   s(   i | ]}t t |tr|t|qS r   )rh   getattrproperty).0propr0   objr   r   
<dictcomp>5  s    
z'Field._get_dialects.<locals>.<dictcomp>c                 S  s    i | ]\}}| d s||qS )_)
startswith)ru   krl   r   r   r   ry   <  s        )dirr{   rs   __dict__	TypeErroritems)rF   retdialectdpropsr   rw   r   _get_dialects)  s"   

 zField._get_dialectsc                 C  s   | j jjjj}| |dS )zS
        Returns the DB field type for this field for the current dialect.
        r7   )rX   _metadbcapabilitiesr   get_for_dialect)rF   r   r   r   r   get_db_field_type@  s   zField.get_db_field_typedict[str, str] | Nonec                   s<   j sdS j d i fddfddtD D S )z
        Returns the DB types for this field.

        :return: A dictionary that is keyed by dialect.
            A blank dialect `""` means it is the default DB field type.
        Nr^   c                   s   i | ]\}}| kr||qS r   r   )ru   r   sql_typerT   r   r   ry   S  s    z,Field.get_db_field_types.<locals>.<dictcomp>c                 3  s:    | ]}| d r|dd  |dd dfV  qdS )rr   r}   Nr7   )r{   r   )ru   keyrn   r   r   	<genexpr>U  s    
z+Field.get_db_field_types.<locals>.<genexpr>)r3   r7   r~   rn   r   )rT   rF   r   get_db_field_typesG  s   

zField.get_db_field_typesr   r   c                 C  sZ   zt | d| }t ||}W n	 ty   Y nw t|tr%t || |S |S t | |dS )z
        Returns a field by dialect override.

        :param dialect: The requested SQL Dialect.
        :param key: The attribute/method name.
        rr   N)rs   AttributeErrorrh   rt   )rF   r   r   dialect_clsdialect_valuer   r   r   r   ^  s   
zField.get_for_dialectserializablec                   s   ddd d fd	d
}ddd}t | d| j}| j|r | jjn| j| jp'| j|r-||n|| j| j| j| j	p9| j|r@|| j
n| j
| j| j| jd}| jrT|  |d< |S )a  
        Describes the field.

        :param serializable:
            ``False`` if you want raw python objects,
            ``True`` for JSON-serializable data. (Defaults to ``True``)

        :return:
            A dictionary containing the field description.

            (This assumes ``serializable=True``, which is the default):

            .. code-block:: python3

                {
                    "name":         str     # Field name
                    "field_type":   str     # Field type
                    "db_column":    str     # Name of DB column
                                            #  Optional: Only for pk/data fields
                    "raw_field":    str     # Name of raw field of the Foreign Key
                                            #  Optional: Only for Foreign Keys
                    "db_field_types": dict  # DB Field types for default and DB overrides
                    "python_type":  str     # Python type
                    "generated":    bool    # Is the field generated by the DB?
                    "nullable":     bool    # Is the column nullable?
                    "unique":       bool    # Is the field unique?
                    "indexed":      bool    # Is the field indexed?
                    "default":      ...     # The default value (coerced to int/float/str/bool/null)
                    "description":  str     # Description of the field (nullable)
                    "docstring":    str     # Field docstring (nullable)
                }

            When ``serializable=False`` is specified some fields are not coerced to valid
            JSON types. The changes are:

            .. code-block:: python3

                {
                    "field_type":   Field   # The Field class used
                    "python_type":  Type    # The actual Python type
                    "default":      ...     # The default value as native type OR a callable
                }
        typr(   r'   r   c                 S  s<   | j dkr| jS | j dkrt| ddS | j  d| j S )Nbuiltinstypingztyping.r^   .)r   r   r   replacer   r   r   r   
_type_name  s
   

z"Field.describe.<locals>._type_namer   str | list[str]c                   st   z| j jW S  ttfy   Y nw z | W S  ty9   z fdd| D W  Y S  ty8   t|  Y  Y S w w )Nc                   s   g | ]} |qS r   r   )ru   _typr   r   r   
<listcomp>  s    z5Field.describe.<locals>.type_name.<locals>.<listcomp>)r   	full_namer   r   r   r   r   r   r   	type_name  s   

z!Field.describe.<locals>.type_namerT   int | float | str | bool | Nonec                 S  sB   t | tttttd fr| S t| rd| j d| j dS t| S )Nz
<function r   >)	rh   intfloatr   r1   r(   callabler   r   r   r   r   r   default_name  s
   z$Field.describe.<locals>.default_namerelated_model)r"   r.   	db_columnpython_typerP   nullablerU   indexedrT   rW   rd   rp   db_field_typesN)r   r(   r'   r   )r   r   r'   r   )rT   r   r'   r   )rs   r.   rc   r?   r   rN   rP   rS   rU   r[   rT   rW   rd   rp   r3   r   )rF   r   r   r   r.   descr   r   r   describes  s(   
-


zField.describe)r9   r   r:   r   r'   r;   )r@   rA   rB   rC   r'   r;   )r@   r   rB   rC   r'   r   )r@   rI   rB   rC   r'   rJ   )r@   r   rL   r   r'   rA   )
NFNFNFNNNN)rN   rO   rP   r1   rQ   rR   rS   r1   rT   r   rU   r1   rV   rR   rW   rO   rX   rI   rY   rZ   r:   r   r'   rA   )rL   r   r@   rg   r'   r   )rL   r   r'   r   )rL   r   r'   rA   )r'   r1   )r'   r&   )r'   rq   )r'   r   )r'   r   )r   r   r   r   r'   r   )r   r1   r'   r&   )r   r   r   __doc__r.   __annotations__r2   r3   r4   r5   r6   r7   r8   r   r-   r
   rG   rM   rf   rj   rk   ri   rt   ro   rp   r   r   r   r   r   __classcell__r   r   r>   r   r,   7   sR   
 V


C






r,   )	metaclass)%
__future__r   sysr`   collections.abcr   enumr   r   r   r   r   r   r	   r
   pypika_tortoise.termsr   tortoise.exceptionsr   r   tortoise.validatorsr   tortoise.modelsr   version_infor   r   r   r   r   r   r   r   r    r(   r!   r,   r   r   r   r   <module>   s.     
