Skip to content

Commit 5e2c453

Browse files
committed
validate inputs to is_hidden
inputs must be absolute. Raise ValueError instead of possibly incorrect result when input is invalid
1 parent ff5270b commit 5e2c453

File tree

1 file changed

+35
-19
lines changed

1 file changed

+35
-19
lines changed

jupyter_core/paths.py

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ def exists(path: str) -> bool:
432432
return True
433433

434434

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:
436436
"""Is a file hidden?
437437
438438
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:
448448
The result of calling stat() on abs_path. If not passed, this function
449449
will call stat() internally.
450450
"""
451-
if Path(abs_path).name.startswith("."):
451+
abs_path = Path(abs_path)
452+
if abs_path.name.startswith("."):
452453
return True
453454

454455
if stat_res is None:
@@ -493,12 +494,13 @@ def is_file_hidden_posix(abs_path: str, stat_res: Optional[Any] = None) -> bool:
493494
The result of calling stat() on abs_path. If not passed, this function
494495
will call stat() internally.
495496
"""
496-
if Path(abs_path).name.startswith("."):
497+
abs_path = Path(abs_path)
498+
if abs_path.name.startswith("."):
497499
return True
498500

499501
if stat_res is None or stat.S_ISLNK(stat_res.st_mode):
500502
try:
501-
stat_res = Path(abs_path).stat()
503+
stat_res = abs_path.stat()
502504
except OSError as e:
503505
if e.errno == errno.ENOENT:
504506
return False
@@ -523,7 +525,7 @@ def is_file_hidden_posix(abs_path: str, stat_res: Optional[Any] = None) -> bool:
523525
is_file_hidden = is_file_hidden_posix
524526

525527

526-
def is_hidden(abs_path: str, abs_root: str = "") -> bool:
528+
def is_hidden(abs_path: str | Path, abs_root: str | Path = "") -> bool:
527529
"""Is a file hidden or contained in a hidden directory?
528530
529531
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:
537539
538540
Parameters
539541
----------
540-
abs_path : unicode
542+
abs_path : str or Path
541543
The absolute path to check for hidden directories.
542-
abs_root : unicode
544+
abs_root : str or Path
543545
The absolute path of the root directory in which hidden directories
544546
should be checked for.
545547
"""
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
548553

549554
if abs_path == abs_root:
555+
# root itself is never hidden
550556
return False
551557

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+
552571
if is_file_hidden(abs_path):
553572
return True
554573

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):
559576
return True
560577

561578
# check UF_HIDDEN on any location up to root.
562579
# 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():
567582
continue
583+
if parent == abs_root:
584+
break
568585
try:
569586
# may fail on Windows junctions
570-
st = os.lstat(path)
587+
st = parent.lstat()
571588
except OSError:
572589
return True
573590
if getattr(st, "st_flags", 0) & UF_HIDDEN:
574591
return True
575-
path = str(Path(path).parent)
576592

577593
return False
578594

0 commit comments

Comments
 (0)