Skip to content

Commit 6854549

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 a009e43 commit 6854549

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
@@ -433,7 +433,7 @@ def exists(path: str) -> bool:
433433
return True
434434

435435

436-
def is_file_hidden_win(abs_path: str, stat_res: Optional[Any] = None) -> bool:
436+
def is_file_hidden_win(abs_path: str | Path, stat_res: Optional[Any] = None) -> bool:
437437
"""Is a file hidden?
438438
439439
This only checks the file itself; it should be called in combination with
@@ -449,7 +449,8 @@ def is_file_hidden_win(abs_path: str, stat_res: Optional[Any] = None) -> bool:
449449
The result of calling stat() on abs_path. If not passed, this function
450450
will call stat() internally.
451451
"""
452-
if Path(abs_path).name.startswith("."):
452+
abs_path = Path(abs_path)
453+
if abs_path.name.startswith("."):
453454
return True
454455

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

500502
if stat_res is None or stat.S_ISLNK(stat_res.st_mode):
501503
try:
502-
stat_res = Path(abs_path).stat()
504+
stat_res = abs_path.stat()
503505
except OSError as e:
504506
if e.errno == errno.ENOENT:
505507
return False
@@ -524,7 +526,7 @@ def is_file_hidden_posix(abs_path: str, stat_res: Optional[Any] = None) -> bool:
524526
is_file_hidden = is_file_hidden_posix
525527

526528

527-
def is_hidden(abs_path: str, abs_root: str = "") -> bool:
529+
def is_hidden(abs_path: str | Path, abs_root: str | Path = "") -> bool:
528530
"""Is a file hidden or contained in a hidden directory?
529531
530532
This will start with the rightmost path element and work backwards to the
@@ -538,42 +540,56 @@ def is_hidden(abs_path: str, abs_root: str = "") -> bool:
538540
539541
Parameters
540542
----------
541-
abs_path : unicode
543+
abs_path : str or Path
542544
The absolute path to check for hidden directories.
543-
abs_root : unicode
545+
abs_root : str or Path
544546
The absolute path of the root directory in which hidden directories
545547
should be checked for.
546548
"""
547-
abs_path = os.path.normpath(abs_path)
548-
abs_root = os.path.normpath(abs_root)
549+
abs_path = Path(os.path.normpath(abs_path))
550+
if abs_root:
551+
abs_root = Path(os.path.normpath(abs_root))
552+
else:
553+
abs_root = abs_path.root
549554

550555
if abs_path == abs_root:
556+
# root itself is never hidden
551557
return False
552558

559+
# check that arguments are valid
560+
if not abs_path.is_absolute():
561+
_msg = f"{abs_path=} is not absolute. abs_path must be absolute."
562+
raise ValueError(_msg)
563+
if not abs_root.is_absolute():
564+
_msg = f"{abs_root=} is not absolute. abs_root must be absolute."
565+
raise ValueError(_msg)
566+
if not abs_path.is_relative_to(abs_root):
567+
_msg = (
568+
f"{abs_path=} is not a subdirectory of {abs_root=}. abs_path must be within abs_root."
569+
)
570+
raise ValueError(_msg)
571+
553572
if is_file_hidden(abs_path):
554573
return True
555574

556-
if not abs_root:
557-
abs_root = abs_path.split(os.sep, 1)[0] + os.sep
558-
inside_root = abs_path[len(abs_root) :]
559-
if any(part.startswith(".") for part in Path(inside_root).parts):
575+
relative_path = abs_path.relative_to(abs_root)
576+
if any(part.startswith(".") for part in relative_path.parts):
560577
return True
561578

562579
# check UF_HIDDEN on any location up to root.
563580
# is_file_hidden() already checked the file, so start from its parent dir
564-
path = str(Path(abs_path).parent)
565-
while path and path.startswith(abs_root) and path != abs_root:
566-
if not Path(path).exists():
567-
path = str(Path(path).parent)
581+
for parent in abs_path.parents:
582+
if not parent.exists():
568583
continue
584+
if parent == abs_root:
585+
break
569586
try:
570587
# may fail on Windows junctions
571-
st = os.lstat(path)
588+
st = parent.lstat()
572589
except OSError:
573590
return True
574591
if getattr(st, "st_flags", 0) & UF_HIDDEN:
575592
return True
576-
path = str(Path(path).parent)
577593

578594
return False
579595

0 commit comments

Comments
 (0)