Skip to content

Commit d533154

Browse files
Harden extension list parsing for unreadable items
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent a0811f5 commit d533154

2 files changed

Lines changed: 57 additions & 2 deletions

File tree

hyperbrowser/client/managers/extension_utils.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,16 @@ def parse_extension_list_response_data(response_data: Any) -> List[ExtensionResp
106106
f"{index} but got {_get_type_name(extension)}"
107107
)
108108
try:
109-
parsed_extensions.append(ExtensionResponse(**dict(extension)))
109+
extension_payload = dict(extension)
110+
except HyperbrowserError:
111+
raise
112+
except Exception as exc:
113+
raise HyperbrowserError(
114+
f"Failed to read extension object at index {index}",
115+
original_error=exc,
116+
) from exc
117+
try:
118+
parsed_extensions.append(ExtensionResponse(**extension_payload))
110119
except HyperbrowserError:
111120
raise
112121
except Exception as exc:

tests/test_extension_utils.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import pytest
1+
from collections.abc import Iterator, Mapping
22
from types import MappingProxyType
33

4+
import pytest
5+
46
from hyperbrowser.client.managers import extension_utils
57
from hyperbrowser.client.managers.extension_utils import (
68
parse_extension_list_response_data,
@@ -244,3 +246,47 @@ def __iter__(self):
244246
parse_extension_list_response_data({"extensions": _BrokenExtensionsList([{}])})
245247

246248
assert exc_info.value.original_error is not None
249+
250+
251+
def test_parse_extension_list_response_data_wraps_unreadable_extension_object():
252+
class _BrokenExtensionMapping(Mapping[str, object]):
253+
def __iter__(self) -> Iterator[str]:
254+
raise RuntimeError("cannot iterate extension object")
255+
256+
def __len__(self) -> int:
257+
return 1
258+
259+
def __getitem__(self, key: str) -> object:
260+
_ = key
261+
return "ignored"
262+
263+
with pytest.raises(
264+
HyperbrowserError, match="Failed to read extension object at index 0"
265+
) as exc_info:
266+
parse_extension_list_response_data(
267+
{"extensions": [_BrokenExtensionMapping()]}
268+
)
269+
270+
assert exc_info.value.original_error is not None
271+
272+
273+
def test_parse_extension_list_response_data_preserves_hyperbrowser_extension_read_errors():
274+
class _BrokenExtensionMapping(Mapping[str, object]):
275+
def __iter__(self) -> Iterator[str]:
276+
raise HyperbrowserError("custom extension read failure")
277+
278+
def __len__(self) -> int:
279+
return 1
280+
281+
def __getitem__(self, key: str) -> object:
282+
_ = key
283+
return "ignored"
284+
285+
with pytest.raises(
286+
HyperbrowserError, match="custom extension read failure"
287+
) as exc_info:
288+
parse_extension_list_response_data(
289+
{"extensions": [_BrokenExtensionMapping()]}
290+
)
291+
292+
assert exc_info.value.original_error is None

0 commit comments

Comments
 (0)