
    h                         S SK Jr  S SKrS SKrS SKrS SKrS SKrS SKJr  S SKJr  S SK	J
r
   " S S\R                  5      r\SS j5       rSSS
 jjr\4SS jjr\4SS jjrSS jrSSS jjrS\
" S5      S	4SS jjrg)    )annotationsN)contextmanager)datetime)Pathc                  .    \ rS rSrSrSS jrS rS rSrg)	WorkingDirectory   a  
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                `    Xl         [        R                  " 5       R                  5       U l        g)zJInitialize the WorkingDirectory context manager with the target directory.N)dirr   cwdresolve)selfnew_dirs     Q/home/james-whalen/.local/lib/python3.13/site-packages/ultralytics/utils/files.py__init__WorkingDirectory.__init__+   s    88:%%'    c                D    [         R                  " U R                  5        g)zZChange the current working directory to the specified directory upon entering the context.N)oschdirr   )r   s    r   	__enter__WorkingDirectory.__enter__0       
r   c                D    [         R                  " U R                  5        g)z@Restore the original working directory when exiting the context.N)r   r   r   )r   exc_typeexc_valexc_tbs       r   __exit__WorkingDirectory.__exit__4   r   r   )r   r   N)r   
str | Path)	__name__
__module____qualname____firstlineno____doc__r   r   r   __static_attributes__ r   r   r   r      s    6(
r   r   c           	   #    #    S[        U 5      ;   Ga@  [        U [         5      n[        U 5      n [        R                  " 5        n[        U5      U R
                  R                  SS5      -  nU R                  5       (       a  [        R                  " X5        OEU R                  5       (       a0  UR                  R                  SSS9  [        R                  " X5         U(       a  [        U5      OUv   UR                  5       (       a  [        R                  " X0SS9  O+UR                  5       (       a  [        R                  " X05        SSS5        gU v   g! UR                  5       (       a  [        R                  " X0SS9  f UR                  5       (       a  [        R                  " X05        f f = f! , (       d  f       g= f7f)aM  
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_paths       r   spaces_in_pathr@   9   s?    * c$iD#&Dz ((*gG}tyy'8'8c'BBH {{}}/%%dT%BT,	1'-c(m8; ??$$OOH$G%%''LL0' +*. 
 ??$$OOH$G%%''LL0 (% +*s9   AGBF4E4AF4
GAF11F44
G>GFc                   [        U 5      n U R                  5       (       a  U(       d  U R                  5       (       a  U R                  S5      U R                  4OU S4u  p[        SS5       H3  nU  U U U 3n[        R                  R                  U5      (       a  M3    O   [        W5      n U(       a  U R                  SSS9  U $ )a-  
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, optional): If True, the path will not be incremented and returned as-is.
    sep (str, optional): Separator to use between the path and the incrementation number.
    mkdir (bool, optional): 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
    i'  Tr+   )	r   existsr8   with_suffixsuffixranger   r<   r:   )r<   r-   sepr:   rF   nps          r   increment_pathrK   m   s    > :D{{}}X>Bllnn((,dkk:SWY[R\ q$A&aS)A77>>!$$   Aw

4$
/Kr   c                    [         R                  " 5       [         R                  " [        U 5      R	                  5       R
                  5      -
  nUR                  $ )z>Return days since the last modification of the specified file.)r   nowfromtimestampr   statst_mtimedays)r<   dts     r   file_agerS      s7    	(00d1B1K1KL	LB77Nr   c                    [         R                  " [        U 5      R                  5       R                  5      nUR
                   SUR                   SUR                   3$ )z7Return the file modification date in 'YYYY-M-D' format.-)r   rN   r   rO   rP   yearmonthday)r<   ts     r   	file_daterZ      sF    tDz099:AffXQqwwiq((r   c                *   [        U [        [        45      (       ax  Sn[        U 5      n U R                  5       (       a  U R	                  5       R
                  U-  $ U R                  5       (       a$  [        S U R                  S5       5       5      U-  $ g)z9Return the size of a file or directory in megabytes (MB).i   c              3     #    U  H5  oR                  5       (       d  M  UR                  5       R                  v   M7     g 7f)N)r8   rO   st_size).0fs     r   	<genexpr>file_size.<locals>.<genexpr>   s'     R1BAiik'qvvx''1Bs   ?!?z**/*g        )	r0   r/   r   r8   rO   r]   r5   sumglob)r<   mbs     r   	file_sizere      sq    $d$$Dz<<>>99;&&++[[]]R61BRRUWWWr   .c                    [         R                   " U  S3SS9nU(       a"  [        U[        R                  R                  S9$ S$ )zcReturn the path to the most recent 'last.pt' file in the specified directory for resuming training.z/**/last*.ptT)	recursive)keyrB   )rc   maxr   r<   getctime)
search_dir	last_lists     r   get_latest_runrn      s7    		ZL5FI3<3ybgg../D"Dr   )z
yolo11n.ptc                4   SSK Jn  SSKJn  US-  nUR	                  SSS9  U  Hq  nX-  n[        SU 35        U" U5      nUR                  5         U(       a  U" S5      UR                  l        XV-  n	[        S	U S
U	 35        UR                  U	5        Ms     g)aM  
Update and re-save specified YOLO models in an 'updated_models' subdirectory.

Args:
    model_names (tuple, optional): Model filenames to update.
    source_dir (Path, optional): Directory containing models and target subdirectory.
    update_names (bool, optional): 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)
ultralyticsrp   ultralytics.nn.autobackendrq   r:   printhalfmodelnamessave)
model_names
source_dirupdate_namesrp   rq   
target_dir
model_name
model_pathrw   	save_paths
             r   update_modelsr      s     !>..JTD1!
,
#J<01 Z 

 3L AEKK +	 	
:,j<=

9 "r   )r<   r    )FrB   F)
r<   r    r-   boolrH   r/   r:   r   returnr   )r<   r    r   int)r<   r    r   r/   )r<   r    r   float)rf   )rl   r/   r   r/   )rz   tupler{   r   r|   r   )
__future__r   
contextlibrc   r   r6   r1   r   r   pathlibr   ContextDecoratorr   r@   rK   __file__rS   rZ   re   rn   r   r'   r   r   <module>r      s    #   	   %  'z22 'T 0 0f-` !)  "* )	E (74PS9kp $r   