o
    8wiZ                     @   s  d dl Z d dlZd dlZd dlmZ d dlmZmZmZ d dl	m
Z
 d dl mZ d dlmZmZmZmZ d dlmZ d dlmZmZ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! G dd deZ"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edeeef defddZ)dedeeef de*e*e e+e,ef f fddZ-dedeeef de+e,ef fddZ.de#de&ddfd d!Z/dd"d#ed$ed%ee0 d&edef
d'd(Z1dFd)ed*ee, defd+d,Z2d-ed.e"defd/d0Z3e
dFd1e0d*ee, ded2 fd3d4Z4d5e,d6ed$e*ed7f d&e+e,ef d8e+e,ef d9e*e,d7f de*e$e*ed7f e+e,ef f fd:d;Z5de#d<e&ddfd=d>Z6d?e&de&fd@dAZ7de&fdBdCZ8G dDdE dEe+Z9dS )G    N)OrderedDict)	GeneratorIterableSized)contextmanager)partial)AnyCallableOptionalUnion)get_all_subclasses)BatchSampler
DataLoaderIterableDatasetSampler)	TypeGuard)LightningEnum)MisconfigurationException)rank_zero_warn)pl_worker_init_functionc                   @   s&   e Zd ZdZdZdeddfddZdS )_WrapAttrTagsetdelargsreturnNc                 G   s   | | j krtnt}|| S N)SETsetattrdelattr)selfr   fn r!   \/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/lightning_fabric/utilities/data.py__call__&   s   z_WrapAttrTag.__call__)__name__
__module____qualname__r   DELr   r#   r!   r!   r!   r"   r   "   s    r   
dataloaderr   c                 C   s   t | do
t| jtS )Ndataset)hasattr
isinstancer)   r   )r(   r!   r!   r"   has_iterable_dataset,   s   r,   c              	   C   s,   zt | }W |S  ttfy   d}Y |S w )z>Try to get the length of an object, return ``None`` otherwise.N)len	TypeErrorNotImplementedErrorr(   lengthr!   r!   r"   	sized_len0   s   
r2   c                 C   sD   t | }|dkrtd| jj d |durt| rtd |duS )z<Checks if a given object has ``__len__`` method implemented.r   `z>` returned 0 length. Please make sure this was your intention.NzYour `IterableDataset` has `__len__` defined. In combination with multi-process data loading (when num_workers > 1), `__len__` could be inaccurate if each worker is not configured independently to avoid having duplicate data.)r2   r   	__class__r$   r,   r0   r!   r!   r"   has_len:   s   r5   samplerc                 C   s$   t | |\}}t| g|R i |S r   )$_get_dataloader_init_args_and_kwargs_reinstantiate_wrapped_cls)r(   r6   dl_args	dl_kwargsr!   r!   r"   _update_dataloaderK   s   r;   c              
      s  t | tstd|  dt| d}|r!| j}| j| j | j}ndd t| 	 D d }| j
d< d tt| jj}tdd	 | D }|ro|r_|d
d ttjj	 D  n|ttjj |dd  |sfdd|	 D d fdd	 D d}d|}t |trd d< d d< nt| |  fdd| D }|rt|}	| jj}
ddd	 |	D }td|
 d|	 d|
 d| d	|stt B |  }|rt|}| jj}
td|
 d| d|
 d|fS )NzThe dataloader z0 needs to subclass `torch.utils.data.DataLoader`__pl_saved_argsc                 S   s    i | ]\}}| d s||qS )_)
startswith.0kvr!   r!   r"   
<dictcomp>_   s     z8_get_dataloader_init_args_and_kwargs.<locals>.<dictcomp>multiprocessing_contextr!   c                 s   s    | ]	}|j |ju V  qd S r   )kindVAR_KEYWORDr@   pr!   r!   r"   	<genexpr>i       z7_get_dataloader_init_args_and_kwargs.<locals>.<genexpr>c                 S   s"   i | ]\}}|j |jur||qS r!   )defaultemptyr?   r!   r!   r"   rC   p   s    r   c                    s*   h | ]\}}| v r|j  | ur|qS r!   )rK   )r@   namerH   )attrsr!   r"   	<setcomp>y   s   * z7_get_dataloader_init_args_and_kwargs.<locals>.<setcomp>r)   c                    s   i | ]\}}| v r||qS r!   r!   r?   )non_defaultsr!   r"   rC   ~   s    batch_samplerr6   c                    sD   h | ]}|j |j|jfv r |j|ju r |jvr |j vr|jqS r!   )rE   POSITIONAL_ONLYPOSITIONAL_OR_KEYWORDrK   rL   rM   rG   )	arg_namesr:   r!   r"   rO      s    

