RESTFly 2.0.4__tar.gz → 2.0.5__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 (34) hide show
  1. {restfly-2.0.4 → restfly-2.0.5}/PKG-INFO +19 -2
  2. {restfly-2.0.4 → restfly-2.0.5}/RESTFly.egg-info/PKG-INFO +19 -2
  3. restfly-2.0.5/RESTFly.egg-info/requires.txt +6 -0
  4. restfly-2.0.5/pyproject.toml +74 -0
  5. {restfly-2.0.4 → restfly-2.0.5}/restfly/_async.py +12 -6
  6. {restfly-2.0.4 → restfly-2.0.5}/restfly/_base.py +0 -4
  7. {restfly-2.0.4 → restfly-2.0.5}/restfly/_sync.py +12 -6
  8. restfly-2.0.5/restfly/_version.py +1 -0
  9. {restfly-2.0.4 → restfly-2.0.5}/tests/test_client_async.py +7 -0
  10. {restfly-2.0.4 → restfly-2.0.5}/tests/test_client_sync.py +7 -0
  11. restfly-2.0.4/RESTFly.egg-info/requires.txt +0 -3
  12. restfly-2.0.4/pyproject.toml +0 -54
  13. restfly-2.0.4/restfly/_version.py +0 -1
  14. {restfly-2.0.4 → restfly-2.0.5}/LICENSE +0 -0
  15. {restfly-2.0.4 → restfly-2.0.5}/README.md +0 -0
  16. {restfly-2.0.4 → restfly-2.0.5}/RESTFly.egg-info/SOURCES.txt +0 -0
  17. {restfly-2.0.4 → restfly-2.0.5}/RESTFly.egg-info/dependency_links.txt +0 -0
  18. {restfly-2.0.4 → restfly-2.0.5}/RESTFly.egg-info/top_level.txt +0 -0
  19. {restfly-2.0.4 → restfly-2.0.5}/restfly/__init__.py +0 -0
  20. {restfly-2.0.4 → restfly-2.0.5}/restfly/_errors.py +0 -0
  21. {restfly-2.0.4 → restfly-2.0.5}/restfly/_iterator.py +0 -0
  22. {restfly-2.0.4 → restfly-2.0.5}/restfly/_models.py +0 -0
  23. {restfly-2.0.4 → restfly-2.0.5}/restfly/_utils.py +0 -0
  24. {restfly-2.0.4 → restfly-2.0.5}/restfly/types.py +0 -0
  25. {restfly-2.0.4 → restfly-2.0.5}/setup.cfg +0 -0
  26. {restfly-2.0.4 → restfly-2.0.5}/tests/test_apimodel.py +0 -0
  27. {restfly-2.0.4 → restfly-2.0.5}/tests/test_client_base.py +0 -0
  28. {restfly-2.0.4 → restfly-2.0.5}/tests/test_endpoint_async.py +0 -0
  29. {restfly-2.0.4 → restfly-2.0.5}/tests/test_endpoint_sync.py +0 -0
  30. {restfly-2.0.4 → restfly-2.0.5}/tests/test_errors.py +0 -0
  31. {restfly-2.0.4 → restfly-2.0.5}/tests/test_examples_httpbin_client.py +0 -0
  32. {restfly-2.0.4 → restfly-2.0.5}/tests/test_iterators.py +0 -0
  33. {restfly-2.0.4 → restfly-2.0.5}/tests/test_utils_assignment.py +0 -0
  34. {restfly-2.0.4 → restfly-2.0.5}/tests/test_utils_unmarshal.py +0 -0
@@ -1,13 +1,30 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RESTFly
3
- Version: 2.0.4
3
+ Version: 2.0.5
4
4
  Summary: Write your own API Client libraries quickly.
5
- Requires-Python: >=3.12
5
+ Project-URL: Homepage, https://restfly.rtfd.io
6
+ Project-URL: Documentation, https://restfly.rtfd.io
7
+ Project-URL: Repository, https://github.com/librestfly/restfly
8
+ Project-URL: Issues, https://github.com/librestfly/restfly/issues
9
+ Project-URL: Releases, https://github.com/librestfly/restfly/tags
10
+ Keywords: rest,api
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Programming Language :: Python :: 3.15
19
+ Classifier: Topic :: Internet :: WWW/HTTP
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Requires-Python: >=3.11
6
22
  Description-Content-Type: text/markdown
7
23
  License-File: LICENSE
8
24
  Requires-Dist: httpx>=0.28.1
9
25
  Requires-Dist: pydantic>=2.12.5
10
26
  Requires-Dist: pydantic-xml>=2.19.0
27
+ Requires-Dist: typing-extensions>=4.16.0; python_full_version < "3.12"
11
28
  Dynamic: license-file
