o
    ?߱i"                  	   @   s4  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 d dl	m
Z
mZmZ d dlZd dlZd dlmZmZ d dlmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZ defddZdd Zd"dedee e!  dedefddZ"de!de!fddZ#d#de!defddZ$d$de!dededdfd d!Z%dS )%    N)fields)is_dataclass)AnyDictOptional)compose
initialize)ConfigStore)GlobalHydra)
DictConfig	OmegaConf)Config)logreturnc                 C   s   t | p
tt| S )z
    Check if the object is an instance of an attrs class or a dataclass.

    Args:
        obj: The object to check.

    Returns:
        bool: True if the object is an instance of an attrs class or a dataclass, False otherwise.
    )r   attrhastypeobj r   ]/data/cameron/vidgen/cosmos-predict2.5/cosmos_predict2/_src/imaginaire/utils/config_helper.pyis_attrs_or_dataclass$   s   
r   c                 C   sH   t | rdd t| D S tt| r dd tt| D S td)a4  
    Get the fields of an attrs class or a dataclass.

    Args:
        obj: The object to get fields from. Must be an instance of an attrs class or a dataclass.

    Returns:
        list: A list of field names.

    Raises:
        ValueError: If the object is neither an attrs class nor a dataclass.
    c                 S      g | ]}|j qS r   name.0fieldr   r   r   
<listcomp>?       zget_fields.<locals>.<listcomp>c                 S   r   r   r   r   r   r   r   r   A   r   z5The object is neither an attrs class nor a dataclass.)r   dataclass_fieldsr   r   r   r   
ValueErrorr   r   r   r   
get_fields1   s
   r"   Fconfig	overridesremove_defaultsc                    s  dd }t j| |r|ndd}t|ddid}|r1|d d	kr+td
| d|d  |dd }t }|jd|d t  sbt	dd t
d|d}t| W d   n1 s\w   Y  nt
d|d}t| dtdtdtf fdd  | |} | S )z
    :param config: the instance of class `Config` (usually from `make_config`)
    :param overrides: list of overrides for config
    :return: the composed instance of class `Config`
    c                 S   s
   | j dkS )Ndefaultsr   )f_r   r   r   remove_defaults_filterO   s   
z(override.<locals>.remove_defaults_filterN)filterallow_objectsT)contentflagsr   z--zNHydra config overrides must be separated with a "--" token. but got overrides=z, and overrides[0]=   r#   )r   node)Zversion_base)config_namer$   ref_instancekwargsr   c           
         s  t | }|s|S tt| }t|tst|tsJ dt| }|| }||ksD||sDJ d| d| d| dt|  d| 
i }|D ]} t	| ||| ||< qHzt| d	i |}W |S  t
y }	 ztdt|  d|  t|	 |	d}	~	ww )
a  
        Construct an instance of the same type as ref_instance using the provided dictionary or data or unstructured data

        Args:
            ref_instance: The reference instance to determine the type and fields when needed
            kwargs: A dictionary of keyword arguments to use for constructing the new instance or primitive data or unstructured data

        Returns:
            Any: A new instance of the same type as ref_instance constructed using the provided kwargs or the primitive data or unstructured data

        Raises:
            AssertionError: If the fields do not match or if extra keys are found.
            Exception: If there is an error constructing the new instance.
        z+kwargs must be a dictionary or a DictConfigzFields mismatch: z != z. Extra keys found: z 
 	 when constructing z with zError when constructing Nr   )r   setr"   
isinstancedictr   keysissubsetr   getattr	Exceptionr   error)
r1   r2   is_typeZ
ref_fieldsr6   
extra_keysZresolved_kwargsr'   new_instanceeconfig_from_dictr   r   r@   g   s0   $
z"override.<locals>.config_from_dict)attrsasdictr   r!   r	   instancestorer
   is_initializedr   r   r   resolver   )r#   r$   r%   r)   config_dictconfig_omegaconfcsr   r?   r   overrideF   s,   	


*rJ   config_filec                 C   sV   |  dstd td | dddd}tj|d u r)td| d|S )	Nz.pyz*Config file cannot be specified as module.zUPlease provide the path to the Python config file (relative to the Imaginaire4 root)./. zImaginaire4 config module (z) not found.)endswithr   r:   replace	importlibutil	find_specr!   )rK   config_moduler   r   r   get_config_module   s   


rU   full_module_namereloadc                 C   s0   | t jv r|rtt j|   dS t|  dS )z
    Import a module by name.

    Args:
        full_module_name: The fully qualified name of the module to import.
        reload: If True, reload the module if it's already imported.
    N)sysmodulesrQ   rW   import_module)rV   rW   r   r   r   rZ      s   rZ   Tpackage_pathskip_underscorec                    sb   t rdnd d|   t| }|j}dtdtddf fdd	 |D ]} ||  q'dS )
a  
    Import all modules from the specified package path recursively.

    This function is typically used in conjunction with Hydra to ensure that all modules
    within a specified package are imported, which is necessary for registering configurations.

    Example usage:
    ```python
    import_all_modules_from_package("projects.cosmos.diffusion.v1.config.experiment", reload=True, skip_underscore=False)
    ```

    Args:
        package_path (str): The dotted path to the package from which to import all modules.
        reload (bool): Flag to determine whether to reload modules if they're already imported.
        skip_underscore (bool): If True, skips importing modules that start with an underscore.
    	Reloading	Importingz all modules from package 	directoryprefixr   Nc                    s   t | gD ]?\}}}r|drtd| d q| d| }tr)dnd d|  t|d |rEtj| |} || qd	S )
a  
        Recursively imports or reloads all modules in the given directory.

        Args:
            directory (str): The file system path to the current package directory.
            prefix (str): The module prefix (e.g., 'projects.cosmos.diffusion.v1.config').
        r(   zSkipping module z  as it starts with an underscorerM   r]   r^   z module )rW   N)	pkgutiliter_modules
startswithr   debugrZ   ospathjoin)r_   r`   r(   module_nameis_pkgrV   Zsub_package_directoryimport_modules_recursivelyrW   r\   r   r   rk      s   
zCimport_all_modules_from_package.<locals>.import_modules_recursively)r   criticalrQ   rZ   __path__str)r[   rW   r\   packageZpackage_directoryr_   r   rj   r   import_all_modules_from_package   s   
rp   )NF)F)FT)&rQ   importlib.utilre   ra   rX   dataclassesr   r    r   typingr   r   r   r   rA   hydrar   r   Zhydra.core.config_storer	   Zhydra.core.global_hydrar
   	omegaconfr   r   &cosmos_predict2._src.imaginaire.configr   %cosmos_predict2._src.imaginaire.utilsr   boolr   r"   listrn   rJ   rU   rZ   rp   r   r   r   r   <module>   s,   $P 