z, c                 s   s    | ]	}d | dV  qdS )z`self.r3   Nr!   )r@   arg_namer!   r!   r"   rI      rJ   z,Trying to inject custom `Sampler` into the `z` instance. This would fail as some of the `__init__` arguments are not available as instance attributes. The missing attributes are z. If you instantiate your `zZ` inside a `*_dataloader` hook of your module, we will do this for you. Otherwise, define z inside your `__init__`.z&Trying to inject parameters into the `z{` instance. This would fail as it doesn't expose all its attributes in the `__init__` signature. The missing arguments are z. HINT: If you wrote the `zA` class, add the `__init__` arguments or allow passing `**kwargs`) r+   r   
ValueErrorr*   r<   __pl_saved_kwargs__pl_saved_arg_names	__datasetvarsitemsrD   dictinspect	signature__init__
parametersanyvaluesupdatepopaddgetr   '_dataloader_init_kwargs_resolve_samplersortedr4   r$   joinr   r   keysr.   )r(   r6   was_wrappedr9   original_datasetparamshas_variadic_kwargsr)   required_argssorted_required_argsdataloader_cls_namemissing_args_messagemissing_kwargssorted_missing_kwargsr!   )rT   rN   r:   rP   r"   r7   P   sx   







	r7   c              
   C   s  t | d}|durt|turt|}t|drG|j}|j}|j}|j}td|||||\}}}|s;t	d|j
 dt|g|R i |}n:t|dr}t|dr}z|||j|jd	}W n$ t	y| }	 zd
dl}
|
dt|	}|ss t	d|	d}	~	ww t	ddd|dddS |dddS )zThis function is used to handle the sampler, batch_sampler arguments associated within a DataLoader for its re-
    instantiation.rQ   Nr<   r6   zYTrying to inject a modified sampler into the batch sampler; however, it seems the class `z` does not have an argument called `sampler.` To mitigate this, expose an argument `sampler` in the `__init__` method of your custom class.
batch_size	drop_last)ru   rv   r   z:.*__init__\(\) (got multiple values)|(missing \d required)ak   Lightning can't inject a (distributed) sampler into your batch sampler, because it doesn't subclass PyTorch's `BatchSampler`. To mitigate this, either follow the API of `BatchSampler` or set`.setup_dataloaders(..., use_distributed_sampler=False)`. If you choose the latter, you will be responsible for handling the distributed sampling within your batch sampler.F   )r6   shufflerQ   ru   rv   )r6   rx   rQ   )getattrtyper   r*   r<   rW   __pl_saved_default_kwargsrX   _replace_value_in_saved_argsr.   r&   r8   ru   rv   rematchstr)r(   r6   rQ   batch_sampler_clsr   kwargsdefault_kwargsrT   successexr}   r~   r!   r!   r"   rg      s^   



rg   rankc                 C   sD   t | dsd S ttjddr| jd u r tt|d| _d S d S d S )Nworker_init_fnPL_SEED_WORKERSr   )r   )r*   intosenvironrf   r   r   r   )r(   r   r!   r!   r"   _auto_add_worker_init_fn   s
   
r   )explicit_clsorig_objectr   r   r   c                O   s   |d u rt | n|}z	||i |}W n6 tyI } z*dd l}|dt|}|s* | d }	d|j d|	 d|	 d|	 d	}
t|
|d }~ww t| dg }|D ]\}}||g|R   qR|S )	Nr   z-.*__init__\(\) got multiple values .* '(\w+)'zThe zd implementation has an error where more than one `__init__` argument can be passed to its parent's `zr=...` `__init__` argument. This is likely caused by allowing passing both a custom argument that will map to the `zc` argument as well as `**kwargs`. `kwargs` should be filtered to make sure they don't contain the `zR` key. This argument was automatically passed to your object by PyTorch Lightning.__pl_attrs_record)	rz   r.   r}   r~   r   groupsr$   r   ry   )r   r   r   r   constructorresultr   r}   r~   argumentmessageattrs_recordr    r!   r!   r"   r8      s0   

r8   initstore_explicit_argc              	      s.   t  dtdtdtddf fdd}|S )zWraps the ``__init__`` method of classes (currently :class:`~torch.utils.data.DataLoader` and
    :class:`~torch.utils.data.BatchSampler`) in order to enable re-instantiation of custom subclasses.objr   r   r   Nc                    s"  t | dd}t| dd tj}tdd | D }t|d t	|  fdd|
 D }t| dsUt| d| t| d	  t| d
 t| d| d ur}v rmt| d |  n v r}t| d    | g|R i   t| d| d S )N__pl_inside_initFTc                 s   s8    | ]}|j d kr|j|j|jfvr|j |jfV  qdS )r   N)rM   rE   VAR_POSITIONALrF   rK   )r@   paramr!   r!   r"   rI   (  s    
z5_wrap_init_method.<locals>.wrapper.<locals>.<genexpr>c                    s2   i | ]\}}| vr|vr|t jjkr||qS r!   )r]   	ParameterrL   )r@   rM   valuer   param_namesr!   r"   rC   0  s
    z6_wrap_init_method.<locals>.wrapper.<locals>.<dictcomp>r<   rW   rX   r{   __)ry   object__setattr__r]   r^   r`   r   rb   tupler-   r[   r*   index)r   r   r   old_inside_initrm   parameters_defaultsr   r   r   r   r"   wrapper   s,   
 z"_wrap_init_method.<locals>.wrapper	functoolswrapsr   )r   r   r   r!   r   r"   _wrap_init_method  s   "'r   methodtagc                    s*   t  dtdtddf fdd}|S )zWraps the ``__setattr__`` or ``__delattr__`` method of classes (currently :class:`~torch.utils.data.DataLoader`
    and :class:`~torch.utils.data.BatchSampler`) in order to enable re- instantiation of custom subclasses.r   r   r   Nc                    s   |^}}t | dd\}}||ko|k }t| d|f  | g|R   |rBt | ddsBt | dg }||f t| d| t| d||f d S )N__pl_current_call)Nr   r   Tr   )ry   r   r   append)r   r   rM   r=   prev_call_nameprev_call_method
