3232    across different working directories. 
3333""" 
3434
35+ import  os 
3536import  re 
36- from  pathlib  import  Path 
37+ import  shutil 
38+ import  subprocess 
39+ import  sys 
3740from  contextlib  import  suppress 
38- import   os ,  sys ,  shutil ,  subprocess 
39- import   stat 
41+ from   pathlib   import   Path 
42+ 
4043
4144def  _is_windows_junction (p : Path ) ->  bool :
42-     """Return True if path is a directory junction (reparse point mount point).""" 
45+     """Return True if path is a directory junction.""" 
46+     if  not  sys .platform .startswith ("win" ):
47+         return  False 
48+ 
4349    try :
44-         st  =  p .lstat ()
45-         return  getattr (st , "st_reparse_tag" , 0 ) ==  stat .IO_REPARSE_TAG_MOUNT_POINT 
46-     except  (OSError , AttributeError ):
50+         # On Windows, check if it's a directory that's not a symlink 
51+         # Junctions appear as directories but resolve to different paths 
52+         return  p .exists () and  p .is_dir () and  not  p .is_symlink () and  p .resolve () !=  p 
53+     except  (OSError , RuntimeError ):
54+         # Handle cases where path operations fail 
4755        return  False 
4856
57+ 
4958def  _safe_remove_path (p : Path ) ->  None :
5059    """Remove file/dir/symlink/junction at p without following links.""" 
5160    if  not  os .path .lexists (str (p )):
@@ -54,12 +63,14 @@ def _safe_remove_path(p: Path) -> None:
5463        if  p .is_symlink ():
5564            p .unlink ()
5665        elif  _is_windows_junction (p ):
57-             os .rmdir (p )
66+             # Use rmdir for Windows junctions 
67+             p .rmdir ()
5868        elif  p .is_dir ():
5969            shutil .rmtree (p )
6070        else :
6171            p .unlink ()
6272
73+ 
6374def  _make_latest_windows (latest : Path , target : Path ) ->  None :
6475    # Clean previous latest (symlink/junction/dir/file) 
6576    _safe_remove_path (latest )
@@ -69,15 +80,20 @@ def _make_latest_windows(latest: Path, target: Path) -> None:
6980
7081    # Try junction first (no admin needed), fallback to copy 
7182    try :
72-         subprocess .run (
73-             ["cmd" , "/c" , "mklink" , "/J" , str (tmp ), str (target .resolve ())],
83+         # nosec B603, B607: Windows-specific command for creating junction 
84+         subprocess .run (  # noqa: S603 
85+             ["cmd" , "/c" , "mklink" , "/J" , str (tmp ), str (target .resolve ())],  # noqa: S607 
7486            check = True ,
7587            capture_output = True ,
7688        )
77-     except  Exception :
89+     except  ( subprocess . CalledProcessError ,  OSError ,  FileNotFoundError ) :
7890        shutil .copytree (target , tmp )
91+     else :
92+         tmp .replace (latest )
93+         return 
94+ 
95+     tmp .replace (latest )
7996
80-     os .replace (tmp , latest )
8197
8298def  create_versioned_dir (root_dir : str  |  Path ) ->  Path :
8399    """Create a new version directory and update the ``latest`` symbolic link. 
0 commit comments