U
    Ph?                     @  s   d dl mZ d dlZd dlZd dlZd dlZd dlmZmZ d dl	m
Z
mZ d dlmZ d dlm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mZ d
ddddgZG dd deZG dd
 d
ZG dd dZG dd deeZ G dd deZ!dS )    )annotationsN)ABCabstractmethod)MappingSequence)import_module)pformat)Any)EXPR_KEY)CompInitModeensure_tuplefirstinstantiateoptional_import	run_debugrun_evalComponentLocator
ConfigItemConfigExpressionConfigComponentInstantiablec                   @  s<   e Zd ZdZeddddddZedddddd	Zd
S )r   z0
    Base class for an instantiable object.
    r	   bool)argskwargsreturnc                 O  s   t d| jj ddS )z^
        Return a boolean flag to indicate whether the object should be instantiated.
        	subclass  must implement this method.NNotImplementedError	__class____name__selfr   r    r#   M/home/dell461/cl/sdc2/HISourceFinder-master-l/src/monai/bundle/config_item.pyis_disabled#   s    zInstantiable.is_disabledobjectc                 O  s   t d| jj ddS )zK
        Instantiate the target component and return the instance.
        r   r   Nr   r!   r#   r#   r$   r   *   s    zInstantiable.instantiateN)r    
__module____qualname____doc__r   r%   r   r#   r#   r#   r$   r      s
   c                   @  sR   e Zd ZdZdZdddddZdd	d
dZdddddZdddddZdS )r   a7  
    Scan all the available classes and functions in the MONAI package and map them with the module paths in a table.
    It's used to locate the module path for provided component name.

    Args:
        excludes: if any string of the `excludes` exists in the full module name, don't import this module.

    monaiNSequence[str] | str | Noneexcludesc                 C  s    |d krg nt || _d | _d S N)r   r-   _components_table)r"   r-   r#   r#   r$   __init__>   s    zComponentLocator.__init__z	list[str]r   c                   s    fddt jD S )za
        Find all the modules start with MOD_START and don't contain any of `excludes`.

        c                   s4   g | ],   jrt fd djD r qS )c                 3  s   | ]}| kV  qd S r.   r#   ).0smr#   r$   	<genexpr>G   s     zAComponentLocator._find_module_names.<locals>.<listcomp>.<genexpr>)
startswith	MOD_STARTallr-   )r2   r"   r4   r$   
<listcomp>G   s       z7ComponentLocator._find_module_names.<locals>.<listcomp>)sysmodulesr:   r#   r:   r$   _find_module_namesB   s    z#ComponentLocator._find_module_nameszSequence[str] | strzdict[str, list])modnamesr   c              	   C  s   i }t |D ]v}z\t|}t|D ]D\}}t|s@t|r$|j|kr$||krZg ||< || | q$W q tk
r   Y qX q|S )z
        Find all the classes and functions in the modules with specified `modnames`.

        Args:
            modnames: names of the target modules to find all the classes and functions.

        )	r   r   inspect
getmembersisclass
isfunctionr'   appendModuleNotFoundError)r"   r?   tablemodnamemodulenameobjr#   r#   r$   _find_classes_or_functionsI   s    z+ComponentLocator._find_classes_or_functionsstrzlist[str] | str | None)rI   r   c                 C  sb   t |tstd| d| jdkr4| |  | _| j|}t |tr^t|dkr^|d }|S )a  
        Get the full module name of the class or function with specified ``name``.
        If target component name exists in multiple packages or modules, return a list of full module names.

        Args:
            name: name of the expected class or function.

        z(`name` must be a valid string, but got: .N   r   )	
isinstancerL   
ValueErrorr/   rK   r>   getlistlen)r"   rI   modsr#   r#   r$   get_component_module_name`   s    	

z*ComponentLocator.get_component_module_name)N)	r    r'   r(   r)   r8   r0   r>   rK   rU   r#   r#   r#   r$   r   2   s   	c                   @  sX   e Zd ZdZdddddddZdd	d
dZdddddZdd Zdd	ddZdS )r   a  
    Basic data structure to represent a configuration item.

    A `ConfigItem` instance can optionally have a string id, so that other items can refer to it.
    It has a build-in `config` property to store the configuration object.

    Args:
        config: content of a config item, can be objects of any types,
            a configuration resolver may interpret the content to generate a configuration object.
        id: name of the current config item, defaults to empty string.

     r	   rL   None)configidr   c                 C  s   || _ || _d S r.   rX   rY   )r"   rX   rY   r#   r#   r$   r0      s    zConfigItem.__init__r1   c                 C  s   | j S )zj
        Get the ID name of current config item, useful to identify config items during parsing.

        )rY   r:   r#   r#   r$   get_id   s    zConfigItem.get_idrX   r   c                 C  s
   || _ dS )z
        Replace the content of `self.config` with new `config`.
        A typical usage is to modify the initial config content at runtime.

        Args:
            config: content of a `ConfigItem`.

        NrX   )r"   rX   r#   r#   r$   update_config   s    	zConfigItem.update_configc                 C  s   | j S )zA
        Get the config content of current config item.

        r]   r:   r#   r#   r$   
