Skip to content

release: 1.22.0 - #182

Open
stainless-app[bot] wants to merge 16 commits into
mainfrom
release-please--branches--main--changes--next
Open

release: 1.22.0#182
stainless-app[bot] wants to merge 16 commits into
mainfrom
release-please--branches--main--changes--next

Conversation

@stainless-app

@stainless-app stainless-app Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Automated Release PR

1.22.0 (2026-08-20)

Full Changelog: v1.21.0...v1.22.0

Features

  • internal/types: support eagerly validating pydantic iterators (04e4187)
  • stlc: configurable CI runner and private-production-repo support in workflow templates (48c8386)
  • support setting headers via env (30a033a)

Bug Fixes

  • client: add missing f-string prefix in file type error message (ab34d42)
  • client: preserve hardcoded query params when merging with user params (987fbc7)
  • ensure file data are only sent as 1 parameter (a7c0bac)
  • use correct field name format for multipart file arrays (c335429)

Performance Improvements

  • client: optimize file structure copying in multipart requests (ea9d673)

Chores

  • internal: allow the mock server port to be set with STAINLESS_MOCK_PORT (23f1a89)
  • internal: more robust bootstrap script (2291709)
  • internal: reformat pyproject.toml (acc97d1)
  • tests: bump steady to v0.22.1 (02f10ea)

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

@cursor

cursor Bot commented Apr 8, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes affect core request construction (query merge, multipart file extraction/copying) used by all API calls; behavior fixes could alter edge-case requests but are covered by new tests.

Overview
Release 1.22.0 bumps package metadata, changelog, and the tracked OpenAPI spec URL.

HTTP client behavior adds optional default headers from the LUMAAI_CUSTOM_HEADERS environment variable (newline-separated Name: value lines, merged under explicit default_headers). Request building now merges query strings embedded in the request URL with caller params, with explicit params winning on conflicts.

Multipart / file uploads gain configurable array field naming in extract_files (brackets, repeat, comma, indices), safer dict key removal for array-only path tails, and deepcopy_with_paths instead of full-structure deepcopy_minimal when preparing bodies so extract_files mutations do not corrupt caller data.

Pydantic v2 adds an EagerIterable annotated type that eagerly validates iterable fields and avoids empty model_dump after generator consumption.

CI and dev tooling: Stainless SDK repos use depot-ubuntu-24.04 via startsWith(github.repository, 'stainless-sdks/'), GitHub Actions are pinned to commit SHAs, mock tests use Steady v0.22.1 and optional STAINLESS_MOCK_PORT, and bootstrap treats unset SKIP_BREW more safely.

Reviewed by Cursor Bugbot for commit 937bd8e. Bugbot is set up for automated code reviews on this repo. Configure here.

@stainless-app

stainless-app Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor Author

🧪 Testing

To try out this version of the SDK:

pip install 'https://pkg.stainless.com/s/luma_ai-python/23f1a89bccccb84f438e2b8bf91928f5c1c746b8/lumaai-1.21.0-py3-none-any.whl'

Expires at: Sat, 19 Sep 2026 04:57:47 GMT
Updated at: Thu, 20 Aug 2026 04:57:47 GMT

@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from daa341f to c1c63c6 Compare April 11, 2026 08:00
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from c1c63c6 to c267c54 Compare April 18, 2026 07:23
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from c267c54 to e979d10 Compare April 18, 2026 07:25
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from e979d10 to 9c43dac Compare April 23, 2026 03:50
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from 9c43dac to 6c0aed9 Compare April 28, 2026 04:24
@stainless-app stainless-app Bot changed the title release: 1.21.1 release: 1.22.0 Apr 28, 2026
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from 6c0aed9 to 081e108 Compare April 28, 2026 04:45
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from 081e108 to 8e32391 Compare May 1, 2026 04:46
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from 8e32391 to 4643c9e Compare May 1, 2026 04:50
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from 4643c9e to 0e0ddb8 Compare May 1, 2026 04:54
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from 0e0ddb8 to 9e2ce51 Compare May 9, 2026 03:55
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from 9e2ce51 to 4929b7c Compare May 12, 2026 03:47
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.
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from 4929b7c to 215a2ab Compare May 13, 2026 04:04
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from 215a2ab to ab9d80a Compare July 18, 2026 02:15
@stainless-app
stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from ab9d80a to 937bd8e Compare August 20, 2026 04:57

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Array file paths drop non-lists
    • extract_files now pops leftover path segments only when the value is actually a list, so a single file or other non-list stays in the request body instead of being discarded.

Create PR

Or push these changes by commenting:

@cursor push b7dac59259
Preview (b7dac59259)
diff --git a/src/lumaai/_utils/_utils.py b/src/lumaai/_utils/_utils.py
--- a/src/lumaai/_utils/_utils.py
+++ b/src/lumaai/_utils/_utils.py
@@ -109,8 +109,10 @@
     if is_dict(obj):
         try:
             # Remove the field if there are no more dict keys in the path,
-            # only "<array>" traversal markers or end.
-            if all(p == "<array>" for p in path[index:]):
+            # only "<array>" traversal markers or end. Only pop leftover
+            # "<array>" segments when the value is actually a list.
+            remaining = path[index:]
+            if not remaining or (all(p == "<array>" for p in remaining) and is_list(obj.get(key))):
                 item = obj.pop(key)
             else:
                 item = obj[key]

diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py
--- a/tests/test_extract_files.py
+++ b/tests/test_extract_files.py
@@ -41,6 +41,20 @@
     assert query == {"title": "hello"}
 
 
+def test_array_path_does_not_drop_non_list() -> None:
+    query = {"files": b"single file", "title": "hello"}
+    assert extract_files(query, paths=[["files", "<array>"]]) == []
+    assert query == {"files": b"single file", "title": "hello"}
+
+    nested = {"foo": {"files": b"single file"}, "keep": 1}
+    assert extract_files(nested, paths=[["foo", "files", "<array>"]]) == []
+    assert nested == {"foo": {"files": b"single file"}, "keep": 1}
+
+    query2 = {"files": {"not": "a list"}}
+    assert extract_files(query2, paths=[["files", "<array>"]]) == []
+    assert query2 == {"files": {"not": "a list"}}
+
+
 @pytest.mark.parametrize(
     "query,paths,expected",
     [

You can send follow-ups to the cloud agent here.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 937bd8e. Configure here.

if (len(path)) == index:
# Remove the field if there are no more dict keys in the path,
# only "<array>" traversal markers or end.
if all(p == "<array>" for p in path[index:]):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Array file paths drop non-lists

Medium Severity

extract_files now pops a field whenever the remaining path is only <array> markers, before confirming the value is a list. A single file (or other non-list) is removed from the body and never emitted as a multipart part, so that input is dropped from the request entirely.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 937bd8e. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants