o
    Whj                     @   s   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 G dd de j	Z
edd ZdddZefddZefddZdd ZdddZdedd	fddZdS )    N)contextmanager)datetime)Pathc                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	WorkingDirectorya  
    A context manager and decorator for temporarily changing the working directory.

    This class allows for the temporary change of the working directory using a context manager or decorator.
    It ensures that the original working directory is restored after the context or decorated function completes.

    Attributes:
        dir (Path | str): The new directory to switch to.
        cwd (Path): The original current working directory before the switch.

    Methods:
        __enter__: Changes the current directory to the specified directory.
        __exit__: Restores the original working directory on context exit.

    Examples:
        Using as a context manager:
        >>> with WorkingDirectory('/path/to/new/dir'):
        >>> # Perform operations in the new directory
        >>>     pass

        Using as a decorator:
        >>> @WorkingDirectory('/path/to/new/dir')
        >>> def some_function():
        >>> # Perform operations in the new directory
        >>>     pass
    c                 C   s   || _ t  | _dS )zgSets the working directory to 'new_dir' upon instantiation for use with context managers or decorators.N)dirr   cwdresolve)selfnew_dir r   K/var/www/vscode/kcb/lib/python3.10/site-packages/ultralytics/utils/files.py__init__)   s   zWorkingDirectory.__init__c                 C      t | j dS )z[Changes the current working directory to the specified directory upon entering the context.N)oschdirr   )r	   r   r   r   	__enter__.      zWorkingDirectory.__enter__c                 C   r   )zARestores the original working directory when exiting the context.N)r   r   r   )r	   exc_typeexc_valexc_tbr   r   r   __exit__2   r   zWorkingDirectory.__exit__N)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r      s
    r   c                 c   s0   dt | v rt| t }t| } t u}t|| jdd }|  r+t	| | n| 
 r=|jjddd t| | z"|rDt |n|V  W | rUtj	|| dd n,|
 r_t||  n| rmtj	|| dd w |
 rxt||  w w W d   dS W d   dS 1 sw   Y  dS | V  dS )au  
    Context manager to handle paths with spaces in their names.

    If a path contains spaces, it replaces them with underscores, copies the file/directory to the new path, executes
    the context code block, then copies the file/directory back to its original location.

    Args:
        path (str | Path): The original path that may contain spaces.

    Yields:
        (Path | str): Temporary path with spaces replaced by underscores if spaces were present, otherwise the original path.

    Examples:
        >>> with spaces_in_path('/path/with spaces') as new_path:
        >>> # Your code here
        >>>     pass
     _Tparentsexist_ok)dirs_exist_okN)str
isinstancer   tempfileTemporaryDirectorynamereplaceis_dirshutilcopytreeis_fileparentmkdircopy2)pathstringtmp_dirtmp_pathr   r   r   spaces_in_path7   s8   

"
r2   F c                 C   s   t | } |  r:|s:|  r| d| jfn| df\} }tddD ]}|  | | | }tj|s5 nq!t |} |rC| jddd | S )ao  
    Increment a file or directory path, i.e., runs/exp --> runs/exp{sep}2, runs/exp{sep}3, ... etc.

    If the path exists and `exist_ok` is not True, the path will be incremented by appending a number and `sep` to
    the end of the path. If the path is a file, the file extension will be preserved. If the path is a directory, the
    number will be appended directly to the end of the path.

    Args:
        path (str | Path): Path to increment.
        exist_ok (bool): If True, the path will not be incremented and returned as-is.
        sep (str): Separator to use between the path and the incrementation number.
        mkdir (bool): Create a directory if it does not exist.

    Returns:
        (Path): Incremented path.

    Examples:
        Increment a directory path:
        >>> from pathlib import Path
        >>> path = Path("runs/exp")
        >>> new_path = increment_path(path)
        >>> print(new_path)
        runs/exp2

        Increment a file path:
        >>> path = Path("runs/exp/results.txt")
        >>> new_path = increment_path(path)
        >>> print(new_path)
        runs/exp/results2.txt
    r3      i'  Tr   )	r   existsr*   with_suffixsuffixranger   r.   r,   )r.   r   sepr,   r7   npr   r   r   increment_pathk   s   $r<   c                 C   s"   t  t t|  j }|jS )z>Return days since the last modification of the specified file.)r   nowfromtimestampr   statst_mtimedays)r.   dtr   r   r   file_age   s   rC   c                 C   s.   t t|  j}|j d|j d|j S )z8Returns the file modification date in 'YYYY-M-D' format.-)r   r>   r   r?   r@   yearmonthday)r.   tr   r   r   	file_date   s   rI   c                 C   sX   t | ttfr*d}t| } |  r|  j| S |  r*tdd | dD | S dS )z:Returns the size of a file or directory in megabytes (MB).i   c                 s   s"    | ]}|  r| jV  qd S )N)r*   r?   st_size).0fr   r   r   	<genexpr>   s     zfile_size.<locals>.<genexpr>z**/*g        )	r"   r!   r   r*   r?   rJ   r'   sumglob)r.   mbr   r   r   	file_size   s   rQ   .c                 C   s,   t j |  ddd}|rt|tjjdS dS )zdReturns the path to the most recent 'last.pt' file in the specified directory for resuming training.z/**/last*.ptT)	recursive)keyr3   )rO   maxr   r.   getctime)
search_dir	last_listr   r   r   get_latest_run   s   rY   )z
yolo11n.ptc           
      C   s   ddl m} ddlm} |d }|jddd | D ]0}|| }td|  ||}|  |r6|d|j_|| }	td	| d
|	  |	|	 qdS )ae  
    Update and re-save specified YOLO models in an 'updated_models' subdirectory.

    Args:
        model_names (Tuple[str, ...]): Model filenames to update.
        source_dir (Path): Directory containing models and target subdirectory.
        update_names (bool): Update model names from a data YAML.

    Examples:
        Update specified YOLO models and save them in 'updated_models' subdirectory:
        >>> from ultralytics.utils.files import update_models
        >>> model_names = ("yolo11n.pt", "yolov8s.pt")
        >>> update_models(model_names, source_dir=Path("/models"), update_names=True)
    r   )YOLO)default_class_namesupdated_modelsTr   zLoading model from z
coco8.yamlz
Re-saving z
 model to N)
ultralyticsrZ   ultralytics.nn.autobackendr[   r,   printhalfmodelnamessave)
model_names
source_dirupdate_namesrZ   r[   
target_dir
model_name
model_pathra   	save_pathr   r   r   update_models   s   rk   )Fr3   F)rR   )
contextlibrO   r   r(   r#   r   r   pathlibr   ContextDecoratorr   r2   r<   __file__rC   rI   rQ   rY   rk   r   r   r   r   <module>   s"   *

30
