spitch 1.23.0__tar.gz → 1.24.1__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.

Potentially problematic release.


This version of spitch might be problematic. Click here for more details.

Files changed (76) hide show
  1. spitch-1.24.1/.release-please-manifest.json +3 -0
  2. {spitch-1.23.0 → spitch-1.24.1}/CHANGELOG.md +33 -0
  3. {spitch-1.23.0 → spitch-1.24.1}/PKG-INFO +5 -6
  4. {spitch-1.23.0 → spitch-1.24.1}/README.md +1 -1
  5. {spitch-1.23.0 → spitch-1.24.1}/SECURITY.md +1 -1
  6. spitch-1.24.1/bin/publish-pypi +6 -0
  7. {spitch-1.23.0 → spitch-1.24.1}/pyproject.toml +3 -5
  8. {spitch-1.23.0 → spitch-1.24.1}/requirements-dev.lock +1 -0
  9. {spitch-1.23.0 → spitch-1.24.1}/requirements.lock +1 -0
  10. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_models.py +6 -3
  11. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_response.py +2 -1
  12. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_utils/_transform.py +47 -2
  13. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_utils/_typing.py +2 -0
  14. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_version.py +1 -1
  15. {spitch-1.23.0 → spitch-1.24.1}/tests/test_client.py +1 -1
  16. {spitch-1.23.0 → spitch-1.24.1}/tests/test_transform.py +20 -1
  17. spitch-1.23.0/.release-please-manifest.json +0 -3
  18. spitch-1.23.0/bin/publish-pypi +0 -9
  19. {spitch-1.23.0 → spitch-1.24.1}/.gitignore +0 -0
  20. {spitch-1.23.0 → spitch-1.24.1}/CONTRIBUTING.md +0 -0
  21. {spitch-1.23.0 → spitch-1.24.1}/LICENSE +0 -0
  22. {spitch-1.23.0 → spitch-1.24.1}/api.md +0 -0
  23. {spitch-1.23.0 → spitch-1.24.1}/bin/check-release-environment +0 -0
  24. {spitch-1.23.0 → spitch-1.24.1}/examples/.keep +0 -0
  25. {spitch-1.23.0 → spitch-1.24.1}/examples/example.py +0 -0
  26. {spitch-1.23.0 → spitch-1.24.1}/mypy.ini +0 -0
  27. {spitch-1.23.0 → spitch-1.24.1}/noxfile.py +0 -0
  28. {spitch-1.23.0 → spitch-1.24.1}/release-please-config.json +0 -0
  29. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/__init__.py +0 -0
  30. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_base_client.py +0 -0
  31. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_client.py +0 -0
  32. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_compat.py +0 -0
  33. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_constants.py +0 -0
  34. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_exceptions.py +0 -0
  35. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_files.py +0 -0
  36. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_qs.py +0 -0
  37. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_resource.py +0 -0
  38. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_streaming.py +0 -0
  39. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_types.py +0 -0
  40. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_utils/__init__.py +0 -0
  41. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_utils/_logs.py +0 -0
  42. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_utils/_proxy.py +0 -0
  43. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_utils/_reflection.py +0 -0
  44. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_utils/_streams.py +0 -0
  45. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_utils/_sync.py +0 -0
  46. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/_utils/_utils.py +0 -0
  47. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/lib/.keep +0 -0
  48. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/py.typed +0 -0
  49. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/resources/__init__.py +0 -0
  50. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/resources/speech.py +0 -0
  51. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/resources/text.py +0 -0
  52. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/types/__init__.py +0 -0
  53. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/types/speech_generate_params.py +0 -0
  54. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/types/speech_transcribe_params.py +0 -0
  55. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/types/speech_transcribe_response.py +0 -0
  56. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/types/text_tone_mark_params.py +0 -0
  57. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/types/text_tone_mark_response.py +0 -0
  58. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/types/text_translate_params.py +0 -0
  59. {spitch-1.23.0 → spitch-1.24.1}/src/spitch/types/text_translate_response.py +0 -0
  60. {spitch-1.23.0 → spitch-1.24.1}/tests/__init__.py +0 -0
  61. {spitch-1.23.0 → spitch-1.24.1}/tests/api_resources/__init__.py +0 -0
  62. {spitch-1.23.0 → spitch-1.24.1}/tests/api_resources/test_speech.py +0 -0
  63. {spitch-1.23.0 → spitch-1.24.1}/tests/api_resources/test_text.py +0 -0
  64. {spitch-1.23.0 → spitch-1.24.1}/tests/conftest.py +0 -0
  65. {spitch-1.23.0 → spitch-1.24.1}/tests/sample_file.txt +0 -0
  66. {spitch-1.23.0 → spitch-1.24.1}/tests/test_deepcopy.py +0 -0
  67. {spitch-1.23.0 → spitch-1.24.1}/tests/test_extract_files.py +0 -0
  68. {spitch-1.23.0 → spitch-1.24.1}/tests/test_files.py +0 -0
  69. {spitch-1.23.0 → spitch-1.24.1}/tests/test_models.py +0 -0
  70. {spitch-1.23.0 → spitch-1.24.1}/tests/test_qs.py +0 -0
  71. {spitch-1.23.0 → spitch-1.24.1}/tests/test_required_args.py +0 -0
  72. {spitch-1.23.0 → spitch-1.24.1}/tests/test_response.py +0 -0
  73. {spitch-1.23.0 → spitch-1.24.1}/tests/test_streaming.py +0 -0
  74. {spitch-1.23.0 → spitch-1.24.1}/tests/test_utils/test_proxy.py +0 -0
  75. {spitch-1.23.0 → spitch-1.24.1}/tests/test_utils/test_typing.py +0 -0
  76. {spitch-1.23.0 → spitch-1.24.1}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "1.24.1"
