Skip to content

Commit 413ee5d

Browse files
release: 1.11.0 (#58)
* fix(parsing): parse extra field types * codegen metadata * chore(project): add settings file for vscode * feat(client): support file upload requests * codegen metadata * release: 1.11.0 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
1 parent a68fd20 commit 413ee5d

File tree

13 files changed

+90
-17
lines changed

13 files changed

+90
-17
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
.prism.log
2-
.vscode
32
_dev
43

54
__pycache__

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "1.10.1"
2+
".": "1.11.0"
33
}

.stats.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 89
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/knock%2Fknock-592610bb4a05ea45115eba7544acd8efbab327749d0f78bd83e164aa305dc0a7.yml
3-
openapi_spec_hash: 6a65b9127625d9479ba6bff2ba3f8d37
4-
config_hash: c835f0912492c3f1189f78f876c7c90c
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/knock%2Fknock-f83c849e3e1c614100e19d79e4bd38ae67353a8316264cf89e4e721f3c1a5739.yml
3+
openapi_spec_hash: 01ad62e55b345d5c077dad6144249e32
4+
config_hash: bc9a0a4aa4fd3ff568da7da96bf17419

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"python.analysis.importFormat": "relative",
3+
}

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# Changelog
22

3+
## 1.11.0 (2025-08-05)
4+
5+
Full Changelog: [v1.10.1...v1.11.0](https://github.com/knocklabs/knock-python/compare/v1.10.1...v1.11.0)
6+
7+
### Features
8+
9+
* **client:** support file upload requests ([19135e5](https://github.com/knocklabs/knock-python/commit/19135e542bd4d6a02ee58a6ed9aa4517ec240af4))
10+
11+
12+
### Bug Fixes
13+
14+
* **parsing:** parse extra field types ([4f39573](https://github.com/knocklabs/knock-python/commit/4f39573da7cf9751493d45420aa3c1fd6855b96a))
15+
16+
17+
### Chores
18+
19+
* **project:** add settings file for vscode ([4c4c3b6](https://github.com/knocklabs/knock-python/commit/4c4c3b687846aa7898359fb2db897dc1639c2066))
20+
321
## 1.10.1 (2025-07-22)
422

523
Full Changelog: [v1.10.0...v1.10.1](https://github.com/knocklabs/knock-python/compare/v1.10.0...v1.10.1)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "knockapi"
3-
version = "1.10.1"
3+
version = "1.11.0"
44
description = "The official Python library for the knock API"
55
dynamic = ["readme"]
66
license = "Apache-2.0"

src/knockapi/_base_client.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,10 @@ def _build_request(
532532
is_body_allowed = options.method.lower() != "get"
533533

534534
if is_body_allowed:
535-
kwargs["json"] = json_data if is_given(json_data) else None
535+
if isinstance(json_data, bytes):
536+
kwargs["content"] = json_data
537+
else:
538+
kwargs["json"] = json_data if is_given(json_data) else None
536539
kwargs["files"] = files
537540
else:
538541
headers.pop("Content-Type", None)

src/knockapi/_files.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ def _transform_file(file: FileTypes) -> HttpxFileTypes:
6969
return file
7070

7171
if is_tuple_t(file):
72-
return (file[0], _read_file_content(file[1]), *file[2:])
72+
return (file[0], read_file_content(file[1]), *file[2:])
7373

7474
raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple")
7575

7676

77-
def _read_file_content(file: FileContent) -> HttpxFileContent:
77+
def read_file_content(file: FileContent) -> HttpxFileContent:
7878
if isinstance(file, os.PathLike):
7979
return pathlib.Path(file).read_bytes()
8080
return file
@@ -111,12 +111,12 @@ async def _async_transform_file(file: FileTypes) -> HttpxFileTypes:
111111
return file
112112

113113
if is_tuple_t(file):
114-
return (file[0], await _async_read_file_content(file[1]), *file[2:])
114+
return (file[0], await async_read_file_content(file[1]), *file[2:])
115115

116116
raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple")
117117

118118

119-
async def _async_read_file_content(file: FileContent) -> HttpxFileContent:
119+
async def async_read_file_content(file: FileContent) -> HttpxFileContent:
120120
if isinstance(file, os.PathLike):
121121
return await anyio.Path(file).read_bytes()
122122

src/knockapi/_models.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,18 @@ def construct( # pyright: ignore[reportIncompatibleMethodOverride]
208208
else:
209209
fields_values[name] = field_get_default(field)
210210

211+
extra_field_type = _get_extra_fields_type(__cls)
212+
211213
_extra = {}
212214
for key, value in values.items():
213215
if key not in model_fields:
216+
parsed = construct_type(value=value, type_=extra_field_type) if extra_field_type is not None else value
217+
214218
if PYDANTIC_V2:
215-
_extra[key] = value
219+
_extra[key] = parsed
216220
else:
217221
_fields_set.add(key)
218-
fields_values[key] = value
222+
fields_values[key] = parsed
219223

220224
object.__setattr__(m, "__dict__", fields_values)
221225

@@ -370,6 +374,23 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object:
370374
return construct_type(value=value, type_=type_, metadata=getattr(field, "metadata", None))
371375

372376

377+
def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None:
378+
if not PYDANTIC_V2:
379+
# TODO
380+
return None
381+
382+
schema = cls.__pydantic_core_schema__
383+
if schema["type"] == "model":
384+
fields = schema["schema"]
385+
if fields["type"] == "model-fields":
386+
extras = fields.get("extras_schema")
387+
if extras and "cls" in extras:
388+
# mypy can't narrow the type
389+
return extras["cls"] # type: ignore[no-any-return]
390+
391+
return None
392+
393+
373394
def is_basemodel(type_: type) -> bool:
374395
"""Returns whether or not the given type is either a `BaseModel` or a union of `BaseModel`"""
375396
if is_union(type_):

src/knockapi/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

33
__title__ = "knockapi"
4-
__version__ = "1.10.1" # x-release-please-version
4+
__version__ = "1.11.0" # x-release-please-version

0 commit comments

Comments
 (0)