release: 1.13.0#90
Conversation
|
🧪 Testing To try out this version of the SDK: Expires at: Mon, 17 Aug 2026 02:01:40 GMT |
fb971ec to
e889513
Compare
90b3bef to
db10a21
Compare
db10a21 to
6d49353
Compare
6d49353 to
d268a9a
Compare
d268a9a to
5f516f5
Compare
5f516f5 to
7f7ddc2
Compare
7f7ddc2 to
40b6b4e
Compare
Pin all GitHub Actions referenced in generated workflows (both first-party `actions/*` and third-party) to immutable commit SHAs. Updating pinned actions is now a deliberate codegen-side bump rather than implicit on every workflow run.
40b6b4e to
7a76d3d
Compare
7a76d3d to
4e52788
Compare
4e52788 to
0990b2d
Compare
…t in workflow templates
0990b2d to
ac8db1b
Compare
There was a problem hiding this comment.
Pull request overview
Note
Copilot could not run the full agentic suite for this review because it was automatically requested on a bot-authored pull request. Request a review from Copilot under Reviewers to retry with the full agentic suite. Improved support for bot-authored pull requests is coming soon.
Updates the SDK for the 1.13.0 release by extending response models, improving multipart file extraction flexibility, and adding internal robustness improvements (Pydantic iterable validation, env-driven headers), plus release/versioning and CI hardening.
Changes:
- Add
created_atto job response types and bump version to 1.13.0 (including changelog/manifest updates). - Add configurable
array_formatfor multipart file array field naming and expand related tests. - Introduce
EagerIterableto eagerly validate/serialize iterables under Pydantic v2 and add regression tests; pin GitHub Actions to SHAs.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_models.py | Adds tests for new EagerIterable behavior across iterable inputs. |
| tests/test_files.py | Adjusts assertions around extracted multipart file entries. |
| tests/test_extract_files.py | Adds coverage for array_format controlling multipart field names. |
| src/landingai_ade/types/parse_job_list_response.py | Adds optional created_at field to job list model. |
| src/landingai_ade/types/parse_job_get_response.py | Adds optional created_at field to job get model. |
| src/landingai_ade/_version.py | Bumps package version constant to 1.13.0. |
| src/landingai_ade/_utils/_utils.py | Adds array_format support to extract_files and array key emission logic. |
| src/landingai_ade/_types.py | Centralizes ArrayFormat/NestedFormat literals. |
| src/landingai_ade/_qs.py | Uses centralized ArrayFormat/NestedFormat types from _types. |
| src/landingai_ade/_models.py | Adds EagerIterable implementation for Pydantic v2 schema/serialization. |
| src/landingai_ade/_files.py | Fixes missing f-string in a TypeError message. |
| src/landingai_ade/_client.py | Adds support for default headers via LANDINGAI_ADE_CUSTOM_HEADERS env var. |
| pyproject.toml | Bumps version and normalizes mypy exclude formatting. |
| CHANGELOG.md | Adds 1.13.0 release notes. |
| .stats.yml | Updates OpenAPI spec URL/hash metadata. |
| .release-please-manifest.json | Updates release-please manifest version to 1.13.0. |
| .github/workflows/release-doctor.yml | Pins actions/checkout to a specific commit SHA. |
| .github/workflows/publish-pypi.yml | Pins actions/checkout to a specific commit SHA. |
| .github/workflows/ci.yml | Pins actions to SHAs and updates runner selection logic for Stainless repos. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ([1, 2, 3], [1, 2, 3]), | ||
| ((1, 2, 3), (1, 2, 3)), | ||
| (set([1, 2, 3]), set([1, 2, 3])), | ||
| (iter([1, 2, 3]), [1, 2, 3]), | ||
| ([], []), | ||
| ((x for x in [1, 2, 3]), [1, 2, 3]), | ||
| (map(lambda x: x, [1, 2, 3]), [1, 2, 3]), | ||
| (frozenset([1, 2, 3]), frozenset([1, 2, 3])), | ||
| (deque([1, 2, 3]), deque([1, 2, 3])), |
| assert m.model_dump()["data"]["items"] == list(expected_validated) | ||
| assert m.model_dump()["data"]["items"] == list(expected_validated) |
| extracted = extract_files(copied, paths=[["items", "<array>", "file"]]) | ||
|
|
||
| assert extracted == [("items[][file]", file1), ("items[][file]", file2)] | ||
| assert [entry for _, entry in extracted] == [file1, file2] |
| raise NotImplementedError( | ||
| f"Unknown array_format value: {array_format}, choose from {', '.join(get_args(ArrayFormat))}" | ||
| ) |
| custom_headers_env = os.environ.get("LANDINGAI_ADE_CUSTOM_HEADERS") | ||
| if custom_headers_env is not None: | ||
| parsed: dict[str, str] = {} | ||
| for line in custom_headers_env.split("\n"): | ||
| colon = line.find(":") | ||
| if colon >= 0: | ||
| parsed[line[:colon].strip()] = line[colon + 1 :].strip() | ||
| default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} |
| custom_headers_env = os.environ.get("LANDINGAI_ADE_CUSTOM_HEADERS") | ||
| if custom_headers_env is not None: | ||
| parsed: dict[str, str] = {} | ||
| for line in custom_headers_env.split("\n"): | ||
| colon = line.find(":") | ||
| if colon >= 0: | ||
| parsed[line[:colon].strip()] = line[colon + 1 :].strip() | ||
| default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} |
| custom_headers_env = os.environ.get("LANDINGAI_ADE_CUSTOM_HEADERS") | ||
| if custom_headers_env is not None: | ||
| parsed: dict[str, str] = {} | ||
| for line in custom_headers_env.split("\n"): | ||
| colon = line.find(":") | ||
| if colon >= 0: | ||
| parsed[line[:colon].strip()] = line[colon + 1 :].strip() | ||
| default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} |
| created_at: Optional[int] = None | ||
| """Unix timestamp (seconds) for when the job was created. | ||
|
|
||
| Mirrors received_at; exposed so clients have an explicit creation time. | ||
| """ |
| custom_headers_env = os.environ.get("LANDINGAI_ADE_CUSTOM_HEADERS") | ||
| if custom_headers_env is not None: | ||
| parsed: dict[str, str] = {} | ||
| for line in custom_headers_env.split("\n"): | ||
| colon = line.find(":") | ||
| if colon >= 0: | ||
| parsed[line[:colon].strip()] = line[colon + 1 :].strip() | ||
| default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} |
Automated Release PR
1.13.0 (2026-07-18)
Full Changelog: v1.12.0...v1.13.0
Features
Bug Fixes
Chores
Documentation
This pull request is managed by Stainless's GitHub App.
The semver version number is based on included commit messages. Alternatively, you can manually set the version number in the title of this pull request.
For a better experience, it is recommended to use either rebase-merge or squash-merge when merging this pull request.
🔗 Stainless website
📚 Read the docs
🙋 Reach out for help or questions