3
+ }
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.24.1 (2025-04-14)
4
+
5
+ Full Changelog: [v1.24.0...v1.24.1](https://github.com/spi-tch/spitch-python/compare/v1.24.0...v1.24.1)
6
+
7
+ ### Bug Fixes
8
+
9
+ * **ci:** ensure pip is always available ([#135](https://github.com/spi-tch/spitch-python/issues/135)) ([761ba1e](https://github.com/spi-tch/spitch-python/commit/761ba1e39992907bff53ae44b4332579dc08239b))
10
+ * **ci:** remove publishing patch ([#136](https://github.com/spi-tch/spitch-python/issues/136)) ([f43dc79](https://github.com/spi-tch/spitch-python/commit/f43dc79390698c45ed10756420728263a8f50881))
11
+ * **perf:** optimize some hot paths ([1259f9c](https://github.com/spi-tch/spitch-python/commit/1259f9c3cce0cc184954586edc5cc47cc9cefc27))
12
+ * **perf:** skip traversing types for NotGiven values ([bb37b4e](https://github.com/spi-tch/spitch-python/commit/bb37b4eaff98d495dd2a717030629c73a1200050))
13
+ * **types:** handle more discriminated union shapes ([#133](https://github.com/spi-tch/spitch-python/issues/133)) ([6c0a695](https://github.com/spi-tch/spitch-python/commit/6c0a6959efc1f3ffd1da2f5af4117ccf0e1f3488))
14
+
15
+
16
+ ### Chores
17
+
18
+ * fix typos ([#137](https://github.com/spi-tch/spitch-python/issues/137)) ([d6fedfb](https://github.com/spi-tch/spitch-python/commit/d6fedfb2ad26407907d40738e3897e47676657bd))
19
+ * **internal:** bump rye to 0.44.0 ([#132](https://github.com/spi-tch/spitch-python/issues/132)) ([3ff0800](https://github.com/spi-tch/spitch-python/commit/3ff08004657e1e2bd0e0bca888808ec1e45dd87c))
20
+ * **internal:** codegen related update ([#131](https://github.com/spi-tch/spitch-python/issues/131)) ([d4355bf](https://github.com/spi-tch/spitch-python/commit/d4355bfb4f5a231335066471af0bc9f42958b971))
21
+ * **internal:** expand CI branch coverage ([a10e485](https://github.com/spi-tch/spitch-python/commit/a10e4852c17d5bfac1f07846e740aeb00693a34c))
22
+ * **internal:** reduce CI branch coverage ([bb74d2c](https://github.com/spi-tch/spitch-python/commit/bb74d2c5719c2dedeca969227177fc2e5a1d34ca))
23
+ * **internal:** remove extra empty newlines ([#129](https://github.com/spi-tch/spitch-python/issues/129)) ([606964f](https://github.com/spi-tch/spitch-python/commit/606964f05336f9bb47cea4a8e0b51b9720b8d866))
24
+ * **internal:** remove trailing character ([#138](https://github.com/spi-tch/spitch-python/issues/138)) ([713749a](https://github.com/spi-tch/spitch-python/commit/713749a9ec9db9d52e013dd65dd13e49f3c6918d))
25
+ * **internal:** slight transform perf improvement ([#139](https://github.com/spi-tch/spitch-python/issues/139)) ([3362024](https://github.com/spi-tch/spitch-python/commit/3362024e9b76f382378ddebf7cb708710ddbcf48))
26
+ * slight wording improvement in README ([#140](https://github.com/spi-tch/spitch-python/issues/140)) ([77cd1b3](https://github.com/spi-tch/spitch-python/commit/77cd1b3d2608dcd2af9e57bdd53ec8a90c9867fe))
27
+
28
+ ## 1.24.0 (2025-03-11)
29
+
30
+ Full Changelog: [v1.23.0...v1.24.0](https://github.com/spi-tch/spitch-python/compare/v1.23.0...v1.24.0)
31
+
32
+ ### Features
33
+
34
+ * **api:** update via SDK Studio ([#126](https://github.com/spi-tch/spitch-python/issues/126)) ([123d303](https://github.com/spi-tch/spitch-python/commit/123d303e48eb1baaf3eb8880e6e1d66294409c98))
35
+
3
36
  ## 1.23.0 (2025-03-11)
4
37
 
5
38
  Full Changelog: [v1.22.0...v1.23.0](https://github.com/spi-tch/spitch-python/compare/v1.22.0...v1.23.0)
@@ -1,12 +1,11 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.3
2
2
  Name: spitch
3
- Version: 1.23.0
3
+ Version: 1.24.1
4
4
  Summary: The official Python library for the spitch API
5
5
  Project-URL: Homepage, https://github.com/spi-tch/spitch-python
6
6
  Project-URL: Repository, https://github.com/spi-tch/spitch-python
7
- Author-email: Spitch <developer@spitch.app>
8
- License-Expression: Apache-2.0
9
- License-File: LICENSE
7
+ Author-email: Spitch <dev@spitch.app>
8
+ License: Apache-2.0
10
9
  Classifier: Intended Audience :: Developers
11
10
  Classifier: License :: OSI Approved :: Apache Software License
12
11
  Classifier: Operating System :: MacOS
@@ -114,7 +113,7 @@ Typed requests and responses provide autocomplete and documentation within your
114
113
 
115
114
  ## File uploads
116
115
 
117
- Request parameters that correspond to file uploads can be passed as `bytes`, a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.
116
+ Request parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.
118
117
 
119
118
  ```python
120
119
  from pathlib import Path
@@ -81,7 +81,7 @@ Typed requests and responses provide autocomplete and documentation within your
81
81
 
82
82
  ## File uploads
83
83
 
84
- Request parameters that correspond to file uploads can be passed as `bytes`, a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.
84
+ Request parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.
85
85
 
86
86
  ```python
87
87
  from pathlib import Path
@@ -20,7 +20,7 @@ or products provided by Spitch please follow the respective company's security r
20
20
 
21
21
  ### Spitch Terms and Policies
22
22
 
23
- Please contact developer@spitch.app for any questions or concerns regarding security of our services.
23
+ Please contact dev@spitch.app for any questions or concerns regarding security of our services.
24
24
 
25
25
  ---
26
26
 
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -eux
4
+ mkdir -p dist
5
+ rye build --clean
6
+ rye publish --yes --token=$PYPI_TOKEN
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "spitch"
3
- version = "1.23.0"
3
+ version = "1.24.1"
4
4
  description = "The official Python library for the spitch API"
5
5
  dynamic = ["readme"]
6
6
  license = "Apache-2.0"
7
7
  authors = [
8
- { name = "Spitch", email = "developer@spitch.app" },
8
+ { name = "Spitch", email = "dev@spitch.app" },
9
9
  ]
10
10
  dependencies = [
11
11
  "httpx>=0.23.0, <0.28.0",
@@ -39,7 +39,6 @@ Homepage = "https://github.com/spi-tch/spitch-python"
39
39
  Repository = "https://github.com/spi-tch/spitch-python"
40
40
 
41
41
 
42
-
43
42
  [tool.rye]
44
43
  managed = true
45
44
  # version pins are in requirements-dev.lock
@@ -88,7 +87,7 @@ typecheck = { chain = [
88
87
  "typecheck:mypy" = "mypy ."
89
88
 
90
89
  [build-system]
91
- requires = ["hatchling", "hatch-fancy-pypi-readme"]
90
+ requires = ["hatchling==1.26.3", "hatch-fancy-pypi-readme"]
92
91
  build-backend = "hatchling.build"
93
92
 
94
93
  [tool.hatch.build]
@@ -153,7 +152,6 @@ reportImplicitOverride = true
153
152
  reportImportCycles = false
154
153
  reportPrivateUsage = false
155
154
 
156
-
157
155
  [tool.ruff]
158
156
  line-length = 120
159
157
  output-format = "grouped"
@@ -7,6 +7,7 @@
7
7
  # all-features: true
8
8
  # with-sources: false
9
9
  # generate-hashes: false
10
+ # universal: false
10
11
 
11
12
  -e file:.
12
13
  annotated-types==0.6.0
@@ -7,6 +7,7 @@
7
7
  # all-features: true
8
8
  # with-sources: false
9
9
  # generate-hashes: false
10
+ # universal: false
10
11
 
11
12
  -e file:.
12
13
  annotated-types==0.6.0
@@ -64,7 +64,7 @@ from ._compat import (
64
64
  from ._constants import RAW_RESPONSE_HEADER
65
65
 
66
66
  if TYPE_CHECKING:
67
- from pydantic_core.core_schema import ModelField, LiteralSchema, ModelFieldsSchema
67
+ from pydantic_core.core_schema import ModelField, ModelSchema, LiteralSchema, ModelFieldsSchema
68
68
 
69
69
  __all__ = ["BaseModel", "GenericModel"]
70
70
 
@@ -642,15 +642,18 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any,
642
642
 
643
643
  def _extract_field_schema_pv2(model: type[BaseModel], field_name: str) -> ModelField | None:
644
644
  schema = model.__pydantic_core_schema__
645
+ if schema["type"] == "definitions":
646
+ schema = schema["schema"]
647
+
645
648
  if schema["type"] != "model":
646
649
  return None
647
650
 
651
+ schema = cast("ModelSchema", schema)
648
652
  fields_schema = schema["schema"]
649
653
  if fields_schema["type"] != "model-fields":
650
654
  return None
651
655
 
652
656
  fields_schema = cast("ModelFieldsSchema", fields_schema)
653
-
654
657
  field = fields_schema["fields"].get(field_name)
655
658
  if not field:
656
659
  return None
@@ -674,7 +677,7 @@ def set_pydantic_config(typ: Any, config: pydantic.ConfigDict) -> None:
674
677
  setattr(typ, "__pydantic_config__", config) # noqa: B010
675
678
 
676
679
 
677
- # our use of subclasssing here causes weirdness for type checkers,
680
+ # our use of subclassing here causes weirdness for type checkers,
678
681
  # so we just pretend that we don't subclass
679
682
  if TYPE_CHECKING:
680
683
  GenericModel = BaseModel
@@ -126,7 +126,7 @@ class BaseAPIResponse(Generic[R]):
126
126
  )
127
127
 
128
128
  def _parse(self, *, to: type[_T] | None = None) -> R | _T:
129
- cast_to = to if to is not None else self._cast_to
129
+ cast_to = to if to is not None else self._cast_to
130
130
 
131
131
  # unwrap `Annotated[T, ...]` -> `T`
132
132
  if cast_to and is_annotated_type(cast_to):
@@ -261,6 +261,7 @@ class BaseAPIResponse(Generic[R]):
261
261
  )
262
262
 
263
263
 
264
+
264
265
  class APIResponse(BaseAPIResponse[R]):
265
266
  @overload
266
267
  def parse(self, *, to: type[_T]) -> _T: ...
@@ -5,13 +5,15 @@ import base64
5
5
  import pathlib
6
6
  from typing import Any, Mapping, TypeVar, cast
7
7
  from datetime import date, datetime
8
- from typing_extensions import Literal, get_args, override, get_type_hints
8
+ from typing_extensions import Literal, get_args, override, get_type_hints as _get_type_hints
9
9
 
10
10
  import anyio
11
11
  import pydantic
12
12
 
13
13
  from ._utils import (
14
14
  is_list,
15
+ is_given,
16
+ lru_cache,
15
17
  is_mapping,
16
18
  is_iterable,
17
19
  )
@@ -108,6 +110,7 @@ def transform(
108
110
  return cast(_T, transformed)
109
111
 
110
112
 
113
+ @lru_cache(maxsize=8096)
111
114
  def _get_annotated_type(type_: type) -> type | None:
112
115
  """If the given type is an `Annotated` type then it is returned, if not `None` is returned.
113
116
 
@@ -126,7 +129,7 @@ def _get_annotated_type(type_: type) -> type | None:
126
129
  def _maybe_transform_key(key: str, type_: type) -> str:
127
130
  """Transform the given `data` based on the annotations provided in `type_`.
128
131
 
129
- Note: this function only looks at `Annotated` types that contain `PropertInfo` metadata.
132
+ Note: this function only looks at `Annotated` types that contain `PropertyInfo` metadata.
130
133
  """
131
134
  annotated_type = _get_annotated_type(type_)
132
135
  if annotated_type is None:
@@ -142,6 +145,10 @@ def _maybe_transform_key(key: str, type_: type) -> str:
142
145
  return key
143
146
 
144
147
 
148
+ def _no_transform_needed(annotation: type) -> bool:
149
+ return annotation == float or annotation == int
150
+
151
+
145
152
  def _transform_recursive(
146
153
  data: object,
147
154
  *,
@@ -184,6 +191,15 @@ def _transform_recursive(
184
191
  return cast(object, data)
185
192
 
186
193
  inner_type = extract_type_arg(stripped_type, 0)
194
+ if _no_transform_needed(inner_type):
195
+ # for some types there is no need to transform anything, so we can get a small
196
+ # perf boost from skipping that work.
197
+ #
198
+ # but we still need to convert to a list to ensure the data is json-serializable
199
+ if is_list(data):
200
+ return data
201
+ return list(data)
202
+
187
203
  return [_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data]
188
204
 
189
205
  if is_union_type(stripped_type):
@@ -245,6 +261,11 @@ def _transform_typeddict(
245
261
  result: dict[str, object] = {}
246
262
  annotations = get_type_hints(expected_type, include_extras=True)
247
263
  for key, value in data.items():
264
+ if not is_given(value):
265
+ # we don't need to include `NotGiven` values here as they'll
266
+ # be stripped out before the request is sent anyway
267
+ continue
268
+
248
269
  type_ = annotations.get(key)
249
270
  if type_ is None:
250
271
  # we do not have a type annotation for this field, leave it as is
@@ -332,6 +353,15 @@ async def _async_transform_recursive(
332
353
  return cast(object, data)
333
354
 
334
355
  inner_type = extract_type_arg(stripped_type, 0)
356
+ if _no_transform_needed(inner_type):
357
+ # for some types there is no need to transform anything, so we can get a small
358
+ # perf boost from skipping that work.
359
+ #
360
+ # but we still need to convert to a list to ensure the data is json-serializable
361
+ if is_list(data):
362
+ return data
363
+ return list(data)
364
+
335
365
  return [await _async_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data]
336
366
 
337
367
  if is_union_type(stripped_type):
@@ -393,6 +423,11 @@ async def _async_transform_typeddict(
393
423
  result: dict[str, object] = {}
394
424
  annotations = get_type_hints(expected_type, include_extras=True)
395
425
  for key, value in data.items():
426
+ if not is_given(value):
427
+ # we don't need to include `NotGiven` values here as they'll
428
+ # be stripped out before the request is sent anyway
429
+ continue
430
+
396
431
  type_ = annotations.get(key)
397
432
  if type_ is None:
398
433
  # we do not have a type annotation for this field, leave it as is
@@ -400,3 +435,13 @@ async def _async_transform_typeddict(
400
435
  else:
401
436
  result[_maybe_transform_key(key, type_)] = await _async_transform_recursive(value, annotation=type_)
402
437
  return result
438
+
439
+
440
+ @lru_cache(maxsize=8096)
441
+ def get_type_hints(
442
+ obj: Any,
443
+ globalns: dict[str, Any] | None = None,
444
+ localns: Mapping[str, Any] | None = None,
445
+ include_extras: bool = False,
446
+ ) -> dict[str, Any]:
447
+ return _get_type_hints(obj, globalns=globalns, localns=localns, include_extras=include_extras)
@@ -4,6 +4,7 @@ from typing import Any, TypeVar, Iterable, cast
4
4
  from collections import abc as _c_abc
5
5
  from typing_extensions import Required, Annotated, get_args, get_origin
6
6
 
7
+ from ._utils import lru_cache
7
8
  from .._types import InheritsGeneric
8
9
  from .._compat import is_union as _is_union
9
10
 
@@ -37,6 +38,7 @@ def is_typevar(typ: type) -> bool:
37
38
 
38
39
 
39
40
  # Extracts T from Annotated[T, ...] or from Required[Annotated[T, ...]]
41
+ @lru_cache(maxsize=8096)
40
42
  def strip_annotated_type(typ: type) -> type:
41
43
  if is_required_type(typ) or is_annotated_type(typ):
42
44
  return strip_annotated_type(cast(type, get_args(typ)[0]))
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "spitch"
4
- __version__ = "1.23.0" # x-release-please-version
4
+ __version__ = "1.24.1" # x-release-please-version
@@ -1618,7 +1618,7 @@ class TestAsyncSpitch:
1618
1618
  import threading
1619
1619
 
1620
1620
  from spitch._utils import asyncify
1621
- from spitch._base_client import get_platform
1621
+ from spitch._base_client import get_platform
1622
1622
 
1623
1623
  async def test_main() -> None:
1624
1624
  result = await asyncify(get_platform)()
@@ -8,7 +8,7 @@ from typing_extensions import Required, Annotated, TypedDict
8
8
 
9
9
  import pytest
10
10
 
11
- from spitch._types import Base64FileInput
11
+ from spitch._types import NOT_GIVEN, Base64FileInput
12
12
  from spitch._utils import (
13
13
  PropertyInfo,
14
14
  transform as _transform,
@@ -432,3 +432,22 @@ async def test_base64_file_input(use_async: bool) -> None:
432
432
  assert await transform({"foo": io.BytesIO(b"Hello, world!")}, TypedDictBase64Input, use_async) == {
433
433
  "foo": "SGVsbG8sIHdvcmxkIQ=="
434
434
  } # type: ignore[comparison-overlap]
435
+
436
+
437
+ @parametrize
438
+ @pytest.mark.asyncio
439
+ async def test_transform_skipping(use_async: bool) -> None:
440
+ # lists of ints are left as-is
441
+ data = [1, 2, 3]
442
+ assert await transform(data, List[int], use_async) is data
443
+
444
+ # iterables of ints are converted to a list
445
+ data = iter([1, 2, 3])
446
+ assert await transform(data, Iterable[int], use_async) == [1, 2, 3]
447
+
448
+
449
+ @parametrize
450
+ @pytest.mark.asyncio
451
+ async def test_strips_notgiven(use_async: bool) -> None:
452
+ assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"}
453
+ assert await transform({"foo_bar": NOT_GIVEN}, Foo1, use_async) == {}
@@ -1,3 +0,0 @@
1
- {
2
- ".": "1.23.0"
3
- }
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- set -eux
4
- mkdir -p dist
5
- rye build --clean
6
- # Patching importlib-metadata version until upstream library version is updated
7
- # https://github.com/pypa/twine/issues/977#issuecomment-2189800841
8
- "$HOME/.rye/self/bin/python3" -m pip install 'importlib-metadata==7.2.1'
9
- rye publish --yes --token=$PYPI_TOKEN
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes