wexample-api 6.8.11__tar.gz → 6.8.12__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 (31) hide show
  1. wexample_api-6.8.12/PKG-INFO +114 -0
  2. wexample_api-6.8.12/README.md +93 -0
  3. {wexample_api-6.8.11 → wexample_api-6.8.12}/pyproject.toml +3 -3
  4. {wexample_api-6.8.11 → wexample_api-6.8.12}/tests/.gitkeep +0 -0
  5. wexample_api-6.8.11/PKG-INFO +0 -276
  6. wexample_api-6.8.11/README.md +0 -255
  7. wexample_api-6.8.11/src/wexample_api/models/__init__.py +0 -0
  8. wexample_api-6.8.11/tests/common/__init__.py +0 -0
  9. wexample_api-6.8.11/tests/demo/__init__.py +0 -0
  10. wexample_api-6.8.11/tests/new_architecture/__init__.py +0 -0
  11. {wexample_api-6.8.11 → wexample_api-6.8.12}/src/wexample_api/__init__.py +0 -0
  12. {wexample_api-6.8.11/src/wexample_api/__pycache__ → wexample_api-6.8.12/src/wexample_api/common}/__init__.py +0 -0
  13. {wexample_api-6.8.11 → wexample_api-6.8.12}/src/wexample_api/common/abstract_gateway.py +0 -0
  14. {wexample_api-6.8.11 → wexample_api-6.8.12}/src/wexample_api/common/http_request_payload.py +0 -0
  15. {wexample_api-6.8.11/src/wexample_api/common → wexample_api-6.8.12/src/wexample_api/const}/__init__.py +0 -0
  16. {wexample_api-6.8.11 → wexample_api-6.8.12}/src/wexample_api/const/http.py +0 -0
  17. {wexample_api-6.8.11/src/wexample_api/common/__pycache__ → wexample_api-6.8.12/src/wexample_api/demo}/__init__.py +0 -0
  18. {wexample_api-6.8.11 → wexample_api-6.8.12}/src/wexample_api/demo/demo_simple_gateway.py +0 -0
  19. {wexample_api-6.8.11/src/wexample_api/const → wexample_api-6.8.12/src/wexample_api/enums}/__init__.py +0 -0
  20. {wexample_api-6.8.11 → wexample_api-6.8.12}/src/wexample_api/enums/http.py +0 -0
  21. {wexample_api-6.8.11/src/wexample_api/const/__pycache__ → wexample_api-6.8.12/src/wexample_api/errors}/__init__.py +0 -0
  22. {wexample_api-6.8.11 → wexample_api-6.8.12}/src/wexample_api/errors/gateway_authentication_error.py +0 -0
  23. {wexample_api-6.8.11 → wexample_api-6.8.12}/src/wexample_api/errors/gateway_connexion_error.py +0 -0
  24. {wexample_api-6.8.11/src/wexample_api/demo → wexample_api-6.8.12/src/wexample_api/middleware}/__init__.py +0 -0
  25. {wexample_api-6.8.11/src/wexample_api/enums → wexample_api-6.8.12/src/wexample_api/models}/__init__.py +0 -0
  26. {wexample_api-6.8.11 → wexample_api-6.8.12}/src/wexample_api/py.typed +0 -0
  27. {wexample_api-6.8.11/src/wexample_api/enums/__pycache__ → wexample_api-6.8.12/tests/common}/__init__.py +0 -0
  28. {wexample_api-6.8.11 → wexample_api-6.8.12}/tests/common/test_http_request_payload.py +0 -0
  29. {wexample_api-6.8.11/src/wexample_api/errors → wexample_api-6.8.12/tests/demo}/__init__.py +0 -0
  30. {wexample_api-6.8.11 → wexample_api-6.8.12}/tests/demo/test_demo_simple_gateway.py +0 -0
  31. {wexample_api-6.8.11/src/wexample_api/middleware → wexample_api-6.8.12/tests/new_architecture}/__init__.py +0 -0