get_config   s    zConfigItem.get_configc                 C  s   t | j dt| j S )Nz: 
)typer    r   rX   r:   r#   r#   r$   __repr__   s    zConfigItem.__repr__N)rV   )	r    r'   r(   r)   r0   r[   r^   r_   ra   r#   r#   r#   r$   r   u   s   c                      s   e Zd ZdZdddddhZd d	d
dddd fddZed	ddddZdd Zdd Z	ddddZ
d	ddddZ  ZS )!r   a
  
    Subclass of :py:class:`monai.bundle.ConfigItem`, this class uses a dictionary with string keys to
    represent a component of `class` or `function` and supports instantiation.

    Currently, three special keys (strings surrounded by ``_``) are defined and interpreted beyond the regular literals:

        - class or function identifier of the python module, specified by ``"_target_"``,
          indicating a monai built-in Python class or function such as ``"LoadImageDict"``,
          or a full module name, e.g. ``"monai.transforms.LoadImageDict"``, or a callable, e.g. ``"$@model.forward"``.
        - ``"_requires_"`` (optional): specifies reference IDs (string starts with ``"@"``) or ``ConfigExpression``
          of the dependencies for this ``ConfigComponent`` object. These dependencies will be
          evaluated/instantiated before this object is instantiated.  It is useful when the
          component doesn't explicitly depend on the other `ConfigItems` via its arguments,
          but requires the dependencies to be instantiated/evaluated beforehand.
        - ``"_disabled_"`` (optional): a flag to indicate whether to skip the instantiation.
        - ``"_desc_"`` (optional): free text descriptions of the component for code readability.
        - ``"_mode_"`` (optional): operating mode for invoking the callable ``component`` defined by ``"_target_"``:

            - ``"default"``: returns ``component(**kwargs)``
            - ``"callable"``: returns ``component`` or, if ``kwargs`` are provided, ``functools.partial(component, **kwargs)``
            - ``"debug"``: returns ``pdb.runcall(component, **kwargs)``

    Other fields in the config content are input arguments to the python module.

    .. code-block:: python

        from monai.bundle import ComponentLocator, ConfigComponent

        locator = ComponentLocator(excludes=["modules_to_exclude"])
        config = {
            "_target_": "LoadImaged",
            "keys": ["image", "label"]
        }

        configer = ConfigComponent(config, id="test", locator=locator)
        image_loader = configer.instantiate()
        print(image_loader)  # <monai.transforms.io.dictionary.LoadImaged object at 0x7fba7ad1ee50>

    Args:
        config: content of a config item.
        id: name of the current config item, defaults to empty string.
        locator: a ``ComponentLocator`` to convert a module name string into the actual python module.
            if `None`, a ``ComponentLocator(excludes=excludes)`` will be used.
        excludes: if ``locator`` is None, create a new ``ComponentLocator`` with ``excludes``.
            See also: :py:class:`monai.bundle.ComponentLocator`.

    _target_