12
29
 
13
30
  ![RESTFly Logo](docs/_static/logo-light-hero.svg)
@@ -1,13 +1,30 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RESTFly
3
- Version: 2.0.4
3
+ Version: 2.0.5
4
4
  Summary: Write your own API Client libraries quickly.
5
- Requires-Python: >=3.12
5
+ Project-URL: Homepage, https://restfly.rtfd.io
6
+ Project-URL: Documentation, https://restfly.rtfd.io
7
+ Project-URL: Repository, https://github.com/librestfly/restfly
8
+ Project-URL: Issues, https://github.com/librestfly/restfly/issues
9
+ Project-URL: Releases, https://github.com/librestfly/restfly/tags
10
+ Keywords: rest,api
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Programming Language :: Python :: 3.15
19
+ Classifier: Topic :: Internet :: WWW/HTTP
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Requires-Python: >=3.11
6
22
  Description-Content-Type: text/markdown
7
23
  License-File: LICENSE
8
24
  Requires-Dist: httpx>=0.28.1
9
25
  Requires-Dist: pydantic>=2.12.5
10
26
  Requires-Dist: pydantic-xml>=2.19.0
27
+ Requires-Dist: typing-extensions>=4.16.0; python_full_version < "3.12"
11
28
  Dynamic: license-file
12
29
 
13
30
  ![RESTFly Logo](docs/_static/logo-light-hero.svg)
@@ -0,0 +1,6 @@
1
+ httpx>=0.28.1
2
+ pydantic>=2.12.5
3
+ pydantic-xml>=2.19.0
4
+
5
+ [:python_full_version < "3.12"]
6
+ typing-extensions>=4.16.0
@@ -0,0 +1,74 @@
1
+ [project]
2
+ name = "RESTFly"
3
+ version = "2.0.5"
4
+ description = "Write your own API Client libraries quickly."
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ dependencies = [
8
+ "httpx>=0.28.1",
9
+ "pydantic>=2.12.5",
10
+ "pydantic-xml>=2.19.0",
11
+ "typing-extensions>=4.16.0 ; python_full_version < '3.12'",
12
+ ]
13
+ classifiers = [
14
+ "Development Status :: 5 - Production/Stable",
15
+ "Intended Audience :: Developers",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ "Programming Language :: Python :: 3.14",
21
+ "Programming Language :: Python :: 3.15",
22
+ "Topic :: Internet :: WWW/HTTP",
23
+ "Topic :: Software Development :: Libraries",
24
+ ]
25
+ keywords = ["rest", "api"]
26
+
27
+ [project.urls]
28
+ Homepage = "https://restfly.rtfd.io"
29
+ Documentation = "https://restfly.rtfd.io"
30
+ Repository = "https://github.com/librestfly/restfly"
31
+ Issues = "https://github.com/librestfly/restfly/issues"
32
+ Releases = "https://github.com/librestfly/restfly/tags"
33
+
34
+ [dependency-groups]
35
+ dev = [
36
+ "build>=1.4.3",
37
+ "hatch>=1.16.5",
38
+ "mypy>=1.20.0",
39
+ "pre-commit>=4.5.1",
40
+ "ptpython>=3.0.32",
41
+ "pylsp-mypy>=0.7.1",
42
+ "rust-just>=1.50.0",
43
+ ]
44
+ docs = [
45
+ "furo>=2025.12.19",
46
+ "sphinx>=9.0.0",
47
+ "sphinxcontrib-mermaid>=2.0.1",
48
+ ]
49
+ test = [
50
+ "mypy>=1.20.0",
51
+ "pytest>=9.0.2",
52
+ "pytest-asyncio>=1.3.0",
53
+ "pytest-cov>=7.1.0",
54
+ "pytest-httpx>=0.36.0",
55
+ "ruff>=0.15.11",
56
+ "rust-just>=1.50.0",
57
+ "ty>=0.0.32",
58
+ ]
59
+
60
+ [tool.pytest.ini_options]
61
+ pythonpath = [".", "examples"]
62
+ addopts = "--cov-report term-missing:skip-covered --cov=restfly"
63
+ testpaths = ["tests"]
64
+ asyncio_mode = "auto"
65
+
66
+ [tool.ty.src]
67
+ respect-ignore-files = true
68
+
69
+ [tool.ty.environment]
70
+ extra-paths = ["./examples"]
71
+
72
+ [tool.esbonio.sphinx]
73
+ buildArguments = ["sphinx-build", "-M", "html", "docs", "docs/_build"]
74
+ pythonCommand = ["uv", "run", "python"]
@@ -1,11 +1,17 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import random
4
+ import sys
4
5
  from asyncio import sleep
