
    i3                        U d Z ddlZddlZddlZddlZddlZg dZ ej                  e      Z	da
ded<   	 ddZdd	Zej                   G d
 d             Z ed      Zej                   G d de             Z G d d      Zdeej*                  z  fdZdedeeej0                  f   fdZdeeej0                  f   deeej0                  f   deeef   deeee   f   fdZdee   dee   deeej0                  f   deeej0                  f   deeef   deeee   f   fdZd deeej0                  f   deeej0                  f   dee   dz  fdZy)!aB  Configuration class :py:class:`Config` with deep-update, schema validation
and deprecated names.

The :py:class:`Config` class implements a configuration that is based on
structured dictionaries.  The configuration schema is defined in a dictionary
structure and the configuration data is given in a dictionary structure.
    N)ConfigUNSETSchemaIssueset_global_cfgget_global_cfgzConfig | NoneCFGr   c                     | a y N)r   )cfgs    */root/searxng/searx/botdetection/config.pyr   r      s    
C    returnc                  0    t         t        d      t         S )Nz-Botdetection's config is not yet initialized.)r   
ValueError r   r   r   r      s    
{HIIJr   c                   ,    e Zd ZdZdefdZd Zd ZeZy)FALSEzClass of ``False`` singletonmsgc                     || _         y r
   r   )selfr   s     r   __init__zFALSE.__init__*   s	    r   c                      y)NFr   r   s    r   __bool__zFALSE.__bool__-   s    r   c                     | j                   S r
   r   r   s    r   __str__zFALSE.__str__0   s    xxr   N)	__name__
__module____qualname____doc__strr   r   r   __repr__r   r   r   r   r   %   s"    &C  Hr   r   z<UNSET>c                   L     e Zd ZdZdej
                  d   def fdZd Z xZ	S )r   z>Exception to store and/or raise a message from a schema issue.level)warninvalidr   c                 2    || _         t        | 	  |       y r
   )r%   superr   )r   r%   r   	__class__s      r   r   zSchemaIssue.__init__=   s    
r   c                 @    d| j                    d| j                  d    S )Nz[cfg schema z] r   )r%   argsr   s    r   r   zSchemaIssue.__str__A   s!    djj\DIIaL>::r   )
r   r   r    r!   typingLiteralr"   r   r   __classcell__)r*   s   @r   r   r   9   s(    Hfnn->? c ;r   r   c            	          e Zd ZU dZeZeed<   edej                  dej                  de
eef   dd fd       Zde
eej                  f   de
eef   fd	Zd
edej                  fdZde
eej                  f   fdZde
eej                  f   fdZdefdZedfdedej                  dedej                  fdZdedej                  fdZdede
eej                  f   fdZefdedej                  fdZefdedej                  fdZy)r   z!Base class used for configurationr   schema_filecfg_file
deprecatedr   c                    t         j                  d|        | t        |      |      }|j                         st         j	                  d|       |S t         j                  d|       t        |      }|j                  |      \  }}|D ]   }t         j                  t        |             " |st        d| d      |j                  |       |S )Nzload schema file: %s)
cfg_schemar3   zmissing config file: %szload config file: %sz
schema of z is invalid!)
logdebug	toml_loadexistswarningvalidateerrorr"   	TypeErrorupdate)	clsr1   r2   r3   r   upd_cfgis_valid
issue_listr   s	            r   	from_tomlzConfig.from_tomlJ   s    
 			(+6Y{3
K KK18<J 			((3H%"||G4* 	 CIIc#h	 j
,?@@

7
r   r5   c                 T    || _         || _        t        j                  |      | _        y)a  Constructor of class Config.

        :param cfg_schema: Schema of the configuration
        :param deprecated: dictionary that maps deprecated configuration names to a messages

        These values are needed for validation, see :py:obj:`validate`.

        N)r5   r3   copydeepcopyr   )r   r5   r3   s      r   r   zConfig.__init__b   s"     2<*4*.--
*Cr   keyc                 $    | j                  |      S r
   )get)r   rG   s     r   __getitem__zConfig.__getitem__o   s    xx}r   r   c                 D    t        | j                  || j                        S )znValidation of dictionary ``cfg`` on :py:obj:`Config.SCHEMA`.
        Validation is done by :py:obj:`validate`.)r;   r5   r3   )r   r   s     r   r;   zConfig.validater   s     doo>>r   r@   c                 0    t        | j                  |       y)z)Update this configuration by ``upd_cfg``.N)dict_deepupdater   )r   r@   s     r   r>   zConfig.updatex   s     	'*r   namec                 .    t        || j                        S )z?Returns default value of field ``name`` in ``self.cfg_schema``.)valuer5   )r   rN   s     r   defaultzConfig.default}   s    T4??++r   TrQ   replacec                     | j                  |      }|j                  |j                  d      d   t              }|t        u r|t        u rt	        |      |}|rt        |t              r|| z  }|S )zReturns the value to which ``name`` points in the configuration.

        If there is no such ``name`` in the config and the ``default`` is
        :py:obj:`UNSET`, a :py:obj:`KeyError` is raised.
        .)_get_parent_dictrI   splitr   KeyError
