
    Ef@/                         d Z ddlZddlmZ ddlmZmZ i Z ee          Z	 ej
        e          Z G d de          Z G d de          Z G d	 d
e          Zd Zd Zd Zd Zd ZdS )av  
    lml.plugin
    ~~~~~~~~~~~~~~~~~~~

    lml divides the plugins into two category: load-me-later plugins and
    load-me-now ones. load-me-later plugins refer to the plugins were
    loaded when needed due its bulky and/or memory hungry dependencies.
    Those plugins has to use lml and respect lml's design principle.

    load-me-now plugins refer to the plugins are immediately imported. All
    conventional Python classes are by default immediately imported.

    :class:`~lml.plugin.PluginManager` should be inherited to form new
    plugin manager class. If you have more than one plugins in your
    architecture, it is advisable to have one class per plugin type.

    :class:`~lml.plugin.PluginInfoChain` helps the plugin module to
    declare the available plugins in the module.

    :class:`~lml.plugin.PluginInfo` can be subclassed to describe
    your plugin. Its method :meth:`~lml.plugin.PluginInfo.tags`
    can be overridden to help its matching :class:`~lml.plugin.PluginManager`
    to look itself up.

    :copyright: (c) 2017-2020 by Onni Software Ltd.
    :license: New BSD License, see LICENSE for more details
    N)defaultdict)
json_dumpsdo_import_classc                   4    e Zd ZdZ	 ddZd Zd Zd Zd ZdS )	
PluginInfoa)  
    Information about the plugin.

    It is used together with PluginInfoChain to describe the plugins.
    Meanwhile, it is a class decorator and can be used to register a plugin
    immediately for use, in other words, the PluginInfo decorated plugin
    class is not loaded later.

    Parameters
    -------------
    name:
       plugin name

    absolute_import_path:
       absolute import path from your plugin name space for your plugin class

    tags:
       a list of keywords help the plugin manager to retrieve your plugin

    keywords:
       Another custom properties.

    Examples
    -------------

    For load-me-later plugins:

        >>> info = PluginInfo("sample",
        ...      abs_class_path='lml.plugin.PluginInfo', # demonstration only.
        ...      tags=['load-me-later'],
        ...      custom_property = 'I am a custom property')
        >>> print(info.module_name)
        lml
        >>> print(info.custom_property)
        I am a custom property

    For load-me-now plugins:

        >>> @PluginInfo("sample", tags=['load-me-now'])
        ... class TestPlugin:
        ...     def echo(self, words):
        ...         print("echoing %s" % words)

    Now let's retrive the second plugin back:

        >>> class SamplePluginManager(PluginManager):
        ...     def __init__(self):
        ...         PluginManager.__init__(self, "sample")
        >>> sample_manager = SamplePluginManager()
        >>> test_plugin=sample_manager.get_a_plugin("load-me-now")
        >>> test_plugin.echo("hey..")
        echoing hey..

    Nc                 L    || _         || _        d | _        || _        || _        d S N)plugin_typeabsolute_import_pathcls
properties_PluginInfo__tags)selfr
   abs_class_pathtagskeywordss        L/var/www/ffwdstore.be/apps/py-env/lib/python3.11/site-packages/lml/plugin.py__init__zPluginInfo.__init___   s-     '$2!"    c                     |dk    r6| j         r!| j                             d          d         }n| j        j        }|S | j                            |          S )Nmodule_name.r   )r   splitr   
__module__r   get)r   namer   s      r   __getattr__zPluginInfo.__getattr__h   s[    =  ( 2"7==cBB1E"h1""4(((r   c              #   J   K   | j         | j        V  dS | j         D ]}|V  dS )z
        A list of tags for identifying the plugin class

        The plugin class is described at the absolute_import_path
        N)r   r
   )r   tags     r   r   zPluginInfo.tagsq   sK       ;""""""{  				 r   c                 r    | j         | j        d}|                    | j                   t	          |          S )N)r
   path)r
   r   updater   r   )r   reps     r   __repr__zPluginInfo.__repr__}   s<    +-
 
 	