5
- from collections.abc import AsyncIterator, Callable
6
+ from collections.abc import AsyncGenerator, Callable
6
7
  from contextlib import asynccontextmanager
7
8
  from ssl import SSLContext
8
- from typing import Any, overload, override
9
+ from typing import Any, overload
10
+
11
+ if sys.version_info < (3, 12):
12
+ from typing_extensions import override
13
+ else:
14
+ from typing import override
9
15
 
10
16
  from ._base import APIBaseEndpoint, APIClientBase, APIError
11
17
  from ._errors import ErrorStatus, RetryError
@@ -38,7 +44,6 @@ from .types import (
38
44
  ResponseXMLModel,
39
45
  TimeoutTypes,
40
46
  UseClientDefault,
41
- codes,
42
47
  )
43
48
 
44
49
 
@@ -90,7 +95,7 @@ class AsyncHTTPClientVerbs:
90
95
  extensions: RequestExtensions | None = None,
91
96
  max_retries: int | None = None,
92
97
  error_map: dict[int, ErrorStatus] | None = None,
93
- ) -> AsyncIterator[Response]:
98
+ ) -> AsyncGenerator[Response]:
94
99
  """
95
100
  Construct and send an HTTP request and stream the response back. This is an
96
101
  alternative method to making a call to _request that also supports closing of
@@ -1535,11 +1540,12 @@ class AsyncAPIClient(APIClientBase, AsyncHTTPClientVerbs):
1535
1540
  response = await self._client.send(
1536
1541
  request, auth=auth, follow_redirects=follow_redirects, stream=stream
1537
1542
  )
1543
+ is_ok = response.status_code >= 200 and response.status_code < 300
1538
1544
 
1539
1545
  # If the response is ok, then we should return the response. If a model is
1540
1546
  # presented to us, then we will pass the model to the unmarshal utility to
1541
1547
  # handle transitioning the data into the expected class.
1542
- if response.status_code == codes.OK and response_model:
1548
+ if is_ok and response_model:
1543
1549
  return unmarshal(
1544
1550
  response=response,
1545
1551
  model=response_model,
@@ -1549,7 +1555,7 @@ class AsyncAPIClient(APIClientBase, AsyncHTTPClientVerbs):
1549
1555
  )
1550
1556
 
1551
1557
  # If no model was passed, then simply return the response object.
1552
- elif response.status_code == codes.OK:
1558
+ elif is_ok:
1553
1559
  return response
1554
1560
 
1555
1561
  # As the response wasn't ok, let's grab the ErrorStatus object that relates
@@ -50,9 +50,6 @@ class APIClientBase:
50
50
  _base_url: str = ""
51
51
  """ The base URL fragment to prefix all API calls with. """
52
52
 
53
- # _client: Client | AsyncClient
54
- """ HTTPX Client Session object """
55
-
56
53
  _json_load_kwargs: dict[str, Any]
57
54
  """ Client-level Pydantic BaseModel.model_validate kwargs """
58
55
 
@@ -322,7 +319,6 @@ class APIBaseEndpoint:
322
319
  The same logging handler that the client has, it also exists here for convenience.
323
320
  """
324
321
 
325
- # _client: APIClientBase
326
322
  """
327
323
  The client object that this endpoint is associated with. Provided here in order to
328
324
  interact with other endpoints that may be grafted to the client.
@@ -1,11 +1,17 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import random
4
- from collections.abc import Callable, Iterator
4
+ import sys
5
+ from collections.abc import Callable, Generator
5
6
  from contextlib import contextmanager
6
7
  from ssl import SSLContext
7
8
  from time import sleep
8
- from typing import Any, Final, Self, overload, override
9
+ from typing import Any, Self, overload
10
+
11
+ if sys.version_info < (3, 12):
12
+ from typing_extensions import override
13
+ else:
14
+ from typing import override
9
15
 
10
16
  from ._base import APIBaseEndpoint, APIClientBase
11
17
  from ._errors import APIError, ErrorStatus, RetryError
@@ -37,7 +43,6 @@ from .types import (
37
43
  ResponseModel,
38
44
  TimeoutTypes,
39
45
  UseClientDefault,
40
- codes,
41
46
  )
42
47
 
43
48
 
@@ -89,7 +94,7 @@ class HTTPClientVerbs:
89
94
  extensions: RequestExtensions | None = None,
90
95
  max_retries: int | None = None,
91
96
  error_map: dict[int, ErrorStatus] | None = None,
92
- ) -> Iterator[Response]:
97
+ ) -> Generator[Response]:
93
98
  """
94
99
  Construct and send an HTTP request and stream the response back. This is an
