Skip to content

Commit f4f791a

Browse files
Require concrete string strip outputs in file utility normalization
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 8d65412 commit f4f791a

File tree

2 files changed

+76
-5
lines changed

2 files changed

+76
-5
lines changed

hyperbrowser/client/file_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def _validate_error_message_text(message_value: str, *, field_name: str) -> None
1010
raise HyperbrowserError(f"{field_name} must be a string")
1111
try:
1212
normalized_message = message_value.strip()
13-
if not isinstance(normalized_message, str):
13+
if type(normalized_message) is not str:
1414
raise TypeError(f"normalized {field_name} must be a string")
1515
is_empty = len(normalized_message) == 0
1616
except HyperbrowserError:
@@ -67,7 +67,7 @@ def ensure_existing_file_path(
6767
raise HyperbrowserError("file_path must resolve to a string path")
6868
try:
6969
stripped_normalized_path = normalized_path.strip()
70-
if not isinstance(stripped_normalized_path, str):
70+
if type(stripped_normalized_path) is not str:
7171
raise TypeError("normalized file_path must be a string")
7272
except HyperbrowserError:
7373
raise

tests/test_file_utils.py

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,13 +361,39 @@ def strip(self, chars=None): # type: ignore[override]
361361
assert isinstance(exc_info.value.original_error, RuntimeError)
362362

363363

364+
def test_ensure_existing_file_path_wraps_missing_message_string_subclass_strip_results(
365+
tmp_path: Path,
366+
):
367+
class _BrokenMissingMessage(str):
368+
class _NormalizedMessage(str):
369+
pass
370+
371+
def strip(self, chars=None): # type: ignore[override]
372+
_ = chars
373+
return self._NormalizedMessage("missing")
374+
375+
file_path = tmp_path / "file.txt"
376+
file_path.write_text("content")
377+
378+
with pytest.raises(
379+
HyperbrowserError, match="Failed to normalize missing_file_message"
380+
) as exc_info:
381+
ensure_existing_file_path(
382+
str(file_path),
383+
missing_file_message=_BrokenMissingMessage("missing"),
384+
not_file_message="not-file",
385+
)
386+
387+
assert isinstance(exc_info.value.original_error, TypeError)
388+
389+
364390
def test_ensure_existing_file_path_wraps_missing_message_character_validation_failures(
365391
tmp_path: Path,
366392
):
367393
class _BrokenMissingMessage(str):
368394
def strip(self, chars=None): # type: ignore[override]
369395
_ = chars
370-
return self
396+
return "missing"
371397

372398
def __iter__(self):
373399
raise RuntimeError("missing message iteration exploded")
@@ -433,6 +459,32 @@ def strip(self, chars=None): # type: ignore[override]
433459
assert isinstance(exc_info.value.original_error, RuntimeError)
434460

435461

462+
def test_ensure_existing_file_path_wraps_not_file_message_string_subclass_strip_results(
463+
tmp_path: Path,
464+
):
465+
class _BrokenNotFileMessage(str):
466+
class _NormalizedMessage(str):
467+
pass
468+
469+
def strip(self, chars=None): # type: ignore[override]
470+
_ = chars
471+
return self._NormalizedMessage("not-file")
472+
473+
file_path = tmp_path / "file.txt"
474+
file_path.write_text("content")
475+
476+
with pytest.raises(
477+
HyperbrowserError, match="Failed to normalize not_file_message"
478+
) as exc_info:
479+
ensure_existing_file_path(
480+
str(file_path),
481+
missing_file_message="missing",
482+
not_file_message=_BrokenNotFileMessage("not-file"),
483+
)
484+
485+
assert isinstance(exc_info.value.original_error, TypeError)
486+
487+
436488
def test_ensure_existing_file_path_wraps_file_path_strip_runtime_errors():
437489
class _BrokenPath(str):
438490
def strip(self, chars=None): # type: ignore[override]
@@ -449,6 +501,25 @@ def strip(self, chars=None): # type: ignore[override]
449501
assert isinstance(exc_info.value.original_error, RuntimeError)
450502

451503

504+
def test_ensure_existing_file_path_wraps_file_path_string_subclass_strip_results():
505+
class _BrokenPath(str):
506+
class _NormalizedPath(str):
507+
pass
508+
509+
def strip(self, chars=None): # type: ignore[override]
510+
_ = chars
511+
return self._NormalizedPath("/tmp/path.txt")
512+
513+
with pytest.raises(HyperbrowserError, match="file_path is invalid") as exc_info:
514+
ensure_existing_file_path(
515+
_BrokenPath("/tmp/path.txt"),
516+
missing_file_message="missing",
517+
not_file_message="not-file",
518+
)
519+
520+
assert isinstance(exc_info.value.original_error, TypeError)
521+
522+
452523
def test_ensure_existing_file_path_wraps_file_path_contains_runtime_errors():
453524
class _BrokenPath(str):
454525
def strip(self, chars=None): # type: ignore[override]
@@ -466,7 +537,7 @@ def __contains__(self, item): # type: ignore[override]
466537
not_file_message="not-file",
467538
)
468539

469-
assert isinstance(exc_info.value.original_error, RuntimeError)
540+
assert isinstance(exc_info.value.original_error, TypeError)
470541

471542

472543
def test_ensure_existing_file_path_wraps_file_path_character_iteration_runtime_errors():
@@ -489,4 +560,4 @@ def __iter__(self):
489560
not_file_message="not-file",
490561
)
491562

492-
assert isinstance(exc_info.value.original_error, RuntimeError)
563+
assert isinstance(exc_info.value.original_error, TypeError)

0 commit comments

Comments
 (0)