
    i&                         d Z ddlZddlZddlZddlZddlZddlmZ ddl	m
Z
mZ ej                  rddlmZ  G d dej                        Zej"                   G d	 d
             Z G d deeef         Zy)a  Engine's traits are fetched from the origin engines and stored in a JSON file
in the *data folder*.  Most often traits are languages and region codes and
their mapping from SearXNG's representation to the representation in the origin
search engine.  For new traits new properties can be added to the class
:py:class:`EngineTraits`.

To load traits from the persistence :py:obj:`EngineTraitsMap.from_data` can be
used.
    N)locales)ENGINE_TRAITSdata_dir   )Enginec                   T     e Zd ZdZdej
                  dej
                  f fdZ xZS )EngineTraitsEncoderzZEncodes :class:`EngineTraits` to a serializable object, see
    :class:`json.JSONEncoder`.oreturnc                 Z    t        |t              r|j                  S t        |   |      S )z4Return dictionary of a :class:`EngineTraits` object.)
isinstanceEngineTraits__dict__superdefault)selfr
   	__class__s     '/root/searxng/searx/enginelib/traits.pyr   zEngineTraitsEncoder.default   s&    a&::wq!!    )__name__
__module____qualname____doc__tAnyr   __classcell__)r   s   @r   r	   r	      s(    "" "155 " "r   r	   c                      e Zd ZU dZ ej
                  e      Zeeef   e	d<   	  ej
                  e      Z
eeef   e	d<   	 dZedz  e	d<   	 dZej                  d   e	d<   	  ej
                  e      Zeeej                   f   e	d	<   	 dd
ededz  dedz  fdZdd
ededz  dedz  fdZd
edefdZd Zedd       ZddZddZy)r   z9The class is intended to be instantiated for each engine.)default_factoryregions	languagesN
all_locale	traits_v1	data_typecustomsearxng_localer   r   c                     |dk(  r| j                   | j                   S t        j                  || j                  |      S )a  Return engine's language string that *best fits* to SearXNG's locale.

        :param searxng_locale: SearXNG's internal representation of locale
          selected by the user.

        :param default: engine's default language

        The *best fits* rules are implemented in
        :py:obj:`searx.locales.get_engine_locale`.  Except for the special value ``all``
        which is determined from :py:obj:`EngineTraits.all_locale`.
        allr   )r!   r   get_engine_localer    r   r%   r   s      r   get_languagezEngineTraits.get_languageW   s9     U"t'B??"((QXYYr   c                     |dk(  r| j                   | j                   S t        j                  || j                  |      S )a  Return engine's region string that best fits to SearXNG's locale.

        :param searxng_locale: SearXNG's internal representation of locale
          selected by the user.

        :param default: engine's default region

        The *best fits* rules are implemented in
        :py:obj:`searx.locales.get_engine_locale`.  Except for the special value ``all``
        which is determined from :py:obj:`EngineTraits.all_locale`.
        r'   r(   )r!   r   r)   r   r*   s      r   
get_regionzEngineTraits.get_regiong   s8     U"t'B??"((wWWr   c                     | j                   dk(  r-t        | j                  |      xs | j                  |            S t	        d| j                   z        )a7  A *locale* (SearXNG's internal representation) is considered to be
        supported by the engine if the *region* or the *language* is supported
        by the engine.

        For verification the functions :py:func:`EngineTraits.get_region` and
        :py:func:`EngineTraits.get_language` are used.
        r"   #engine traits of type %s is unknown)r#   boolr-   r+   	TypeError)r   r%   s     r   is_locale_supportedz EngineTraits.is_locale_supportedw   sI     >>[(7\4;L;L^;\]]=NOOr   c                 >    t        di t        j                  |       S )z&Create a copy of the dataclass object. )r   dataclassesasdict)r   s    r   copyzEngineTraits.copy   s    7k00677r   c                 F    t        |dd      }d}|r |        } ||       |S )zCall a function ``fetch_traits(engine_traits)`` from engines namespace to fetch
        and set properties from the origin engine in the object ``engine_traits``.  If
        function does not exists, ``None`` is returned.
        fetch_traitsN)getattr)clsenginer9   engine_traitss       r   r9   zEngineTraits.fetch_traits   s/     v~t<EM'r   c                 t    | j                   dk(  r| j                  |       yt        d| j                   z        )zSet traits from self object in a :py:obj:`.Engine` namespace.

        :param engine: engine instance build by :py:func:`searx.engines.load_engine`
        r"   r/   N)r#   _set_traits_v1r1   )r   r<   s     r   
set_traitszEngineTraits.set_traits   s3     >>[('ADNNRSSr   c                 2   | j                         }d}|j                  }t        |d      rS|j                  |vr%t	        ||j
                  d|j                  fz        |j                  ||j                     i|_        |j                  }t        |d      rS|j                  |vr%t	        ||j
                  d|j                  fz        |j                  ||j                     i|_        t        |j                  xs |j                        |_	        ||_
        y )Nz4settings.yml - engine: '%s' / %s: '%s' not supportedlanguageregion)r7   r    hasattrrB   
ValueErrornamer   rC   r0   language_supporttraits)r   r<   rH   _msgr    r   s         r   r?   zEngineTraits._set_traits_v1   s     E$$	6:&i/ j&//(R!RSS &6??1KLF..68$}}G+ h(N!NOO$mmWV]]-CDFN"&v'7'7'I6>>"J r   )N)r<   Engine | types.ModuleTyper   zEngineTraits | None)r<   rJ   r   N)r   r   r   r   r5   fielddictr   str__annotations__r    r!   r#   r   Literalr$   r   r+   r-   r0   r2   r7   classmethodr9   r@   r?   r4   r   r   r   r   $   s1   C/k//EGT#s(^E  !2 1 1$ GItCH~G  "Jd
! )4Iqyy%3  1{00FFDaeeFZ3 Zt ZsUYz Z X XsTz XSSWZ X P# P$ P8  	Tr   r   c                       e Zd ZU dZedz  j                         Zej                  e	d<   	 d Z
edd       Zedej                  egdf   dd fd	       Zdd
Zy)EngineTraitsMapz@A python dictionary to map :class:`EngineTraits` by engine name.zengine_traits.jsonENGINE_TRAITS_FILEc                     t        | j                  dd      5 }t        j                  | |ddt               ddd       y# 1 sw Y   yxY w)zBStore EngineTraitsMap in in file :py:obj:`self.ENGINE_TRAITS_FILE`wzutf-8)encoding   T)indent	sort_keysr;   N)openrS   jsondumpr	   )r   fs     r   	save_datazEngineTraitsMap.save_data   sD    $))3A 	RQIIdAa4=PQ	R 	R 	Rs   AA
r   c                 h     |        }t        j                         D ]  \  }}t        di |||<    |S )zHInstantiate :class:`EngineTraitsMap` object from :py:obj:`ENGINE_TRAITS`r4   )r   itemsr   )r;   objkvs       r   	from_datazEngineTraitsMap.from_data   s=     e!'') 	'DAq!&A&CF	'
r   logNc                    ddl m} t        |j                        }|j                           |        }|D ]t  }|j                  |   }d }	 t        j                  |      }|- ||ddt        |j                        d	        ||dd
t        |j                               |||<   v |S # t        $ rQ} |d|d|       t        j                  |      }	|	r |d|z         t	        di |	}n |d|z         Y d }~d }~ww xY w)Nr   )engineszERROR: while fetch_traits z: z@WARNING: re-use old values from fetch_traits - ENGINE_TRAITS[%s]z@WARNING: no old values available for ENGINE_TRAITS[%s], skipping20z: SearXNG languages -->  z: SearXNG regions   --> r4   )searxrg   listsortr   r9   	Exceptionr   getlenr    r   )
r;   re   rg   namesra   engine_namer<   rH   excrc   s
             r   r9   zEngineTraitsMap.fetch_traits   s   	
 W__%

e  	*K070LFF	j%226: !+s6K[K[G\]^c&..FYZ[#)K '	** 
  j+sKL!%%k2Z]hhi).A.FZ]hhijs   
B..	D7ADDc                     t        d      }|j                  | j                         v r| |j                     }n+|j                  | j                         v r| |j                     }|j	                  |       y)zSet traits in a :py:obj:`Engine` namespace.

        :param engine: engine instance build by :py:func:`searx.engines.load_engine`
        r"   )r#   N)r   rF   keysr<   r@   )r   r<   r=   s      r   r@   zEngineTraitsMap.set_traits   s^     %{;;;$))+% -M]]diik) !/M  (r   )r   rR   )r<   rJ   )r   r   r   r   r   resolverS   pathlibPathrN   r^   rP   rd   r   CallablerM   r9   r@   r4   r   r   rR   rR      sx    J(03G(G'P'P'RRAR
   qzz3%+6 ;L  @)r   rR   )r   r5   r[   rv   typestypingr   rj   r   
searx.datar   r   TYPE_CHECKING r   JSONEncoderr	   	dataclassr   rL   rM   rR   r4   r   r   <module>r      sx          .??"$** " Y Y YxG)d3,- G)r   