95
100
  alternative method to making a call to _request that also supports closing of
@@ -1529,11 +1534,12 @@ class APIClient(APIClientBase, HTTPClientVerbs):
1529
1534
  response = self._client.send(
1530
1535
  request, auth=auth, follow_redirects=follow_redirects, stream=stream
1531
1536
  )
1537
+ is_ok = response.status_code >= 200 and response.status_code < 300
1532
1538
 
1533
1539
  # If the response is ok, then we should return the response. If a model is
1534
1540
  # presented to us, then we will pass the model to the unmarshal utility to
1535
1541
  # handle transitioning the data into the expected class.
1536
- if response.status_code == codes.OK and response_model:
1542
+ if is_ok and response_model:
1537
1543
  return unmarshal(
1538
1544
  response=response,
1539
1545
  model=response_model,
@@ -1543,7 +1549,7 @@ class APIClient(APIClientBase, HTTPClientVerbs):
1543
1549
  )
1544
1550
 
1545
1551
  # If no model was passed, then simply return the response object.
1546
- elif response.status_code == codes.OK:
1552
+ elif is_ok:
1547
1553
  return response
1548
1554
 
1549
1555
  # As the response wasn't ok, let's grab the ErrorStatus object that relates
@@ -0,0 +1 @@
1
+ version = "2.0.5"
@@ -276,3 +276,10 @@ async def test_client_stream_method(client: AsyncAPIClient, httpx_mock: HTTPXMoc
276
276
  b.write(data)
277
277
  b.seek(0)
278
278
  assert json.load(b) == payload
279
+
280
+
281
+ async def test_client_204_response(client: AsyncAPIClient, httpx_mock: HTTPXMock):
282
+ httpx_mock.add_response(status_code=204, url="https://httpbin.org/get")
283
+ resp = await client._get("/get")
284
+ assert isinstance(resp, Response)
285
+ assert resp.status_code == 204
@@ -308,3 +308,10 @@ def test_client_stream_method(client: APIClient, httpx_mock: HTTPXMock):
308
308
  b.write(data)
309
309
  b.seek(0)
310
310
  assert json.load(b) == payload
311
+
312
+
313
+ def test_client_204_response(client: APIClient, httpx_mock: HTTPXMock):
314
+ httpx_mock.add_response(status_code=204, url="https://httpbin.org/get")
315
+ resp = client._get("/get")
316
+ assert isinstance(resp, Response)
317
+ assert resp.status_code == 204
@@ -1,3 +0,0 @@
1
- httpx>=0.28.1
2
- pydantic>=2.12.5
3
- pydantic-xml>=2.19.0
@@ -1,54 +0,0 @@
1
- [project]
2
- name = "RESTFly"
3
- version = "2.0.4"
4
- description = "Write your own API Client libraries quickly."
5
- readme = "README.md"
6
- requires-python = ">=3.12"
7
- dependencies = [
8
- "httpx>=0.28.1",
9
- "pydantic>=2.12.5",
10
- "pydantic-xml>=2.19.0",
11
- ]
12
-
13
- [dependency-groups]
14
- dev = [
15
- "build>=1.4.3",
16
- "hatch>=1.16.5",
17
- "mypy>=1.20.0",
18
- "pre-commit>=4.5.1",
19
- "ptpython>=3.0.32",
20
- "pylsp-mypy>=0.7.1",
21
- "rust-just>=1.50.0",
22
- ]
23
- docs = [
24
- "furo>=2025.12.19",
25
- "sphinx>=9.1.0",
26
- "sphinxcontrib-mermaid>=2.0.1",
27
- ]
28
- test = [
29
- "mypy>=1.20.0",
30
- "pytest>=9.0.2",
31
- "pytest-asyncio>=1.3.0",
32
- "pytest-cov>=7.1.0",
33
- "pytest-httpx>=0.36.0",
34
- "ruff>=0.15.11",
35
- "rust-just>=1.50.0",
36
- "ty>=0.0.32",
37
- ]
38
-
39
- [tool.pytest.ini_options]
40
- pythonpath = [".", "examples"]
41
- addopts = "--cov-report term-missing:skip-covered --cov=restfly"
42
- testpaths = ["tests"]
43
- asyncio_mode = "auto"
44
-
45
- [tool.ty.src]
46
- respect-ignore-files = true
47
-
48
-
49
- [tool.ty.environment]
50
- extra-paths = ["./examples"]
51
-
52
- [tool.esbonio.sphinx]
53
- buildArguments = ["sphinx-build", "-M", "html", "docs", "docs/_build"]
54
- pythonCommand = ["uv", "run", "python"]
@@ -1 +0,0 @@
1
- version = "2.0.3"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes