o
    i.                     @   s  U d Z ddlZddlmZ ddlmZmZmZmZm	Z	m
Z
 g dZeeZeeeeef f ed< eeZeeeeef f ed< e	dd	d
ZdedefddZde
deee f de
deee f fddZG dd	 d	Z			d(dededee de
ee edf def
ddZ	d)dedededefddZdedee fddZdedee fddZ	d*dedede
eee df fdd Zd!ed"edefd#d$Zded%efd&d'ZdS )+zn
Universal registry to support registration and loading of child classes and plugins
of neuralmagic utilities
    N)defaultdict)AnyDictListOptionalTypeVarUnion)RegistryMixinregisterget_from_registryregistered_namesregistered_aliasesstandardize_lookup_name_ALIAS_REGISTRY	_REGISTRY r	   )boundnamereturnc                 C   s   |  dd dd S )aD  
    Standardize the given name for lookup in the registry.
    This will replace all underscores and spaces with hyphens and
    convert the name to lowercase.

    example:
    ```
    standardize_lookup_name("Foo_bar baz") == "foo-bar-baz"
    ```

    :param name: name to standardize
    :return: standardized name
    _- )replacelowerr    r   X/home/ubuntu/.local/lib/python3.10/site-packages/compressed_tensors/registry/registry.pyr   (   s   r   c                 C   s,   | d u rd S t | trt| S dd | D S )Nc                 S   s   g | ]}t |qS r   )r   ).0nr   r   r   
<listcomp>A   s    z*standardize_alias_name.<locals>.<listcomp>)
isinstancestrr   r   r   r   r   standardize_alias_name9   s
   
r"   c                   @   s   e Zd ZU dZdZeed< e	ddee	 de
ee	 e	df fddZe	dd	ede	de
e	ee	 df fd
dZedee de	defddZedee de	defddZedee	 fddZedee	 fddZdS )r	   a  
    Universal registry to support registration and loading of child classes and plugins
    of neuralmagic utilities.

    Classes that require a registry or plugins may add the `RegistryMixin` and use
    `register` and `load` as the main entrypoints for adding new implementations and
    loading requested values from its registry.

    If a class should only have its child classes in its registry, the class should
    set the static attribute `registry_requires_subclass` to True

    example
    ```python
    class Dataset(RegistryMixin):
        pass


    # register with default name
    @Dataset.register()
    class ImageNetDataset(Dataset):
        pass

    # load as "ImageNetDataset"
    imagenet = Dataset.load("ImageNetDataset")

    # register with custom name
    @Dataset.register(name="cifar-dataset")
    class Cifar(Dataset):
        pass

    Note: the name will be standardized for lookup in the registry.
    For example, if a class is registered as "cifar_dataset" or
    "cifar dataset", it will be stored as "cifar-dataset". The user
    will be able to load the class with any of the three name variants.

    # register with multiple aliases
    @Dataset.register(alias=["cifar-10-dataset", "cifar_100_dataset"])
    class Cifar(Dataset):
        pass

    # load as "cifar-dataset"
    cifar = Dataset.load_from_registry("cifar-dataset")

    # load from custom file that implements a dataset
    mnist = Dataset.load_from_registry("/path/to/mnnist_dataset.py:MnistDataset")
    ```
    Fregistry_requires_subclassNr   aliasc                    s   dt f fdd}|S )a  
        Decorator for registering a value (ie class or function) wrapped by this
        decorator to the base class (class that .register is called from)

        :param name: name or list of names to register the wrapped value as,
            defaults to value.__name__
        :param alias: alias or list of aliases to register the wrapped value as,
            defaults to None
        :return: register decorator
        valuec                    s   j |  d | S )N)r   r$   )register_value)r%   r$   clsr   r   r   	decorator   s   z)RegistryMixin.register.<locals>.decorator)r   )r(   r   r$   r)   r   r'   r   r
   y   s   zRegistryMixin.registerr%   c                 C   s   t | |||| jd dS )aR  
        Registers the given value to the class `.register_value` is called from
        :param value: value to register
        :param name: name to register the wrapped value as,
            defaults to value.__name__
        :param alias: alias or list of aliases to register the wrapped value as,
            defaults to None
        )parent_classr%   r   r$   require_subclassN)r
   r#   )r(   r%   r   r$   r   r   r   r&      s   
