a
    »ÏOcÏ-  ã                   @   sf   d dl Z d dlmZ d dlmZ dd„ ZG dd„ dƒZG dd	„ d	ƒZG d
d„ dƒZG dd„ deƒZ	dS )é    N)Úwraps)ÚRESOURCES_BY_TAGc                    s2   t  ˆ ¡}|j|j ‰}tˆ ƒ‡ ‡fdd„ƒ}|S )z³
    decorator that checks function arguments for `concrete` and `resource`
    and will properly set them to class references if a string (reftag) is
    passed as the value
    c                     s~   d}| d }ˆdd … D ]V}| | }|dkrFt |tƒrF|j| | |< n |dkrft |tƒrf|j| | |< |d7 }qˆ | i |¤ŽS )Nr   é   ÚconcreteÚresource)Ú
isinstanceÚstrÚREFTAG_CONCRETEÚREFTAG_RESOURCE)ÚargsÚkwargsÚiÚbackendÚnameÚvalue©ÚfnÚnames© úH/var/www/html/gsl.tools/lib/python3.9/site-packages/peeringdb/backend.pyÚwrapped   s    
zreftag_to_cls.<locals>.wrapped)ÚinspectÚgetfullargspecr   Údefaultsr   )r   ÚspecÚ_r   r   r   r   Úreftag_to_cls   s
    
r   c                   @   s   e Zd ZdZdd„ ZdS )ÚFieldzp
    We use this to provide field instances to backends that
    don't use classes to describe their fields
    c                 C   s   || _ d | _d S ©N)r   Úcolumn)Úselfr   r   r   r   Ú__init__&   s    zField.__init__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r!   r   r   r   r   r       s   r   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚEmptyContextzG
    We use this to provide a dummy context wherever it's optional
    c                 C   s   d S r   r   ©r    r   r   r   Ú	__enter__1   s    zEmptyContext.__enter__c                 G   s   d S r   r   )r    r   r   r   r   Ú__exit__4   s    zEmptyContext.__exit__N)r"   r#   r$   r%   r(   r)   r   r   r   r   r&   +   s   r&   c                   @   s8   e Zd ZdZeZedd„ ƒZdd„ Zdd„ Z	dd	„ Z
d
S )ÚBasezƒ
    Backend base class.

    Do NOT extend this directly when implementing a new backend, instead
    extend Interface below.
    c                 C   s&   t | dƒs dd„ | j ¡ D ƒ| _| jS )NÚ_CONCRETE_MAPc                 S   s   i | ]\}}||“qS r   r   )Ú.0Úresr   r   r   r   Ú
<dictcomp>G   s   z%Base.CONCRETE_MAP.<locals>.<dictcomp>)ÚhasattrÚRESOURCE_MAPÚitemsr+   r'   r   r   r   ÚCONCRETE_MAPD   s
    
