prelude-python-sdk 0.1.0a3__tar.gz → 0.1.0a5__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 (82) hide show
  1. prelude_python_sdk-0.1.0a5/.release-please-manifest.json +3 -0
  2. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/CHANGELOG.md +35 -0
  3. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/PKG-INFO +5 -4
  4. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/README.md +4 -2
  5. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/mypy.ini +4 -1
  6. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/pyproject.toml +2 -2
  7. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/requirements-dev.lock +3 -1
  8. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_base_client.py +8 -4
  9. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_compat.py +3 -5
  10. prelude_python_sdk-0.1.0a5/src/prelude_python_sdk/_utils/_sync.py +71 -0
  11. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_version.py +1 -1
  12. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/types/verification_check_response.py +3 -3
  13. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/types/verification_create_params.py +8 -1
  14. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/types/verification_create_response.py +7 -7
  15. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/types/watch_feed_back_response.py +1 -2
  16. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/types/watch_predict_response.py +3 -3
  17. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/api_resources/test_transactional.py +18 -18
  18. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/api_resources/test_verification.py +2 -0
  19. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_client.py +38 -0
  20. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_models.py +8 -0
  21. prelude_python_sdk-0.1.0a3/.release-please-manifest.json +0 -3
  22. prelude_python_sdk-0.1.0a3/src/prelude_python_sdk/_utils/_sync.py +0 -81
  23. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/.gitignore +0 -0
  24. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/CONTRIBUTING.md +0 -0
  25. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/LICENSE +0 -0
  26. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/SECURITY.md +0 -0
  27. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/api.md +0 -0
  28. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/bin/check-release-environment +0 -0
  29. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/bin/publish-pypi +0 -0
  30. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/examples/.keep +0 -0
  31. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/noxfile.py +0 -0
  32. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/release-please-config.json +0 -0
  33. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/requirements.lock +0 -0
  34. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude/lib/.keep +0 -0
  35. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/__init__.py +0 -0
  36. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_client.py +0 -0
  37. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_constants.py +0 -0
  38. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_exceptions.py +0 -0
  39. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_files.py +0 -0
  40. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_models.py +0 -0
  41. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_qs.py +0 -0
  42. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_resource.py +0 -0
  43. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_response.py +0 -0
  44. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_streaming.py +0 -0
  45. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_types.py +0 -0
  46. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_utils/__init__.py +0 -0
  47. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_utils/_logs.py +0 -0
  48. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_utils/_proxy.py +0 -0
  49. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_utils/_reflection.py +0 -0
  50. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_utils/_streams.py +0 -0
  51. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_utils/_transform.py +0 -0
  52. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_utils/_typing.py +0 -0
  53. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/_utils/_utils.py +0 -0
  54. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/lib/.keep +0 -0
  55. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/py.typed +0 -0
  56. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/resources/__init__.py +0 -0
  57. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/resources/transactional.py +0 -0
  58. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/resources/verification.py +0 -0
  59. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/resources/watch.py +0 -0
  60. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/types/__init__.py +0 -0
  61. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/types/transactional_send_params.py +0 -0
  62. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/types/transactional_send_response.py +0 -0
  63. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/types/verification_check_params.py +0 -0
  64. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/types/watch_feed_back_params.py +0 -0
  65. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_python_sdk/types/watch_predict_params.py +0 -0
  66. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/src/prelude_sdk/lib/.keep +0 -0
  67. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/__init__.py +0 -0
  68. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/api_resources/__init__.py +0 -0
  69. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/api_resources/test_watch.py +0 -0
  70. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/conftest.py +0 -0
  71. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/sample_file.txt +0 -0
  72. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_deepcopy.py +0 -0
  73. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_extract_files.py +0 -0
  74. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_files.py +0 -0
  75. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_qs.py +0 -0
  76. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_required_args.py +0 -0
  77. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_response.py +0 -0
  78. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_streaming.py +0 -0
  79. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_transform.py +0 -0
  80. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_utils/test_proxy.py +0 -0
  81. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/test_utils/test_typing.py +0 -0
  82. {prelude_python_sdk-0.1.0a3 → prelude_python_sdk-0.1.0a5}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.1.0-alpha.5"
