Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d4c7737
chore(internal): more robust bootstrap script
stainless-app[bot] Apr 23, 2026
1e34228
fix: use correct field name format for multipart file arrays
stainless-app[bot] Apr 28, 2026
6dd2b05
feat: support setting headers via env
stainless-app[bot] Apr 28, 2026
a6ddb71
codegen metadata
stainless-app[bot] Apr 30, 2026
198e317
feat(api): Task Groups v1 added to SDK
stainless-app[bot] Apr 30, 2026
fe73738
codegen metadata
stainless-app[bot] May 1, 2026
b3c0639
chore(internal): reformat pyproject.toml
stainless-app[bot] May 1, 2026
1c47c8b
feat(api): manual updates
stainless-app[bot] May 6, 2026
174407f
feat(api): manual updates
stainless-app[bot] May 6, 2026
e4008e4
feat(api): manual updates
stainless-app[bot] May 6, 2026
532ee8f
fix(types): preserve back-compat aliases for renamed inline classes
NormallyGaussian May 6, 2026
540471a
chore: stop tracking uv.lock (project uses requirements*.lock from rye)
NormallyGaussian May 6, 2026
8cb17ac
feat(api): manual updates
stainless-app[bot] May 6, 2026
b1b9858
fix(types): use module-level alias instead of import-as
NormallyGaussian May 6, 2026
89b1495
chore(scripts): follow alias and attribute redirections in breaking-c…
NormallyGaussian May 6, 2026
892f474
fix(scripts): satisfy pyright in alias resolver
NormallyGaussian May 6, 2026
f63ad0a
fix(scripts): remove unreachable check and redundant type annotation
NormallyGaussian May 6, 2026
dc6119f
fix: re-export TaskGroup from parallel.types.beta and silence reportD…
NormallyGaussian May 6, 2026
a61b60b
release: 0.6.0
stainless-app[bot] May 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ dist
.envrc
codegen.log
Brewfile.lock.json
uv.lock
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.5.1"
".": "0.6.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 24
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/parallel-web%2Fparallel-sdk-66ee13c3475d2c76f0956f258f0469903155b83ef02e839641be94cdc2014cf3.yml
openapi_spec_hash: 88af7b88725bead1f8ccdcaeb436fadb
config_hash: e17d82e9cb35004e5f9a9d3c4cf51aeb
configured_endpoints: 38
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/parallel-web/parallel-sdk-b134f034fe11499d713c03d07778aba8a395d7e3cbbc3d8a4bd2891f0aa970ba.yml
openapi_spec_hash: c4fc5b0cb3bc48076f736a0ad2b2e75e
config_hash: 27cd9354fb0ac3129cbf269737cece6c
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# Changelog

## 0.6.0 (2026-05-06)

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

### Features