_disabled_Z
_requires_Z_desc__mode_rV   Nr	   rL   zComponentLocator | Noner+   rW   )rX   rY   locatorr-   r   c                   s,   t  j||d |d kr"t|dn|| _d S )NrZ   r,   )superr0   r   re   )r"   rX   rY   re   r-   r   r#   r$   r0      s    zConfigComponent.__init__r   r\   c                 C  s   t | tod| kS )z
        Check whether this config represents a `class` or `function` that is to be instantiated.

        Args:
            config: input config content to check.

        rb   )rO   r   r]   r#   r#   r$   is_instantiable   s    	zConfigComponent.is_instantiablec              	   C  s~   t |  }|d}t|ts$|S | j|}|dkr<|S t|trpt	d| d| d|d  d |d }| d| S )	z
        Resolve the target module name from current config content.
        The config content must have ``"_target_"`` key.

        rb   Nz+there are more than 1 component have name `z`: z, use the first one `r   zP. if want to use others, please set its full module path in `_target_` directly.rM   )
dictr_   rQ   rO   rL   re   rU   rR   warningswarn)r"   rX   targetrH   r#   r#   r$   resolve_module_name   s    


z#ConfigComponent.resolve_module_namec                   s    fdd    D S )zq
        Utility function used in `instantiate()` to resolve the arguments from current config content.

        c                   s    i | ]\}}| j kr||qS r#   )non_arg_keys)r2   kvr:   r#   r$   
<dictcomp>	  s     
  z0ConfigComponent.resolve_args.<locals>.<dictcomp>)r_   itemsr:   r#   r:   r$   resolve_args  s    zConfigComponent.resolve_argsr1   c                 C  s2   |   dd}t|tr*|  dkS t|S )zg
        Utility function used in `instantiate()` to check whether to skip the instantiation.

        rc   Ftrue)r_   rQ   rO   rL   lowerstripr   )r"   Z_is_disabledr#   r#   r$   r%     s    zConfigComponent.is_disabledr&   )r   r   c                 K  sT   |  |  r|  rdS |  }|  dtj}|  }|| t	||f|S )a  
        Instantiate component based on ``self.config`` content.
        The target component must be a `class` or a `function`, otherwise, return `None`.

        Args:
            kwargs: args to override / add the config args when instantiation.

        Nrd   )
rh   r_   r%   rm   rQ   r   DEFAULTrs   updater   )r"   r   rG   moder   r#   r#   r$   r     s    	
zConfigComponent.instantiate)rV   NN)r    r'   r(   r)   rn   r0   staticmethodrh   rm   rs   r%   r   __classcell__r#   r#   rg   r$   r      s   0   

c                      s   e Zd ZdZeZeZdddddd fd	d
ZdddddZdddddddZ	e
dddddZe
dddddZ  ZS )r   a  
    Subclass of :py:class:`monai.bundle.ConfigItem`, the `ConfigItem` represents an executable expression
    (execute based on ``eval()``, or import the module to the `globals` if it's an import statement).

    See also:

        - https://docs.python.org/3/library/functions.html#eval.

    For example:

    .. code-block:: python

        import monai
        from monai.bundle import ConfigExpression

        config = "$monai.__version__"
        expression = ConfigExpression(config, id="test", globals={"monai": monai})
        print(expression.evaluate())

    Args:
        config: content of a config item.
        id: name of current config item, defaults to empty string.
        globals: additional global context to evaluate the string.

    rV   Nr	   rL   zdict | NonerW   )rX   rY   globalsr   c                   s&   t  j||d |d k	r|ni | _d S )NrZ   )rf   r0   r|   )r"   rX   rY   r|   rg   r#   r$   r0   E  s    zConfigExpression.__init__z
Any | None)import_stringr   c                 C  s   t tt|}t|tjtjfs*dS t|jdk r<dS t|jdkr\t	
d| d |jd j |jd j }}|dkr|n| }t|tjrt|j | d\| j|< }| j| S t|tjrt| \| j|< }| j| S dS )zJparse single import statement such as "from monai.transforms import ResizeNrN   z ignoring multiple import alias 'z'.r   )rI   )r   astiter_child_nodesparserO   Import
ImportFromrS   namesrj   rk   rI   asnamer   rH   r|   )r"   r}   noderI   r   _r#   r#   r$   _parse_import_stringI  s     

z%ConfigExpression._parse_import_stringzstr | Any | None)r|   localsr   c           
   
   C  s(  |   }t|sdS | |t| jd }|dk	r:|S | jsT|t| jd  S t| j}|dk	r|	 D ]*\}}||krt
d| d |||< qntszt|t| jd ||W S  tk
r } ztd|  |W 5 d}~X Y nX t
d| d ddl}	|	|t| jd || dS )a  
        Execute the current config content and return the result if it is expression, based on Python `eval()`.
        For more details: https://docs.python.org/3/library/functions.html#eval.

        Args:
            globals: besides ``self.globals``, other global symbols used in the expression at runtime.
            locals: besides ``globals``, may also have some local symbols used in the expression at runtime.

        Nzthe new global variable `z-` conflicts with `self.globals`, override it.zFailed to evaluate z

pdb: value=zV
See also Debugger commands documentation: https://docs.python.org/3/library/pdb.html
r   )r_   r   is_expressionr   rS   prefixr   ri   r|   rr   rj   rk   r   eval	ExceptionRuntimeErrorpdbrun)
r"   r|   r   valueZoptional_moduleglobals_ro   rp   er   r#   r#   r$   evaluate\  s2    



"
zConfigExpression.evaluatezdict | list | strr   r\   c                 C  s   t |to|| jS )z
        Check whether the config is an executable expression string.
        Currently, a string starts with ``"$"`` character is interpreted as an expression.

        Args:
            config: input config content to check.

        )rO   rL   r7   r   clsrX   r#   r#   r$   r     s    
zConfigExpression.is_expressionc              	   C  sL   |  |sdS d|krdS tttt|t| jd  tjtj	fS )z
        Check whether the config is an import statement (a special case of expression).

        Args:
            config: input config content to check.
        FimportN)
r   rO   r   r~   r   r   rS   r   r   r   r   r#   r#   r$   is_import_statement  s    
" 
z$ConfigExpression.is_import_statement)rV   N)NN)r    r'   r(   r)   r
   r   r   r0   r   r   classmethodr   r   r{   r#   r#   rg   r$   r   '  s   &)"
__future__r   r~   r@   r<   rj   abcr   r   collections.abcr   r   	importlibr   pprintr   typingr	   monai.bundle.utilsr
   monai.utilsr   r   r   r   r   r   r   __all__r   r   r   r   r   r#   r#   r#   r$   <module>   s$   $C/ 