ÿzBase.CONCRETE_MAPc                 C   s
   | j | S )zm
        returns the concrete class for the resource

        Returns:

            - concrete class
        )r0   )r    r-   r   r   r   Úget_concreteL   s    zBase.get_concretec                 C   s
   || j v S )z´
        check if concrete class exists in the resource -> concrete mapping

        Returns:

            - bool: True if class exists in the resource -> concrete mapping
        ©r2   ©r    Úclsr   r   r   Úis_concreteV   s    zBase.is_concretec                 C   s
   | j | S )zs
        returns the resource class for the concrete class

        Returns:

            - resource class
        r4   r5   r   r   r   Úget_resource`   s    zBase.get_resourceN)r"   r#   r$   r%   r   r
   Úpropertyr2   r3   r7   r8   r   r   r   r   r*   8   s   


r*   c                   @   s(  e Zd ZdZi Zi Zed6dd„ƒZed7dd„ƒZedd„ ƒZ	ed	d
„ ƒZ
e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d8dd„ƒZedd„ ƒZedd „ ƒZed!d"„ ƒZd#d$„ Zd%d&„ Zd'd(„ Zed)d*„ ƒZed+d,„ ƒZd-d.„ Zed/d0„ ƒZd9d2d3„Zd4d5„ Z dS ):Ú	InterfacezN
    backend adapter interface

    extend this when making a new backend
    Nc                 C   s   t S )a|  
        should return the exception class that will
        be raised when an object fails validation

        Arguments:

            - concrete: if your backend has class specific validation
                errors and this is set, return the exception class that would be
                raised for this concrete class.

        Returns:

            - Exception class
        ©Ú	Exception©r6   r   r   r   r   Úvalidation_error{   s    zInterface.validation_errorc                 C   s   t S )a  
        should return the exception class that will
        be raised when an object cannot be found

        Arguments:

            - concrete: if your backend has class specific object missing
                errors and this is set, return the exception class that would be
                raised for this concrete class.

        Returns:

            - Exception class
        r;   r=   r   r   r   Úobject_missing_error�   s    zInterface.object_missing_errorc                 C   s   t ƒ S )zå
        Allows you to return an atomic transaction context
        if your backend supports it, if it does not, leave as is

        This should never return None

        Returns:

            - python context instance
        )r&   ©r6   r   r   r   Úatomic_transactionŸ   s    zInterface.atomic_transactionc                 C   s   dS )zn
        operations that need to be done ONCE during runtime
        to prepare usage for the backend
        Nr   r@   r   r   r   Úsetup­   s    zInterface.setupc                 K   s
   t ƒ ‚dS )zÂ
        should create object from dict and return it

        Arguments:

            - concrete: concrete class

        Keyword Arguments:

            - object field names -> values
        N©ÚNotImplementedError)r    r   Údatar   r   r   Úcreate_object¼   s    zInterface.create_objectc                 C   s
   t ƒ ‚dS )zD
        Delete all objects, essentially empty the database
        NrC   r'   r   r   r   Ú
delete_allÌ   s    zInterface.delete_allc                 C   s
   t ƒ ‚dS )a2  
        Should parse error messages and collect the missing relationship
        errors as a dict of Resource -> {id set} and return it

        Arguments:

            - obj: concrete object instance
            - exc: exception instance

        Returns:

            - dict: {Resource : [ids]}
        NrC   )r    ÚobjÚexcr   r   r   Údetect_missing_relationsÒ   s    z"Interface.detect_missing_relationsc                 C   s
   t ƒ ‚dS )aJ  
        Should parse error message and collect any that describe violations
        of a uniqueness constraint.

        return the curresponding fields, else None

        Arguments:

            - exc: exception instance

        Returns:

            - list: list of fields
            - None: if no uniqueness errors
        NrC   )r    rI   r   r   r   Údetect_uniqueness_errorâ   s    z!Interface.detect_uniqueness_errorc                 C   s
   t ƒ ‚dS )z»
        Should return a list of field names for the concrete class

        Arguments:

            - concrete: concrete class

        Returns:

            - list: [<str>,...]
        NrC   ©r    r   r   r   r   Úget_field_namesô   s    zInterface.get_field_namesc                 C   s
   t ƒ ‚dS )zË
        Return concrete class for relationship by field name

        Arguments:

            - concrete: concrete class
            - field_name

        Returns:

            - concrete class
        NrC   ©r    r   Ú
field_namer   r   r   Úget_field_concrete  s    zInterface.get_field_concretec                 C   s
   t ƒ ‚dS )zÝ
        should return instance of object with matching id

        Arguments:

            - concrete: concrete class
            - id: object primary key value

        Returns:

            - concrete instance
        NrC   )r    r   Úidr   r   r   Ú
get_object  s    zInterface.get_objectc                 C   s
   t ƒ ‚dS )a\  
        very simply search function that should return
        collection of objects where field matches value

        Arguments:

            - concrete: concrete class
            - field_name: query this field for a match
            - value: match this value (simple equal matching)

        Returns:

            - concrete instance
        NrC   ©r    r   rO   r   r   r   r   Úget_object_by#  s    zInterface.get_object_byc                 C   s
   t ƒ ‚dS )aT  
        should return collection of objects

        Arguments:

            - concrete: concrete class
            - ids: if specified should be a list of primary
                key values and only objects matching those
                values should be returned

        Returns:

            - collection of concrete instances
        NrC   )r    r   Úidsr   r   r   Úget_objects5  s    zInterface.get_objectsc                 C   s
   t ƒ ‚dS )ak  
        very simple search function that should return
        collection of objects where field matches value

        Arguments:

            - concrete: concrete class
            - field_name: query this field for a match
            - value: match this value (simple equal matching)

        Returns:

            - collection of concrete instances
        NrC   )r    r   Úfieldr   r   r   r   Úget_objects_byG  s    zInterface.get_objects_byc                 C   s
   t ƒ ‚dS )aq  
        Should return a tuple containing bools on whether
        a field signifies a relationship and if it's a single
        relationship or a relationship to multiple objects

        Arguments:

            - concrete: concrete class
            - field_name: query this field for a match

        Returns:

            - tuple: (bool related, bool many)
        NrC   rN   r   r   r   Úis_field_relatedY  s    zInterface.is_field_relatedc                 C   s
   t ƒ ‚dS )zØ
        should return unix epoch timestamp of the `updated` field
        of the most recently updated object

        Arguments:

            - concrete: concrete class

        Returns:

            - int
        NrC   rL   r   r   r   Úlast_changek  s    zInterface.last_changec                 C   s
   t ƒ ‚dS )zk
        Save the object instance

        Arguments:

            - obj: concrete object instance
        NrC   ©r    rH   r   r   r   Úsave{  s    zInterface.savec                 C   s
   t ƒ ‚dS )a  
        Setup a many to many relationship

        Arguments:

            - obj: concrete object instance
            - field_name: name of the field that holds the relationship
            - objs: collection of concrete objects to setup relationships with
        NrC   )r    rH   rO   Úobjsr   r   r   Úset_relation_many_to_many…  s    
z#Interface.set_relation_many_to_manyc                 C   s   t |||ƒ dS )a#  
        update field on a concrete instance to value

        this does not have to commit to the database, which will be
        handled separately via the `save` method.

        Arguments:

            - obj: concrete object instance
            - field_name
            - value
        N)Úsetattr)r    rH   rO   r   r   r   r   Úupdate‘  s    zInterface.updatec                 C   s   t |ƒS )a  
        Should retrun a field instance, if your backend does not use
        classes to describe fields, leave this as is

        Arguments:

            - concrete: concrete class
            - field_name

        Returns:

            - field instance
        ©r   rN   r   r   r   Ú	get_field¢  s    zInterface.get_fieldc                 C   s   dd„ |   |¡D ƒS )a  
        Should return a collection of fields, if your backend does not
        use classes to describe fields, leave this as is

        Arguments:

            - concrete: concrete class

        Returns:

            - collection of field instances
        c                 S   s   g | ]}t |ƒ‘qS r   ra   )r,   r   r   r   r   Ú
<listcomp>Á  ó    z(Interface.get_fields.<locals>.<listcomp>)Úfield_namesrL   r   r   r   Ú
get_fields³  s    zInterface.get_fieldsc                 C   s   dS )z‰
        Should take an object instance and validate / clean it

        Arguments:

            - obj: concrete object instance
        Nr   r[   r   r   r   ÚcleanÃ  s    zInterface.cleanc                 C   s   dS )zø
        Should take a value and a field definition and do a value
        conversion if needed.

        should return the new value.

        Arguments:

            - concrete: concrete class
            - field_name
            - value
        Nr   rS   r   r   r   Úconvert_fieldÌ  s    zInterface.convert_fieldr   c                 C   s   dS )z½
        Do database migrations

        Arguments:

            - verbosity <int>: arbitrary verbosity setting, 0 = be silent,
                1 = show some info about migrations.
        Nr   )r    Ú	verbosityr   r   r   Úmigrate_databaseÛ  s    zInterface.migrate_databasec                 K   s   dS )zl
        Should return whether the database is fully migrated

        Returns:

            - bool
        Tr   )r    r   r   r   r   Úis_database_migratedå  s    zInterface.is_database_migrated)N)N)N)r   )!r"   r#   r$   r%   r0   r	   Úclassmethodr>   r?   rA   rB   r   rF   rG   rJ   rK   rM   rP   rR   rT   rV   rX   rY   rZ   r\   r^   r`   rb   rf   rg   rh   rj   rk   r   r   r   r   r:   k   sX   












	


r:   )
r   Ú	functoolsr   Zpeeringdb.resourcer   r   r   r&   r*   r:   r   r   r   r   Ú<module>   s   3