* **api:** manual updates ([8cb17ac](https://github.com/parallel-web/parallel-sdk-python/commit/8cb17ac6d6c9a5a9e6443d9ecf5c121250b2eed2))
* **api:** manual updates ([e4008e4](https://github.com/parallel-web/parallel-sdk-python/commit/e4008e4f8432a6c3e2341d18fee37fcedf8a530e))
* **api:** manual updates ([174407f](https://github.com/parallel-web/parallel-sdk-python/commit/174407ff7467789e19d3abeffcaccd36fd35e786))
* **api:** manual updates ([1c47c8b](https://github.com/parallel-web/parallel-sdk-python/commit/1c47c8baa579a403064e59a5fbb75400315951c9))
* **api:** Task Groups v1 added to SDK ([198e317](https://github.com/parallel-web/parallel-sdk-python/commit/198e317bb3b5e5961e63c1c04bac0eb593385b7b))
* support setting headers via env ([6dd2b05](https://github.com/parallel-web/parallel-sdk-python/commit/6dd2b05bcf25259ae50e650376c3182913439487))


### Bug Fixes

* re-export TaskGroup from parallel.types.beta and silence reportDeprecated ([dc6119f](https://github.com/parallel-web/parallel-sdk-python/commit/dc6119f6dccdef75bdbe4ce838dd8ba51cc2428a))
* **scripts:** remove unreachable check and redundant type annotation ([f63ad0a](https://github.com/parallel-web/parallel-sdk-python/commit/f63ad0ae48994be8b16c20438bb80c61cd943fec))
* **scripts:** satisfy pyright in alias resolver ([892f474](https://github.com/parallel-web/parallel-sdk-python/commit/892f4743488ae5d8c4683123193da4f4e61d2464))
* **types:** preserve back-compat aliases for renamed inline classes ([532ee8f](https://github.com/parallel-web/parallel-sdk-python/commit/532ee8f32ecbaf611f0ff5f6c80a532e2f0bcd66))
* **types:** use module-level alias instead of import-as ([b1b9858](https://github.com/parallel-web/parallel-sdk-python/commit/b1b9858ffa95d90871ce36b06e510638e3546bde))
* use correct field name format for multipart file arrays ([1e34228](https://github.com/parallel-web/parallel-sdk-python/commit/1e3422859a25c66804f7f588fd24276417c52057))


### Chores

* **internal:** more robust bootstrap script ([d4c7737](https://github.com/parallel-web/parallel-sdk-python/commit/d4c773762e983a657fb4c6f5d39529c3467e0994))
* **internal:** reformat pyproject.toml ([b3c0639](https://github.com/parallel-web/parallel-sdk-python/commit/b3c063982542886a490679f840ca0fad94695227))
* **scripts:** follow alias and attribute redirections in breaking-change detection ([89b1495](https://github.com/parallel-web/parallel-sdk-python/commit/89b1495236f280eee8af7c48ecff3ff2453291bd))
* stop tracking uv.lock (project uses requirements*.lock from rye) ([540471a](https://github.com/parallel-web/parallel-sdk-python/commit/540471afb4da3a6ed485af15554cb548e7086bbd))

## 0.5.1 (2026-04-22)

Full Changelog: [v0.5.0...v0.5.1](https://github.com/parallel-web/parallel-sdk-python/compare/v0.5.0...v0.5.1)
Expand Down
66 changes: 66 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ from parallel.types import (
ExtractResponse,
ExtractResult,
FetchPolicy,
FullContentSettings,
SearchResult,
UsageItem,
WebSearchResult,
Expand All @@ -40,9 +41,13 @@ from parallel.types import (
JsonSchema,
ParsedTaskRunResult,
RunInput,
TaskAdvancedSettings,
TaskRun,
TaskRunJsonOutput,
TaskRunProgressMessageEvent,
TaskRunProgressStatsEvent,
TaskRunResult,
TaskRunSourceStats,
TaskRunTextOutput,
TaskSpec,
TextSchema,
Expand All @@ -54,9 +59,70 @@ Methods:
- <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>
- <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>
- <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>
- <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>

Convenience methods:

- <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>
- <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>
# TaskGroup

Types:

```python
from parallel.types import (
TaskGroup,
TaskGroupRunResponse,
TaskGroupStatus,
TaskGroupStatusEvent,
TaskGroupEventsResponse,
TaskGroupGetRunsResponse,
)
```

Methods:

- <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>
- <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>
- <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>
- <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>
- <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>
- <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>

# Monitor

Types:

```python
from parallel.types import (
AdvancedMonitorSettings,
CreateMonitorRequest,
Monitor,
MonitorCompletionEvent,
MonitorErrorEvent,
MonitorEventStreamEvent,
MonitorEventStreamResponseSettings,
MonitorEventStreamSettings,
MonitorSnapshotEvent,
MonitorSnapshotOutput,
MonitorSnapshotResponseSettings,
MonitorSnapshotSettings,
MonitorWebhook,
PaginatedMonitorEvents,
PaginatedMonitorResponse,
UpdateMonitorEventStreamSettings,
UpdateMonitorRequest,
)
```

Methods:

- <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>
- <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>
- <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>
- <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>
- <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>
- <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>
- <code title="post /v1/monitors/{monitor_id}/trigger">client.monitor.<a href="./src/parallel/resources/monitor.py">trigger</a>(monitor_id) -> None</code>

# [Beta](src/parallel/resources/beta/api.md)
9 changes: 7 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "parallel-web"
version = "0.5.1"
version = "0.6.0"
description = "The official Python library for the Parallel API"
dynamic = ["readme"]
license = "MIT"
Expand Down Expand Up @@ -158,6 +158,11 @@ reportOverlappingOverload = false

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

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

strict_equality = true
implicit_reexport = true
Expand Down
2 changes: 1 addition & 1 deletion scripts/bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -e

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

if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then
if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then
brew bundle check >/dev/null 2>&1 || {
echo -n "==> Install Homebrew dependencies? (y/N): "
read -r response
Expand Down
62 changes: 59 additions & 3 deletions scripts/detect-breaking-changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,67 @@
from rich.style import Style


def _resolve_redirect(obj: griffe.Object | griffe.Alias) -> griffe.Object | griffe.Alias | None:
"""Follow back-compat redirections to a real class definition.

We use two patterns to preserve import paths after a schema rename:
* `from .new_path import NewClass` → `griffe.Alias`
* `OldName = NewClass` (module-level assignment) → `griffe.Attribute`
Both are runtime-equivalent re-exports and should expose the target
class's attributes for breaking-change detection. Without resolving them,
griffe reports every old attribute as removed.
"""
visited: set[int] = set()
current: griffe.Object | griffe.Alias = obj
while id(current) not in visited:
visited.add(id(current))
if isinstance(current, griffe.Alias):
try:
return current.final_target
except Exception:
return None
if isinstance(current, griffe.Attribute):
value = current.value
parent = current.parent
if parent is None or value is None:
return None
if isinstance(value, griffe.ExprName):
next_obj = parent.members.get(str(value))
if next_obj is None:
return None
current = next_obj
continue
if isinstance(value, griffe.ExprAttribute):
# Qualified path like `task_group_status.TaskGroupStatus`.
# Walk segment by segment, resolving any module aliases as we go.
next_obj = parent
for segment in value.values:
if not isinstance(segment, griffe.ExprName):
continue
if isinstance(next_obj, griffe.Alias):
try:
next_obj = next_obj.final_target
except Exception:
return None
if next_obj is None or not hasattr(next_obj, "members"):
return None
next_obj = next_obj.members.get(str(segment))
if next_obj is None:
return None
current = next_obj
continue
return None
return current
return None


def public_members(obj: griffe.Object | griffe.Alias) -> dict[str, griffe.Object | griffe.Alias]:
target = _resolve_redirect(obj)
if target is not None and target is not obj:
obj = target

if isinstance(obj, griffe.Alias):
# ignore imports for now, they're technically part of the public API
# but we don't have good preventative measures in place to prevent
# changing them
# Truly opaque alias we couldn't resolve.
return {}

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