isaacus 0.6.1__tar.gz → 0.8.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 (84) hide show
  1. {isaacus-0.6.1 → isaacus-0.8.0}/.gitignore +0 -1
  2. isaacus-0.8.0/.release-please-manifest.json +3 -0
  3. {isaacus-0.6.1 → isaacus-0.8.0}/CHANGELOG.md +59 -0
  4. {isaacus-0.6.1 → isaacus-0.8.0}/CONTRIBUTING.md +1 -2
  5. {isaacus-0.6.1 → isaacus-0.8.0}/PKG-INFO +43 -3
  6. {isaacus-0.6.1 → isaacus-0.8.0}/README.md +38 -2
  7. {isaacus-0.6.1 → isaacus-0.8.0}/SECURITY.md +2 -2
  8. {isaacus-0.6.1 → isaacus-0.8.0}/bin/check-release-environment +1 -1
  9. {isaacus-0.6.1 → isaacus-0.8.0}/pyproject.toml +6 -2
  10. {isaacus-0.6.1 → isaacus-0.8.0}/requirements-dev.lock +33 -2
  11. {isaacus-0.6.1 → isaacus-0.8.0}/requirements.lock +29 -2
  12. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/__init__.py +2 -1
  13. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_base_client.py +53 -4
  14. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_models.py +33 -7
  15. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_types.py +2 -0
  16. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_version.py +1 -1
  17. {isaacus-0.6.1 → isaacus-0.8.0}/tests/api_resources/classifications/test_universal.py +3 -1
  18. {isaacus-0.6.1 → isaacus-0.8.0}/tests/api_resources/extractions/test_qa.py +3 -1
  19. {isaacus-0.6.1 → isaacus-0.8.0}/tests/api_resources/test_rerankings.py +3 -1
  20. {isaacus-0.6.1 → isaacus-0.8.0}/tests/conftest.py +39 -6
  21. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_client.py +130 -75
  22. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_models.py +73 -1
  23. isaacus-0.6.1/.release-please-manifest.json +0 -3
  24. {isaacus-0.6.1 → isaacus-0.8.0}/LICENSE +0 -0
  25. {isaacus-0.6.1 → isaacus-0.8.0}/api.md +0 -0
  26. {isaacus-0.6.1 → isaacus-0.8.0}/bin/publish-pypi +0 -0
  27. {isaacus-0.6.1 → isaacus-0.8.0}/examples/.keep +0 -0
  28. {isaacus-0.6.1 → isaacus-0.8.0}/mypy.ini +0 -0
  29. {isaacus-0.6.1 → isaacus-0.8.0}/noxfile.py +0 -0
  30. {isaacus-0.6.1 → isaacus-0.8.0}/release-please-config.json +0 -0
  31. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_client.py +0 -0
  32. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_compat.py +0 -0
  33. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_constants.py +0 -0
  34. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_exceptions.py +0 -0
  35. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_files.py +0 -0
  36. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_qs.py +0 -0
  37. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_resource.py +0 -0
  38. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_response.py +0 -0
  39. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_streaming.py +0 -0
  40. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_utils/__init__.py +0 -0
  41. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_utils/_logs.py +0 -0
  42. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_utils/_proxy.py +0 -0
  43. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_utils/_reflection.py +0 -0
  44. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_utils/_resources_proxy.py +0 -0
  45. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_utils/_streams.py +0 -0
  46. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_utils/_sync.py +0 -0
  47. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_utils/_transform.py +0 -0
  48. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_utils/_typing.py +0 -0
  49. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/_utils/_utils.py +0 -0
  50. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/lib/.keep +0 -0
  51. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/py.typed +0 -0
  52. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/resources/__init__.py +0 -0
  53. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/resources/classifications/__init__.py +0 -0
  54. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/resources/classifications/classifications.py +0 -0
  55. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/resources/classifications/universal.py +0 -0
  56. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/resources/extractions/__init__.py +0 -0
  57. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/resources/extractions/extractions.py +0 -0
  58. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/resources/extractions/qa.py +0 -0
  59. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/resources/rerankings.py +0 -0
  60. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/types/__init__.py +0 -0
  61. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/types/classifications/__init__.py +0 -0
  62. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/types/classifications/universal_classification.py +0 -0
  63. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/types/classifications/universal_create_params.py +0 -0
  64. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/types/extractions/__init__.py +0 -0
  65. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/types/extractions/answer_extraction.py +0 -0
  66. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/types/extractions/qa_create_params.py +0 -0
  67. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/types/reranking.py +0 -0
  68. {isaacus-0.6.1 → isaacus-0.8.0}/src/isaacus/types/reranking_create_params.py +0 -0
  69. {isaacus-0.6.1 → isaacus-0.8.0}/tests/__init__.py +0 -0
  70. {isaacus-0.6.1 → isaacus-0.8.0}/tests/api_resources/__init__.py +0 -0
  71. {isaacus-0.6.1 → isaacus-0.8.0}/tests/api_resources/classifications/__init__.py +0 -0
  72. {isaacus-0.6.1 → isaacus-0.8.0}/tests/api_resources/extractions/__init__.py +0 -0
  73. {isaacus-0.6.1 → isaacus-0.8.0}/tests/sample_file.txt +0 -0
  74. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_deepcopy.py +0 -0
  75. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_extract_files.py +0 -0
  76. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_files.py +0 -0
  77. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_qs.py +0 -0
  78. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_required_args.py +0 -0
  79. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_response.py +0 -0
  80. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_streaming.py +0 -0
  81. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_transform.py +0 -0
  82. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_utils/test_proxy.py +0 -0
  83. {isaacus-0.6.1 → isaacus-0.8.0}/tests/test_utils/test_typing.py +0 -0
  84. {isaacus-0.6.1 → isaacus-0.8.0}/tests/utils.py +0 -0