first_callr   r   r   r!   r"   r   O  s   z"_wrap_attr_method.<locals>.wrapperr   )r   r   r   r!   r   r"   _wrap_attr_methodK  s   r   base_cls)NNNc              	   c   s    t | | hB }|D ]D}d|jv r|j|_t|j||_dtjfdtjffD ]'\}}||jv s3|| u rMd| }t||t	|| t||t
t	||| q&q
dV  |D ]#}dD ]}d| |jv rvt||t	|d|  t|d|  qXqTdS )zThis context manager is used to add support for re-instantiation of custom (subclasses) of `base_cls`.

    It patches the ``__init__``, ``__setattr__`` and ``__delattr__`` methods.

    r_   r   __delattr____oldN)r   r   r_   )r   __dict__r_   __old__init__r   r   r   r'   r   ry   r   r   )r   r   classesclspatch_fn_namer   
saved_namepatched_namer!   r!   r"   _replace_dunder_methodsf  s,   

r   replace_keyreplace_value.r   rT   c                 C   sj   | |v r| | }|d| |f ||d d  }d||fS | |v s'| |v r0||| < d||fS d||fS )zTries to replace an argument value in a saved list of args and kwargs.

    Returns a tuple indicating success of the operation and modified saved args and kwargs

    Nrw   TF)r   )r   r   r   r   r   rT   replace_indexr!   r!   r"   r|     s   
"


