Skip to content

Commit 3d68b23

Browse files
release: 1.0.0 (#27)
Automated Release PR --- ## 1.0.0 (2026-06-02) Full Changelog: [v0.6.0...v1.0.0](v0.6.0...v1.0.0) ### ⚠ BREAKING CHANGES * **api:** clean up beta features ### Features * **api:** 1.0.0 changes ([f399080](f399080)) * **api:** Add parallel_beta typing back ([004ce9f](004ce9f)) * **api:** clean up beta features ([f533161](f533161)) * **api:** Remove beta: tasks, task groups, search, and extract from SDK ([b7bcade](b7bcade)) * **internal/types:** support eagerly validating pydantic iterators ([6c148b4](6c148b4)) ### Bug Fixes * **client:** add missing f-string prefix in file type error message ([6fa3eac](6fa3eac)) --- This pull request is managed by Stainless's [GitHub App](https://github.com/apps/stainless-app). The [semver version number](https://semver.org/#semantic-versioning-specification-semver) is based on included [commit messages](https://www.conventionalcommits.org/en/v1.0.0/). 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](https://www.stainlessapi.com) 📚 Read the [docs](https://app.stainlessapi.com/docs) 🙋 [Reach out](mailto:support@stainlessapi.com) for help or questions --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
1 parent b9dc5ed commit 3d68b23

60 files changed

Lines changed: 436 additions & 4415 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
runs-on: ${{ github.repository == 'stainless-sdks/parallel-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
2222
if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')
2323
steps:
24-
- uses: actions/checkout@v6
24+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2525

2626
- name: Install Rye
2727
run: |
@@ -46,7 +46,7 @@ jobs:
4646
id-token: write
4747
runs-on: ${{ github.repository == 'stainless-sdks/parallel-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
4848
steps:
49-
- uses: actions/checkout@v6
49+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
5050

5151
- name: Install Rye
5252
run: |
@@ -67,7 +67,7 @@ jobs:
6767
github.repository == 'stainless-sdks/parallel-sdk-python' &&
6868
!startsWith(github.ref, 'refs/heads/stl/')
6969
id: github-oidc
70-
uses: actions/github-script@v8
70+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
7171
with:
7272
script: core.setOutput('github_token', await core.getIDToken());
7373

@@ -87,7 +87,7 @@ jobs:
8787
runs-on: ${{ github.repository == 'stainless-sdks/parallel-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
8888
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
8989
steps:
90-
- uses: actions/checkout@v6
90+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
9191

9292
- name: Install Rye
9393
run: |

.github/workflows/detect-breaking-changes.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
run: |
1616
echo "FETCH_DEPTH=$(expr ${{ github.event.pull_request.commits }} + 1)" >> $GITHUB_ENV
1717
18-
- uses: actions/checkout@v6
18+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1919
with:
2020
# Ensure we can check out the pull request base in the script below.
2121
fetch-depth: ${{ env.FETCH_DEPTH }}

.github/workflows/publish-pypi.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
runs-on: ubuntu-latest
1515

1616
steps:
17-
- uses: actions/checkout@v6
17+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1818

1919
- name: Install Rye
2020
run: |

.github/workflows/release-doctor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
if: github.repository == 'parallel-web/parallel-sdk-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next')
1313

1414
steps:
15-
- uses: actions/checkout@v6
15+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1616

1717
- name: Check release environment
1818
run: |

.release-please-manifest.json

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

.stats.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 38
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/parallel-web/parallel-sdk-b134f034fe11499d713c03d07778aba8a395d7e3cbbc3d8a4bd2891f0aa970ba.yml
3-
openapi_spec_hash: c4fc5b0cb3bc48076f736a0ad2b2e75e
4-
config_hash: 27cd9354fb0ac3129cbf269737cece6c
1+
configured_endpoints: 30
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/parallel-web/parallel-sdk-ffc54f0dafed1e8e209559eee680a2c1968a9a17e7e74a49d2f45b6470449be2.yml
3+
openapi_spec_hash: d953a6e7b41db65161edc059ca84257b
4+
config_hash: 8572a2d7a5ede9ade3be8ad4d8aafd7d

CHANGELOG.md

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

3+
## 1.0.0 (2026-06-02)
4+
5+
Full Changelog: [v0.6.0...v1.0.0](https://github.com/parallel-web/parallel-sdk-python/compare/v0.6.0...v1.0.0)
6+
7+
### ⚠ BREAKING CHANGES
8+
9+
* **api:** clean up beta features
10+
11+
### Features
12+
13+
* **api:** 1.0.0 changes ([f399080](https://github.com/parallel-web/parallel-sdk-python/commit/f3990800a98eefef82f21902406d90073c050de1))
14+
* **api:** Add parallel_beta typing back ([004ce9f](https://github.com/parallel-web/parallel-sdk-python/commit/004ce9f53eaabe12e676f9f6ae3d0a000dfeabc2))
15+
* **api:** clean up beta features ([f533161](https://github.com/parallel-web/parallel-sdk-python/commit/f53316197d11be2900710b447007c07f9c89e427))
16+
* **api:** Remove beta: tasks, task groups, search, and extract from SDK ([b7bcade](https://github.com/parallel-web/parallel-sdk-python/commit/b7bcade5a866ea8ef08de244b251c140b17f18f2))
17+
* **internal/types:** support eagerly validating pydantic iterators ([6c148b4](https://github.com/parallel-web/parallel-sdk-python/commit/6c148b449af221b634c8dd77c3846401c2d092b8))
18+
19+
20+
### Bug Fixes
21+
22+
* **client:** add missing f-string prefix in file type error message ([6fa3eac](https://github.com/parallel-web/parallel-sdk-python/commit/6fa3eaca98c7d94d0a98596227ab2f10968cea86))
23+
324
## 0.6.0 (2026-05-06)
425

526
Full Changelog: [v0.5.1...v0.6.0](https://github.com/parallel-web/parallel-sdk-python/compare/v0.5.1...v0.6.0)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "parallel-web"
3-
version = "0.6.0"
3+
version = "1.0.0"
44
description = "The official Python library for the Parallel API"
55
dynamic = ["readme"]
66
license = "MIT"

src/parallel/_files.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ async def async_to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles
9999
elif is_sequence_t(files):
100100
files = [(key, await _async_transform_file(file)) for key, file in files]
101101
else:
102-
raise TypeError("Unexpected file type input {type(files)}, expected mapping or sequence")
102+
raise TypeError(f"Unexpected file type input {type(files)}, expected mapping or sequence")
103103

104104
return files
105105

src/parallel/_models.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
ClassVar,
2626
Protocol,
2727
Required,
28+
Annotated,
2829
ParamSpec,
30+
TypeAlias,
2931
TypedDict,
3032
TypeGuard,
3133
final,
@@ -79,7 +81,15 @@
7981
from ._constants import RAW_RESPONSE_HEADER
8082

8183
if TYPE_CHECKING:
84+
from pydantic import GetCoreSchemaHandler, ValidatorFunctionWrapHandler
85+
from pydantic_core import CoreSchema, core_schema
8286
from pydantic_core.core_schema import ModelField, ModelSchema, LiteralSchema, ModelFieldsSchema
87+
else:
88+
try:
89+
from pydantic_core import CoreSchema, core_schema
90+
except ImportError:
91+
CoreSchema = None
92+
core_schema = None
8393

8494
__all__ = ["BaseModel", "GenericModel"]
8595

@@ -396,6 +406,76 @@ def model_dump_json(
396406
)
397407

398408

409+
class _EagerIterable(list[_T], Generic[_T]):
410+
"""
411+
Accepts any Iterable[T] input (including generators), consumes it
412+
eagerly, and validates all items upfront.
413+
414+
Validation preserves the original container type where possible
415+
(e.g. a set[T] stays a set[T]). Serialization (model_dump / JSON)
416+
always emits a list — round-tripping through model_dump() will not
417+
restore the original container type.
418+
"""
419+
420+
@classmethod
421+
def __get_pydantic_core_schema__(
422+
cls,
423+
source_type: Any,
424+
handler: GetCoreSchemaHandler,
425+
) -> CoreSchema:
426+
(item_type,) = get_args(source_type) or (Any,)
427+
item_schema: CoreSchema = handler.generate_schema(item_type)
428+
list_of_items_schema: CoreSchema = core_schema.list_schema(item_schema)
429+
430+
return core_schema.no_info_wrap_validator_function(
431+
cls._validate,
432+
list_of_items_schema,
433+
serialization=core_schema.plain_serializer_function_ser_schema(
434+
cls._serialize,
435+
info_arg=False,
436+
),
437+
)
438+
439+
@staticmethod
440+
def _validate(v: Iterable[_T], handler: "ValidatorFunctionWrapHandler") -> Any:
441+
original_type: type[Any] = type(v)
442+
443+
# Normalize to list so list_schema can validate each item
444+
if isinstance(v, list):
445+
items: list[_T] = v
446+
else:
447+
try:
448+
items = list(v)
449+
except TypeError as e:
450+
raise TypeError("Value is not iterable") from e
451+
452+
# Validate items against the inner schema
453+
validated: list[_T] = handler(items)
454+
455+
# Reconstruct original container type
456+
if original_type is list:
457+
return validated
458+
# str(list) produces the list's repr, not a string built from items,
459+
# so skip reconstruction for str and its subclasses.
460+
if issubclass(original_type, str):
461+
return validated
462+
try:
463+
return original_type(validated)
464+
except (TypeError, ValueError):
465+
# If the type cannot be reconstructed, just return the validated list
466+
return validated
467+
468+
@staticmethod
469+
def _serialize(v: Iterable[_T]) -> list[_T]:
470+
"""Always serialize as a list so Pydantic's JSON encoder is happy."""
471+
if isinstance(v, list):
472+
return v
473+
return list(v)
474+
475+
476+
EagerIterable: TypeAlias = Annotated[Iterable[_T], _EagerIterable]
477+
478+
399479
def _construct_field(value: object, field: FieldInfo, key: str) -> object:
400480
if value is None:
401481
return field_get_default(field)

0 commit comments

Comments
 (0)