4?####r   c                 4    || _         t          | |           |S r	   )r   _register_a_plugin)r   r   s     r   __call__zPluginInfo.__call__   s    4%%%
r   )NN)	__name__r   __qualname____doc__r   r   r   r$   r'    r   r   r   r   '   st        5 5p 6:   ) ) )
 
 
      r   r   c                   ,    e Zd ZdZd ZddZd Zd ZdS )PluginInfoChainzr
    Pandas style, chained list declaration

    It is used in the plugin packages to list all plugin classes
    c                 z    t          j        | j        j        dz   | j        j        z             | _        || _        d S Nr   )logging	getLogger	__class__r   r(   _loggerr   )r   r!   s     r   r   zPluginInfoChain.__init__   s=    (N%+dn.EE
 
  r   Nc                 r    t          ||                     |          fi |}|                     |           | S )z
        Add a plain plugin

        Parameters
        -------------

        plugin_type:
          plugin manager name

        submodule:
          the relative import path to your plugin class
        )r   _get_abs_pathadd_a_plugin_instance)r   r
   	submoduler   a_plugin_infos        r   add_a_pluginzPluginInfoChain.add_a_plugin   sN     #++I66
 
:B
 
 	""=111r   c                 p    | j                             d|j        |j                   t	          |           | S )z
        Add a plain plugin

        Parameters
        -------------

        plugin_info_instance:
          an instance of PluginInfo

        The developer has to specify the absolute import path
        zadd %s as '%s' plugin)r3   debugr   r
   _load_me_later)r   plugin_info_instances     r   r6   z%PluginInfoChain.add_a_plugin_instance   sC     	# 5 ,	
 	
 	

 	+,,,r   c                     | j         d|S r/   )r   )r   r7   s     r   r5   zPluginInfoChain._get_abs_path   s    ***II66r   r	   )r(   r   r)   r*   r   r9   r6   r5   r+   r   r   r-   r-      s_                 (  (7 7 7 7 7r   r-   c                   J    e Zd ZdZd Zd Zd Zd ZddZd Z	d	 Z
d
 Zd ZdS )PluginManagerz
    Load plugin info into in-memory dictionary for later import

    Parameters
    --------------

    plugin_type:
        the plugin type. All plugins of this plugin type will be
        registered to it.
    c                     || _         t          t                    | _        t	                      | _        t          j        | j        j	        dz   | j        j
        z             | _        t          |            d S r/   )plugin_namer   listregistrydict
tag_groupsr0   r1   r2   r   r(   r3   _register_class)r   r
   s     r   r   zPluginManager.__init__   se    &#D))&&(N%+dn.EE
 
 	r   c                 t    | j                             d           |                     |          } |            S )z Get a plugin

        Parameters
        ---------------

        key:
             the key to find the plugins

        keywords:
             additional parameters for help the retrieval of the plugins
        zget a plugin called)r3   r;   load_me_now)r   keyr   plugins       r   get_a_pluginzPluginManager.get_a_plugin   s9     	0111!!#&&vxxr   c                     | j                             | j                                                   t	          d| j        d|          )zRaise plugin not found exception

        Override this method to raise custom exception

        Parameters
        -----------------

        key:
            the key to find the plugin
        zNo z is found for )r3   r;   rD   keys	ExceptionrB   )r   rJ   s     r   raise_exceptionzPluginManager.raise_exception   sH     	4=--//000i43C3C3CSSIJJJr   c                 p    | j                             d|j                   |                     |           dS )z
        Register a plugin info for later loading

        Parameters
        --------------

        plugin_info:
            a instance of plugin info
        zload %s laterN)r3   r;   r   &_update_registry_and_expand_tag_groups)r   plugin_infos     r   load_me_laterzPluginManager.load_me_later   s9     	?K,LMMM33K@@@@@r   Nc                    |r| j                             |           |                                }|| j        v r| j        |         D ]0}|                     |          }t          |          }|r||k    r/ n2| j                             d|z             |                     |           | j                             d||           |S |                     |           dS )z
        Import a plugin from plugin registry

        Parameters
        -----------------

        key:
            the key to find the plugin

        library:
            to use a specific plugin module
        z%s is not installedzload %s now for '%s'N)r3   r;   lowerrD   dynamic_load_library_get_me_pypi_package_namerP   )r   rJ   libraryr   _PluginManager__keyrS   r   r   s           r   rI   zPluginManager.load_me_now  s      	)Lx(((		DM!!#}U3 
* 
*//<<7<< {g55E ""#87#BCCC$$S)))L5sC@@@J  %%%%%r   c                     |j         =| j                            d|j        z              t	          |j                  }||_         |j         S )zDynamically load the plugin info if not loaded


        Parameters
        --------------

        a_plugin_info:
            a instance of plugin info
        Nzimport )r   r3   r;   r   r   )r   r8   r   s      r   rW   z"PluginManager.dynamic_load_library&  sL     $Ly=+MMNNN!-"DEEC #M  r   c                     | j                             dt          |                     ||_        |                     |           dS )z for dynamically loaded plugin during runtime

        Parameters
        --------------

        plugin_cls:
            the actual plugin class refered to by the second parameter

        plugin_info:
            a instance of plugin info
        zregister %sN)r3   r;   _show_me_your_namer   rR   )r   
