@@ -432,7 +432,7 @@ def exists(path: str) -> bool:
432
432
return True
433
433
434
434
435
- def is_file_hidden_win (abs_path : str , stat_res : Optional [Any ] = None ) -> bool :
435
+ def is_file_hidden_win (abs_path : str | Path , stat_res : Optional [Any ] = None ) -> bool :
436
436
"""Is a file hidden?
437
437
438
438
This only checks the file itself; it should be called in combination with
@@ -448,7 +448,8 @@ def is_file_hidden_win(abs_path: str, stat_res: Optional[Any] = None) -> bool:
448
448
The result of calling stat() on abs_path. If not passed, this function
449
449
will call stat() internally.
450
450
"""
451
- if Path (abs_path ).name .startswith ("." ):
451
+ abs_path = Path (abs_path )
452
+ if abs_path .name .startswith ("." ):
452
453
return True
453
454
454
455
if stat_res is None :
@@ -493,12 +494,13 @@ def is_file_hidden_posix(abs_path: str, stat_res: Optional[Any] = None) -> bool:
493
494
The result of calling stat() on abs_path. If not passed, this function
494
495
will call stat() internally.
495
496
"""
496
- if Path (abs_path ).name .startswith ("." ):
497
+ abs_path = Path (abs_path )
498
+ if abs_path .name .startswith ("." ):
497
499
return True
498
500
499
501
if stat_res is None or stat .S_ISLNK (stat_res .st_mode ):
500
502
try :
501
- stat_res = Path ( abs_path ) .stat ()
503
+ stat_res = abs_path .stat ()
502
504
except OSError as e :
503
505
if e .errno == errno .ENOENT :
504
506
return False
@@ -523,7 +525,7 @@ def is_file_hidden_posix(abs_path: str, stat_res: Optional[Any] = None) -> bool:
523
525
is_file_hidden = is_file_hidden_posix
524
526
525
527
526
- def is_hidden (abs_path : str , abs_root : str = "" ) -> bool :
528
+ def is_hidden (abs_path : str | Path , abs_root : str | Path = "" ) -> bool :
527
529
"""Is a file hidden or contained in a hidden directory?
528
530
529
531
This will start with the rightmost path element and work backwards to the
@@ -537,42 +539,56 @@ def is_hidden(abs_path: str, abs_root: str = "") -> bool:
537
539
538
540
Parameters
539
541
----------
540
- abs_path : unicode
542
+ abs_path : str or Path
541
543
The absolute path to check for hidden directories.
542
- abs_root : unicode
544
+ abs_root : str or Path
543
545
The absolute path of the root directory in which hidden directories
544
546
should be checked for.
545
547
"""
546
- abs_path = os .path .normpath (abs_path )
547
- abs_root = os .path .normpath (abs_root )
548
+ abs_path = Path (os .path .normpath (abs_path ))
549
+ if abs_root :
550
+ abs_root = Path (os .path .normpath (abs_root ))
551
+ else :
552
+ abs_root = abs_path .root
548
553
549
554
if abs_path == abs_root :
555
+ # root itself is never hidden
550
556
return False
551
557
558
+ # check that arguments are valid
559
+ if not abs_path .is_absolute ():
560
+ _msg = f"{ abs_path = } is not absolute. abs_path must be absolute."
561
+ raise ValueError (_msg )
562
+ if not abs_root .is_absolute ():
563
+ _msg = f"{ abs_root = } is not absolute. abs_root must be absolute."
564
+ raise ValueError (_msg )
565
+ if not abs_path .is_relative_to (abs_root ):
566
+ _msg = (
567
+ f"{ abs_path = } is not a subdirectory of { abs_root = } . abs_path must be within abs_root."
568
+ )
569
+ raise ValueError (_msg )
570
+
552
571
if is_file_hidden (abs_path ):
553
572
return True
554
573
555
- if not abs_root :
556
- abs_root = abs_path .split (os .sep , 1 )[0 ] + os .sep
557
- inside_root = abs_path [len (abs_root ) :]
558
- if any (part .startswith ("." ) for part in Path (inside_root ).parts ):
574
+ relative_path = abs_path .relative_to (abs_root )
575
+ if any (part .startswith ("." ) for part in relative_path .parts ):
559
576
return True
560
577
561
578
# check UF_HIDDEN on any location up to root.
562
579
# is_file_hidden() already checked the file, so start from its parent dir
563
- path = str (Path (abs_path ).parent )
564
- while path and path .startswith (abs_root ) and path != abs_root :
565
- if not Path (path ).exists ():
566
- path = str (Path (path ).parent )
580
+ for parent in abs_path .parents :
581
+ if not parent .exists ():
567
582
continue
583
+ if parent == abs_root :
584
+ break
568
585
try :
569
586
# may fail on Windows junctions
570
- st = os .lstat (path )
587
+ st = parent .lstat ()
571
588
except OSError :
572
589
return True
573
590
if getattr (st , "st_flags" , 0 ) & UF_HIDDEN :
574
591
return True
575
- path = str (Path (path ).parent )
576
592
577
593
return False
578
594
0 commit comments