@@ -0,0 +1,114 @@
1
+ Metadata-Version: 2.1
2
+ Name: wexample-api
3
+ Version: 6.8.12
4
+ Summary: Provides an AbstractGateway base class that handles HTTP requests with rate limiting, status-code validation, retry logic, and structured error reporting for building typed API client gateways
5
+ Author-Email: weeger <contact@wexample.com>
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Project-URL: homepage, https://github.com/wexample/python-api
11
+ Requires-Python: >=3.10
12
+ Requires-Dist: attrs>=23.1.0
13
+ Requires-Dist: cattrs>=23.1.0
14
+ Requires-Dist: requests
15
+ Requires-Dist: wexample-helpers>=20.6.0
16
+ Requires-Dist: wexample-prompt>=16.0.7
17
+ Provides-Extra: dev
18
+ Requires-Dist: pytest; extra == "dev"
19
+ Requires-Dist: pytest-cov; extra == "dev"
20
+ Description-Content-Type: text/markdown
21
+
22
+ # api
23
+
24
+ Version: 6.8.12
25
+
26
+ Provides an AbstractGateway base class that handles HTTP requests with rate limiting, status-code validation, retry logic, and structured error reporting for building typed API client gateways
27
+
28
+ ## Table of Contents
29
+
30
+ - [Install](#install)
31
+ - [Tests](#tests)
32
+ - [Roadmap](#roadmap)
33
+ - [Status Compatibility](#status-compatibility)
34
+ - [Useful Links](#useful-links)
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ pip install wexample-api
40
+ ```
41
+
42
+ Requires Python >=3.10.
43
+
44
+ ## Tests
45
+
46
+ This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.
47
+
48
+ ### Installation
49
+
50
+ First, install the required testing dependencies:
51
+ ```bash
52
+ .venv/bin/python -m pip install pytest pytest-cov
53
+ ```
54
+
55
+ ### Basic Usage
56
+
57
+ Run all tests with coverage:
58
+ ```bash
59
+ .venv/bin/python -m pytest --cov --cov-report=html
60
+ ```
61
+
62
+ ### Common Commands
63
+ ```bash
64
+ # Run tests with coverage for a specific module
65
+ .venv/bin/python -m pytest --cov=your_module
66
+
67
+ # Show which lines are not covered
68
+ .venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
69
+
70
+ # Generate an HTML coverage report
71
+ .venv/bin/python -m pytest --cov=your_module --cov-report=html
72
+
73
+ # Combine terminal and HTML reports
74
+ .venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
75
+
76
+ # Run specific test file with coverage
77
+ .venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
78
+ ```
79
+
80
+ ### Viewing HTML Reports
81
+
82
+ After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.
83
+
84
+ ### Coverage Threshold
85
+
86
+ To enforce a minimum coverage percentage:
87
+ ```bash
88
+ .venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
89
+ ```
90
+
91
+ This will cause the test suite to fail if coverage drops below 80%.
92
+
93
+ ## Known Limitations & Roadmap
94
+
95
+ Current limitations and planned features are tracked in the GitHub issues.
96
+
97
+ See the [project roadmap](https://github.com/wexample/python-api/issues) for upcoming features and improvements.
98
+
99
+ ## Status & Compatibility
100
+
101
+ **Maturity**: Production-ready
102
+
103
+ **Python Support**: >=3.10
104
+
105
+ **OS Support**: Linux, macOS, Windows
106
+
107
+ **Status**: Actively maintained
108
+
109
+ ## Useful Links
110
+
111
+ - **Homepage**: https://github.com/wexample/python-api
112
+ - **Issue Tracker**: https://github.com/wexample/python-api/issues
113
+ - **Discussions**: https://github.com/wexample/python-api/discussions
114
+ - **PyPI**: [pypi.org/project/wexample-api](https://pypi.org/project/wexample-api/)
@@ -0,0 +1,93 @@
1
+ # api
2
+
3
+ Version: 6.8.12
4
+
5
+ Provides an AbstractGateway base class that handles HTTP requests with rate limiting, status-code validation, retry logic, and structured error reporting for building typed API client gateways
6
+
7
+ ## Table of Contents
8
+
9
+ - [Install](#install)
10
+ - [Tests](#tests)
11
+ - [Roadmap](#roadmap)
12
+ - [Status Compatibility](#status-compatibility)
13
+ - [Useful Links](#useful-links)
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pip install wexample-api
19
+ ```
20
+
21
+ Requires Python >=3.10.
22
+
23
+ ## Tests
24
+
25
+ This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.
26
+
27
+ ### Installation
28
+
29
+ First, install the required testing dependencies:
30
+ ```bash
31
+ .venv/bin/python -m pip install pytest pytest-cov
32
+ ```
33
+
34
+ ### Basic Usage
35
+
36
+ Run all tests with coverage:
37
+ ```bash
38
+ .venv/bin/python -m pytest --cov --cov-report=html
39
+ ```
40
+
41
+ ### Common Commands
42
+ ```bash
43
+ # Run tests with coverage for a specific module
44
+ .venv/bin/python -m pytest --cov=your_module
45
+
46
+ # Show which lines are not covered
47
+ .venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
48
+
49
+ # Generate an HTML coverage report
50
+ .venv/bin/python -m pytest --cov=your_module --cov-report=html
51
+
52
+ # Combine terminal and HTML reports
53
+ .venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
54
+
55
+ # Run specific test file with coverage
56
+ .venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
57
+ ```
58
+
59
+ ### Viewing HTML Reports
60
+
61
+ After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.
62
+
63
+ ### Coverage Threshold
64
+
65
+ To enforce a minimum coverage percentage:
66
+ ```bash
67
+ .venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
68
+ ```
69
+
70
+ This will cause the test suite to fail if coverage drops below 80%.
71
+
72
+ ## Known Limitations & Roadmap
73
+
74
+ Current limitations and planned features are tracked in the GitHub issues.
75
+
76
+ See the [project roadmap](https://github.com/wexample/python-api/issues) for upcoming features and improvements.
77
+
78
+ ## Status & Compatibility
79
+
80
+ **Maturity**: Production-ready
81
+
82
+ **Python Support**: >=3.10
83
+
84
+ **OS Support**: Linux, macOS, Windows
85
+
86
+ **Status**: Actively maintained
87
+
88
+ ## Useful Links
89
+
90
+ - **Homepage**: https://github.com/wexample/python-api
91
+ - **Issue Tracker**: https://github.com/wexample/python-api/issues
92
+ - **Discussions**: https://github.com/wexample/python-api/discussions
93
+ - **PyPI**: [pypi.org/project/wexample-api](https://pypi.org/project/wexample-api/)
@@ -6,7 +6,7 @@ build-backend = "pdm.backend"
6
6
 
7
7
  [project]
8
8
  name = "wexample-api"
9
- version = "6.8.11"
9
+ version = "6.8.12"
10
10
  description = "Provides an AbstractGateway base class that handles HTTP requests with rate limiting, status-code validation, retry logic, and structured error reporting for building typed API client gateways"
11
11
  authors = [
12
12
  { name = "weeger", email = "contact@wexample.com" },
@@ -21,8 +21,8 @@ dependencies = [
21
21
  "attrs>=23.1.0",
22
22
  "cattrs>=23.1.0",
23
23
  "requests",
24
- "wexample-helpers>=20.5.0",
25
- "wexample-prompt>=16.0.0",
24
+ "wexample-helpers>=20.6.0",
25
+ "wexample-prompt>=16.0.7",
26
26
  ]
27
27
 
28
28
  [project.readme]
@@ -1,276 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: wexample-api
3
- Version: 6.8.11
4
- Summary: Provides an AbstractGateway base class that handles HTTP requests with rate limiting, status-code validation, retry logic, and structured error reporting for building typed API client gateways
5
- Author-Email: weeger <contact@wexample.com>
6
- License: MIT
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: License :: OSI Approved :: MIT License
9
- Classifier: Operating System :: OS Independent
10
- Project-URL: homepage, https://github.com/wexample/python-api
11
- Requires-Python: >=3.10
12
- Requires-Dist: attrs>=23.1.0
13
- Requires-Dist: cattrs>=23.1.0
14
- Requires-Dist: requests
15
- Requires-Dist: wexample-helpers>=20.5.0
16
- Requires-Dist: wexample-prompt>=16.0.0
17
- Provides-Extra: dev
18
- Requires-Dist: pytest; extra == "dev"
19
- Requires-Dist: pytest-cov; extra == "dev"
20
- Description-Content-Type: text/markdown
21
-
22
- # api
23
-
24
- Version: 6.8.11
25
-
26
- `wexample-api` provides an `AbstractGateway` base class for building typed HTTP API client gateways in Python. It wraps `requests` with built-in rate limiting, configurable timeout, status-code validation, exponential-backoff retries, and structured error reporting via `wexample-prompt`, so a concrete gateway only needs to declare a `base_url` and call `make_request`. The package targets Python developers who integrate third-party REST APIs and want to centralise connection handling, logging, and error propagation without writing the same boilerplate for each service.
27
-
28
- ## Table of Contents
29
-
30
- - [Installation](#installation)
31
- - [Quickstart](#quickstart)
32
- - [Tests](#tests)
33
- - [Architecture](#architecture)
34
- - [Integration in the Suite](#integration-in-the-suite)
35
- - [Dependencies](#dependencies)
36
- - [Versioning & Compatibility Policy](#versioning--compatibility-policy)
37
- - [License](#license)
38
- - [About us](#about-us)
39
- - [Known Limitations & Roadmap](#known-limitations--roadmap)
40
- - [Status & Compatibility](#status--compatibility)
41
- - [Useful Links](#useful-links)
42
- - [Migration Notes](#migration-notes)
43
-
44
- ## Installation
45
-
46
- ```bash
47
- pip install wexample-api
48
- ```
49
-
50
- Requires Python >=3.10.
51
-
52
- ## Quickstart
53
-
54
- Install the package:
55
-
56
- ```bash
57
- pip install wexample-api
58
- ```
59
-
60
- Subclass `AbstractGateway`, pass `base_url` and an `IoManager`, then call `make_request`:
61
-
62
- ```python
63
- from wexample_api.common.abstract_gateway import AbstractGateway
64
- from wexample_api.enums.http import HttpMethod
65
- from wexample_helpers.decorator.base_class import base_class
66
- from wexample_prompt.common.io_manager import IoManager
67
-
68
- @base_class
69
- class JsonPlaceholderGateway(AbstractGateway):
70
- def get_post(self, post_id: int) -> dict | None:
71
- response = self.make_request(
72
- endpoint=f"/posts/{post_id}",
73
- method=HttpMethod.GET,
74
- expected_status_codes=200,
75
- )
76
- return response.json() if response else None
77
-
78
- gateway = JsonPlaceholderGateway(
79
- base_url="https://jsonplaceholder.typicode.com",
80
- io=IoManager(),
81
- )
82
-
83
- post = gateway.get_post(1)
84
- print(post["title"])
85
- # sunt aut facere repellat provident occaecati excepturi optio reprehenderit
86
- ```
87
-
88
- `make_request` returns the raw `requests.Response` when the actual status code is in `expected_status_codes`, or `None` when it is not. Omitting `expected_status_codes` accepts any response. The `@base_class` decorator is required: `AbstractGateway` uses `wexample_helpers` field initialisation that depends on it.
89
-
90
- A runnable, annotated version of this example lives at examples/common/http_request_example.py.
91
-
92
- ## Tests
93
-
94
- This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.
95
-
96
- ### Installation
97
-
98
- First, install the required testing dependencies:
99
- ```bash
100
- .venv/bin/python -m pip install pytest pytest-cov
101
- ```
102
-
103
- ### Basic Usage
104
-
105
- Run all tests with coverage:
106
- ```bash
107
- .venv/bin/python -m pytest --cov --cov-report=html
108
- ```
109
-
110
- ### Common Commands
111
- ```bash
112
- # Run tests with coverage for a specific module
113
- .venv/bin/python -m pytest --cov=your_module
114
-
115
- # Show which lines are not covered
116
- .venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
117
-
118
- # Generate an HTML coverage report
119
- .venv/bin/python -m pytest --cov=your_module --cov-report=html
120
-
121
- # Combine terminal and HTML reports
122
- .venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
123
-
124
- # Run specific test file with coverage
125
- .venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
126
- ```
127
-
128
- ### Viewing HTML Reports
129
-
130
- After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.
131
-
132
- ### Coverage Threshold
133
-
134
- To enforce a minimum coverage percentage:
135
- ```bash
136
- .venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
137
- ```
138
-
139
- This will cause the test suite to fail if coverage drops below 80%.
140
-
141
- ## Architecture
142
-
143
- `wexample-api` ships one thing: `AbstractGateway`, a base class callers subclass to build typed HTTP clients. The rest of the package feeds that class — enums for the HTTP vocabulary, a payload dataclass that carries each request's parameters, two error types for the failure modes gateways commonly signal, and a demo subclass that shows the pattern in use.
144
-
145
- ### Modules
146
-
147
- | File | Owns |
148
- |------|------|
149
- | src/wexample_api/common/abstract_gateway.py | `AbstractGateway` — the only class callers subclass |
150
- | src/wexample_api/common/http_request_payload.py | `HttpRequestPayload` — value object assembled for each call |
151
- | src/wexample_api/enums/http.py | `HttpMethod`, `ContentType`, `Header` enums |
152
- | src/wexample_api/const/http.py | `HTTP_METHOD_MAP` — string-to-`HttpMethod` lookup |
153
- | src/wexample_api/errors/gateway_connexion_error.py | `GatewayConnectionError` |
154
- | src/wexample_api/errors/gateway_authentication_error.py | `GatewayAuthenticationError` |
155
- | src/wexample_api/demo/demo_simple_gateway.py | `DemoSimpleGateway` — concrete subclass used in tests |
156
-
157
- `src/wexample_api/middleware/` and `src/wexample_api/models/` are currently empty; they are stubs reserved for a planned rework documented in `.wex/journal/todo/abstract-gateway-rework.md`.
158
-
159
- ### AbstractGateway
160
-
161
- `AbstractGateway` inherits three mixins from `wexample-helpers` and `wexample-prompt`:
162
-
163
- - `WithIoManager` — exposes `self.io` for structured terminal output (`debug`, `error`, `properties`)
164
- - `HasTwoStepInit` — two-phase initialisation; `setup()` is the second phase
165
- - `HasSnakeShortClassNameClassMixin` — `get_class_name_suffix` strips `"GatewayService"` from derived class names
166
-
167
- Its public fields control the request lifecycle:
168
-
169
- - `base_url` — prepended to every endpoint
170
- - `default_headers` — merged into every call's header dict
171
- - `connected` / `rate_limit_delay` / `timeout` — connection and throttle configuration
172
- - `quiet` — suppresses non-error log lines when `True`
173
- - `last_exception` / `last_request_time` — per-instance mutable state written after each call
174
-
175
- Concrete subclasses declare domain methods (e.g. `get_user`, `create_item`) and delegate to `self.make_request`.
176
-
177
- ### HttpRequestPayload
178
-
179
- `HttpRequestPayload` is the internal transfer object for one HTTP call. `make_request` constructs it with `HttpRequestPayload.from_endpoint()`, which joins `base_url` and `endpoint` (stripping duplicate slashes) and coerces a bare `int` in `expected_status_codes` to a one-element list. The payload object then travels into `handle_api_response`, where it provides the URL, method, data, and `call_origin` for log lines and error details.
180
-
181
- ### Call path through make_request
182
-
183
- 1. **Retry wrapper.** If `retries > 0`, the call is handed to `RetryableCallbackManager` from `wexample-helpers`, which re-invokes `make_request` with `raise_exceptions=True` and exponential back-off (`backoff_base_seconds=3`), retrying only on `GatewayError`.
184
-
185
- 2. **Payload assembly.** `HttpRequestPayload.from_endpoint()` constructs the full URL and normalises the status-code argument.
186
-
187
- 3. **Connection.** If `self.connected` is `False`, `connect()` is called; the base implementation sets the flag and returns `True`. Subclasses override this to perform real handshakes.
188
-
189
- 4. **Rate limiting.** `_handle_rate_limiting()` sleeps as needed so that consecutive calls are at least `rate_limit_delay` seconds apart.
190
-
191
- 5. **Body dispatch.** The content type of the merged headers determines how the body travels: `files=` for multipart, `data=` for `application/x-www-form-urlencoded`, `application/octet-stream`, and `text/plain`, `json=` for everything else (including when no `Content-Type` is set).
192
-
193
- 6. **HTTP call.** `requests.request(**request_kwargs)` executes the call. On `RequestException`, a `GatewayError` is created, stored in `last_exception`, and passed to `handle_api_response` with `response=None`; if `raise_exceptions=True` the error is raised instead.
194
-
195
- 7. **Status validation.** If `expected_status_codes` was supplied and the response status is not in the set, a `GatewayError` is created (and raised immediately when `raise_exceptions=True`).
196
-
197
- 8. **Response handling.** `handle_api_response` logs the outcome via `self.io` and returns the `requests.Response` object, or `None` when the call failed and `fatal_on_error` is `False`. When `fatal_on_error` is `True`, it calls `self.io.error(..., fatal=True)`, which terminates the process.
198
-
199
- ### Errors
200
-
201
- Both `GatewayConnectionError` and `GatewayAuthenticationError` subclass `GatewayError` from `wexample-helpers`. `AbstractGateway.make_request` itself raises only `GatewayError`; the two subclasses are available for concrete gateways that need callers to distinguish the failure mode.
202
-
203
- ### External dependencies
204
-
205
- `AbstractGateway` calls `requests.request` directly — the `requests` library is the only HTTP transport. `wexample-prompt` supplies `IoManager` for all output. `wexample-helpers` supplies `RetryableCallbackManager`, `GatewayError`, and the class infrastructure (`base_class` decorator, `public_field`, `HasTwoStepInit`).
206
-
207
- ## Integration in the Suite
208
-
209
- This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
210
-
211
- ### Related Packages
212
-
213
- The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
214
-
215
- ## Dependencies
216
-
217
- - attrs: >=23.1.0
218
- - cattrs: >=23.1.0
219
- - requests:
220
- - wexample-helpers: >=20.5.0
221
- - wexample-prompt: >=16.0.0
222
-
223
- ## Versioning & Compatibility Policy
224
-
225
- Wexample packages follow **Semantic Versioning** (SemVer):
226
-
227
- - **MAJOR**: Breaking changes
228
- - **MINOR**: New features, backward compatible
229
- - **PATCH**: Bug fixes, backward compatible
230
-
231
- We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
232
-
233
- ## License
234
-
235
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
236
-
237
- Free to use in both personal and commercial projects.
238
-
239
- ## About us
240
-
241
- [Wexample](https://wexample.com) stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
242
-
243
- This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
244
-
245
- Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
246
-
247
- Built and maintained by [Romain Weeger](https://weeger.io).
248
-
249
- ## Known Limitations & Roadmap
250
-
251
- Current limitations and planned features are tracked in the GitHub issues.
252
-
253
- See the [project roadmap](https://github.com/wexample/python-api/issues) for upcoming features and improvements.
254
-
255
- ## Status & Compatibility
256
-
257
- **Maturity**: Production-ready
258
-
259
- **Python Support**: >=3.10
260
-
261
- **OS Support**: Linux, macOS, Windows
262
-
263
- **Status**: Actively maintained
264
-
265
- ## Useful Links
266
-
267
- - **Homepage**: https://github.com/wexample/python-api
268
- - **Issue Tracker**: https://github.com/wexample/python-api/issues
269
- - **Discussions**: https://github.com/wexample/python-api/discussions
270
- - **PyPI**: [pypi.org/project/wexample-api](https://pypi.org/project/wexample-api/)
271
-
272
- ## Migration Notes
273
-
274
- When upgrading between major versions, refer to the migration guides in the documentation.
275
-
276
- Breaking changes are clearly documented with upgrade paths and examples.
@@ -1,255 +0,0 @@
1
- # api
2
-
3
- Version: 6.8.11
4
-
5
- `wexample-api` provides an `AbstractGateway` base class for building typed HTTP API client gateways in Python. It wraps `requests` with built-in rate limiting, configurable timeout, status-code validation, exponential-backoff retries, and structured error reporting via `wexample-prompt`, so a concrete gateway only needs to declare a `base_url` and call `make_request`. The package targets Python developers who integrate third-party REST APIs and want to centralise connection handling, logging, and error propagation without writing the same boilerplate for each service.
6
-
7
- ## Table of Contents
8
-
9
- - [Installation](#installation)
10
- - [Quickstart](#quickstart)
11
- - [Tests](#tests)
12
- - [Architecture](#architecture)
13
- - [Integration in the Suite](#integration-in-the-suite)
14
- - [Dependencies](#dependencies)
15
- - [Versioning & Compatibility Policy](#versioning--compatibility-policy)
16
- - [License](#license)
17
- - [About us](#about-us)
18
- - [Known Limitations & Roadmap](#known-limitations--roadmap)
19
- - [Status & Compatibility](#status--compatibility)
20
- - [Useful Links](#useful-links)
21
- - [Migration Notes](#migration-notes)
22
-
23
- ## Installation
24
-
25
- ```bash
26
- pip install wexample-api
27
- ```
28
-
29
- Requires Python >=3.10.
30
-
31
- ## Quickstart
32
-
33
- Install the package:
34
-
35
- ```bash
36
- pip install wexample-api
37
- ```
38
-
39
- Subclass `AbstractGateway`, pass `base_url` and an `IoManager`, then call `make_request`:
40
-
41
- ```python
42
- from wexample_api.common.abstract_gateway import AbstractGateway
43
- from wexample_api.enums.http import HttpMethod
44
- from wexample_helpers.decorator.base_class import base_class
45
- from wexample_prompt.common.io_manager import IoManager
46
-
47
- @base_class
48
- class JsonPlaceholderGateway(AbstractGateway):
49
- def get_post(self, post_id: int) -> dict | None:
50
- response = self.make_request(
51
- endpoint=f"/posts/{post_id}",
52
- method=HttpMethod.GET,
53
- expected_status_codes=200,
54
- )
55
- return response.json() if response else None
56
-
57
- gateway = JsonPlaceholderGateway(
58
- base_url="https://jsonplaceholder.typicode.com",
59
- io=IoManager(),
60
- )
61
-
62
- post = gateway.get_post(1)
63
- print(post["title"])
64
- # sunt aut facere repellat provident occaecati excepturi optio reprehenderit
65
- ```
66
-
67
- `make_request` returns the raw `requests.Response` when the actual status code is in `expected_status_codes`, or `None` when it is not. Omitting `expected_status_codes` accepts any response. The `@base_class` decorator is required: `AbstractGateway` uses `wexample_helpers` field initialisation that depends on it.
68
-
69
- A runnable, annotated version of this example lives at examples/common/http_request_example.py.
70
-
71
- ## Tests
72
-
73
- This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.
74
-
75
- ### Installation
76
-
77
- First, install the required testing dependencies:
78
- ```bash
79
- .venv/bin/python -m pip install pytest pytest-cov
80
- ```
81
-
82
- ### Basic Usage
83
-
84
- Run all tests with coverage:
85
- ```bash
86
- .venv/bin/python -m pytest --cov --cov-report=html
87
- ```
88
-
89
- ### Common Commands
90
- ```bash
91
- # Run tests with coverage for a specific module
92
- .venv/bin/python -m pytest --cov=your_module
93
-
94
- # Show which lines are not covered
95
- .venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
96
-
97
- # Generate an HTML coverage report
98
- .venv/bin/python -m pytest --cov=your_module --cov-report=html
99
-
100
- # Combine terminal and HTML reports
101
- .venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
102
-
103
- # Run specific test file with coverage
104
- .venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
105
- ```
106
-
107
- ### Viewing HTML Reports
108
-
109
- After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.
110
-
111
- ### Coverage Threshold
112
-
113
- To enforce a minimum coverage percentage:
114
- ```bash
115
- .venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
116
- ```
117
-
118
- This will cause the test suite to fail if coverage drops below 80%.
119
-
120
- ## Architecture
121
-
122
- `wexample-api` ships one thing: `AbstractGateway`, a base class callers subclass to build typed HTTP clients. The rest of the package feeds that class — enums for the HTTP vocabulary, a payload dataclass that carries each request's parameters, two error types for the failure modes gateways commonly signal, and a demo subclass that shows the pattern in use.
123
-
124
- ### Modules
125
-
126
- | File | Owns |
127
- |------|------|
128
- | src/wexample_api/common/abstract_gateway.py | `AbstractGateway` — the only class callers subclass |
129
- | src/wexample_api/common/http_request_payload.py | `HttpRequestPayload` — value object assembled for each call |
130
- | src/wexample_api/enums/http.py | `HttpMethod`, `ContentType`, `Header` enums |
131
- | src/wexample_api/const/http.py | `HTTP_METHOD_MAP` — string-to-`HttpMethod` lookup |
132
- | src/wexample_api/errors/gateway_connexion_error.py | `GatewayConnectionError` |
133
- | src/wexample_api/errors/gateway_authentication_error.py | `GatewayAuthenticationError` |
134
- | src/wexample_api/demo/demo_simple_gateway.py | `DemoSimpleGateway` — concrete subclass used in tests |
135
-
136
- `src/wexample_api/middleware/` and `src/wexample_api/models/` are currently empty; they are stubs reserved for a planned rework documented in `.wex/journal/todo/abstract-gateway-rework.md`.
137
-
138
- ### AbstractGateway
139
-
140
- `AbstractGateway` inherits three mixins from `wexample-helpers` and `wexample-prompt`:
141
-
142
- - `WithIoManager` — exposes `self.io` for structured terminal output (`debug`, `error`, `properties`)
143
- - `HasTwoStepInit` — two-phase initialisation; `setup()` is the second phase
144
- - `HasSnakeShortClassNameClassMixin` — `get_class_name_suffix` strips `"GatewayService"` from derived class names
145
-
146
- Its public fields control the request lifecycle:
147
-
148
- - `base_url` — prepended to every endpoint
149
- - `default_headers` — merged into every call's header dict
150
- - `connected` / `rate_limit_delay` / `timeout` — connection and throttle configuration
151
- - `quiet` — suppresses non-error log lines when `True`
152
- - `last_exception` / `last_request_time` — per-instance mutable state written after each call
153
-
154
- Concrete subclasses declare domain methods (e.g. `get_user`, `create_item`) and delegate to `self.make_request`.
155
-
156
- ### HttpRequestPayload
157
-
158
- `HttpRequestPayload` is the internal transfer object for one HTTP call. `make_request` constructs it with `HttpRequestPayload.from_endpoint()`, which joins `base_url` and `endpoint` (stripping duplicate slashes) and coerces a bare `int` in `expected_status_codes` to a one-element list. The payload object then travels into `handle_api_response`, where it provides the URL, method, data, and `call_origin` for log lines and error details.
159
-
160
- ### Call path through make_request
161
-
162
- 1. **Retry wrapper.** If `retries > 0`, the call is handed to `RetryableCallbackManager` from `wexample-helpers`, which re-invokes `make_request` with `raise_exceptions=True` and exponential back-off (`backoff_base_seconds=3`), retrying only on `GatewayError`.
163
-
164
- 2. **Payload assembly.** `HttpRequestPayload.from_endpoint()` constructs the full URL and normalises the status-code argument.
165
-
166
- 3. **Connection.** If `self.connected` is `False`, `connect()` is called; the base implementation sets the flag and returns `True`. Subclasses override this to perform real handshakes.
167
-
168
- 4. **Rate limiting.** `_handle_rate_limiting()` sleeps as needed so that consecutive calls are at least `rate_limit_delay` seconds apart.
169
-
170
- 5. **Body dispatch.** The content type of the merged headers determines how the body travels: `files=` for multipart, `data=` for `application/x-www-form-urlencoded`, `application/octet-stream`, and `text/plain`, `json=` for everything else (including when no `Content-Type` is set).
171
-
172
- 6. **HTTP call.** `requests.request(**request_kwargs)` executes the call. On `RequestException`, a `GatewayError` is created, stored in `last_exception`, and passed to `handle_api_response` with `response=None`; if `raise_exceptions=True` the error is raised instead.
173
-
174
- 7. **Status validation.** If `expected_status_codes` was supplied and the response status is not in the set, a `GatewayError` is created (and raised immediately when `raise_exceptions=True`).
175
-
176
- 8. **Response handling.** `handle_api_response` logs the outcome via `self.io` and returns the `requests.Response` object, or `None` when the call failed and `fatal_on_error` is `False`. When `fatal_on_error` is `True`, it calls `self.io.error(..., fatal=True)`, which terminates the process.
177
-
178
- ### Errors
179
-
180
- Both `GatewayConnectionError` and `GatewayAuthenticationError` subclass `GatewayError` from `wexample-helpers`. `AbstractGateway.make_request` itself raises only `GatewayError`; the two subclasses are available for concrete gateways that need callers to distinguish the failure mode.
181
-
182
- ### External dependencies
183
-
184
- `AbstractGateway` calls `requests.request` directly — the `requests` library is the only HTTP transport. `wexample-prompt` supplies `IoManager` for all output. `wexample-helpers` supplies `RetryableCallbackManager`, `GatewayError`, and the class infrastructure (`base_class` decorator, `public_field`, `HasTwoStepInit`).
185
-
186
- ## Integration in the Suite
187
-
188
- This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
189
-
190
- ### Related Packages
191
-
192
- The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
193
-
194
- ## Dependencies
195
-
196
- - attrs: >=23.1.0
197
- - cattrs: >=23.1.0
198
- - requests:
199
- - wexample-helpers: >=20.5.0
200
- - wexample-prompt: >=16.0.0
201
-
202
- ## Versioning & Compatibility Policy
203
-
204
- Wexample packages follow **Semantic Versioning** (SemVer):
205
-
206
- - **MAJOR**: Breaking changes
207
- - **MINOR**: New features, backward compatible
208
- - **PATCH**: Bug fixes, backward compatible
209
-
210
- We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
211
-
212
- ## License
213
-
214
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
215
-
216
- Free to use in both personal and commercial projects.
217
-
218
- ## About us
219
-
220
- [Wexample](https://wexample.com) stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
221
-
222
- This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
223
-
224
- Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
225
-
226
- Built and maintained by [Romain Weeger](https://weeger.io).
227
-
228
- ## Known Limitations & Roadmap
229
-
230
- Current limitations and planned features are tracked in the GitHub issues.
231
-
232
- See the [project roadmap](https://github.com/wexample/python-api/issues) for upcoming features and improvements.
233
-
234
- ## Status & Compatibility
235
-
236
- **Maturity**: Production-ready
237
-
238
- **Python Support**: >=3.10
239
-
240
- **OS Support**: Linux, macOS, Windows
241
-
242
- **Status**: Actively maintained
243
-
244
- ## Useful Links
245
-
246
- - **Homepage**: https://github.com/wexample/python-api
247
- - **Issue Tracker**: https://github.com/wexample/python-api/issues
248
- - **Discussions**: https://github.com/wexample/python-api/discussions
249
- - **PyPI**: [pypi.org/project/wexample-api](https://pypi.org/project/wexample-api/)
250
-
251
- ## Migration Notes
252
-
253
- When upgrading between major versions, refer to the migration guides in the documentation.
254
-
255
- Breaking changes are clearly documented with upgrade paths and examples.
File without changes
File without changes
File without changes
File without changes