@@ -1,5 +1,4 @@
1
1
  .prism.log
2
- .vscode
3
2
  _dev
4
3
 
5
4
  __pycache__
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.8.0"
3
+ }
@@ -1,5 +1,64 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.0 (2025-07-25)
4
+
5
+ Full Changelog: [v0.7.0...v0.8.0](https://github.com/isaacus-dev/isaacus-python/compare/v0.7.0...v0.8.0)
6
+
7
+ ### Features
8
+
9
+ * clean up environment call outs ([3ee6948](https://github.com/isaacus-dev/isaacus-python/commit/3ee69481b6a6198503d06c6aa137ba69f7940db6))
10
+ * **client:** add support for aiohttp ([fba17e9](https://github.com/isaacus-dev/isaacus-python/commit/fba17e98279aa6d93dd3c9b6f9b95246b4fac813))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **ci:** correct conditional ([53c81d9](https://github.com/isaacus-dev/isaacus-python/commit/53c81d9e14882ae83a72c15481c8933226e668fa))
16
+ * **ci:** release-doctor — report correct token name ([3cb8672](https://github.com/isaacus-dev/isaacus-python/commit/3cb8672052edf1d1c4e72a5866fde3776d43a4e2))
17
+ * **client:** correctly parse binary response | stream ([5e316fe](https://github.com/isaacus-dev/isaacus-python/commit/5e316feaf5270e54321a917a9cd59efb2c42fcb3))
18
+ * **client:** don't send Content-Type header on GET requests ([2a5d531](https://github.com/isaacus-dev/isaacus-python/commit/2a5d531e7553aa012352d9dd85d280f4374b7ae7))
19
+ * **parsing:** correctly handle nested discriminated unions ([c5d5715](https://github.com/isaacus-dev/isaacus-python/commit/c5d571569cdafad9bd1392baf232287dca72855d))
20
+ * **parsing:** ignore empty metadata ([dd88d17](https://github.com/isaacus-dev/isaacus-python/commit/dd88d179302966445c63831f4b6f20491fe5632e))
21
+ * **parsing:** parse extra field types ([ba334c7](https://github.com/isaacus-dev/isaacus-python/commit/ba334c75676c37da235abfddd7c9746f89307c22))
22
+ * **tests:** fix: tests which call HTTP endpoints directly with the example parameters ([638c7c4](https://github.com/isaacus-dev/isaacus-python/commit/638c7c4df7ecbc189480a0cba2d93125f9b97d2f))
23
+
24
+
25
+ ### Chores
26
+
27
+ * **ci:** change upload type ([e79525c](https://github.com/isaacus-dev/isaacus-python/commit/e79525c4ffe9601c3b7c5e39a94c93c248cfbf33))
28
+ * **ci:** enable for pull requests ([29244fd](https://github.com/isaacus-dev/isaacus-python/commit/29244fdb33a5706480e1c7314099a14ae177ee06))
29
+ * **ci:** only run for pushes and fork pull requests ([94ed1eb](https://github.com/isaacus-dev/isaacus-python/commit/94ed1ebf9fc4111236f1db2a5d326f081079bdc8))
30
+ * **internal:** bump pinned h11 dep ([5836163](https://github.com/isaacus-dev/isaacus-python/commit/58361635226de79f5ff27e953ec03dfeb392b3e0))
31
+ * **internal:** codegen related update ([cdfe0be](https://github.com/isaacus-dev/isaacus-python/commit/cdfe0beceeeaa21e4a24b6cdc86264dcaa3808f1))
32
+ * **internal:** update conftest.py ([e4a5936](https://github.com/isaacus-dev/isaacus-python/commit/e4a59368bd7d42d65fd368b03a208b2aa32a9144))
33
+ * **package:** mark python 3.13 as supported ([0f7b5d1](https://github.com/isaacus-dev/isaacus-python/commit/0f7b5d1c588adf28b502727948dceaa9ed54ee86))
34
+ * **project:** add settings file for vscode ([d6435b0](https://github.com/isaacus-dev/isaacus-python/commit/d6435b09a03f202867843ee83737b319ccef4ea6))
35
+ * **readme:** fix version rendering on pypi ([b09f1ad](https://github.com/isaacus-dev/isaacus-python/commit/b09f1ad5ce2624d23a32fc1d966f7d9703cd4ad3))
36
+ * **readme:** update badges ([cd48569](https://github.com/isaacus-dev/isaacus-python/commit/cd485693063d03f092d5be7f024b0f7e23da0897))
37
+ * **tests:** add tests for httpx client instantiation & proxies ([5d2c5b9](https://github.com/isaacus-dev/isaacus-python/commit/5d2c5b9e20bd80acd05240217b6be3991b46aae2))
38
+ * **tests:** run tests in parallel ([3f0e6da](https://github.com/isaacus-dev/isaacus-python/commit/3f0e6da6d9c6d9cd46cfa382da55a0b6a07d9d49))
39
+ * **tests:** skip some failing tests on the latest python versions ([b2b3fa8](https://github.com/isaacus-dev/isaacus-python/commit/b2b3fa82b87e9cc7e23164cc5589b3e157e635df))
40
+
41
+
42
+ ### Documentation
43
+
44
+ * **client:** fix httpx.Timeout documentation reference ([b68d394](https://github.com/isaacus-dev/isaacus-python/commit/b68d3944df0ca58b7df3e89e06e90799f7ade25b))
45
+
46
+ ## 0.7.0 (2025-06-03)
47
+
48
+ Full Changelog: [v0.6.1...v0.7.0](https://github.com/isaacus-dev/isaacus-python/compare/v0.6.1...v0.7.0)
49
+
50
+ ### Features
51
+
52
+ * **client:** add follow_redirects request option ([40221d5](https://github.com/isaacus-dev/isaacus-python/commit/40221d56d887dcfb693d67883a47403c680f6062))
53
+
54
+
55
+ ### Chores
56
+
57
+ * **ci:** fix installation instructions ([157308b](https://github.com/isaacus-dev/isaacus-python/commit/157308b71eefc75af2e76acd10664eb5633b9110))
58
+ * **ci:** upload sdks to package manager ([9f9915c](https://github.com/isaacus-dev/isaacus-python/commit/9f9915ce18a288ab157b8f75c21de724507267d7))
59
+ * **docs:** grammar improvements ([eb2766f](https://github.com/isaacus-dev/isaacus-python/commit/eb2766f59d477222ae93c06c32e06ab1ff94645f))
60
+ * **docs:** remove reference to rye shell ([96a0239](https://github.com/isaacus-dev/isaacus-python/commit/96a0239f103261c69ead957c62fdee27497192ed))
61
+
3
62
  ## 0.6.1 (2025-05-10)
4
63
 
5
64
  Full Changelog: [v0.6.0...v0.6.1](https://github.com/isaacus-dev/isaacus-python/compare/v0.6.0...v0.6.1)
@@ -17,8 +17,7 @@ $ rye sync --all-features
17
17
  You can then run scripts using `rye run python script.py` or by activating the virtual environment:
18
18
 
19
19
  ```sh
20
- $ rye shell
21
- # or manually activate - https://docs.python.org/3/library/venv.html#how-venvs-work
20
+ # Activate the virtual environment - https://docs.python.org/3/library/venv.html#how-venvs-work
22
21
  $ source .venv/bin/activate
23
22
 
24
23
  # now you can omit the `rye run` prefix
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: isaacus
3
- Version: 0.6.1
3
+ Version: 0.8.0
4
4
  Summary: The official Python library for the isaacus API
5
5
  Project-URL: Homepage, https://github.com/isaacus-dev/isaacus-python
6
6
  Project-URL: Repository, https://github.com/isaacus-dev/isaacus-python
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.9
18
18
  Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
21
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
23
  Classifier: Typing :: Typed
23
24
  Requires-Python: >=3.8
@@ -27,11 +28,15 @@ Requires-Dist: httpx<1,>=0.23.0
27
28
  Requires-Dist: pydantic<3,>=1.9.0
28
29
  Requires-Dist: sniffio
29
30
  Requires-Dist: typing-extensions<5,>=4.10
31
+ Provides-Extra: aiohttp
32
+ Requires-Dist: aiohttp; extra == 'aiohttp'
33
+ Requires-Dist: httpx-aiohttp>=0.1.8; extra == 'aiohttp'
30
34
  Description-Content-Type: text/markdown
31
35
 
32
36
  # Isaacus Python API library
33
37
 
34
- [![PyPI version](https://img.shields.io/pypi/v/isaacus.svg)](https://pypi.org/project/isaacus/)
38
+ <!-- prettier-ignore -->
39
+ [![PyPI version](https://img.shields.io/pypi/v/isaacus.svg?label=pypi%20(stable))](https://pypi.org/project/isaacus/)
35
40
 
36
41
  The Isaacus Python library provides convenient access to the Isaacus REST API from any Python 3.8+
37
42
  application. The library includes type definitions for all request params and response fields,
@@ -103,6 +108,41 @@ asyncio.run(main())
103
108
 
104
109
  Functionality between the synchronous and asynchronous clients is otherwise identical.
105
110
 
111
+ ### With aiohttp
112
+
113
+ By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.
114
+
115
+ You can enable this by installing `aiohttp`:
116
+
117
+ ```sh
118
+ # install from PyPI
119
+ pip install isaacus[aiohttp]
120
+ ```
121
+
122
+ Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
123
+
124
+ ```python
125
+ import asyncio
126
+ from isaacus import DefaultAioHttpClient
127
+ from isaacus import AsyncIsaacus
128
+
129
+
130
+ async def main() -> None:
131
+ async with AsyncIsaacus(
132
+ api_key="My API Key",
133
+ http_client=DefaultAioHttpClient(),
134
+ ) as client:
135
+ universal_classification = await client.classifications.universal.create(
136
+ model="kanon-universal-classifier",
137
+ query="This is a confidentiality clause.",
138
+ texts=["I agree not to tell anyone about the document."],
139
+ )
140
+ print(universal_classification.classifications)
141
+
142
+
143
+ asyncio.run(main())
144
+ ```
145
+
106
146
  ## Using types
107
147
 
108
148
  Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:
@@ -207,7 +247,7 @@ client.with_options(max_retries=5).classifications.universal.create(
207
247
  ### Timeouts
208
248
 
209
249
  By default requests time out after 1 minute. You can configure this with a `timeout` option,
210
- which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object:
250
+ which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:
211
251
 
212
252
  ```python
213
253
  from isaacus import Isaacus
@@ -1,6 +1,7 @@
1
1
  # Isaacus Python API library
2
2
 
3
- [![PyPI version](https://img.shields.io/pypi/v/isaacus.svg)](https://pypi.org/project/isaacus/)
3
+ <!-- prettier-ignore -->
4
+ [![PyPI version](https://img.shields.io/pypi/v/isaacus.svg?label=pypi%20(stable))](https://pypi.org/project/isaacus/)
4
5
 
5
6
  The Isaacus Python library provides convenient access to the Isaacus REST API from any Python 3.8+
6
7
  application. The library includes type definitions for all request params and response fields,
@@ -72,6 +73,41 @@ asyncio.run(main())
72
73
 
73
74
  Functionality between the synchronous and asynchronous clients is otherwise identical.
74
75
 
76
+ ### With aiohttp
77
+
78
+ By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.
79
+
80
+ You can enable this by installing `aiohttp`:
81
+
82
+ ```sh
83
+ # install from PyPI
84
+ pip install isaacus[aiohttp]
85
+ ```
86
+
87
+ Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
88
+
89
+ ```python
90
+ import asyncio
91
+ from isaacus import DefaultAioHttpClient
92
+ from isaacus import AsyncIsaacus
93
+
94
+
95
+ async def main() -> None:
96
+ async with AsyncIsaacus(
97
+ api_key="My API Key",
98
+ http_client=DefaultAioHttpClient(),
99
+ ) as client:
100
+ universal_classification = await client.classifications.universal.create(
101
+ model="kanon-universal-classifier",
102
+ query="This is a confidentiality clause.",
103
+ texts=["I agree not to tell anyone about the document."],
104
+ )
105
+ print(universal_classification.classifications)
106
+
107
+
108
+ asyncio.run(main())
109
+ ```
110
+
75
111
  ## Using types
76
112
 
77
113
  Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:
@@ -176,7 +212,7 @@ client.with_options(max_retries=5).classifications.universal.create(
176
212
  ### Timeouts
177
213
 
178
214
  By default requests time out after 1 minute. You can configure this with a `timeout` option,
179
- which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object:
215
+ which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:
180
216
 
181
217
  ```python
182
218
  from isaacus import Isaacus
@@ -16,11 +16,11 @@ before making any information public.
16
16
  ## Reporting Non-SDK Related Security Issues
17
17
 
18
18
  If you encounter security issues that are not directly related to SDKs but pertain to the services
19
- or products provided by Isaacus please follow the respective company's security reporting guidelines.
19
+ or products provided by Isaacus, please follow the respective company's security reporting guidelines.
20
20
 
21
21
  ### Isaacus Terms and Policies
22
22
 
23
- Please contact security@isaacus.com for any questions or concerns regarding security of our services.
23
+ Please contact security@isaacus.com for any questions or concerns regarding the security of our services.
24
24
 
25
25
  ---
26
26
 
@@ -3,7 +3,7 @@
3
3
  errors=()
4
4
 
5
5
  if [ -z "${PYPI_TOKEN}" ]; then
6
- errors+=("The ISAACUS_PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
6
+ errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
7
7
  fi
8
8
 
9
9
  lenErrors=${#errors[@]}
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "isaacus"
3
- version = "0.6.1"
3
+ version = "0.8.0"
4
4
  description = "The official Python library for the isaacus API"
5
5
  dynamic = ["readme"]
6
6
  license = "Apache-2.0"
@@ -24,6 +24,7 @@ classifiers = [
24
24
  "Programming Language :: Python :: 3.10",
25
25
  "Programming Language :: Python :: 3.11",
26
26
  "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
27
28
  "Operating System :: OS Independent",
28
29
  "Operating System :: POSIX",
29
30
  "Operating System :: MacOS",
@@ -37,6 +38,8 @@ classifiers = [
37
38
  Homepage = "https://github.com/isaacus-dev/isaacus-python"
38
39
  Repository = "https://github.com/isaacus-dev/isaacus-python"
39
40
 
41
+ [project.optional-dependencies]
42
+ aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"]
40
43
 
41
44
  [tool.rye]
42
45
  managed = true
@@ -54,6 +57,7 @@ dev-dependencies = [
54
57
  "importlib-metadata>=6.7.0",
55
58
  "rich>=13.7.1",
56
59
  "nest_asyncio==1.6.0",
60
+ "pytest-xdist>=3.6.1",
57
61
  ]
58
62
 
59
63
  [tool.rye.scripts]
@@ -125,7 +129,7 @@ replacement = '[\1](https://github.com/isaacus-dev/isaacus-python/tree/main/\g<2
125
129
 
126
130
  [tool.pytest.ini_options]
127
131
  testpaths = ["tests"]
128
- addopts = "--tb=short"
132
+ addopts = "--tb=short -n auto"
129
133
  xfail_strict = true
130
134
  asyncio_mode = "auto"
131
135
  asyncio_default_fixture_loop_scope = "session"
@@ -10,6 +10,13 @@
10
10
  # universal: false
11
11
 
12
12
  -e file:.
13
+ aiohappyeyeballs==2.6.1
14
+ # via aiohttp
15
+ aiohttp==3.12.8
16
+ # via httpx-aiohttp
17
+ # via isaacus
18
+ aiosignal==1.3.2
19
+ # via aiohttp
13
20
  annotated-types==0.6.0
14
21
  # via pydantic
15
22
  anyio==4.4.0
@@ -17,6 +24,10 @@ anyio==4.4.0
17
24
  # via isaacus
18
25
  argcomplete==3.1.2
19
26
  # via nox
27
+ async-timeout==5.0.1
28
+ # via aiohttp
29
+ attrs==25.3.0
30
+ # via aiohttp
20
31
  certifi==2023.7.22
21
32
  # via httpcore
22
33
  # via httpx
@@ -30,18 +41,27 @@ distro==1.8.0
30
41
  exceptiongroup==1.2.2
31
42
  # via anyio
32
43
  # via pytest
44
+ execnet==2.1.1
45
+ # via pytest-xdist
33
46
  filelock==3.12.4
34
47
  # via virtualenv
35
- h11==0.14.0
48
+ frozenlist==1.6.2
49
+ # via aiohttp
50
+ # via aiosignal
51
+ h11==0.16.0
36
52
  # via httpcore
37
- httpcore==1.0.2
53
+ httpcore==1.0.9
38
54
  # via httpx
39
55
  httpx==0.28.1
56
+ # via httpx-aiohttp
40
57
  # via isaacus
41
58
  # via respx
59
+ httpx-aiohttp==0.1.8
60
+ # via isaacus
42
61
  idna==3.4
43
62
  # via anyio
44
63
  # via httpx
64
+ # via yarl
45
65
  importlib-metadata==7.0.0
46
66
  iniconfig==2.0.0
47
67
  # via pytest
@@ -49,6 +69,9 @@ markdown-it-py==3.0.0
49
69
  # via rich
50
70
  mdurl==0.1.2
51
71
  # via markdown-it-py
72
+ multidict==6.4.4
73
+ # via aiohttp
74
+ # via yarl
52
75
  mypy==1.14.1
53
76
  mypy-extensions==1.0.0
54
77
  # via mypy
@@ -63,6 +86,9 @@ platformdirs==3.11.0
63
86
  # via virtualenv
64
87
  pluggy==1.5.0
65
88
  # via pytest
89
+ propcache==0.3.1
90
+ # via aiohttp
91
+ # via yarl
66
92
  pydantic==2.10.3
67
93
  # via isaacus
68
94
  pydantic-core==2.27.1
@@ -72,7 +98,9 @@ pygments==2.18.0
72
98
  pyright==1.1.399
73
99
  pytest==8.3.3
74
100
  # via pytest-asyncio
101
+ # via pytest-xdist
75
102
  pytest-asyncio==0.24.0
103
+ pytest-xdist==3.7.0
76
104
  python-dateutil==2.8.2
77
105
  # via time-machine
78
106
  pytz==2023.3.post1
@@ -94,11 +122,14 @@ tomli==2.0.2
94
122
  typing-extensions==4.12.2
95
123
  # via anyio
96
124
  # via isaacus
125
+ # via multidict
97
126
  # via mypy
98
127
  # via pydantic
99
128
  # via pydantic-core
100
129
  # via pyright
101
130
  virtualenv==20.24.5
102
131
  # via nox
132
+ yarl==1.20.0
133
+ # via aiohttp
103
134
  zipp==3.17.0
104
135
  # via importlib-metadata
@@ -10,11 +10,22 @@
10
10
  # universal: false
11
11
 
12
12
  -e file:.
13
+ aiohappyeyeballs==2.6.1
14
+ # via aiohttp
15
+ aiohttp==3.12.8
16
+ # via httpx-aiohttp
17
+ # via isaacus
18
+ aiosignal==1.3.2
19
+ # via aiohttp
13
20
  annotated-types==0.6.0
14
21
  # via pydantic
15
22
  anyio==4.4.0
16
23
  # via httpx
17
24
  # via isaacus
25
+ async-timeout==5.0.1
26
+ # via aiohttp
27
+ attrs==25.3.0
28
+ # via aiohttp
18
29
  certifi==2023.7.22
19
30
  # via httpcore
20
31
  # via httpx
@@ -22,15 +33,28 @@ distro==1.8.0
22
33
  # via isaacus
23
34
  exceptiongroup==1.2.2
24
35
  # via anyio
25
- h11==0.14.0
36
+ frozenlist==1.6.2
37
+ # via aiohttp
38
+ # via aiosignal
39
+ h11==0.16.0
26
40
  # via httpcore
27
- httpcore==1.0.2
41
+ httpcore==1.0.9
28
42
  # via httpx
29
43
  httpx==0.28.1
44
+ # via httpx-aiohttp
45
+ # via isaacus
46
+ httpx-aiohttp==0.1.8
30
47
  # via isaacus
31
48
  idna==3.4
32
49
  # via anyio
33
50
  # via httpx
51
+ # via yarl
52
+ multidict==6.4.4
53
+ # via aiohttp
54
+ # via yarl
55
+ propcache==0.3.1
56
+ # via aiohttp
57
+ # via yarl
34
58
  pydantic==2.10.3
35
59
  # via isaacus
36
60
  pydantic-core==2.27.1
@@ -41,5 +65,8 @@ sniffio==1.3.0
41
65
  typing-extensions==4.12.2
42
66
  # via anyio
43
67
  # via isaacus
68
+ # via multidict
44
69
  # via pydantic
45
70
  # via pydantic-core
71
+ yarl==1.20.0
72
+ # via aiohttp
@@ -26,7 +26,7 @@ from ._exceptions import (
26
26
  UnprocessableEntityError,
27
27
  APIResponseValidationError,
28
28
  )
29
- from ._base_client import DefaultHttpxClient, DefaultAsyncHttpxClient
29
+ from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient
30
30
  from ._utils._logs import setup_logging as _setup_logging
31
31
 
32
32
  __all__ = [
@@ -68,6 +68,7 @@ __all__ = [
68
68
  "DEFAULT_CONNECTION_LIMITS",
69
69
  "DefaultHttpxClient",
70
70
  "DefaultAsyncHttpxClient",
71
+ "DefaultAioHttpClient",
71
72
  ]
72
73
 
73
74
  if not _t.TYPE_CHECKING:
@@ -504,6 +504,15 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
504
504
  # work around https://github.com/encode/httpx/discussions/2880
505
505
  kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")}
506
506
 
507
+ is_body_allowed = options.method.lower() != "get"
508
+
509
+ if is_body_allowed:
510
+ kwargs["json"] = json_data if is_given(json_data) else None
511
+ kwargs["files"] = files
512
+ else:
513
+ headers.pop("Content-Type", None)
514
+ kwargs.pop("data", None)
515
+
507
516
  # TODO: report this error to httpx
508
517
  return self._client.build_request( # pyright: ignore[reportUnknownMemberType]
509
518
  headers=headers,
@@ -515,8 +524,6 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
515
524
  # so that passing a `TypedDict` doesn't cause an error.
516
525
  # https://github.com/microsoft/pyright/issues/3526#event-6715453066
517
526
  params=self.qs.stringify(cast(Mapping[str, Any], params)) if params else None,
518
- json=json_data if is_given(json_data) else None,
519
- files=files,
520
527
  **kwargs,
521
528
  )
522
529
 
@@ -935,6 +942,9 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
935
942
  if self.custom_auth is not None:
936
943
  kwargs["auth"] = self.custom_auth
937
944
 
945
+ if options.follow_redirects is not None:
946
+ kwargs["follow_redirects"] = options.follow_redirects
947
+
938
948
  log.debug("Sending HTTP Request: %s %s", request.method, request.url)
939
949
 
940
950
  response = None
@@ -1043,7 +1053,14 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
1043
1053
  ) -> ResponseT:
1044
1054
  origin = get_origin(cast_to) or cast_to
1045
1055
 
1046
- if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
1056
+ if (
1057
+ inspect.isclass(origin)
1058
+ and issubclass(origin, BaseAPIResponse)
1059
+ # we only want to actually return the custom BaseAPIResponse class if we're
1060
+ # returning the raw response, or if we're not streaming SSE, as if we're streaming
1061
+ # SSE then `cast_to` doesn't actively reflect the type we need to parse into
1062
+ and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
1063
+ ):
1047
1064
  if not issubclass(origin, APIResponse):
1048
1065
  raise TypeError(f"API Response types must subclass {APIResponse}; Received {origin}")
1049
1066
 
@@ -1254,6 +1271,24 @@ class _DefaultAsyncHttpxClient(httpx.AsyncClient):
1254
1271
  super().__init__(**kwargs)
1255
1272
 
1256
1273
 
1274
+ try:
1275
+ import httpx_aiohttp
1276
+ except ImportError:
1277
+
1278
+ class _DefaultAioHttpClient(httpx.AsyncClient):
1279
+ def __init__(self, **_kwargs: Any) -> None:
1280
+ raise RuntimeError("To use the aiohttp client you must have installed the package with the `aiohttp` extra")
1281
+ else:
1282
+
1283
+ class _DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore
1284
+ def __init__(self, **kwargs: Any) -> None:
1285
+ kwargs.setdefault("timeout", DEFAULT_TIMEOUT)
1286
+ kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS)
1287
+ kwargs.setdefault("follow_redirects", True)
1288
+
1289
+ super().__init__(**kwargs)
1290
+
1291
+
1257
1292
  if TYPE_CHECKING:
1258
1293
  DefaultAsyncHttpxClient = httpx.AsyncClient
1259
1294
  """An alias to `httpx.AsyncClient` that provides the same defaults that this SDK
@@ -1262,8 +1297,12 @@ if TYPE_CHECKING:
1262
1297
  This is useful because overriding the `http_client` with your own instance of
1263
1298
  `httpx.AsyncClient` will result in httpx's defaults being used, not ours.
1264
1299
  """
1300
+
1301
+ DefaultAioHttpClient = httpx.AsyncClient
1302
+ """An alias to `httpx.AsyncClient` that changes the default HTTP transport to `aiohttp`."""
1265
1303
  else:
1266
1304
  DefaultAsyncHttpxClient = _DefaultAsyncHttpxClient
1305
+ DefaultAioHttpClient = _DefaultAioHttpClient
1267
1306
 
1268
1307
 
1269
1308
  class AsyncHttpxClientWrapper(DefaultAsyncHttpxClient):
@@ -1435,6 +1474,9 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1435
1474
  if self.custom_auth is not None:
1436
1475
  kwargs["auth"] = self.custom_auth
1437
1476
 
1477
+ if options.follow_redirects is not None:
1478
+ kwargs["follow_redirects"] = options.follow_redirects
1479
+
1438
1480
  log.debug("Sending HTTP Request: %s %s", request.method, request.url)
1439
1481
 
1440
1482
  response = None
@@ -1543,7 +1585,14 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1543
1585
  ) -> ResponseT:
1544
1586
  origin = get_origin(cast_to) or cast_to
1545
1587
 
1546
- if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
1588
+ if (
1589
+ inspect.isclass(origin)
1590
+ and issubclass(origin, BaseAPIResponse)
1591
+ # we only want to actually return the custom BaseAPIResponse class if we're
1592
+ # returning the raw response, or if we're not streaming SSE, as if we're streaming
1593
+ # SSE then `cast_to` doesn't actively reflect the type we need to parse into
1594
+ and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
1595
+ ):
1547
1596
  if not issubclass(origin, AsyncAPIResponse):
1548
1597
  raise TypeError(f"API Response types must subclass {AsyncAPIResponse}; Received {origin}")
1549
1598