isinstancer"   )r   rN   rQ   rR   parentvals         r   rI   z
Config.get   si     &&t,jjC,e4%<%tn$Cz#s+*C
r   r[   c                 T    | j                  |      }|||j                  d      d   <   y)zSet the value to which ``name`` points in the configuration.

        If there is no such ``name`` in the config, a :py:obj:`KeyError` is
        raised.
        rT   rU   N)rV   rW   )r   rN   r[   rZ   s       r   setz
Config.set   s+     &&t,&)tzz#r"#r   c                     dj                  |j                  d      d d       }|rt        || j                        }n| j                  }|t        u st        |t              st        |      |S )NrT   rU   )joinrW   rP   r   r   rY   dictrX   )r   rN   parent_namerZ   s       r   rV   zConfig._get_parent_dict   s[    hhtzz#s34,1+txx,HFXXFeOZ%=;''r   c                     | j                  ||      }|t        u r|t        u rt        |      |S t        j                  t        |            S )z;Get a :py:class:`pathlib.Path` object from a config string.)rI   r   rX   pathlibPathr"   )r   rN   rQ   r[   s       r   pathzConfig.path   sE     hhtW%%<%tn$N||CH%%r   c                     | j                  ||      }|t        u r|t        u rt        |      |S t        |      j	                  dd      \  }}t        |i i |gd      }t        ||      S )zVGet python object referred by full qualiffied name (FQN) in the config
        string.rT      r   )rI   r   rX   r"   rsplit
__import__getattr)r   rN   rQ   fqn
modulenamems         r   pyobjzConfig.pyobj   sl     hhtW%%<%tn$N X__S!4Tz2rD615q$r   N)r   r   r    r!   r   object__annotations__classmethodrc   rd   r`   r"   rC   r-   Anyr   rJ   r;   r>   rQ   boolrI   r]   rV   re   rn   r   r   r   r   r   E   sv   +E6GLL GLL VZ[^`c[cVd iq  .D4VZZ#8 Dd3PS8n Ds vzz ?Dfjj1 ?+d3

?3 +
,C , 49$  fjj 4 SYS]S] $* *&** *S T#vzz/-B  5: & &vzz & 6;  #  

  r   	file_namec                 .   	 t        | d      5 }t        j                  |      cd d d        S # 1 sw Y   y xY w# t        j                  $ rH}t	        |      j                  dd      j                  dd      }t        j                  d| |        d }~ww xY w)Nrb	 
 z%s: %s)opentomllibloadTOMLDecodeErrorr"   rR   r6   r<   )rt   fexcr   s       r   r8   r8      s~    )T" 	#a<<?	# 	# 	#"" #htR(00s;		(Is+s*   9 -	9 69 9 BABBrN   	data_dictc                     |}| j                  d      D ]3  }t        |t              r|j                  |t              }|t        u s2 |S  |S )a  Returns the value to which ``name`` points in the ``dat_dict``.

    .. code: python

        >>> data_dict = {
                "foo": {"bar": 1 },
                "bar": {"foo": 2 },
                "foobar": [1, 2, 3],
            }
        >>> value('foobar', data_dict)
        [1, 2, 3]
        >>> value('foo.bar', data_dict)
        1
        >>> value('foo.bar.xxx', data_dict)
        <UNSET>

    rT   )rW   rY   r`   rI   r   )rN   r   ret_valparts       r   rP   rP      sQ    & G

3 gt$kk$.GeN
 Nr   schema_dictr3   c                     g }d}g }t        | t              st        dd      t        |t              st        dddj                  |       d      t	        ||| ||      \  }}||fS )a  Deep validation of dictionary in ``data_dict`` against dictionary in
    ``schema_dict``.  Argument deprecated is a dictionary that maps deprecated
    configuration names to a messages::

        deprecated = {
            "foo.bar" : "config 'foo.bar' is deprecated, use 'bar.foo'",
            "..."     : "..."
        }

    The function returns a python tuple ``(is_valid, issue_list)``:

    ``is_valid``:
      A bool value indicating ``data_dict`` is valid or not.

    ``issue_list``:
      A list of messages (:py:obj:`SchemaIssue`) from the validation::

          [schema warn] data_dict: deprecated 'fontlib.foo': <DEPRECATED['foo.bar']>
          [schema invalid] data_dict: key unknown 'fontlib.foo'
          [schema invalid] data_dict: type mismatch 'fontlib.foo': expected ..., is ...

    If ``schema_dict`` or ``data_dict`` is not a dictionary type a
    :py:obj:`SchemaIssue` is raised.

    Tr'   zschema_dict is not a dict typezdata_dict issuerT   z is not a dict type)rY   r`   r   r_   	_validate)r   r   r3   namesrA   rB   s         r   r;   r;      sx    8 EH$&Jk4()%EFFi&)sxx6GGZ%[\\$UJYPZ[HjZr   r   rB   c                 n   d}|j                         D ]  \  }}| j                  |       dj                  |       }|j                  |      }	|	r!|j                  t	        dd| d|	              t        ||      }
|
t        u r$|	s|j                  t	        dd| d             d}nxt        |
      t        |      k7  r9|j                  t	        dd	| d
t        |
       dt        |                    d}n(t        |t              rt        | ||||      \  }}|xr |}| j                           ||fS )NTrT   r&   zdata_dict 'z': deprecated - r'   z': key unknown in schema_dictFzdata_dict: type mismatch 'z': expected z, is: )itemsappendr_   rI   r   rP   r   typerY   r`   r   pop)r   rB   r   r   r3   rA   rG   
data_valuerN   deprecated_msgschema_value_valid_s                r   r   r     sG    H %??, ZSxx#-k&KvEUVdUe2fghT;/5 !!!+i;tfLi9j"kl ,4
#331$7G\HZG[[abfgqbrast H
D)!%[*jYIFA*FH		;> Zr   	base_dictupd_dictc                    t        | t              st        d      t        |t              st        d      |g }|j                         D ]  \  }}t        |t              rc|| v rFt        | |   t              st        ddj	                  |       d      t        | |   |||gz          at        j                  |      | |<   zt        |t              rc|| v rFt        | |   t              st        ddj	                  |       d      | |   j                  |       t        j                  |      | |<   t        |t              rn|| v rUt        | |   t              st        ddj	                  |       d      | |   j                  |j                                V|j                         | |<   kt        j                  |      | |<    y)	a  Deep-update of dictionary in ``base_dict`` by dictionary in ``upd_dict``.

    For each ``upd_key`` & ``upd_val`` pair in ``upd_dict``:

    0. If types of ``base_dict[upd_key]`` and ``upd_val`` do not match raise a
       :py:obj:`TypeError`.

    1. If ``base_dict[upd_key]`` is a dict: recursively deep-update it by ``upd_val``.

    2. If ``base_dict[upd_key]`` not exist: set ``base_dict[upd_key]`` from a
       (deep-) copy of ``upd_val``.

    3. If ``upd_val`` is a list, extend list in ``base_dict[upd_key]`` by the
       list in ``upd_val``.

    4. If ``upd_val`` is a set, update set in ``base_dict[upd_key]`` by set in
       ``upd_val``.
    z-argument 'base_dict' is not a dictionary typez,argument 'upd_dict' is not a dictionary typeNztype mismatch rT   z!: is not a dict type in base_dictz!: is not a list type in base_dictz : is not a set type in base_dict)rY   r`   r=   r   r_   rM   rE   rF   listextendr]   r>   )r   r   r   upd_keyupd_vals        r   rM   rM   =  s   ( i&GHHh%FGG}$NN, 44 gt$)#!)G"4d;#nSXXe_4EEf$ghhg& &*]]7%;	'"&)# ")G"4d;#nSXXe_4EEf$ghh'"))'2
 &*]]7%;	'"%)#!)G"4c:#nSXXe_4EEe$fgg'"))',,.9
 &-\\^	'"
 "&7!3Igi44r   )r   r   )r   r   r
   ) r!   r-   rE   loggingrc   r|   __all__	getLoggerr   r6   r   rp   r   r   finalr   r   r   r   r   r"   rd   r8   r`   rr   rP   tuplers   r   r;   r   rM   r   r   r   <module>r      s       
Pg!_  (
     	i ;* ; ;v  v rw||+  S&**_ 5 8& c6::o&& 37VZZ3H& VZ[^`c[cVd& 
4k""#& R* 9* [!*  c6::o&*  CO$	* 
 S#X*  4k""#* ZP4tCO4 P4S&**_@U P4^bcf^gjn^n P4r   