Skip to content

Commit b9dc5ed

Browse files
release: 0.6.0 (#26)
Automated Release PR --- ## 0.6.0 (2026-05-06) Full Changelog: [v0.5.1...v0.6.0](v0.5.1...v0.6.0) ### Features * **api:** manual updates ([8cb17ac](8cb17ac)) * **api:** manual updates ([e4008e4](e4008e4)) * **api:** manual updates ([174407f](174407f)) * **api:** manual updates ([1c47c8b](1c47c8b)) * **api:** Task Groups v1 added to SDK ([198e317](198e317)) * support setting headers via env ([6dd2b05](6dd2b05)) ### Bug Fixes * re-export TaskGroup from parallel.types.beta and silence reportDeprecated ([dc6119f](dc6119f)) * **scripts:** remove unreachable check and redundant type annotation ([f63ad0a](f63ad0a)) * **scripts:** satisfy pyright in alias resolver ([892f474](892f474)) * **types:** preserve back-compat aliases for renamed inline classes ([532ee8f](532ee8f)) * **types:** use module-level alias instead of import-as ([b1b9858](b1b9858)) * use correct field name format for multipart file arrays ([1e34228](1e34228)) ### Chores * **internal:** more robust bootstrap script ([d4c7737](d4c7737)) * **internal:** reformat pyproject.toml ([b3c0639](b3c0639)) * **scripts:** follow alias and attribute redirections in breaking-change detection ([89b1495](89b1495)) * stop tracking uv.lock (project uses requirements*.lock from rye) ([540471a](540471a)) --- 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> Co-authored-by: Matt Harris <mharris@parallel.ai>
1 parent f327a0e commit b9dc5ed

92 files changed

Lines changed: 5647 additions & 967 deletions

File tree

Some content is hidden

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

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ dist
1414
.envrc
1515
codegen.log
1616
Brewfile.lock.json
17+
uv.lock

.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.5.1"
2+
".": "0.6.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: 24
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/parallel-web%2Fparallel-sdk-66ee13c3475d2c76f0956f258f0469903155b83ef02e839641be94cdc2014cf3.yml
3-
openapi_spec_hash: 88af7b88725bead1f8ccdcaeb436fadb
4-
config_hash: e17d82e9cb35004e5f9a9d3c4cf51aeb
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

CHANGELOG.md

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

3+
## 0.6.0 (2026-05-06)
4+
5+
Full Changelog: [v0.5.1...v0.6.0](https://github.com/parallel-web/parallel-sdk-python/compare/v0.5.1...v0.6.0)
6+
7+
### Features
8+
9+
* **api:** manual updates ([8cb17ac](https://github.com/parallel-web/parallel-sdk-python/commit/8cb17ac6d6c9a5a9e6443d9ecf5c121250b2eed2))
10+
* **api:** manual updates ([e4008e4](https://github.com/parallel-web/parallel-sdk-python/commit/e4008e4f8432a6c3e2341d18fee37fcedf8a530e))
11+
* **api:** manual updates ([174407f](https://github.com/parallel-web/parallel-sdk-python/commit/174407ff7467789e19d3abeffcaccd36fd35e786))
12+
* **api:** manual updates ([1c47c8b](https://github.com/parallel-web/parallel-sdk-python/commit/1c47c8baa579a403064e59a5fbb75400315951c9))
13+
* **api:** Task Groups v1 added to SDK ([198e317](https://github.com/parallel-web/parallel-sdk-python/commit/198e317bb3b5e5961e63c1c04bac0eb593385b7b))
14+
* support setting headers via env ([6dd2b05](https://github.com/parallel-web/parallel-sdk-python/commit/6dd2b05bcf25259ae50e650376c3182913439487))
15+
16+
17+
### Bug Fixes
18+
19+
* re-export TaskGroup from parallel.types.beta and silence reportDeprecated ([dc6119f](https://github.com/parallel-web/parallel-sdk-python/commit/dc6119f6dccdef75bdbe4ce838dd8ba51cc2428a))
20+
* **scripts:** remove unreachable check and redundant type annotation ([f63ad0a](https://github.com/parallel-web/parallel-sdk-python/commit/f63ad0ae48994be8b16c20438bb80c61cd943fec))
21+
* **scripts:** satisfy pyright in alias resolver ([892f474](https://github.com/parallel-web/parallel-sdk-python/commit/892f4743488ae5d8c4683123193da4f4e61d2464))
22+
* **types:** preserve back-compat aliases for renamed inline classes ([532ee8f](https://github.com/parallel-web/parallel-sdk-python/commit/532ee8f32ecbaf611f0ff5f6c80a532e2f0bcd66))
23+
* **types:** use module-level alias instead of import-as ([b1b9858](https://github.com/parallel-web/parallel-sdk-python/commit/b1b9858ffa95d90871ce36b06e510638e3546bde))
24+
* use correct field name format for multipart file arrays ([1e34228](https://github.com/parallel-web/parallel-sdk-python/commit/1e3422859a25c66804f7f588fd24276417c52057))
25+
26+
27+
### Chores
28+
29+
* **internal:** more robust bootstrap script ([d4c7737](https://github.com/parallel-web/parallel-sdk-python/commit/d4c773762e983a657fb4c6f5d39529c3467e0994))
30+
* **internal:** reformat pyproject.toml ([b3c0639](https://github.com/parallel-web/parallel-sdk-python/commit/b3c063982542886a490679f840ca0fad94695227))
31+
* **scripts:** follow alias and attribute redirections in breaking-change detection ([89b1495](https://github.com/parallel-web/parallel-sdk-python/commit/89b1495236f280eee8af7c48ecff3ff2453291bd))
32+
* stop tracking uv.lock (project uses requirements*.lock from rye) ([540471a](https://github.com/parallel-web/parallel-sdk-python/commit/540471afb4da3a6ed485af15554cb548e7086bbd))
33+
334
## 0.5.1 (2026-04-22)
435

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

api.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ from parallel.types import (
1717
ExtractResponse,
1818
ExtractResult,
1919
FetchPolicy,
20+
FullContentSettings,
2021
SearchResult,
2122
UsageItem,
2223
WebSearchResult,
@@ -40,9 +41,13 @@ from parallel.types import (
4041
JsonSchema,
4142
ParsedTaskRunResult,
4243
RunInput,
44+
TaskAdvancedSettings,
4345
TaskRun,
4446
TaskRunJsonOutput,
47+
TaskRunProgressMessageEvent,
48+
TaskRunProgressStatsEvent,
4549
TaskRunResult,
50+
TaskRunSourceStats,
4651
TaskRunTextOutput,
4752
TaskSpec,
4853
TextSchema,
@@ -54,9 +59,70 @@ Methods:
5459
- <code title="post /v1/tasks/runs">client.task_run.<a href="./src/parallel/resources/task_run.py">create</a>(\*\*<a href="src/parallel/types/task_run_create_params.py">params</a>) -> <a href="./src/parallel/types/task_run.py">TaskRun</a></code>
5560
- <code title="get /v1/tasks/runs/{run_id}">client.task_run.<a href="./src/parallel/resources/task_run.py">retrieve</a>(run_id) -> <a href="./src/parallel/types/task_run.py">TaskRun</a></code>
5661
- <code title="get /v1/tasks/runs/{run_id}/result">client.task_run.<a href="./src/parallel/resources/task_run.py">result</a>(run_id, \*\*<a href="src/parallel/types/task_run_result_params.py">params</a>) -> <a href="./src/parallel/types/task_run_result.py">TaskRunResult</a></code>
62+
- <code title="get /v1/tasks/runs/{run_id}/input">client.task_run.<a href="./src/parallel/resources/task_run.py">retrieve_input</a>(run_id) -> <a href="./src/parallel/types/run_input.py">RunInput</a></code>
5763

5864
Convenience methods:
5965

6066
- <code title="post /v1/tasks/runs">client.task_run.<a href="./src/parallel/resources/task_run.py">execute</a>(input, processor, output: <a href="./src/parallel/types/task_spec_param.py">OutputSchema</a>) -> <a href="./src/parallel/types/task_run_result.py">TaskRunResult</a></code>
6167
- <code title="post /v1/tasks/runs">client.task_run.<a href="./src/parallel/resources/task_run.py">execute</a>(input, processor, output: Type[OutputT]) -> <a href="./src/parallel/types/parsed_task_run_result.py">ParsedTaskRunResult[OutputT]</a></code>
68+
# TaskGroup
69+
70+
Types:
71+
72+
```python
73+
from parallel.types import (
74+
TaskGroup,
75+
TaskGroupRunResponse,
76+
TaskGroupStatus,
77+
TaskGroupStatusEvent,
78+
TaskGroupEventsResponse,
79+
TaskGroupGetRunsResponse,
80+
)
81+
```
82+
83+
Methods:
84+
85+
- <code title="post /v1/tasks/groups">client.task_group.<a href="./src/parallel/resources/task_group.py">create</a>(\*\*<a href="src/parallel/types/task_group_create_params.py">params</a>) -> <a href="./src/parallel/types/task_group.py">TaskGroup</a></code>
86+
- <code title="get /v1/tasks/groups/{taskgroup_id}">client.task_group.<a href="./src/parallel/resources/task_group.py">retrieve</a>(task_group_id) -> <a href="./src/parallel/types/task_group.py">TaskGroup</a></code>
87+
- <code title="post /v1/tasks/groups/{taskgroup_id}/runs">client.task_group.<a href="./src/parallel/resources/task_group.py">add_runs</a>(task_group_id, \*\*<a href="src/parallel/types/task_group_add_runs_params.py">params</a>) -> <a href="./src/parallel/types/task_group_run_response.py">TaskGroupRunResponse</a></code>
88+
- <code title="get /v1/tasks/groups/{taskgroup_id}/events">client.task_group.<a href="./src/parallel/resources/task_group.py">events</a>(task_group_id, \*\*<a href="src/parallel/types/task_group_events_params.py">params</a>) -> <a href="./src/parallel/types/task_group_events_response.py">TaskGroupEventsResponse</a></code>
89+
- <code title="get /v1/tasks/groups/{taskgroup_id}/runs">client.task_group.<a href="./src/parallel/resources/task_group.py">get_runs</a>(task_group_id, \*\*<a href="src/parallel/types/task_group_get_runs_params.py">params</a>) -> <a href="./src/parallel/types/task_group_get_runs_response.py">TaskGroupGetRunsResponse</a></code>
90+
- <code title="get /v1/tasks/groups/{taskgroup_id}/runs/{run_id}">client.task_group.<a href="./src/parallel/resources/task_group.py">retrieve_run</a>(run_id, \*, task_group_id) -> <a href="./src/parallel/types/task_run.py">TaskRun</a></code>
91+
92+
# Monitor
93+
94+
Types:
95+
96+
```python
97+
from parallel.types import (
98+
AdvancedMonitorSettings,
99+
CreateMonitorRequest,
100+
Monitor,
101+
MonitorCompletionEvent,
102+
MonitorErrorEvent,
103+
MonitorEventStreamEvent,
104+
MonitorEventStreamResponseSettings,
105+
MonitorEventStreamSettings,
106+
MonitorSnapshotEvent,
107+
MonitorSnapshotOutput,
108+
MonitorSnapshotResponseSettings,
109+
MonitorSnapshotSettings,
110+
MonitorWebhook,
111+
PaginatedMonitorEvents,
112+
PaginatedMonitorResponse,
113+
UpdateMonitorEventStreamSettings,
114+
UpdateMonitorRequest,
115+
)
116+
```
117+
118+
Methods:
119+
120+
- <code title="post /v1/monitors">client.monitor.<a href="./src/parallel/resources/monitor.py">create</a>(\*\*<a href="src/parallel/types/monitor_create_params.py">params</a>) -> <a href="./src/parallel/types/monitor.py">Monitor</a></code>
121+
- <code title="get /v1/monitors/{monitor_id}">client.monitor.<a href="./src/parallel/resources/monitor.py">retrieve</a>(monitor_id) -> <a href="./src/parallel/types/monitor.py">Monitor</a></code>
122+
- <code title="post /v1/monitors/{monitor_id}/update">client.monitor.<a href="./src/parallel/resources/monitor.py">update</a>(monitor_id, \*\*<a href="src/parallel/types/monitor_update_params.py">params</a>) -> <a href="./src/parallel/types/monitor.py">Monitor</a></code>
123+
- <code title="get /v1/monitors">client.monitor.<a href="./src/parallel/resources/monitor.py">list</a>(\*\*<a href="src/parallel/types/monitor_list_params.py">params</a>) -> <a href="./src/parallel/types/paginated_monitor_response.py">PaginatedMonitorResponse</a></code>
124+
- <code title="post /v1/monitors/{monitor_id}/cancel">client.monitor.<a href="./src/parallel/resources/monitor.py">cancel</a>(monitor_id) -> <a href="./src/parallel/types/monitor.py">Monitor</a></code>
125+
- <code title="get /v1/monitors/{monitor_id}/events">client.monitor.<a href="./src/parallel/resources/monitor.py">events</a>(monitor_id, \*\*<a href="src/parallel/types/monitor_events_params.py">params</a>) -> <a href="./src/parallel/types/paginated_monitor_events.py">PaginatedMonitorEvents</a></code>
126+
- <code title="post /v1/monitors/{monitor_id}/trigger">client.monitor.<a href="./src/parallel/resources/monitor.py">trigger</a>(monitor_id) -> None</code>
127+
62128
# [Beta](src/parallel/resources/beta/api.md)

pyproject.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "parallel-web"
3-
version = "0.5.1"
3+
version = "0.6.0"
44
description = "The official Python library for the Parallel API"
55
dynamic = ["readme"]
66
license = "MIT"
@@ -158,6 +158,11 @@ reportOverlappingOverload = false
158158

159159
reportImportCycles = false
160160
reportPrivateUsage = false
161+
# Deprecation is a runtime concern; type-check warnings produce noise when the
162+
# breaking-change detector compares against pre-deprecation baseline tests.
163+
# Newly-generated tests already add a per-file `# pyright: reportDeprecated=false`
164+
# marker for deprecated resources, so this just promotes that to project-level.
165+
reportDeprecated = false
161166

162167
[tool.mypy]
163168
pretty = true
@@ -169,7 +174,7 @@ show_error_codes = true
169174
#
170175
# We also exclude our `tests` as mypy doesn't always infer
171176
# types correctly and Pyright will still catch any type errors.
172-
exclude = ['src/parallel/_files.py', '_dev/.*.py', 'tests/.*']
177+
exclude = ["src/parallel/_files.py", "_dev/.*.py", "tests/.*"]
173178

174179
strict_equality = true
175180
implicit_reexport = true

scripts/bootstrap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -e
44

55
cd "$(dirname "$0")/.."
66

7-
if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then
7+
if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then
88
brew bundle check >/dev/null 2>&1 || {
99
echo -n "==> Install Homebrew dependencies? (y/N): "
1010
read -r response

scripts/detect-breaking-changes.py

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,67 @@
1010
from rich.style import Style
1111

1212

13+
def _resolve_redirect(obj: griffe.Object | griffe.Alias) -> griffe.Object | griffe.Alias | None:
14+
"""Follow back-compat redirections to a real class definition.
15+
16+
We use two patterns to preserve import paths after a schema rename:
17+
* `from .new_path import NewClass` → `griffe.Alias`
18+
* `OldName = NewClass` (module-level assignment) → `griffe.Attribute`
19+
Both are runtime-equivalent re-exports and should expose the target
20+
class's attributes for breaking-change detection. Without resolving them,
21+
griffe reports every old attribute as removed.
22+
"""
23+
visited: set[int] = set()
24+
current: griffe.Object | griffe.Alias = obj
25+
while id(current) not in visited:
26+
visited.add(id(current))
27+
if isinstance(current, griffe.Alias):
28+
try:
29+
return current.final_target
30+
except Exception:
31+
return None
32+
if isinstance(current, griffe.Attribute):
33+
value = current.value
34+
parent = current.parent
35+
if parent is None or value is None:
36+
return None
37+
if isinstance(value, griffe.ExprName):
38+
next_obj = parent.members.get(str(value))
39+
if next_obj is None:
40+
return None
41+
current = next_obj
42+
continue
43+
if isinstance(value, griffe.ExprAttribute):
44+
# Qualified path like `task_group_status.TaskGroupStatus`.
45+
# Walk segment by segment, resolving any module aliases as we go.
46+
next_obj = parent
47+
for segment in value.values:
48+
if not isinstance(segment, griffe.ExprName):
49+
continue
50+
if isinstance(next_obj, griffe.Alias):
51+
try:
52+
next_obj = next_obj.final_target
53+
except Exception:
54+
return None
55+
if next_obj is None or not hasattr(next_obj, "members"):
56+
return None
57+
next_obj = next_obj.members.get(str(segment))
58+
if next_obj is None:
59+
return None
60+
current = next_obj
61+
continue
62+
return None
63+
return current
64+
return None
65+
66+
1367
def public_members(obj: griffe.Object | griffe.Alias) -> dict[str, griffe.Object | griffe.Alias]:
68+
target = _resolve_redirect(obj)
69+
if target is not None and target is not obj:
70+
obj = target
71+
1472
if isinstance(obj, griffe.Alias):
15-
# ignore imports for now, they're technically part of the public API
16-
# but we don't have good preventative measures in place to prevent
17-
# changing them
73+
# Truly opaque alias we couldn't resolve.
1874
return {}
1975

2076
return {name: value for name, value in obj.all_members.items() if not name.startswith("_")}

0 commit comments

Comments
 (0)