plugin_clsrS   s      r   register_a_pluginzPluginManager.register_a_plugin6  sF     	=*<Z*H*HIII$33K@@@@@r   c                 `    |                                 }| j                            |d           S r	   )rV   rF   r   )r   rJ   rZ   s      r   get_primary_keyzPluginManager.get_primary_keyF  s'    		""5$///r   c                 (   d }t          |                                          D ]m\  }}| j        |                                                             |           |dk    r|                                }|| j        |                                <   nd S )Nr   )	enumerater   rD   rV   appendrF   )r   rS   primary_tagindexrJ   s        r   rR   z4PluginManager._update_registry_and_expand_tag_groupsJ  s    #K$4$4$6$677 	7 	7JE3M#))++&--k:::zz!iikk+6DOCIIKK((		7 	7r   r	   )r(   r   r)   r*   r   rL   rP   rT   rI   rW   r_   ra   rR   r+   r   r   r@   r@      s        	 	     K K KA A A &  &  &  &D! ! ! A A A 0 0 07 7 7 7 7r   r@   c                    t                               d| j                   | t          | j        <   | j        t          v rt          | j                 D ]l}|j        r!t                               d|j                   n-t                               dt          |j                             |                     |           mt          | j        = dS dS )z(Reigister a newly created plugin managerzdeclare '%s' plugin managerzload cached plugin info: %sN)	logr;   rB   PLUG_IN_MANAGERSCACHED_PLUGIN_INFOr   r]   r   rT   )r   rS   s     r   rG   rG   S  s    II+S_===(+S_%
,,,-co> 	+ 	+K/ 			14   
 		1&{77   k****s/// -,r   c                    t                               | j                  }|r|                    ||            dS 	 t                              dt          |j                             n8# t          $ r+ t                              dt          |                     Y nw xY wt          | j                 
                    |            dS )z*module level function to register a pluginz
caching %sN)ri   r   r
   r_   rh   r;   r]   r(   AttributeErrorrj   rd   )rS   r^   managers      r   r&   r&   i  s    "";#:;;G H!!*k:::::	DIIl$6z7J$K$KLLLL 	D 	D 	DIIl$6z$B$BCCCCC	D;23::;GGGGGs   -A) )2BBc                    t                               | j                  }|r|                    |            dS t                              d| j        | j                   t          | j                                     |            dS )z- module level function to load a plugin laterzcaching %s for %sN)	ri   r   r
   rT   rh   r;   r   rj   rd   )rS   rm   s     r   r<   r<   w  s    "";#:;;G 	Hk***** 			,#	
 	
 	

 	;23::;GGGGGr   c                     	 | j         }|                    d          d         }|                    dd          S # t          $ r Y d S w xY w)Nr   r   _-)r   r   replacerl   )moduler   root_module_names      r   rX   rX     s`    '&,,S11!4''S111   tts   7: 
AAc                 j    	 | j         S # t          $ r t          t          |                     cY S w xY wr	   )r(   rl   strtype)cls_func_or_data_types    r   r]   r]     sH    0$-- 0 0 04-../////0s   	 &22)r*   r0   collectionsr   	lml.utilsr   r   ri   rC   rj   r1   r(   rh   objectr   r-   r@   rG   r&   r<   rX   r]   r+   r   r   <module>r|      sX   6  # # # # # # 1 1 1 1 1 1 1 1  [&& g!!a a a a a a a aH67 67 67 67 67f 67 67 67rL7 L7 L7 L7 L7F L7 L7 L7^0 0 0,H H HH H H  0 0 0 0 0r   