r|   epochc                 C   s   i }t | dd }dur||t|< t | dd }dur,t |dd }dur,||t|< | D ]}t |dd}t|r@|| q0dS )a  Calls the ``set_epoch`` method on either the sampler of the given dataloader.

    Every PyTorch dataloader has either a sampler or a batch sampler. If the sampler is wrapped by a
    :class:`~torch.utils.data.distributed.DistributedSampler`, ``set_epoch`` must be called at the beginning
    of every epoch to ensure shuffling applies a new ordering. This has no effect if shuffling is off.

    r6   NrQ   	set_epoch)ry   idrb   callable)r(   r   objectsr6   rQ   r   r   r!   r!   r"   _set_sampler_epoch  s   	r   local_world_sizec                 C   s0   | dk rt d|  dt }td||  d S )a  Suggests an upper bound of ``num_workers`` to use in a PyTorch :class:`~torch.utils.data.DataLoader` based on
    the number of CPU cores available on the system and the number of distributed processes in the current machine.

    Args:
        local_world_size: The number of distributed processes running on the current machine. Set this to the number
            of devices configured in Fabric/Trainer.

    rw   z'`local_world_size` should be >= 1, got .)rV   _num_cpus_availablemax)r   	cpu_countr!   r!   r"   suggested_max_num_workers  s   	r   c                  C   s0   t tdrttdS t } | d u rdS | S )Nsched_getaffinityr   rw   )r*   r   r-   r   r   )r   r!   r!   r"   r     s   
r   c                   @   sX   e Zd ZdZdedefddZdededdfdd	Zd
eddfddZdefddZ	dS )AttributeDicta  A container to store state variables of your program.

    This is a drop-in replacement for a Python dictionary, with the additional functionality to access and modify keys
    through attribute lookup for convenience.

    Use this to define the state of your program, then pass it to
    :meth:`~lightning_fabric.fabric.Fabric.save` and :meth:`~lightning_fabric.fabric.Fabric.load`.

    Example:
        >>> import torch
        >>> model = torch.nn.Linear(2, 2)
        >>> state = AttributeDict(model=model, iter_num=0)
        >>> state.model
        Linear(in_features=2, out_features=2, bias=True)
        >>> state.iter_num += 1
        >>> state.iter_num
        1
        >>> state
        "iter_num": 1
        "model":    Linear(in_features=2, out_features=2, bias=True)

    keyr   c              
   C   sB   z| | W S  t y  } ztdt| j d| d|d }~ww )N'z' object has no attribute ')KeyErrorAttributeErrorrz   r$   )r   r   er!   r!   r"   __getattr__  s   
zAttributeDict.__getattr__valNc                 C   s   || |< d S r   r!   )r   r   r   r!   r!   r"   r     s   zAttributeDict.__setattr__itemc                 C   s   || vrt || |= d S r   )r   )r   r   r!   r!   r"   r     s   
zAttributeDict.__delattr__c                    sX   t  sdS tdd  D }dt|d  d  fddt  D }d	|S )
N c                 s   s    | ]	}t t|V  qd S r   )r-   r   )r@   rA   r!   r!   r"   rI     rJ   z)AttributeDict.__repr__.<locals>.<genexpr>z{:   zs} {}c                    s$   g | ]} d | d | qS )"z":)format)r@   nr   tmp_namer!   r"   
<listcomp>  s   $ z*AttributeDict.__repr__.<locals>.<listcomp>
)r-   r   r   rh   rj   ri   )r   max_key_lengthrowsr!   r   r"   __repr__  s   
zAttributeDict.__repr__)
r$   r%   r&   __doc__r   r   r   r   r   r   r!   r!   r!   r"   r     s    r   r   ):r   r]   r   collectionsr   collections.abcr   r   r   
contextlibr   r   typingr   r	   r
   r   $lightning_utilities.core.inheritancer   torch.utils.datar   r   r   r   typing_extensionsr    lightning_fabric.utilities.enumsr   %lightning_fabric.utilities.exceptionsr   $lightning_fabric.utilities.rank_zeror   lightning_fabric.utilities.seedr   r   r   boolr,   r   r2   r5   r;   r   r\   r   r7   rg   r   rz   r8   r   r   r   r|   r   r   r   r   r!   r!   r!   r"   <module>   sv   



]


I(/"




