o $ ilA@sddlmZddlZddlZddlmZmZddlmZddl m Z m Z m Z ddl mZmZmZddlmZmZdgZGd ddZdS) ) annotationsN)IteratorSequence)Any)ConfigComponentConfigExpression ConfigItem)DEPRECATED_ID_MAPPING ID_REF_KEY ID_SEP_KEY)allow_missing_referencelook_up_optionReferenceResolverc@seZdZdZdZeZeZe ededZ e Z dCdDdd Z d d ZdEddZdFddZdGdHddZ dCdId!d"ZdJd#d$ZdKd&d'ZedLd)d*ZdMd,d-ZedGdNd0d1ZedOd3d4ZedPd7d8ZedQd;d<ZedCdRd>d?ZedCdSdAdBZdS)Tra Utility class to manage a set of ``ConfigItem`` and resolve the references between them. This class maintains a set of ``ConfigItem`` objects and their associated IDs. The IDs must be unique within this set. A string in ``ConfigItem`` starting with ``@`` will be treated as a reference to other ``ConfigItem`` objects by ID. Since ``ConfigItem`` may have a nested dictionary or list structure, the reference string may also contain the separator ``::`` to refer to a substructure by key indexing for a dictionary or integer indexing for a list. In this class, resolving references is essentially substitution of the reference strings with the corresponding python objects. A typical workflow of resolving references is as follows: - Add multiple ``ConfigItem`` objects to the ``ReferenceResolver`` by ``add_item()``. - Call ``get_resolved_content()`` to automatically resolve the references. This is done (recursively) by: - Convert the items to objects, for those do not have references to other items. - If it is instantiable, instantiate it and cache the class instance in ``resolved_content``. - If it is an expression, evaluate it and save the value in ``resolved_content``. - Substitute the reference strings with the corresponding objects. Args: items: ``ConfigItem``s to resolve, this could be added later with ``add_item()``. Z __local_refsz (?:\w*)(?:z\w*)*NitemsSequence[ConfigItem] | NonecCs&|durindd|D|_i|_dS)NcSsi|]}||qS)get_id).0irra/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/bundle/reference_resolver.py >sz.ReferenceResolver.__init__..rresolved_content)selfrrrr__init__<s zReferenceResolver.__init__cCsi|_i|_dS)zQ Clear all the added `ConfigItem` and all the resolved content. NrrrrrresetAs zReferenceResolver.resetreturnboolcCs t|jSN)rrrrrr is_resolvedIs zReferenceResolver.is_resolveditemrNonecCs$|}||jvr dS||j|<dS)zk Add a ``ConfigItem`` to the resolver. Args: item: a ``ConfigItem``. N)rr)rr!idrrradd_itemLs zReferenceResolver.add_itemFr#strresolvekwargsrConfigItem | NonecKs8||}|r||jvr|jdd|i||j|S)a Get the ``ConfigItem`` by id. If ``resolve=True``, the returned item will be resolved, that is, all the reference strings are substituted by the corresponding ``ConfigItem`` objects. Args: id: id of the expected config item. resolve: whether to resolve the item if it is not resolved, default to False. kwargs: keyword arguments to pass to ``_resolve_one_item()``. Currently support ``instantiate`` and ``eval_expr``. Both are defaulting to True. r#Nr) normalize_idr_resolve_one_itemrget)rr#r&r'rrrget_itemYs  zReferenceResolver.get_item waiting_listset[str] | None#ConfigExpression | str | Any | Nonec KsF||}||jvr|j|Szt||jd|ddd}Wnty3}z td|d|d}~wwt|ts;|S| }|durFt }| ||jD]$\}}||jvrtt|t rt| | rt|dd ro|n||j|<qP|j||d D]V} | |vrtd | d |d | |jvrz t| |jddWn%ty}zd| d} |jst| |t| WYd}~q~d}~ww|jd| |d||| q~|j|||jd} |j| dt|tr|dd r|n||j|<n%t|t r|dd } | r|j|j|jidn||j|<n| |j|<|j|S)aC Resolve and return one ``ConfigItem`` of ``id``, cache the resolved result in ``resolved_content``. If it has unresolved references, recursively resolve the referring items first. Args: id: id name of ``ConfigItem`` to be resolved. waiting_list: set of ids pending to be resolved. It's used to detect circular references such as: `{"name": "A", "dep": "@B"}` and `{"name": "B", "dep": "@A"}`. kwargs: keyword arguments to pass to ``_resolve_one_item()``. Currently support ``instantiate``, ``eval_expr`` and ``default``. `instantiate` and `eval_expr` are defaulting to True, `default` is the target config item if the `id` is not in the config content, must be a `ConfigItem` object. Fdefault no_default)print_all_optionsr0zid='z&' is not found in the config resolver.N eval_exprT)configr#zdetected circular references 'z ' for id='z' in the config content.)r2zthe referring item `@z'` is not defined in the config content.)r#r-)r4r#refs)r4 instantiate)globalsr)r)rr rr+ ValueErrorKeyError isinstancer get_configsetaddris_import_statementevaluatefind_refs_in_configkeysr warningswarnr*discardupdate_config_with_refs update_configrr6_vars) rr#r-r'r!errZ item_configtvdmsg new_configrun_evalrrrr*ksd                    z#ReferenceResolver._resolve_one_itemcKs|jdd|i|S)a Get the resolved ``ConfigItem`` by id. Args: id: id name of the expected item. kwargs: keyword arguments to pass to ``_resolve_one_item()``. Currently support ``instantiate``, ``eval_expr`` and ``default``. `instantiate` and `eval_expr` are defaulting to True, `default` is the target config item if the `id` is not in the config content, must be a `ConfigItem` object. r#Nr)r*)rr#r'rrrget_resolved_contents z&ReferenceResolver.get_resolved_content Any | NonecCs||jvr |j|SdS)zy Remove the resolved ``ConfigItem`` by id. Args: id: id name of the expected item. N)rpop)rr#rrrremove_resolved_contentsz)ReferenceResolver.remove_resolved_content str | intcCst|d|jS)z Normalize the id string to consistently use `cls.sep`. Args: id: id string to be normalized. #)r%replacesep)clsr#rrrr)szReferenceResolver.normalize_idr4cCsRt|tr'tD]\}}||vr&td|d|d||||<q |S)z Update deprecated identifiers in `config` using `DEPRECATED_ID_MAPPING`. This will replace names that are marked as deprecated with their replacement. Args: config: input config to be updated. zDetected deprecated name 'z)' in configuration file, replacing with 'z'.)r:dictr rrArBrCrQ)rr4_idZ_new_idrrrnormalize_meta_ids  z#ReferenceResolver.normalize_meta_idlast list[str]cCsD|s |||jS|||jd}d|dd|dgS)z Split the id string into a list of strings by `cls.sep`. Args: id: id string to be split. last: whether to split the rightmost part of the id. default is False (split all parts). N)r)splitrVrsplitjoin)rWr#r[resrrrsplit_ids zReferenceResolver.split_idIterator[tuple[str, str, Any]]ccsVt|tr |nt|D]\}}|dkr||j|n|}|||fVqdS)z Iterate over the sub-configs of the input config, the output `sub_id` uses `cls.sep` to denote substructure. Args: id: id string of the current input config. config: input config to be iterated. r^N)r:rXr enumeraterV)rWr#r4krJsub_idrrriter_subconfigss " z!ReferenceResolver.iter_subconfigsvaluedict[str, int]cCsdi}||}|j|}t|}|D]}|s||kr/|t|jd}||dd||<q|S)z Match regular expression for the input string to find the references. The reference string starts with ``"@"``, like: ``"@XXX::YYY::ZZZ"``. Args: value: input value to match regular expression. Nrr])r) id_matcherfindallr is_expressionlenrefr+)rWrjr5result value_is_exprr!r#rrrmatch_refs_patterns    z$ReferenceResolver.match_refs_patternr5rXcCs||}|j|}|jtddt|}|D]@}|s!||krY|t|jd}||vrAd|d}|js;t |t |q|rQ| ||j d|d}q||krY||}q|S)a Match regular expression for the input string to update content with the references. The reference part starts with ``"@"``, like: ``"@XXX::YYY::ZZZ"``. References dictionary must contain the referring IDs as keys. Args: value: input value to match regular expression. refs: all the referring components with ids as keys, default to `None`. T)keyreverseNzcan not find expected ID 'z' in the references.z['z'])r)rlrmsortrorrnrpr r9rBrCrUrG)rWrjr5rqrrr!Zref_idrLrrrupdate_refs_patterns&     z%ReferenceResolver.update_refs_patterndict[str, int] | Nonec Cs|pi}t|tr |j|dD]\}}||d|||<qt|ttfs)|S|||D]\}}}t |sBt |rF||vrFd||<| |||}q/|S)a7 Recursively search all the content of input config item to get the ids of references. References mean: the IDs of other config items (``"@XXX"`` in this config item), or the sub-item in the config is `instantiable`, or the sub-item in the config is `expression`. For `dict` and `list`, recursively check the sub-items. Args: config: input config content to search. id: ID name for the input config item. refs: dict of the ID name and count of found references, default to `None`. )rjrr]) r:r%rsrr+listrXriris_instantiablerrnr@) rWr4r#r5refs_count_rhrJrrrr@?s z%ReferenceResolver.find_refs_in_config dict | Nonec Cs|pi}t|tr|||St|ttfs|St|}|||D]6\}}}t|s2t |rA||} t|r@| dur@q#n| |||} t|trT| || in| | q#|S)aD With all the references in ``refs``, update the input config content with references and return the new config. Args: config: input config content to update. id: ID name for the input config. refs: all the referring content with ids, default to `None`. N)r:r%rwryrXtyperirrzrrnrEupdateappend) rWr4r#r5r{retidxrhrJupdatedrrrrEYs     z)ReferenceResolver.update_config_with_refsr)rr)rr)r!rrr")F)r#r%r&rr'rrr()r#r%r-r.r'rrr/)r#r%r'rrr/)r#r%rrP)r#rSrr%)r4rrr)r#rSr[rrr\)r#r%r4rrre)rjr%rrk)rjr%r5rXrr%)r4rr#r%r5rxrrk)r4rr#r%r5r~rr)__name__ __module__ __qualname____doc__rGr rVr rprecompilerlr rrr r$r,r*rOrR classmethodr)rZrdrirsrwr@rErrrrrs>     J      %) __future__rrrBcollections.abcrrtypingrmonai.bundle.config_itemrrrmonai.bundle.utilsr r r monai.utilsr r __all__rrrrrs