local-web-services-python-sdk 0.1.5__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. local_web_services_python_sdk-0.2.0/BUILD +17 -0
  2. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/PKG-INFO +3 -3
  3. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/pyproject.toml +6 -3
  4. local_web_services_python_sdk-0.2.0/requirements.txt +173 -0
  5. local_web_services_python_sdk-0.2.0/src/lws_testing/_builders/__init__.py +1 -0
  6. local_web_services_python_sdk-0.1.5/src/lws_testing/_builders/mock.py → local_web_services_python_sdk-0.2.0/src/lws_testing/_builders/fake.py +17 -17
  7. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_transport/inprocess.py +17 -17
  8. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/session.py +6 -6
  9. local_web_services_python_sdk-0.2.0/tests/BUILD +15 -0
  10. local_web_services_python_sdk-0.2.0/tests/pytest_runner.py +10 -0
  11. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/tests/unit/test_session_imports.py +1 -1
  12. local_web_services_python_sdk-0.1.5/src/lws_testing/_builders/__init__.py +0 -1
  13. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/.github/workflows/ci.yml +0 -0
  14. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/.github/workflows/publish.yml +0 -0
  15. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/.gitignore +0 -0
  16. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/Makefile +0 -0
  17. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/README.md +0 -0
  18. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/__init__.py +0 -0
  19. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_builders/chaos.py +0 -0
  20. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_builders/iam.py +0 -0
  21. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_discovery/__init__.py +0 -0
  22. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_discovery/cdk.py +0 -0
  23. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_discovery/hcl.py +0 -0
  24. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_logs.py +0 -0
  25. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_resources/__init__.py +0 -0
  26. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_resources/dynamodb.py +0 -0
  27. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_resources/s3.py +0 -0
  28. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_resources/sqs.py +0 -0
  29. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/_transport/__init__.py +0 -0
  30. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/src/lws_testing/fixtures.py +0 -0
  31. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/tests/__init__.py +0 -0
  32. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/tests/unit/__init__.py +0 -0
  33. {local_web_services_python_sdk-0.1.5 → local_web_services_python_sdk-0.2.0}/tests/unit/test_session_lifecycle.py +0 -0
@@ -0,0 +1,17 @@
1
+ load("@pip_python_sdk//:requirements.bzl", "requirement")
2
+ load("@rules_python//python:defs.bzl", "py_library", "py_test")
3
+
4
+ py_library(
5
+ name = "lws_testing",
6
+ srcs = glob(["src/**/*.py"]),
7
+ imports = ["src"],
8
+ visibility = ["//visibility:public"],
9
+ deps = [
10
+ "//core:lws",
11
+ requirement("httpx"),
12
+ requirement("botocore"),
13
+ requirement("pyyaml"),
14
+ ],
15
+ )
16
+
17
+ # Tests live in //lang/python/sdk/tests:tests to avoid output-path prefix conflicts.
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: local-web-services-python-sdk
3
- Version: 0.1.5
3
+ Version: 0.2.0
4
4
  Summary: Python testing SDK for local-web-services — in-process pytest fixtures and boto3 helpers
5
5
  Project-URL: Homepage, https://local-web-services.github.io
6
6
  Project-URL: Repository, https://github.com/local-web-services/local-web-services-sdk-python
7
7
  Project-URL: Issues, https://github.com/local-web-services/local-web-services-sdk-python/issues
8
8
  License-Expression: MIT
9
- Keywords: aws,boto3,dynamodb,local,mocking,pytest,s3,sqs,testing
9
+ Keywords: aws,boto3,dynamodb,faking,local,pytest,s3,sqs,testing
10
10
  Classifier: Development Status :: 3 - Alpha
11
11
  Classifier: Framework :: Pytest
12
12
  Classifier: Intended Audience :: Developers
@@ -19,7 +19,7 @@ Classifier: Topic :: Software Development :: Testing
19
19
  Requires-Python: >=3.11
20
20
  Requires-Dist: botocore>=1.34.0
21
21
  Requires-Dist: httpx>=0.27.0
22
- Requires-Dist: local-web-services>=0.17.2
22
+ Requires-Dist: local-web-services>=0.18.0
23
23
  Requires-Dist: pyyaml>=6.0