zRegistryMixin.register_valuer(   r   c                 K   s   | j |d}|di |S )an  
        :param name: name of registered class to load
        :param constructor_kwargs: arguments to pass to the constructor retrieved
            from the registry
        :return: loaded object registered to this class under the given name,
            constructed with the given kwargs. Raises error if the name is
            not found in the registry
        r   Nr   )get_value_from_registry)r(   r   constructor_kwargsconstructorr   r   r   load_from_registry   s   
z RegistryMixin.load_from_registryc                 C   s   t | || jdS )z
        :param name: name to retrieve from the registry
        :return: value from retrieved the registry for the given name, raises
            error if not found
        )r*   r   r+   )r   r#   )r(   r   r   r   r   r,      s
   z%RegistryMixin.get_value_from_registryc                 C      t | S )zE
        :return: list of all names registered to this class
        )r   r(   r   r   r   r         zRegistryMixin.registered_namesc                 C   r0   )zG
        :return: list of all aliases registered to this class
        )r   r1   r   r   r   r      r2   z RegistryMixin.registered_aliases)NNN)__name__
__module____qualname____doc__r#   bool__annotations__classmethodr   r!   r   r   r
   r   r&   typeTr/   r,   r   r   r   r   r   r   r	   D   s6   
 2Fr*   r%   r$   r+   c              	   C   s   |du r|j }t|}t|}t||| d |rt| | |t|  v r?t|  | }||ur=td| d| d| d| dS |t|  |< dS )a  
    :param parent_class: class to register the name under
    :param value: the value to register
    :param name: name to register the wrapped value as, defaults to value.__name__
    :param alias: alias or list of aliases to register the wrapped value as,
        defaults to None
    :param require_subclass: require that value is a subclass of the class this
        method is called from
    N)r   r$   r*   zAttempting to register name  as 	 however   has already been registered as )r4   r   r"   register_alias_validate_subclassr   RuntimeError)r*   r%   r   r$   r+   registered_valuer   r   r   r
      s&   
r
   c                 C   s   t |}d|v r|d\}}t||}n-t|  ||}t|  |}|du rBtd| d|  d|  dt|  d|  dt|  |rIt	| | |S )aZ  
    :param parent_class: class that the name is registered under
    :param name: name to retrieve from the registry of the class
    :param require_subclass: require that value is a subclass of the class this
        method is called from
    :return: value from retrieved the registry for the given name, raises
        error if not found
    :NzUnable to find z registered under type z.
Registered values for z: z
Registered aliases for )
r   split!_import_and_get_value_from_moduler   getr   KeyErrorr   r   rA   )r*   r   r+   module_path
value_nameretrieved_valuer   r   r   r      s*   
r   c                 C   s   t t|   S )zt
    :param parent_class: class to look up the registry of
    :return: all names registered to the given class
    )listr   keys)r*   r   r   r   r     s   r   c                 C   s,   t t|   }t t|tt|  }|S )zv
    :param parent_class: class to look up the registry of
    :return: all aliases registered to the given class
    )rL   r   rM   setr   )r*   registered_aliases_plus_namesr   r   r   r   r      s
   r   c                 C   s   |durt |tr|n|g}ng }| |v r td|  d|  d||  |D ] }|t| v rAtd| d|  d| dt|  | t| |< q'dS )aX  
    Updates the mapping from the alias(es) to the given name.
    If the alias is None, the name is used as the alias.
    ```

    :param name: name that the alias refers to
    :param parent_class: class that the name is registered under
    :param alias: single alias or list of aliases that
        refer to the name, defaults to None
    NzAttempting to register alias z., that is identical to the standardized name: .r=   r>   r?   )r    rL   rH   appendr   )r   r*   r$   
alias_namer   r   r   r@   ,  s*   
r@   rI   rJ   c                 C   sT   t jd| | }t j|}|j| t||d }|s(td| d|  |S )Nplugin_module_for_zUnable to find attribute z in module )	importlibutilspec_from_file_locationmodule_from_specloaderexec_modulegetattrrB   )rI   rJ   specmoduler%   r   r   r   rF   O  s   
rF   child_classc                 C   s$   t || std| d|  dd S )Nzclass z6 is not a subclass of the class it is registered for: rP   )
issubclass
ValueError)r*   r]   r   r   r   rA   d  s   
rA   )NNF)Fr3   )r7   rT   collectionsr   typingr   r   r   r   r   r   __all__dictr   r;   r!   r9   r   r<   r   r"   r	   r8   r
   r   r   r   r@   rF   rA   r   r   r   r   <module>   sh     
 
 
)
%
#