3
+ }
@@ -1,5 +1,40 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0-alpha.5 (2024-12-03)
4
+
5
+ Full Changelog: [v0.1.0-alpha.4...v0.1.0-alpha.5](https://github.com/prelude-so/python-sdk/compare/v0.1.0-alpha.4...v0.1.0-alpha.5)
6
+
7
+ ### Bug Fixes
8
+
9
+ * **client:** compat with new httpx 0.28.0 release ([#20](https://github.com/prelude-so/python-sdk/issues/20)) ([2920a25](https://github.com/prelude-so/python-sdk/commit/2920a25772e640ee100d332658b79836ae0e6375))
10
+
11
+
12
+ ### Chores
13
+
14
+ * **internal:** bump pyright ([#21](https://github.com/prelude-so/python-sdk/issues/21)) ([3af0b97](https://github.com/prelude-so/python-sdk/commit/3af0b979ddee008fc9dabd2a3d7ce78727df3e03))
15
+ * **internal:** exclude mypy from running on tests ([#18](https://github.com/prelude-so/python-sdk/issues/18)) ([375162d](https://github.com/prelude-so/python-sdk/commit/375162d3e52d77faeaf3970a531a32ef60a50815))
16
+
17
+ ## 0.1.0-alpha.4 (2024-11-27)
18
+
19
+ Full Changelog: [v0.1.0-alpha.3...v0.1.0-alpha.4](https://github.com/prelude-so/python-sdk/compare/v0.1.0-alpha.3...v0.1.0-alpha.4)
20
+
21
+ ### Features
22
+
23
+ * **api:** update via SDK Studio ([#12](https://github.com/prelude-so/python-sdk/issues/12)) ([380ea22](https://github.com/prelude-so/python-sdk/commit/380ea22a509deeb05b9b27af7b21aae5a70b4380))
24
+ * **api:** update via SDK Studio ([#16](https://github.com/prelude-so/python-sdk/issues/16)) ([a885d0a](https://github.com/prelude-so/python-sdk/commit/a885d0a4aaa978adf582c8743011765dfc65614f))
25
+
26
+
27
+ ### Chores
28
+
29
+ * **internal:** fix compat model_dump method when warnings are passed ([#13](https://github.com/prelude-so/python-sdk/issues/13)) ([7f9b088](https://github.com/prelude-so/python-sdk/commit/7f9b08842698d0eb6911464089583d56db63e0cf))
30
+ * rebuild project due to codegen change ([#10](https://github.com/prelude-so/python-sdk/issues/10)) ([afd8c51](https://github.com/prelude-so/python-sdk/commit/afd8c5127bce604ba78290aaf62659a3c02471a5))
31
+ * remove now unused `cached-property` dep ([#15](https://github.com/prelude-so/python-sdk/issues/15)) ([292303e](https://github.com/prelude-so/python-sdk/commit/292303e362071f1ba1d7ce2e8311653e4c4ec3f6))
32
+
33
+
34
+ ### Documentation
35
+
36
+ * add info log level to readme ([#14](https://github.com/prelude-so/python-sdk/issues/14)) ([ee4b1b2](https://github.com/prelude-so/python-sdk/commit/ee4b1b2cbfbec80d0ec43cb8e7c54cd0acaad7b9))
37
+
3
38
  ## 0.1.0-alpha.3 (2024-11-14)
4
39
 
5
40
  Full Changelog: [v0.1.0-alpha.2...v0.1.0-alpha.3](https://github.com/prelude-so/python-sdk/compare/v0.1.0-alpha.2...v0.1.0-alpha.3)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: prelude-python-sdk
3
- Version: 0.1.0a3
3
+ Version: 0.1.0a5
4
4
  Summary: The official Python library for the Prelude API
5
5
  Project-URL: Homepage, https://github.com/prelude-so/python-sdk
6
6
  Project-URL: Repository, https://github.com/prelude-so/python-sdk
@@ -22,7 +22,6 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Classifier: Typing :: Typed
23
23
  Requires-Python: >=3.8
24
24
  Requires-Dist: anyio<5,>=3.5.0
25
- Requires-Dist: cached-property; python_version < '3.8'
26
25
  Requires-Dist: distro<2,>=1.7.0
27
26
  Requires-Dist: httpx<1,>=0.23.0
28
27
  Requires-Dist: pydantic<3,>=1.9.0
@@ -225,12 +224,14 @@ Note that requests that time out are [retried twice by default](https://github.c
225
224
 
226
225
  We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.
227
226
 
228
- You can enable logging by setting the environment variable `PRELUDE_LOG` to `debug`.
227
+ You can enable logging by setting the environment variable `PRELUDE_LOG` to `info`.
229
228
 
230
229
  ```shell
231
- $ export PRELUDE_LOG=debug
230
+ $ export PRELUDE_LOG=info
232
231
  ```
233
232
 
233
+ Or to `debug` for more verbose logging.
234
+
234
235
  ### How to tell whether `None` means `null` or missing
235
236
 
236
237
  In an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:
@@ -193,12 +193,14 @@ Note that requests that time out are [retried twice by default](#retries).
193
193
 
194
194
  We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.
195
195
 
196
- You can enable logging by setting the environment variable `PRELUDE_LOG` to `debug`.
196
+ You can enable logging by setting the environment variable `PRELUDE_LOG` to `info`.
197
197
 
198
198
  ```shell
199
- $ export PRELUDE_LOG=debug
199
+ $ export PRELUDE_LOG=info
200
200
  ```
201
201
 
202
+ Or to `debug` for more verbose logging.
203
+
202
204
  ### How to tell whether `None` means `null` or missing
203
205
 
204
206
  In an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:
@@ -5,7 +5,10 @@ show_error_codes = True
5
5
  # Exclude _files.py because mypy isn't smart enough to apply
6
6
  # the correct type narrowing and as this is an internal module
7
7
  # it's fine to just use Pyright.
8
- exclude = ^(src/prelude_python_sdk/_files\.py|_dev/.*\.py)$
8
+ #
9
+ # We also exclude our `tests` as mypy doesn't always infer
10
+ # types correctly and Pyright will still catch any type errors.
11
+ exclude = ^(src/prelude_python_sdk/_files\.py|_dev/.*\.py|tests/.*)$
9
12
 
10
13
  strict_equality = True
11
14
  implicit_reexport = True
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "prelude-python-sdk"
3
- version = "0.1.0-alpha.3"
3
+ version = "0.1.0-alpha.5"
4
4
  description = "The official Python library for the Prelude API"
5
5
  dynamic = ["readme"]
6
6
  license = "Apache-2.0"
@@ -14,7 +14,6 @@ dependencies = [
14
14
  "anyio>=3.5.0, <5",
15
15
  "distro>=1.7.0, <2",
16
16
  "sniffio",
17
- "cached-property; python_version < '3.8'",
18
17
  ]
19
18
  requires-python = ">= 3.8"
20
19
  classifiers = [
@@ -55,6 +54,7 @@ dev-dependencies = [
55
54
  "dirty-equals>=0.6.0",
56
55
  "importlib-metadata>=6.7.0",
57
56
  "rich>=13.7.1",
57
+ "nest_asyncio==1.6.0"
58
58
  ]
59
59
 
60
60
  [tool.rye.scripts]
@@ -51,6 +51,7 @@ mdurl==0.1.2
51
51
  mypy==1.13.0
52
52
  mypy-extensions==1.0.0
53
53
  # via mypy
54
+ nest-asyncio==1.6.0
54
55
  nodeenv==1.8.0
55
56
  # via pyright
56
57
  nox==2023.4.22
@@ -67,7 +68,7 @@ pydantic-core==2.23.4
67
68
  # via pydantic
68
69
  pygments==2.18.0
69
70
  # via rich
70
- pyright==1.1.380
71
+ pyright==1.1.389
71
72
  pytest==8.3.3
72
73
  # via pytest-asyncio
73
74
  pytest-asyncio==0.24.0
@@ -96,6 +97,7 @@ typing-extensions==4.12.2
96
97
  # via prelude-python-sdk
97
98
  # via pydantic
98
99
  # via pydantic-core
100
+ # via pyright
99
101
  virtualenv==20.24.5
100
102
  # via nox
101
103
  zipp==3.17.0
@@ -792,6 +792,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
792
792
  custom_query: Mapping[str, object] | None = None,
793
793
  _strict_response_validation: bool,
794
794
  ) -> None:
795
+ kwargs: dict[str, Any] = {}
795
796
  if limits is not None:
796
797
  warnings.warn(
797
798
  "The `connection_pool_limits` argument is deprecated. The `http_client` argument should be passed instead",
@@ -804,6 +805,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
804
805
  limits = DEFAULT_CONNECTION_LIMITS
805
806
 
806
807
  if transport is not None:
808
+ kwargs["transport"] = transport
807
809
  warnings.warn(
808
810
  "The `transport` argument is deprecated. The `http_client` argument should be passed instead",
809
811
  category=DeprecationWarning,
@@ -813,6 +815,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
813
815
  raise ValueError("The `http_client` argument is mutually exclusive with `transport`")
814
816
 
815
817
  if proxies is not None:
818
+ kwargs["proxies"] = proxies
816
819
  warnings.warn(
817
820
  "The `proxies` argument is deprecated. The `http_client` argument should be passed instead",
818
821
  category=DeprecationWarning,
@@ -856,10 +859,9 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
856
859
  base_url=base_url,
857
860
  # cast to a valid type because mypy doesn't understand our type narrowing
858
861
  timeout=cast(Timeout, timeout),
859
- proxies=proxies,
860
- transport=transport,
861
862
  limits=limits,
862
863
  follow_redirects=True,
864
+ **kwargs, # type: ignore
863
865
  )
864
866
 
865
867
  def is_closed(self) -> bool:
@@ -1358,6 +1360,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1358
1360
  custom_headers: Mapping[str, str] | None = None,
1359
1361
  custom_query: Mapping[str, object] | None = None,
1360
1362
  ) -> None:
1363
+ kwargs: dict[str, Any] = {}
1361
1364
  if limits is not None:
1362
1365
  warnings.warn(
1363
1366
  "The `connection_pool_limits` argument is deprecated. The `http_client` argument should be passed instead",
@@ -1370,6 +1373,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1370
1373
  limits = DEFAULT_CONNECTION_LIMITS
1371
1374
 
1372
1375
  if transport is not None:
1376
+ kwargs["transport"] = transport
1373
1377
  warnings.warn(
1374
1378
  "The `transport` argument is deprecated. The `http_client` argument should be passed instead",
1375
1379
  category=DeprecationWarning,
@@ -1379,6 +1383,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1379
1383
  raise ValueError("The `http_client` argument is mutually exclusive with `transport`")
1380
1384
 
1381
1385
  if proxies is not None:
1386
+ kwargs["proxies"] = proxies
1382
1387
  warnings.warn(
1383
1388
  "The `proxies` argument is deprecated. The `http_client` argument should be passed instead",
1384
1389
  category=DeprecationWarning,
@@ -1422,10 +1427,9 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1422
1427
  base_url=base_url,
1423
1428
  # cast to a valid type because mypy doesn't understand our type narrowing
1424
1429
  timeout=cast(Timeout, timeout),
1425
- proxies=proxies,
1426
- transport=transport,
1427
1430
  limits=limits,
1428
1431
  follow_redirects=True,
1432
+ **kwargs, # type: ignore
1429
1433
  )
1430
1434
 
1431
1435
  def is_closed(self) -> bool:
@@ -145,7 +145,8 @@ def model_dump(
145
145
  exclude=exclude,
146
146
  exclude_unset=exclude_unset,
147
147
  exclude_defaults=exclude_defaults,
148
- warnings=warnings,
148
+ # warnings are not supported in Pydantic v1
149
+ warnings=warnings if PYDANTIC_V2 else True,
149
150
  )
150
151
  return cast(
151
152
  "dict[str, Any]",
@@ -213,9 +214,6 @@ if TYPE_CHECKING:
213
214
  # __set__ is not defined at runtime, but @cached_property is designed to be settable
214
215
  def __set__(self, instance: object, value: _T) -> None: ...
215
216
  else:
216
- try:
217
- from functools import cached_property as cached_property
218
- except ImportError:
219
- from cached_property import cached_property as cached_property
217
+ from functools import cached_property as cached_property
220
218
 
221
219
  typed_cached_property = cached_property
@@ -0,0 +1,71 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ import asyncio
5
+ import functools
6
+ import contextvars
7
+ from typing import Any, TypeVar, Callable, Awaitable
8
+ from typing_extensions import ParamSpec
9
+
10
+ T_Retval = TypeVar("T_Retval")
11
+ T_ParamSpec = ParamSpec("T_ParamSpec")
12
+
13
+
14
+ if sys.version_info >= (3, 9):
15
+ to_thread = asyncio.to_thread
16
+ else:
17
+ # backport of https://docs.python.org/3/library/asyncio-task.html#asyncio.to_thread
18
+ # for Python 3.8 support
19
+ async def to_thread(
20
+ func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs
21
+ ) -> Any:
22
+ """Asynchronously run function *func* in a separate thread.
23
+
24
+ Any *args and **kwargs supplied for this function are directly passed
25
+ to *func*. Also, the current :class:`contextvars.Context` is propagated,
26
+ allowing context variables from the main thread to be accessed in the
27
+ separate thread.
28
+
29
+ Returns a coroutine that can be awaited to get the eventual result of *func*.
30
+ """
31
+ loop = asyncio.events.get_running_loop()
32
+ ctx = contextvars.copy_context()
33
+ func_call = functools.partial(ctx.run, func, *args, **kwargs)
34
+ return await loop.run_in_executor(None, func_call)
35
+
36
+
37
+ # inspired by `asyncer`, https://github.com/tiangolo/asyncer
38
+ def asyncify(function: Callable[T_ParamSpec, T_Retval]) -> Callable[T_ParamSpec, Awaitable[T_Retval]]:
39
+ """
40
+ Take a blocking function and create an async one that receives the same
41
+ positional and keyword arguments. For python version 3.9 and above, it uses
42
+ asyncio.to_thread to run the function in a separate thread. For python version
43
+ 3.8, it uses locally defined copy of the asyncio.to_thread function which was
44
+ introduced in python 3.9.
45
+
46
+ Usage:
47
+
48
+ ```python
49
+ def blocking_func(arg1, arg2, kwarg1=None):
50
+ # blocking code
51
+ return result
52
+
53
+
54
+ result = asyncify(blocking_function)(arg1, arg2, kwarg1=value1)
55
+ ```
56
+
57
+ ## Arguments
58
+
59
+ `function`: a blocking regular callable (e.g. a function)
60
+
61
+ ## Return
62
+
63
+ An async function that takes the same positional and keyword arguments as the
64
+ original one, that when called runs the same original function in a thread worker
65
+ and returns the result.
66
+ """
67
+
68
+ async def wrapper(*args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs) -> T_Retval:
69
+ return await to_thread(function, *args, **kwargs)
70
+
71
+ return wrapper
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "prelude_python_sdk"
4
- __version__ = "0.1.0-alpha.3" # x-release-please-version
4
+ __version__ = "0.1.0-alpha.5" # x-release-please-version
@@ -13,6 +13,9 @@ class Metadata(BaseModel):
13
13
 
14
14
 
15
15
  class VerificationCheckResponse(BaseModel):
16
+ status: Literal["success", "failure", "expired_or_not_found"]
17
+ """The status of the check."""
18
+
16
19
  id: Optional[str] = None
17
20
  """The verification identifier."""
18
21
 
@@ -20,6 +23,3 @@ class VerificationCheckResponse(BaseModel):
20
23
  """The metadata for this verification."""
21
24
 
22
25
  request_id: Optional[str] = None
23
-
24
- status: Optional[Literal["success", "failure", "expired"]] = None
25
- """The status of the check."""
@@ -46,6 +46,13 @@ class Options(TypedDict, total=False):
46
46
  devices.
47
47
  """
48
48
 
49
+ custom_code: str
50
+ """The custom code to use for OTP verification.
51
+
52
+ This feature is only available for compatibility purposes and subject to
53
+ Prelude’s approval. Contact us to discuss your use case.
54
+ """
55
+
49
56
  locale: str
50
57
  """
51
58
  A BCP-47 formatted locale string with the language the text message will be sent
@@ -82,7 +89,7 @@ class Signals(TypedDict, total=False):
82
89
  device_model: str
83
90
  """The model of the user's device."""
84
91
 
85
- device_platform: Literal["android", "ios", "web"]
92
+ device_platform: Literal["android", "ios", "ipados", "tvos", "web"]
86
93
  """The type of the user's device."""
87
94
 
88
95
  ip: str
@@ -13,16 +13,16 @@ class Metadata(BaseModel):
13
13
 
14
14
 
15
15
  class VerificationCreateResponse(BaseModel):
16
- id: Optional[str] = None
16
+ id: str
17
17
  """The verification identifier."""
18
18
 
19
+ method: Literal["message"]
20
+ """The method used for verifying this phone number."""
21
+
22
+ status: Literal["success", "retry", "blocked"]
23
+ """The status of the verification."""
24
+
19
25
  metadata: Optional[Metadata] = None
20
26
  """The metadata for this verification."""
21
27
 
22
- method: Optional[Literal["message"]] = None
23
- """The method used for verifying this phone number."""
24
-
25
28
  request_id: Optional[str] = None
26
-
27
- status: Optional[Literal["success", "retry", "blocked"]] = None
28
- """The status of the verification."""
@@ -1,6 +1,5 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
- from typing import Optional
4
3
 
5
4
  from .._models import BaseModel
6
5
 
@@ -8,5 +7,5 @@ __all__ = ["WatchFeedBackResponse"]
8
7
 
9
8
 
10
9
  class WatchFeedBackResponse(BaseModel):
11
- id: Optional[str] = None
10
+ id: str
12
11
  """A unique identifier for your feedback request."""
@@ -20,10 +20,10 @@ class Reasoning(BaseModel):
20
20
 
21
21
 
22
22
  class WatchPredictResponse(BaseModel):
23
- id: Optional[str] = None
23
+ id: str
24
24
  """A unique identifier for your prediction request."""
25
25
 
26
- prediction: Optional[Literal["allow", "block"]] = None
26
+ prediction: Literal["allow", "block"]
27
27
  """A label indicating the trustworthiness of the phone number."""
28
28
 
29
- reasoning: Optional[Reasoning] = None
29
+ reasoning: Reasoning
@@ -23,8 +23,8 @@ class TestTransactional:
23
23
  @parametrize
24
24
  def test_method_send(self, client: Prelude) -> None:
25
25
  transactional = client.transactional.send(
26
- template_id="template_id",
27
- to="to",
26
+ template_id="template_01jd1xq0cffycayqtdkdbv4d61",
27
+ to="+30123456789",
28
28
  )
29
29
  assert_matches_type(TransactionalSendResponse, transactional, path=["response"])
30
30
 
@@ -34,13 +34,13 @@ class TestTransactional:
34
34
  @parametrize
35
35
  def test_method_send_with_all_params(self, client: Prelude) -> None:
36
36
  transactional = client.transactional.send(
37
- template_id="template_id",
38
- to="to",
37
+ template_id="template_01jd1xq0cffycayqtdkdbv4d61",
38
+ to="+30123456789",
39
39
  callback_url="callback_url",
40
40
  correlation_id="correlation_id",
41
41
  expires_at="expires_at",
42
42
  from_="from",
43
- variables={"foo": "string"},
43
+ variables={"foo": "bar"},
44
44
  )
45
45
  assert_matches_type(TransactionalSendResponse, transactional, path=["response"])
46
46
 
@@ -50,8 +50,8 @@ class TestTransactional:
50
50
  @parametrize
51
51
  def test_raw_response_send(self, client: Prelude) -> None:
52
52
  response = client.transactional.with_raw_response.send(
53
- template_id="template_id",
54
- to="to",
53
+ template_id="template_01jd1xq0cffycayqtdkdbv4d61",
54
+ to="+30123456789",
55
55
  )
56
56
 
57
57
  assert response.is_closed is True
@@ -65,8 +65,8 @@ class TestTransactional:
65
65
  @parametrize
66
66
  def test_streaming_response_send(self, client: Prelude) -> None:
67
67
  with client.transactional.with_streaming_response.send(
68
- template_id="template_id",
69
- to="to",
68
+ template_id="template_01jd1xq0cffycayqtdkdbv4d61",
69
+ to="+30123456789",
70
70
  ) as response:
71
71
  assert not response.is_closed
72
72
  assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -86,8 +86,8 @@ class TestAsyncTransactional:
86
86
  @parametrize
87
87
  async def test_method_send(self, async_client: AsyncPrelude) -> None:
88
88
  transactional = await async_client.transactional.send(
89
- template_id="template_id",
90
- to="to",
89
+ template_id="template_01jd1xq0cffycayqtdkdbv4d61",
90
+ to="+30123456789",
91
91
  )
92
92
  assert_matches_type(TransactionalSendResponse, transactional, path=["response"])
93
93
 
@@ -97,13 +97,13 @@ class TestAsyncTransactional:
97
97
  @parametrize
98
98
  async def test_method_send_with_all_params(self, async_client: AsyncPrelude) -> None:
99
99
  transactional = await async_client.transactional.send(
100
- template_id="template_id",
101
- to="to",
100
+ template_id="template_01jd1xq0cffycayqtdkdbv4d61",
101
+ to="+30123456789",
102
102
  callback_url="callback_url",
103
103
  correlation_id="correlation_id",
104
104
  expires_at="expires_at",
105
105
  from_="from",
106
- variables={"foo": "string"},
106
+ variables={"foo": "bar"},
107
107
  )
108
108
  assert_matches_type(TransactionalSendResponse, transactional, path=["response"])
109
109
 
@@ -113,8 +113,8 @@ class TestAsyncTransactional:
113
113
  @parametrize
114
114
  async def test_raw_response_send(self, async_client: AsyncPrelude) -> None:
115
115
  response = await async_client.transactional.with_raw_response.send(
116
- template_id="template_id",
117
- to="to",
116
+ template_id="template_01jd1xq0cffycayqtdkdbv4d61",
117
+ to="+30123456789",
118
118
  )
119
119
 
120
120
  assert response.is_closed is True
@@ -128,8 +128,8 @@ class TestAsyncTransactional:
128
128
  @parametrize
129
129
  async def test_streaming_response_send(self, async_client: AsyncPrelude) -> None:
130
130
  async with async_client.transactional.with_streaming_response.send(
131
- template_id="template_id",
132
- to="to",
131
+ template_id="template_01jd1xq0cffycayqtdkdbv4d61",
132
+ to="+30123456789",
133
133
  ) as response:
134
134
  assert not response.is_closed
135
135
  assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -40,6 +40,7 @@ class TestVerification:
40
40
  metadata={"correlation_id": "correlation_id"},
41
41
  options={
42
42
  "app_realm": "app_realm",
43
+ "custom_code": "custom_code",
43
44
  "locale": "el-GR",
44
45
  "sender_id": "sender_id",
45
46
  "template_id": "template_id",
@@ -153,6 +154,7 @@ class TestAsyncVerification:
153
154
  metadata={"correlation_id": "correlation_id"},
154
155
  options={
155
156
  "app_realm": "app_realm",
157
+ "custom_code": "custom_code",
156
158
  "locale": "el-GR",
157
159
  "sender_id": "sender_id",
158
160
  "template_id": "template_id",
@@ -4,11 +4,14 @@ from __future__ import annotations
4
4
 
5
5
  import gc
6
6
  import os
7
+ import sys
7
8
  import json
8
9
  import asyncio
9
10
  import inspect
11
+ import subprocess
10
12
  import tracemalloc
11
13
  from typing import Any, Union, cast
14
+ from textwrap import dedent
12
15
  from unittest import mock
13
16
  from typing_extensions import Literal
14
17
 
@@ -1672,3 +1675,38 @@ class TestAsyncPrelude:
1672
1675
  )
1673
1676
 
1674
1677
  assert response.http_request.headers.get("x-stainless-retry-count") == "42"
1678
+
1679
+ def test_get_platform(self) -> None:
1680
+ # A previous implementation of asyncify could leave threads unterminated when
1681
+ # used with nest_asyncio.
1682
+ #
1683
+ # Since nest_asyncio.apply() is global and cannot be un-applied, this
1684
+ # test is run in a separate process to avoid affecting other tests.
1685
+ test_code = dedent("""
1686
+ import asyncio
1687
+ import nest_asyncio
1688
+ import threading
1689
+
1690
+ from prelude_python_sdk._utils import asyncify
1691
+ from prelude_python_sdk._base_client import get_platform
1692
+
1693
+ async def test_main() -> None:
1694
+ result = await asyncify(get_platform)()
1695
+ print(result)
1696
+ for thread in threading.enumerate():
1697
+ print(thread.name)
1698
+
1699
+ nest_asyncio.apply()
1700
+ asyncio.run(test_main())
1701
+ """)
1702
+ with subprocess.Popen(
1703
+ [sys.executable, "-c", test_code],
1704
+ text=True,
1705
+ ) as process:
1706
+ try:
1707
+ process.wait(2)
1708
+ if process.returncode:
1709
+ raise AssertionError("calling get_platform using asyncify resulted in a non-zero exit code")
1710
+ except subprocess.TimeoutExpired as e:
1711
+ process.kill()
1712
+ raise AssertionError("calling get_platform using asyncify resulted in a hung process") from e
@@ -561,6 +561,14 @@ def test_forwards_compat_model_dump_method() -> None:
561
561
  m.model_dump(warnings=False)
562
562
 
563
563
 
564
+ def test_compat_method_no_error_for_warnings() -> None:
565
+ class Model(BaseModel):
566
+ foo: Optional[str]
567
+
568
+ m = Model(foo="hello")
569
+ assert isinstance(model_dump(m, warnings=False), dict)
570
+
571
+
564
572
  def test_to_json() -> None:
565
573
  class Model(BaseModel):
566
574
  foo: Optional[str] = Field(alias="FOO", default=None)
@@ -1,3 +0,0 @@
1
- {
2
- ".": "0.1.0-alpha.3"
3
- }
@@ -1,81 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import functools
4
- from typing import TypeVar, Callable, Awaitable
5
- from typing_extensions import ParamSpec
6
-
7
- import anyio
8
- import anyio.to_thread
9
-
10
- from ._reflection import function_has_argument
11
-
12
- T_Retval = TypeVar("T_Retval")
13
- T_ParamSpec = ParamSpec("T_ParamSpec")
14
-
15
-
16
- # copied from `asyncer`, https://github.com/tiangolo/asyncer
17
- def asyncify(
18
- function: Callable[T_ParamSpec, T_Retval],
19
- *,
20
- cancellable: bool = False,
21
- limiter: anyio.CapacityLimiter | None = None,
22
- ) -> Callable[T_ParamSpec, Awaitable[T_Retval]]:
23
- """
24
- Take a blocking function and create an async one that receives the same
25
- positional and keyword arguments, and that when called, calls the original function
26
- in a worker thread using `anyio.to_thread.run_sync()`. Internally,
27
- `asyncer.asyncify()` uses the same `anyio.to_thread.run_sync()`, but it supports
28
- keyword arguments additional to positional arguments and it adds better support for
29
- autocompletion and inline errors for the arguments of the function called and the
30
- return value.
31
-
32
- If the `cancellable` option is enabled and the task waiting for its completion is
33
- cancelled, the thread will still run its course but its return value (or any raised
34
- exception) will be ignored.
35
-
36
- Use it like this:
37
-
38
- ```Python
39
- def do_work(arg1, arg2, kwarg1="", kwarg2="") -> str:
40
- # Do work
41
- return "Some result"
42
-
43
-
44
- result = await to_thread.asyncify(do_work)("spam", "ham", kwarg1="a", kwarg2="b")
45
- print(result)
46
- ```
47
-
48
- ## Arguments
49
-
50
- `function`: a blocking regular callable (e.g. a function)
51
- `cancellable`: `True` to allow cancellation of the operation
52
- `limiter`: capacity limiter to use to limit the total amount of threads running
53
- (if omitted, the default limiter is used)
54
-
55
- ## Return
56
-
57
- An async function that takes the same positional and keyword arguments as the
58
- original one, that when called runs the same original function in a thread worker
59
- and returns the result.
60
- """
61
-
62
- async def wrapper(*args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs) -> T_Retval:
63
- partial_f = functools.partial(function, *args, **kwargs)
64
-
65
- # In `v4.1.0` anyio added the `abandon_on_cancel` argument and deprecated the old
66
- # `cancellable` argument, so we need to use the new `abandon_on_cancel` to avoid
67
- # surfacing deprecation warnings.
68
- if function_has_argument(anyio.to_thread.run_sync, "abandon_on_cancel"):
69
- return await anyio.to_thread.run_sync(
70
- partial_f,
71
- abandon_on_cancel=cancellable,
72
- limiter=limiter,
73
- )
74
-
75
- return await anyio.to_thread.run_sync(
76
- partial_f,
77
- cancellable=cancellable,
78
- limiter=limiter,
79
- )
80
-
81
- return wrapper