Skip to content

Commit 153af27

Browse files
Add cross-module request wrapper internal reuse guard
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 0988df5 commit 153af27

3 files changed

Lines changed: 67 additions & 0 deletions

File tree

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ This runs lint, format checks, compile checks, tests, and package build.
154154
- `tests/test_readme_examples_listing.py` (README example-listing consistency enforcement),
155155
- `tests/test_request_helper_parse_import_boundary.py` (request-helper import boundary enforcement for direct response parsing imports),
156156
- `tests/test_request_helper_transport_boundary.py` (request-helper transport boundary enforcement through shared model request helpers),
157+
- `tests/test_request_wrapper_internal_reuse.py` (request-wrapper internal reuse of shared model request helpers across profile/team/extension/computer-action modules),
157158
- `tests/test_response_parse_usage_boundary.py` (centralized `parse_response_model(...)` usage boundary enforcement),
158159
- `tests/test_schema_injection_helper_usage.py` (shared schema injection helper usage enforcement in payload builders),
159160
- `tests/test_session_operation_metadata_usage.py` (session manager operation-metadata usage enforcement),

tests/test_architecture_marker_usage.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"tests/test_readme_examples_listing.py",
5656
"tests/test_request_helper_parse_import_boundary.py",
5757
"tests/test_request_helper_transport_boundary.py",
58+
"tests/test_request_wrapper_internal_reuse.py",
5859
"tests/test_response_parse_usage_boundary.py",
5960
"tests/test_examples_syntax.py",
6061
"tests/test_docs_python3_commands.py",
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import ast
2+
from pathlib import Path
3+
4+
import pytest
5+
6+
pytestmark = pytest.mark.architecture
7+
8+
9+
MODULE_WRAPPER_EXPECTATIONS = {
10+
"hyperbrowser/client/managers/profile_request_utils.py": {
11+
"create_profile_resource": ("post_model_request(",),
12+
"get_profile_resource": ("get_model_request(",),
13+
"delete_profile_resource": ("delete_model_request(",),
14+
"list_profile_resources": ("get_model_request(",),
15+
"create_profile_resource_async": ("post_model_request_async(",),
16+
"get_profile_resource_async": ("get_model_request_async(",),
17+
"delete_profile_resource_async": ("delete_model_request_async(",),
18+
"list_profile_resources_async": ("get_model_request_async(",),
19+
},
20+
"hyperbrowser/client/managers/team_request_utils.py": {
21+
"get_team_resource": ("get_model_request(",),
22+
"get_team_resource_async": ("get_model_request_async(",),
23+
},
24+
"hyperbrowser/client/managers/computer_action_request_utils.py": {
25+
"execute_computer_action_request": ("post_model_request_to_endpoint(",),
26+
"execute_computer_action_request_async": (
27+
"post_model_request_to_endpoint_async(",
28+
),
29+
},
30+
"hyperbrowser/client/managers/extension_request_utils.py": {
31+
"create_extension_resource": ("post_model_request(",),
32+
"create_extension_resource_async": ("post_model_request_async(",),
33+
"list_extension_resources": (
34+
"get_model_response_data(",
35+
"parse_extension_list_response_data(",
36+
),
37+
"list_extension_resources_async": (
38+
"get_model_response_data_async(",
39+
"parse_extension_list_response_data(",
40+
),
41+
},
42+
}
43+
44+
45+
def _collect_module_function_sources(module_path: str) -> dict[str, str]:
46+
module_text = Path(module_path).read_text(encoding="utf-8")
47+
module_ast = ast.parse(module_text)
48+
function_sources: dict[str, str] = {}
49+
for node in module_ast.body:
50+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
51+
function_source = ast.get_source_segment(module_text, node)
52+
if function_source is not None:
53+
function_sources[node.name] = function_source
54+
return function_sources
55+
56+
57+
def test_request_wrappers_delegate_to_expected_shared_helpers():
58+
for module_path, wrapper_expectations in MODULE_WRAPPER_EXPECTATIONS.items():
59+
function_sources = _collect_module_function_sources(module_path)
60+
for wrapper_name, expected_markers in wrapper_expectations.items():
61+
wrapper_source = function_sources[wrapper_name]
62+
for expected_marker in expected_markers:
63+
assert expected_marker in wrapper_source
64+
assert "client.transport." not in wrapper_source
65+
assert "parse_response_model(" not in wrapper_source

0 commit comments

Comments
 (0)