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.
- {restfly-2.0.4 → restfly-2.0.5}/PKG-INFO +19 -2
- {restfly-2.0.4 → restfly-2.0.5}/RESTFly.egg-info/PKG-INFO +19 -2
- restfly-2.0.5/RESTFly.egg-info/requires.txt +6 -0
- restfly-2.0.5/pyproject.toml +74 -0
- {restfly-2.0.4 → restfly-2.0.5}/restfly/_async.py +12 -6
- {restfly-2.0.4 → restfly-2.0.5}/restfly/_base.py +0 -4
- {restfly-2.0.4 → restfly-2.0.5}/restfly/_sync.py +12 -6
- restfly-2.0.5/restfly/_version.py +1 -0
- {restfly-2.0.4 → restfly-2.0.5}/tests/test_client_async.py +7 -0
- {restfly-2.0.4 → restfly-2.0.5}/tests/test_client_sync.py +7 -0
- restfly-2.0.4/RESTFly.egg-info/requires.txt +0 -3
- restfly-2.0.4/pyproject.toml +0 -54
- restfly-2.0.4/restfly/_version.py +0 -1
- {restfly-2.0.4 → restfly-2.0.5}/LICENSE +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/README.md +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/RESTFly.egg-info/SOURCES.txt +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/RESTFly.egg-info/dependency_links.txt +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/RESTFly.egg-info/top_level.txt +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/restfly/__init__.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/restfly/_errors.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/restfly/_iterator.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/restfly/_models.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/restfly/_utils.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/restfly/types.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/setup.cfg +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/tests/test_apimodel.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/tests/test_client_base.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/tests/test_endpoint_async.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/tests/test_endpoint_sync.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/tests/test_errors.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/tests/test_examples_httpbin_client.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/tests/test_iterators.py +0 -0
- {restfly-2.0.4 → restfly-2.0.5}/tests/test_utils_assignment.py +0 -0
- {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.
|
|
3
|
+
Version: 2.0.5
|
|
4
4
|
Summary: Write your own API Client libraries quickly.
|
|
5
|
-
|
|
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
|

|
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: RESTFly
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.5
|
|
4
4
|
Summary: Write your own API Client libraries quickly.
|
|
5
|
-
|
|
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
|

|
|
@@ -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
|
|
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
|
|
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
|
-
) ->
|
|
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
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
-
) ->
|
|
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
|
|
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
|
|
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
|
restfly-2.0.4/pyproject.toml
DELETED
|
@@ -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
|
|
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
|