Skip to content

Commit 3df331a

Browse files
Harden display helper plain-string fallback boundaries
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 5041c33 commit 3df331a

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

hyperbrowser/display_utils.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from hyperbrowser.type_utils import is_plain_string
22

33
_TRUNCATED_DISPLAY_SUFFIX = "... (truncated)"
4+
_DEFAULT_BLANK_KEY_FALLBACK = "<blank key>"
45

56

6-
def normalize_display_text(value: str, *, max_length: int) -> str:
7+
def normalize_display_text(value: object, *, max_length: int) -> str:
8+
if not is_plain_string(value):
9+
return ""
710
try:
811
sanitized_value = "".join(
912
"?" if ord(character) < 32 or ord(character) == 127 else character
@@ -23,13 +26,23 @@ def normalize_display_text(value: str, *, max_length: int) -> str:
2326
return ""
2427

2528

29+
def _normalize_blank_key_fallback(*, fallback: object, max_length: int) -> str:
30+
normalized_fallback = normalize_display_text(fallback, max_length=max_length)
31+
if normalized_fallback:
32+
return normalized_fallback
33+
return _DEFAULT_BLANK_KEY_FALLBACK
34+
35+
2636
def format_string_key_for_error(
27-
key: str,
37+
key: object,
2838
*,
2939
max_length: int,
30-
blank_fallback: str = "<blank key>",
40+
blank_fallback: object = _DEFAULT_BLANK_KEY_FALLBACK,
3141
) -> str:
3242
normalized_key = normalize_display_text(key, max_length=max_length)
3343
if not normalized_key:
34-
return blank_fallback
44+
return _normalize_blank_key_fallback(
45+
fallback=blank_fallback,
46+
max_length=max_length,
47+
)
3548
return normalized_key

tests/test_display_utils.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ def test_normalize_display_text_returns_empty_for_non_string_inputs():
3030
assert normalize_display_text(123, max_length=20) == "" # type: ignore[arg-type]
3131

3232

33+
def test_normalize_display_text_rejects_string_subclass_inputs():
34+
class _StringSubclass(str):
35+
pass
36+
37+
assert normalize_display_text(_StringSubclass("value"), max_length=20) == ""
38+
39+
3340
def test_format_string_key_for_error_returns_normalized_key():
3441
assert format_string_key_for_error(" \nkey\t ", max_length=20) == "?key?"
3542

@@ -43,3 +50,17 @@ def test_format_string_key_for_error_supports_custom_blank_fallback():
4350
format_string_key_for_error(" ", max_length=20, blank_fallback="<empty>")
4451
== "<empty>"
4552
)
53+
54+
55+
def test_format_string_key_for_error_sanitizes_custom_blank_fallback():
56+
assert (
57+
format_string_key_for_error(" ", max_length=20, blank_fallback=" \nempty\t ")
58+
== "?empty?"
59+
)
60+
61+
62+
def test_format_string_key_for_error_uses_default_fallback_for_invalid_blank_fallback():
63+
assert (
64+
format_string_key_for_error(" ", max_length=20, blank_fallback=123)
65+
== "<blank key>"
66+
)

0 commit comments

Comments
 (0)