24
24
  Provides-Extra: pytest
25
25
  Requires-Dist: pytest>=8.0.0; extra == 'pytest'
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "local-web-services-python-sdk"
3
- version = "0.1.5"
3
+ version = "0.2.0"
4
4
  description = "Python testing SDK for local-web-services — in-process pytest fixtures and boto3 helpers"
5
5
  readme = "README.md"
6
6
  license = "MIT"
7
7
  requires-python = ">=3.11"
8
- keywords = ["aws", "testing", "pytest", "boto3", "local", "dynamodb", "sqs", "s3", "mocking"]
8
+ keywords = ["aws", "testing", "pytest", "boto3", "local", "dynamodb", "sqs", "s3", "faking"]
9
9
  classifiers = [
10
10
  "Development Status :: 3 - Alpha",
11
11
  "Intended Audience :: Developers",
@@ -21,7 +21,7 @@ dependencies = [
21
21
  "httpx>=0.27.0",
22
22
  "botocore>=1.34.0",
23
23
  "pyyaml>=6.0",
24
- "local-web-services>=0.17.2",
24
+ "local-web-services>=0.18.0",
25
25
  ]
26
26
 
27
27
  [project.optional-dependencies]
@@ -81,3 +81,6 @@ disable = [
81
81
  "R0903", "R0902", "R0913", "R0917", "R0904", "R0911", "R0914", "C0103",
82
82
  "W0603", "W0621", "C0415", "C0116", "W0212",
83
83
  ]
84
+
85
+ [tool.uv.sources]
86
+ local-web-services = { path = "../../../core", editable = true }
@@ -0,0 +1,173 @@
1
+ # This file was autogenerated by uv via the following command:
2
+ # uv export --no-hashes --no-editable --output-file requirements.txt
3
+ aiosqlite==0.22.1
4
+ # via local-web-services
5
+ annotated-doc==0.0.4
6
+ # via
7
+ # fastapi
8
+ # typer
9
+ annotated-types==0.7.0
10
+ # via pydantic
11
+ anyio==4.12.1
12
+ # via
13
+ # httpx
14
+ # starlette
15
+ # watchfiles
16
+ black==26.1.0
17
+ boto3==1.42.54
18
+ botocore==1.42.54
19
+ # via
20
+ # boto3
21
+ # local-web-services-python-sdk
22
+ # s3transfer
23
+ certifi==2026.1.4
24
+ # via
25
+ # httpcore
26
+ # httpx
27
+ # requests
28
+ cffi==2.0.0 ; platform_python_implementation != 'PyPy'
29
+ # via cryptography
30
+ charset-normalizer==3.4.4
31
+ # via requests
32
+ click==8.3.1
33
+ # via
34
+ # black
35
+ # typer
36
+ # uvicorn
37
+ colorama==0.4.6
38
+ # via
39
+ # click
40
+ # pytest
41
+ # radon
42
+ # uvicorn
43
+ croniter==6.0.0
44
+ # via local-web-services
45
+ cryptography==46.0.5
46
+ # via pyjwt
47
+ docker==7.1.0
48
+ # via local-web-services
49
+ fastapi==0.129.0
50
+ # via local-web-services
51
+ h11==0.16.0
52
+ # via
53
+ # httpcore
54
+ # uvicorn
55
+ httpcore==1.0.9
56
+ # via httpx
57
+ httptools==0.7.1
58
+ # via uvicorn
59
+ httpx==0.28.1
60
+ # via
61
+ # local-web-services
62
+ # local-web-services-python-sdk
63
+ idna==3.11
64
+ # via
65
+ # anyio
66
+ # httpx
67
+ # requests
68
+ iniconfig==2.3.0
69
+ # via pytest
70
+ jmespath==1.1.0
71
+ # via
72
+ # boto3
73
+ # botocore
74
+ mando==0.7.1
75
+ # via radon
76
+ markdown-it-py==4.0.0
77
+ # via rich
78
+ mdurl==0.1.2
79
+ # via markdown-it-py
80
+ mypy-extensions==1.1.0
81
+ # via black
82
+ packaging==26.0
83
+ # via
84
+ # black
85
+ # pytest
86
+ pathspec==1.0.4
87
+ # via black
88
+ platformdirs==4.9.2
89
+ # via black
90
+ pluggy==1.6.0
91
+ # via pytest
92
+ pycparser==3.0 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy'
93
+ # via cffi
94
+ pydantic==2.12.5
95
+ # via fastapi
96
+ pydantic-core==2.41.5
97
+ # via pydantic
98
+ pygments==2.19.2
99
+ # via
100
+ # pytest
101
+ # rich
102
+ pyjwt==2.11.0
103
+ # via local-web-services
104
+ pytest==9.0.2
105
+ # via pytest-asyncio
106
+ pytest-asyncio==1.3.0
107
+ python-dateutil==2.9.0.post0
108
+ # via
109
+ # botocore
110
+ # croniter
111
+ python-dotenv==1.2.1
112
+ # via uvicorn
113
+ python-multipart==0.0.22
114
+ # via local-web-services
115
+ pytokens==0.4.1
116
+ # via black
117
+ pytz==2025.2
118
+ # via croniter
119
+ pywin32==311 ; sys_platform == 'win32'
120
+ # via docker
121
+ pyyaml==6.0.3
122
+ # via
123
+ # local-web-services
124
+ # local-web-services-python-sdk
125
+ # uvicorn
126
+ radon==6.0.1
127
+ requests==2.32.5
128
+ # via docker
129
+ rich==14.3.3
130
+ # via
131
+ # local-web-services
132
+ # typer
133
+ ruff==0.15.2
134
+ s3transfer==0.16.0
135
+ # via boto3
136
+ shellingham==1.5.4
137
+ # via typer
138
+ six==1.17.0
139
+ # via
140
+ # mando
141
+ # python-dateutil
142
+ starlette==0.52.1
143
+ # via fastapi
144
+ typer==0.24.0
145
+ # via local-web-services
146
+ typing-extensions==4.15.0
147
+ # via
148
+ # anyio
149
+ # fastapi
150
+ # pydantic
151
+ # pydantic-core
152
+ # pytest-asyncio
153
+ # starlette
154
+ # typing-inspection
155
+ typing-inspection==0.4.2
156
+ # via
157
+ # fastapi
158
+ # pydantic
159
+ urllib3==2.6.3
160
+ # via
161
+ # botocore
162
+ # docker
163
+ # requests
164
+ uvicorn==0.41.0
165
+ # via local-web-services
166
+ uvloop==0.22.1 ; platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'
167
+ # via uvicorn
168
+ watchdog==6.0.0
169
+ # via local-web-services
170
+ watchfiles==1.1.1
171
+ # via uvicorn
172
+ websockets==16.0
173
+ # via uvicorn
@@ -0,0 +1 @@
1
+ """Fluent builders for fake, chaos, and IAM configuration."""
@@ -1,4 +1,4 @@
1
- """Fluent builder for configuring AWS operation mocks."""
1
+ """Fluent builder for configuring AWS operation fakes."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -7,12 +7,12 @@ from typing import Any
7
7
  import httpx
8
8
 
9
9
 
10
- class MockBuilder:
11
- """Fluent builder for AWS service mock responses.
10
+ class FakeBuilder:
11
+ """Fluent builder for AWS service fake responses.
12
12
 
13
13
  Usage::
14
14
 
15
- session.mock("dynamodb").operation("PutItem").respond(
15
+ session.fake("dynamodb").operation("PutItem").respond(
16
16
  status=500,
17
17
  body={"__type": "ProvisionedThroughputExceededException"},
18
18
  )
@@ -23,11 +23,11 @@ class MockBuilder:
23
23
  self._mgmt_port = mgmt_port
24
24
  self._rules: list[dict[str, Any]] = []
25
25
 
26
- def operation(self, operation_name: str) -> _MockRuleBuilder:
27
- """Start building a mock rule for *operation_name*."""
28
- return _MockRuleBuilder(self, operation_name)
26
+ def operation(self, operation_name: str) -> _FakeRuleBuilder:
27
+ """Start building a fake rule for *operation_name*."""
28
+ return _FakeRuleBuilder(self, operation_name)
29
29
 
30
- def _add_rule(self, rule: dict[str, Any]) -> MockBuilder:
30
+ def _add_rule(self, rule: dict[str, Any]) -> FakeBuilder:
31
31
  self._rules.append(rule)
32
32
  self._apply()
33
33
  return self
@@ -35,30 +35,30 @@ class MockBuilder:
35
35
  def _apply(self) -> None:
36
36
  """Push the current rules to the management API."""
37
37
  httpx.post(
38
- f"http://127.0.0.1:{self._mgmt_port}/_ldk/aws-mock",
38
+ f"http://127.0.0.1:{self._mgmt_port}/_ldk/aws-fake",
39
39
  json={self._service: {"enabled": True, "rules": self._rules}},
40
40
  timeout=5.0,
41
41
  )
42
42
 
43
43
  def clear(self) -> None:
44
- """Remove all mock rules for this service."""
44
+ """Remove all fake rules for this service."""
45
45
  self._rules = []
46
46
  httpx.post(
47
- f"http://127.0.0.1:{self._mgmt_port}/_ldk/aws-mock",
47
+ f"http://127.0.0.1:{self._mgmt_port}/_ldk/aws-fake",
48
48
  json={self._service: {"enabled": False, "rules": []}},
49
49
  timeout=5.0,
50
50
  )
51
51
 
52
52
 
53
- class _MockRuleBuilder:
54
- """Intermediate builder — configure a single mock rule."""
53
+ class _FakeRuleBuilder:
54
+ """Intermediate builder — configure a single fake rule."""
55
55
 
56
- def __init__(self, parent: MockBuilder, operation: str) -> None:
56
+ def __init__(self, parent: FakeBuilder, operation: str) -> None:
57
57
  self._parent = parent
58
58
  self._operation = operation
59
59
  self._match_headers: dict[str, str] = {}
60
60
 
61
- def with_header(self, name: str, value: str) -> _MockRuleBuilder:
61
+ def with_header(self, name: str, value: str) -> _FakeRuleBuilder:
62
62
  """Add an additional header match constraint."""
63
63
  self._match_headers[name] = value
64
64
  return self
@@ -69,7 +69,7 @@ class _MockRuleBuilder:
69
69
  body: str | dict[str, Any] = "",
70
70
  content_type: str = "application/json",
71
71
  delay_ms: int = 0,
72
- ) -> MockBuilder:
72
+ ) -> FakeBuilder:
73
73
  """Set the response and register the rule.
74
74
 
75
75
  Args:
@@ -99,7 +99,7 @@ class _MockRuleBuilder:
99
99
 
100
100
  return self._parent._add_rule(rule)
101
101
 
102
- def error(self, error_type: str, message: str = "", status: int = 400) -> MockBuilder:
102
+ def error(self, error_type: str, message: str = "", status: int = 400) -> FakeBuilder:
103
103
  """Respond with a structured AWS error."""
104
104
  import json
105
105
 
@@ -108,9 +108,9 @@ class _StubOrchestrator:
108
108
  def _create_management_app(
109
109
  providers: dict[str, Any],
110
110
  chaos_configs: dict[str, Any],
111
- mock_configs: dict[str, Any],
111
+ fake_configs: dict[str, Any],
112
112
  ) -> Any:
113
- """Build a FastAPI management app with reset, mock, and chaos endpoints."""
113
+ """Build a FastAPI management app with reset, fake, and chaos endpoints."""
114
114
  from fastapi import FastAPI
115
115
  from fastapi.responses import JSONResponse
116
116
  from lws.api.management import _handle_reset, create_management_router
@@ -122,7 +122,7 @@ def _create_management_app(
122
122
  orchestrator=orchestrator,
123
123
  providers=providers,
124
124
  chaos_configs=chaos_configs,
125
- aws_mock_configs=mock_configs,
125
+ aws_fake_configs=fake_configs,
126
126
  )
127
127
  app.include_router(router)
128
128
 
@@ -182,7 +182,7 @@ def _build_service_apps(
182
182
  providers: dict[str, Any],
183
183
  ports: dict[str, int],
184
184
  chaos_configs: dict[str, Any],
185
- mock_configs: dict[str, Any],
185
+ fake_configs: dict[str, Any],
186
186
  cfg: dict[str, list[Any]],
187
187
  ) -> list[tuple[str, Any]]:
188
188
  """Build FastAPI apps for all services; return as (service_name, app) pairs."""
@@ -200,7 +200,7 @@ def _build_service_apps(
200
200
  create_dynamodb_app(
201
201
  providers["dynamodb"],
202
202
  chaos=chaos_configs["dynamodb"],
203
- aws_mock=mock_configs["dynamodb"],
203
+ aws_fake=fake_configs["dynamodb"],
204
204
  ),
205
205
  ),
206
206
  (
@@ -209,7 +209,7 @@ def _build_service_apps(
209
209
  providers["sqs"],
210
210
  port=ports["sqs"],
211
211
  chaos=chaos_configs["sqs"],
212
- aws_mock=mock_configs["sqs"],
212
+ aws_fake=fake_configs["sqs"],
213
213
  ),
214
214
  ),
215
215
  (
@@ -217,7 +217,7 @@ def _build_service_apps(
217
217
  create_s3_app(
218
218
  providers["s3"],
219
219
  chaos=chaos_configs["s3"],
220
- aws_mock=mock_configs["s3"],
220
+ aws_fake=fake_configs["s3"],
221
221
  ),
222
222
  ),
223
223
  (
@@ -225,7 +225,7 @@ def _build_service_apps(
225
225
  create_sns_app(
226
226
  providers["sns"],
227
227
  chaos=chaos_configs["sns"],
228
- aws_mock=mock_configs["sns"],
228
+ aws_fake=fake_configs["sns"],
229
229
  ),
230
230
  ),
231
231
  (
@@ -233,7 +233,7 @@ def _build_service_apps(
233
233
  create_stepfunctions_app(
234
234
  providers["stepfunctions"],
235
235
  chaos=chaos_configs["stepfunctions"],
236
- aws_mock=mock_configs["stepfunctions"],
236
+ aws_fake=fake_configs["stepfunctions"],
237
237
  ),
238
238
  ),
239
239
  (
@@ -241,7 +241,7 @@ def _build_service_apps(
241
241
  create_ssm_app(
242
242
  initial_parameters=cfg["parameters"] or None,
243
243
  chaos=chaos_configs["ssm"],
244
- aws_mock=mock_configs["ssm"],
244
+ aws_fake=fake_configs["ssm"],
245
245
  ),
246
246
  ),
247
247
  (
@@ -249,7 +249,7 @@ def _build_service_apps(
249
249
  create_secretsmanager_app(
250
250
  initial_secrets=cfg["secrets"] or None,
251
251
  chaos=chaos_configs["secretsmanager"],
252
- aws_mock=mock_configs["secretsmanager"],
252
+ aws_fake=fake_configs["secretsmanager"],
253
253
  ),
254
254
  ),
255
255
  ]
@@ -268,7 +268,7 @@ async def _start_all_servers(
268
268
  mgmt_port: int,
269
269
  ) -> list[Any]:
270
270
  """Start uvicorn servers for every service app plus the management app."""
271
- from lws.providers.mockserver.provider import start_uvicorn_server
271
+ from lws.providers.fakeserver.provider import start_uvicorn_server
272
272
 
273
273
  servers: list[Any] = []
274
274
  for svc, app in service_apps:
@@ -302,20 +302,20 @@ async def start_services(
302
302
  passed directly to :func:`stop_services`.
303
303
  """
304
304
  from lws.providers._shared.aws_chaos import AwsChaosConfig
305
- from lws.providers._shared.aws_operation_mock import AwsMockConfig
305
+ from lws.providers._shared.aws_operation_fake import AwsFakeConfig
306
306
 
307
307
  log_handler = _setup_logging()
308
308
  cfg = _convert_spec(spec)
309
309
  providers = _create_providers(cfg, data_dir)
310
310
 
311
311
  chaos_configs: dict[str, Any] = {s: AwsChaosConfig() for s in _SERVICE_NAMES}
312
- mock_configs: dict[str, Any] = {s: AwsMockConfig(service=s) for s in _SERVICE_NAMES}
312
+ fake_configs: dict[str, Any] = {s: AwsFakeConfig(service=s) for s in _SERVICE_NAMES}
313
313
  ports: dict[str, int] = {s: _free_port() for s in _SERVICE_NAMES}
314
314
  mgmt_port = _free_port()
315
315
 
316
- service_apps = _build_service_apps(providers, ports, chaos_configs, mock_configs, cfg)
316
+ service_apps = _build_service_apps(providers, ports, chaos_configs, fake_configs, cfg)
317
317
  await _start_providers(providers)
318
- mgmt_app = _create_management_app(providers, chaos_configs, mock_configs)
318
+ mgmt_app = _create_management_app(providers, chaos_configs, fake_configs)
319
319
  servers = await _start_all_servers(service_apps, ports, mgmt_app, mgmt_port)
320
320
 
321
321
  return log_handler, ports, mgmt_port, servers
@@ -323,7 +323,7 @@ async def start_services(
323
323
 
324
324
  async def stop_services(servers: list[Any]) -> None:
325
325
  """Gracefully stop all servers started by :func:`start_services`."""
326
- from lws.providers.mockserver.provider import stop_uvicorn_server
326
+ from lws.providers.fakeserver.provider import stop_uvicorn_server
327
327
 
328
328
  for server, task in reversed(servers):
329
329
  await stop_uvicorn_server(server, task)
@@ -46,7 +46,7 @@ class LwsSession:
46
46
 
47
47
  Starts all LWS service providers in background threads within the test
48
48
  process, patches boto3 clients, and provides helpers for seeding state,
49
- configuring mocks, capturing logs, and asserting side effects.
49
+ configuring fakes, capturing logs, and asserting side effects.
50
50
 
51
51
  Use as a context manager::
52
52
 
@@ -341,13 +341,13 @@ class LwsSession:
341
341
  """
342
342
  return f"http://127.0.0.1:{self._ports['sqs']}/000000000000/{queue_name}"
343
343
 
344
- # ── Mock / chaos / IAM builders ───────────────────────────────────────────
344
+ # ── Fake / chaos / IAM builders ───────────────────────────────────────────
345
345
 
346
- def mock(self, service: str) -> Any:
347
- """Return a fluent mock builder for the given service."""
348
- from lws_testing._builders.mock import MockBuilder
346
+ def fake(self, service: str) -> Any:
347
+ """Return a fluent fake builder for the given service."""
348
+ from lws_testing._builders.fake import FakeBuilder
349
349
 
350
- return MockBuilder(service, self._mgmt_port)
350
+ return FakeBuilder(service, self._mgmt_port)
351
351
 
352
352
  def chaos(self, service: str) -> Any:
353
353
  """Return a fluent chaos builder for the given service."""
@@ -0,0 +1,15 @@
1
+ load("@pip_python_sdk//:requirements.bzl", "requirement")
2
+ load("@rules_python//python:defs.bzl", "py_test")
3
+
4
+ py_test(
5
+ name = "tests",
6
+ srcs = glob(["**/*.py"]),
7
+ data = ["//core:ldk"],
8
+ imports = ["../src"],
9
+ main = "pytest_runner.py",
10
+ deps = [
11
+ "//lang/python/sdk:lws_testing",
12
+ requirement("pytest"),
13
+ requirement("boto3"),
14
+ ],
15
+ )
@@ -0,0 +1,10 @@
1
+ """Bazel py_test entry point: discovers and runs tests with pytest."""
2
+
3
+ import os
4
+ import sys
5
+
6
+ import pytest
7
+
8
+ if __name__ == "__main__":
9
+ test_dir = os.path.join(os.path.dirname(__file__), "tests")
10
+ sys.exit(pytest.main([test_dir, "-v", "--tb=short"] + sys.argv[1:]))
@@ -43,7 +43,7 @@ def test_resource_helpers_importable():
43
43
  def test_builders_importable():
44
44
  from lws_testing._builders.chaos import ChaosBuilder # noqa: F401
45
45
  from lws_testing._builders.iam import IamBuilder # noqa: F401
46
- from lws_testing._builders.mock import MockBuilder # noqa: F401
46
+ from lws_testing._builders.fake import FakeBuilder # noqa: F401
47
47
 
48
48
 
49
49
  def test_discovery_importable():
@@ -1 +0,0 @@
1
- """Fluent builders for mock, chaos, and IAM configuration."""