From 96f50dbffc919f591a149f89b387ebf19bd4deb0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Sep 2025 02:19:41 +0000 Subject: [PATCH 1/8] chore(internal): update pydantic dependency --- requirements-dev.lock | 7 +++++-- requirements.lock | 7 +++++-- src/parallel/_models.py | 14 ++++++++++---- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index 85bf23e..64ad072 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -91,9 +91,9 @@ pluggy==1.5.0 propcache==0.3.1 # via aiohttp # via yarl -pydantic==2.10.3 +pydantic==2.11.9 # via parallel-web -pydantic-core==2.27.1 +pydantic-core==2.33.2 # via pydantic pygments==2.18.0 # via rich @@ -129,6 +129,9 @@ typing-extensions==4.12.2 # via pydantic # via pydantic-core # via pyright + # via typing-inspection +typing-inspection==0.4.1 + # via pydantic virtualenv==20.24.5 # via nox yarl==1.20.0 diff --git a/requirements.lock b/requirements.lock index 777669a..1158ab6 100644 --- a/requirements.lock +++ b/requirements.lock @@ -55,9 +55,9 @@ multidict==6.4.4 propcache==0.3.1 # via aiohttp # via yarl -pydantic==2.10.3 +pydantic==2.11.9 # via parallel-web -pydantic-core==2.27.1 +pydantic-core==2.33.2 # via pydantic sniffio==1.3.0 # via anyio @@ -68,5 +68,8 @@ typing-extensions==4.12.2 # via parallel-web # via pydantic # via pydantic-core + # via typing-inspection +typing-inspection==0.4.1 + # via pydantic yarl==1.20.0 # via aiohttp diff --git a/src/parallel/_models.py b/src/parallel/_models.py index 3a6017e..6a3cd1d 100644 --- a/src/parallel/_models.py +++ b/src/parallel/_models.py @@ -256,7 +256,7 @@ def model_dump( mode: Literal["json", "python"] | str = "python", include: IncEx | None = None, exclude: IncEx | None = None, - by_alias: bool = False, + by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, @@ -264,6 +264,7 @@ def model_dump( warnings: bool | Literal["none", "warn", "error"] = True, context: dict[str, Any] | None = None, serialize_as_any: bool = False, + fallback: Callable[[Any], Any] | None = None, ) -> dict[str, Any]: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump @@ -295,10 +296,12 @@ def model_dump( raise ValueError("context is only supported in Pydantic v2") if serialize_as_any != False: raise ValueError("serialize_as_any is only supported in Pydantic v2") + if fallback is not None: + raise ValueError("fallback is only supported in Pydantic v2") dumped = super().dict( # pyright: ignore[reportDeprecated] include=include, exclude=exclude, - by_alias=by_alias, + by_alias=by_alias if by_alias is not None else False, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, @@ -313,13 +316,14 @@ def model_dump_json( indent: int | None = None, include: IncEx | None = None, exclude: IncEx | None = None, - by_alias: bool = False, + by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, round_trip: bool = False, warnings: bool | Literal["none", "warn", "error"] = True, context: dict[str, Any] | None = None, + fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, ) -> str: """Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump_json @@ -348,11 +352,13 @@ def model_dump_json( raise ValueError("context is only supported in Pydantic v2") if serialize_as_any != False: raise ValueError("serialize_as_any is only supported in Pydantic v2") + if fallback is not None: + raise ValueError("fallback is only supported in Pydantic v2") return super().json( # type: ignore[reportDeprecated] indent=indent, include=include, exclude=exclude, - by_alias=by_alias, + by_alias=by_alias if by_alias is not None else False, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, From 0f0fa20994ddb2c89d0def2a16a68b9499e1abd4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 02:22:57 +0000 Subject: [PATCH 2/8] chore(types): change optional parameter type from NotGiven to Omit --- src/parallel/__init__.py | 4 +- src/parallel/_base_client.py | 18 +++---- src/parallel/_client.py | 16 +++--- src/parallel/_qs.py | 14 ++--- src/parallel/_types.py | 29 +++++++---- src/parallel/_utils/_transform.py | 4 +- src/parallel/_utils/_utils.py | 8 +-- src/parallel/resources/beta/beta.py | 30 +++++------ src/parallel/resources/beta/task_group.py | 62 +++++++++++------------ src/parallel/resources/beta/task_run.py | 58 ++++++++++----------- src/parallel/resources/task_run.py | 30 +++++------ tests/test_transform.py | 11 +++- 12 files changed, 150 insertions(+), 134 deletions(-) diff --git a/src/parallel/__init__.py b/src/parallel/__init__.py index 8cb966d..6c3a982 100644 --- a/src/parallel/__init__.py +++ b/src/parallel/__init__.py @@ -3,7 +3,7 @@ import typing as _t from . import types -from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes +from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given from ._utils import file_from_path from ._client import ( Client, @@ -48,7 +48,9 @@ "ProxiesTypes", "NotGiven", "NOT_GIVEN", + "not_given", "Omit", + "omit", "ParallelError", "APIError", "APIStatusError", diff --git a/src/parallel/_base_client.py b/src/parallel/_base_client.py index f739aee..97eea99 100644 --- a/src/parallel/_base_client.py +++ b/src/parallel/_base_client.py @@ -42,7 +42,6 @@ from ._qs import Querystring from ._files import to_httpx_files, async_to_httpx_files from ._types import ( - NOT_GIVEN, Body, Omit, Query, @@ -57,6 +56,7 @@ RequestOptions, HttpxRequestFiles, ModelBuilderProtocol, + not_given, ) from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping from ._compat import PYDANTIC_V1, model_copy, model_dump @@ -145,9 +145,9 @@ def __init__( def __init__( self, *, - url: URL | NotGiven = NOT_GIVEN, - json: Body | NotGiven = NOT_GIVEN, - params: Query | NotGiven = NOT_GIVEN, + url: URL | NotGiven = not_given, + json: Body | NotGiven = not_given, + params: Query | NotGiven = not_given, ) -> None: self.url = url self.json = json @@ -595,7 +595,7 @@ def _maybe_override_cast_to(self, cast_to: type[ResponseT], options: FinalReques # we internally support defining a temporary header to override the # default `cast_to` type for use with `.with_raw_response` and `.with_streaming_response` # see _response.py for implementation details - override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, NOT_GIVEN) + override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, not_given) if is_given(override_cast_to): options.headers = headers return cast(Type[ResponseT], override_cast_to) @@ -825,7 +825,7 @@ def __init__( version: str, base_url: str | URL, max_retries: int = DEFAULT_MAX_RETRIES, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, @@ -1356,7 +1356,7 @@ def __init__( base_url: str | URL, _strict_response_validation: bool, max_retries: int = DEFAULT_MAX_RETRIES, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, @@ -1818,8 +1818,8 @@ def make_request_options( extra_query: Query | None = None, extra_body: Body | None = None, idempotency_key: str | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - post_parser: PostParser | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + post_parser: PostParser | NotGiven = not_given, ) -> RequestOptions: """Create a dict of type RequestOptions without keys of NotGiven values.""" options: RequestOptions = {} diff --git a/src/parallel/_client.py b/src/parallel/_client.py index bb7c4a4..9580c5c 100644 --- a/src/parallel/_client.py +++ b/src/parallel/_client.py @@ -3,7 +3,7 @@ from __future__ import annotations import os -from typing import Any, Union, Mapping +from typing import Any, Mapping from typing_extensions import Self, override import httpx @@ -11,13 +11,13 @@ from . import _exceptions from ._qs import Querystring from ._types import ( - NOT_GIVEN, Omit, Timeout, NotGiven, Transport, ProxiesTypes, RequestOptions, + not_given, ) from ._utils import is_given, get_async_library from ._version import __version__ @@ -57,7 +57,7 @@ def __init__( *, api_key: str | None = None, base_url: str | httpx.URL | None = None, - timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -133,9 +133,9 @@ def copy( *, api_key: str | None = None, base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, - max_retries: int | NotGiven = NOT_GIVEN, + max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -227,7 +227,7 @@ def __init__( *, api_key: str | None = None, base_url: str | httpx.URL | None = None, - timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, @@ -303,9 +303,9 @@ def copy( *, api_key: str | None = None, base_url: str | httpx.URL | None = None, - timeout: float | Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, - max_retries: int | NotGiven = NOT_GIVEN, + max_retries: int | NotGiven = not_given, default_headers: Mapping[str, str] | None = None, set_default_headers: Mapping[str, str] | None = None, default_query: Mapping[str, object] | None = None, diff --git a/src/parallel/_qs.py b/src/parallel/_qs.py index 274320c..ada6fd3 100644 --- a/src/parallel/_qs.py +++ b/src/parallel/_qs.py @@ -4,7 +4,7 @@ from urllib.parse import parse_qs, urlencode from typing_extensions import Literal, get_args -from ._types import NOT_GIVEN, NotGiven, NotGivenOr +from ._types import NotGiven, not_given from ._utils import flatten _T = TypeVar("_T") @@ -41,8 +41,8 @@ def stringify( self, params: Params, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> str: return urlencode( self.stringify_items( @@ -56,8 +56,8 @@ def stringify_items( self, params: Params, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> list[tuple[str, str]]: opts = Options( qs=self, @@ -143,8 +143,8 @@ def __init__( self, qs: Querystring = _qs, *, - array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN, - nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN, + array_format: ArrayFormat | NotGiven = not_given, + nested_format: NestedFormat | NotGiven = not_given, ) -> None: self.array_format = qs.array_format if isinstance(array_format, NotGiven) else array_format self.nested_format = qs.nested_format if isinstance(nested_format, NotGiven) else nested_format diff --git a/src/parallel/_types.py b/src/parallel/_types.py index ea5c561..eb5f730 100644 --- a/src/parallel/_types.py +++ b/src/parallel/_types.py @@ -117,18 +117,21 @@ class RequestOptions(TypedDict, total=False): # Sentinel class used until PEP 0661 is accepted class NotGiven: """ - A sentinel singleton class used to distinguish omitted keyword arguments - from those passed in with the value None (which may have different behavior). + For parameters with a meaningful None value, we need to distinguish between + the user explicitly passing None, and the user not passing the parameter at + all. + + User code shouldn't need to use not_given directly. For example: ```py - def get(timeout: Union[int, NotGiven, None] = NotGiven()) -> Response: ... + def create(timeout: Timeout | None | NotGiven = not_given): ... - get(timeout=1) # 1s timeout - get(timeout=None) # No timeout - get() # Default timeout behavior, which may not be statically known at the method definition. + create(timeout=1) # 1s timeout + create(timeout=None) # No timeout + create() # Default timeout behavior ``` """ @@ -140,13 +143,14 @@ def __repr__(self) -> str: return "NOT_GIVEN" -NotGivenOr = Union[_T, NotGiven] +not_given = NotGiven() +# for backwards compatibility: NOT_GIVEN = NotGiven() class Omit: - """In certain situations you need to be able to represent a case where a default value has - to be explicitly removed and `None` is not an appropriate substitute, for example: + """ + To explicitly omit something from being sent in a request, use `omit`. ```py # as the default `Content-Type` header is `application/json` that will be sent @@ -156,8 +160,8 @@ class Omit: # to look something like: 'multipart/form-data; boundary=0d8382fcf5f8c3be01ca2e11002d2983' client.post(..., headers={"Content-Type": "multipart/form-data"}) - # instead you can remove the default `application/json` header by passing Omit - client.post(..., headers={"Content-Type": Omit()}) + # instead you can remove the default `application/json` header by passing omit + client.post(..., headers={"Content-Type": omit}) ``` """ @@ -165,6 +169,9 @@ def __bool__(self) -> Literal[False]: return False +omit = Omit() + + @runtime_checkable class ModelBuilderProtocol(Protocol): @classmethod diff --git a/src/parallel/_utils/_transform.py b/src/parallel/_utils/_transform.py index c19124f..5207549 100644 --- a/src/parallel/_utils/_transform.py +++ b/src/parallel/_utils/_transform.py @@ -268,7 +268,7 @@ def _transform_typeddict( annotations = get_type_hints(expected_type, include_extras=True) for key, value in data.items(): if not is_given(value): - # we don't need to include `NotGiven` values here as they'll + # we don't need to include omitted values here as they'll # be stripped out before the request is sent anyway continue @@ -434,7 +434,7 @@ async def _async_transform_typeddict( annotations = get_type_hints(expected_type, include_extras=True) for key, value in data.items(): if not is_given(value): - # we don't need to include `NotGiven` values here as they'll + # we don't need to include omitted values here as they'll # be stripped out before the request is sent anyway continue diff --git a/src/parallel/_utils/_utils.py b/src/parallel/_utils/_utils.py index 96b7d7f..0ed3c85 100644 --- a/src/parallel/_utils/_utils.py +++ b/src/parallel/_utils/_utils.py @@ -21,7 +21,7 @@ import sniffio -from .._types import NotGiven, FileTypes, NotGivenOr, HeadersLike +from .._types import Omit, NotGiven, FileTypes, HeadersLike _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) @@ -63,7 +63,7 @@ def _extract_items( try: key = path[index] except IndexError: - if isinstance(obj, NotGiven): + if not is_given(obj): # no value was provided - we can safely ignore return [] @@ -126,8 +126,8 @@ def _extract_items( return [] -def is_given(obj: NotGivenOr[_T]) -> TypeGuard[_T]: - return not isinstance(obj, NotGiven) +def is_given(obj: _T | NotGiven | Omit) -> TypeGuard[_T]: + return not isinstance(obj, NotGiven) and not isinstance(obj, Omit) # Type safe methods for narrowing types with TypeVars. diff --git a/src/parallel/resources/beta/beta.py b/src/parallel/resources/beta/beta.py index 3a56ae3..b2f4c70 100644 --- a/src/parallel/resources/beta/beta.py +++ b/src/parallel/resources/beta/beta.py @@ -7,7 +7,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven, SequenceNotStr +from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from .task_run import ( TaskRunResource, @@ -72,18 +72,18 @@ def with_streaming_response(self) -> BetaResourceWithStreamingResponse: def search( self, *, - max_chars_per_result: Optional[int] | NotGiven = NOT_GIVEN, - max_results: Optional[int] | NotGiven = NOT_GIVEN, - objective: Optional[str] | NotGiven = NOT_GIVEN, - processor: Literal["base", "pro"] | NotGiven = NOT_GIVEN, - search_queries: Optional[SequenceNotStr[str]] | NotGiven = NOT_GIVEN, - source_policy: Optional[SourcePolicy] | NotGiven = NOT_GIVEN, + max_chars_per_result: Optional[int] | Omit = omit, + max_results: Optional[int] | Omit = omit, + objective: Optional[str] | Omit = omit, + processor: Literal["base", "pro"] | Omit = omit, + search_queries: Optional[SequenceNotStr[str]] | Omit = omit, + source_policy: Optional[SourcePolicy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SearchResult: """ Searches the web. @@ -168,18 +168,18 @@ def with_streaming_response(self) -> AsyncBetaResourceWithStreamingResponse: async def search( self, *, - max_chars_per_result: Optional[int] | NotGiven = NOT_GIVEN, - max_results: Optional[int] | NotGiven = NOT_GIVEN, - objective: Optional[str] | NotGiven = NOT_GIVEN, - processor: Literal["base", "pro"] | NotGiven = NOT_GIVEN, - search_queries: Optional[SequenceNotStr[str]] | NotGiven = NOT_GIVEN, - source_policy: Optional[SourcePolicy] | NotGiven = NOT_GIVEN, + max_chars_per_result: Optional[int] | Omit = omit, + max_results: Optional[int] | Omit = omit, + objective: Optional[str] | Omit = omit, + processor: Literal["base", "pro"] | Omit = omit, + search_queries: Optional[SequenceNotStr[str]] | Omit = omit, + source_policy: Optional[SourcePolicy] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SearchResult: """ Searches the web. diff --git a/src/parallel/resources/beta/task_group.py b/src/parallel/resources/beta/task_group.py index 0a34e67..657f4a7 100644 --- a/src/parallel/resources/beta/task_group.py +++ b/src/parallel/resources/beta/task_group.py @@ -7,7 +7,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import is_given, maybe_transform, strip_not_given, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -59,13 +59,13 @@ def with_streaming_response(self) -> TaskGroupResourceWithStreamingResponse: def create( self, *, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskGroup: """ Initiates a TaskGroup to group and track multiple runs. @@ -99,7 +99,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskGroup: """ Retrieves aggregated status across runs in a TaskGroup. @@ -128,14 +128,14 @@ def add_runs( task_group_id: str, *, inputs: Iterable[BetaRunInputParam], - default_task_spec: Optional[TaskSpecParam] | NotGiven = NOT_GIVEN, - betas: List[ParallelBetaParam] | NotGiven = NOT_GIVEN, + default_task_spec: Optional[TaskSpecParam] | Omit = omit, + betas: List[ParallelBetaParam] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskGroupRunResponse: """ Initiates multiple task runs within a TaskGroup. @@ -163,7 +163,7 @@ def add_runs( if not task_group_id: raise ValueError(f"Expected a non-empty value for `task_group_id` but received {task_group_id!r}") extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else NOT_GIVEN}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), **(extra_headers or {}), } return self._post( @@ -185,14 +185,14 @@ def events( self, task_group_id: str, *, - last_event_id: Optional[str] | NotGiven = NOT_GIVEN, - api_timeout: Optional[float] | NotGiven = NOT_GIVEN, + last_event_id: Optional[str] | Omit = omit, + api_timeout: Optional[float] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[TaskGroupEventsResponse]: """ Streams events from a TaskGroup: status updates and run completions. @@ -238,19 +238,19 @@ def get_runs( self, task_group_id: str, *, - include_input: bool | NotGiven = NOT_GIVEN, - include_output: bool | NotGiven = NOT_GIVEN, - last_event_id: Optional[str] | NotGiven = NOT_GIVEN, + include_input: bool | Omit = omit, + include_output: bool | Omit = omit, + last_event_id: Optional[str] | Omit = omit, status: Optional[ Literal["queued", "action_required", "running", "completed", "failed", "cancelling", "cancelled"] ] - | NotGiven = NOT_GIVEN, + | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[TaskGroupGetRunsResponse]: """ Retrieves task runs in a TaskGroup and optionally their inputs and outputs. @@ -315,13 +315,13 @@ def with_streaming_response(self) -> AsyncTaskGroupResourceWithStreamingResponse async def create( self, *, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskGroup: """ Initiates a TaskGroup to group and track multiple runs. @@ -355,7 +355,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskGroup: """ Retrieves aggregated status across runs in a TaskGroup. @@ -384,14 +384,14 @@ async def add_runs( task_group_id: str, *, inputs: Iterable[BetaRunInputParam], - default_task_spec: Optional[TaskSpecParam] | NotGiven = NOT_GIVEN, - betas: List[ParallelBetaParam] | NotGiven = NOT_GIVEN, + default_task_spec: Optional[TaskSpecParam] | Omit = omit, + betas: List[ParallelBetaParam] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskGroupRunResponse: """ Initiates multiple task runs within a TaskGroup. @@ -419,7 +419,7 @@ async def add_runs( if not task_group_id: raise ValueError(f"Expected a non-empty value for `task_group_id` but received {task_group_id!r}") extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else NOT_GIVEN}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), **(extra_headers or {}), } return await self._post( @@ -441,14 +441,14 @@ async def events( self, task_group_id: str, *, - last_event_id: Optional[str] | NotGiven = NOT_GIVEN, - api_timeout: Optional[float] | NotGiven = NOT_GIVEN, + last_event_id: Optional[str] | Omit = omit, + api_timeout: Optional[float] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[TaskGroupEventsResponse]: """ Streams events from a TaskGroup: status updates and run completions. @@ -494,19 +494,19 @@ async def get_runs( self, task_group_id: str, *, - include_input: bool | NotGiven = NOT_GIVEN, - include_output: bool | NotGiven = NOT_GIVEN, - last_event_id: Optional[str] | NotGiven = NOT_GIVEN, + include_input: bool | Omit = omit, + include_output: bool | Omit = omit, + last_event_id: Optional[str] | Omit = omit, status: Optional[ Literal["queued", "action_required", "running", "completed", "failed", "cancelling", "cancelled"] ] - | NotGiven = NOT_GIVEN, + | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[TaskGroupGetRunsResponse]: """ Retrieves task runs in a TaskGroup and optionally their inputs and outputs. diff --git a/src/parallel/resources/beta/task_run.py b/src/parallel/resources/beta/task_run.py index 8235a1a..54cda9f 100644 --- a/src/parallel/resources/beta/task_run.py +++ b/src/parallel/resources/beta/task_run.py @@ -6,7 +6,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import is_given, maybe_transform, strip_not_given, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -56,19 +56,19 @@ def create( *, input: Union[str, Dict[str, object]], processor: str, - enable_events: Optional[bool] | NotGiven = NOT_GIVEN, - mcp_servers: Optional[Iterable[McpServerParam]] | NotGiven = NOT_GIVEN, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, - source_policy: Optional[SourcePolicy] | NotGiven = NOT_GIVEN, - task_spec: Optional[TaskSpecParam] | NotGiven = NOT_GIVEN, - webhook: Optional[WebhookParam] | NotGiven = NOT_GIVEN, - betas: List[ParallelBetaParam] | NotGiven = NOT_GIVEN, + enable_events: Optional[bool] | Omit = omit, + mcp_servers: Optional[Iterable[McpServerParam]] | Omit = omit, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, + source_policy: Optional[SourcePolicy] | Omit = omit, + task_spec: Optional[TaskSpecParam] | Omit = omit, + webhook: Optional[WebhookParam] | Omit = omit, + betas: List[ParallelBetaParam] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRun: """ Initiates a task run. @@ -122,7 +122,7 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else NOT_GIVEN}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), **(extra_headers or {}), } return self._post( @@ -155,7 +155,7 @@ def events( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Stream[TaskRunEventsResponse]: """ Streams events for a task run. @@ -192,14 +192,14 @@ def result( self, run_id: str, *, - api_timeout: int | NotGiven = NOT_GIVEN, - betas: List[ParallelBetaParam] | NotGiven = NOT_GIVEN, + api_timeout: int | Omit = omit, + betas: List[ParallelBetaParam] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BetaTaskRunResult: """ Retrieves a run result by run_id, blocking until the run is completed. @@ -218,7 +218,7 @@ def result( if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else NOT_GIVEN}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), **(extra_headers or {}), } return self._get( @@ -259,19 +259,19 @@ async def create( *, input: Union[str, Dict[str, object]], processor: str, - enable_events: Optional[bool] | NotGiven = NOT_GIVEN, - mcp_servers: Optional[Iterable[McpServerParam]] | NotGiven = NOT_GIVEN, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, - source_policy: Optional[SourcePolicy] | NotGiven = NOT_GIVEN, - task_spec: Optional[TaskSpecParam] | NotGiven = NOT_GIVEN, - webhook: Optional[WebhookParam] | NotGiven = NOT_GIVEN, - betas: List[ParallelBetaParam] | NotGiven = NOT_GIVEN, + enable_events: Optional[bool] | Omit = omit, + mcp_servers: Optional[Iterable[McpServerParam]] | Omit = omit, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, + source_policy: Optional[SourcePolicy] | Omit = omit, + task_spec: Optional[TaskSpecParam] | Omit = omit, + webhook: Optional[WebhookParam] | Omit = omit, + betas: List[ParallelBetaParam] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRun: """ Initiates a task run. @@ -325,7 +325,7 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else NOT_GIVEN}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), **(extra_headers or {}), } return await self._post( @@ -358,7 +358,7 @@ async def events( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncStream[TaskRunEventsResponse]: """ Streams events for a task run. @@ -395,14 +395,14 @@ async def result( self, run_id: str, *, - api_timeout: int | NotGiven = NOT_GIVEN, - betas: List[ParallelBetaParam] | NotGiven = NOT_GIVEN, + api_timeout: int | Omit = omit, + betas: List[ParallelBetaParam] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BetaTaskRunResult: """ Retrieves a run result by run_id, blocking until the run is completed. @@ -421,7 +421,7 @@ async def result( if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else NOT_GIVEN}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), **(extra_headers or {}), } return await self._get( diff --git a/src/parallel/resources/task_run.py b/src/parallel/resources/task_run.py index 9fe16d9..c635620 100644 --- a/src/parallel/resources/task_run.py +++ b/src/parallel/resources/task_run.py @@ -10,7 +10,7 @@ from parallel.lib._time import prepare_timeout_float from ..types import task_run_create_params, task_run_result_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -61,15 +61,15 @@ def create( *, input: Union[str, Dict[str, object]], processor: str, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, - source_policy: Optional[SourcePolicy] | NotGiven = NOT_GIVEN, - task_spec: Optional[TaskSpecParam] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, + source_policy: Optional[SourcePolicy] | Omit = omit, + task_spec: Optional[TaskSpecParam] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRun: """ Initiates a task run. @@ -132,7 +132,7 @@ def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRun: """ Retrieves run status by run_id. @@ -162,13 +162,13 @@ def result( self, run_id: str, *, - api_timeout: int | NotGiven = NOT_GIVEN, + api_timeout: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRunResult: """ Retrieves a run result by run_id, blocking until the run is completed. @@ -350,15 +350,15 @@ async def create( *, input: Union[str, Dict[str, object]], processor: str, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, - source_policy: Optional[SourcePolicy] | NotGiven = NOT_GIVEN, - task_spec: Optional[TaskSpecParam] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, + source_policy: Optional[SourcePolicy] | Omit = omit, + task_spec: Optional[TaskSpecParam] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRun: """ Initiates a task run. @@ -421,7 +421,7 @@ async def retrieve( extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRun: """ Retrieves run status by run_id. @@ -451,13 +451,13 @@ async def result( self, run_id: str, *, - api_timeout: int | NotGiven = NOT_GIVEN, + api_timeout: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRunResult: """ Retrieves a run result by run_id, blocking until the run is completed. diff --git a/tests/test_transform.py b/tests/test_transform.py index 7653574..15692f8 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -8,7 +8,7 @@ import pytest -from parallel._types import NOT_GIVEN, Base64FileInput +from parallel._types import Base64FileInput, omit, not_given from parallel._utils import ( PropertyInfo, transform as _transform, @@ -450,4 +450,11 @@ async def test_transform_skipping(use_async: bool) -> None: @pytest.mark.asyncio async def test_strips_notgiven(use_async: bool) -> None: assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} - assert await transform({"foo_bar": NOT_GIVEN}, Foo1, use_async) == {} + assert await transform({"foo_bar": not_given}, Foo1, use_async) == {} + + +@parametrize +@pytest.mark.asyncio +async def test_strips_omit(use_async: bool) -> None: + assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} + assert await transform({"foo_bar": omit}, Foo1, use_async) == {} From c3250e26311cc9b767d06a112317b74f73f78644 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 02:26:27 +0000 Subject: [PATCH 3/8] chore: do not install brew dependencies in ./scripts/bootstrap by default --- scripts/bootstrap | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/bootstrap b/scripts/bootstrap index e84fe62..b430fee 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,10 +4,18 @@ set -e cd "$(dirname "$0")/.." -if ! command -v rye >/dev/null 2>&1 && [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { - echo "==> Installing Homebrew dependencies…" - brew bundle + echo -n "==> Install Homebrew dependencies? (y/N): " + read -r response + case "$response" in + [yY][eE][sS]|[yY]) + brew bundle + ;; + *) + ;; + esac + echo } fi From 8989f9120217bba2c95b2b256a2767f885311652 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 02:13:20 +0000 Subject: [PATCH 4/8] fix: do not set headers with default to omit --- src/parallel/resources/beta/task_group.py | 4 ++-- src/parallel/resources/beta/task_run.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/parallel/resources/beta/task_group.py b/src/parallel/resources/beta/task_group.py index 657f4a7..8e3fe02 100644 --- a/src/parallel/resources/beta/task_group.py +++ b/src/parallel/resources/beta/task_group.py @@ -163,7 +163,7 @@ def add_runs( if not task_group_id: raise ValueError(f"Expected a non-empty value for `task_group_id` but received {task_group_id!r}") extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else not_given}), **(extra_headers or {}), } return self._post( @@ -419,7 +419,7 @@ async def add_runs( if not task_group_id: raise ValueError(f"Expected a non-empty value for `task_group_id` but received {task_group_id!r}") extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else not_given}), **(extra_headers or {}), } return await self._post( diff --git a/src/parallel/resources/beta/task_run.py b/src/parallel/resources/beta/task_run.py index 54cda9f..63c1306 100644 --- a/src/parallel/resources/beta/task_run.py +++ b/src/parallel/resources/beta/task_run.py @@ -122,7 +122,7 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else not_given}), **(extra_headers or {}), } return self._post( @@ -218,7 +218,7 @@ def result( if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else not_given}), **(extra_headers or {}), } return self._get( @@ -325,7 +325,7 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else not_given}), **(extra_headers or {}), } return await self._post( @@ -421,7 +421,7 @@ async def result( if not run_id: raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") extra_headers = { - **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else omit}), + **strip_not_given({"parallel-beta": ",".join(str(e) for e in betas) if is_given(betas) else not_given}), **(extra_headers or {}), } return await self._get( From 176f9d318d9d9367b61e40fb6f8c27576e75deb4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 01:42:17 +0000 Subject: [PATCH 5/8] feat(api): Add progress meter to Task Run events --- .stats.yml | 4 +-- src/parallel/resources/beta/task_group.py | 26 ++++++++++++++++--- src/parallel/resources/beta/task_run.py | 24 ++++++++--------- src/parallel/types/beta/beta_run_input.py | 12 ++++----- .../types/beta/beta_run_input_param.py | 12 ++++----- src/parallel/types/beta/search_result.py | 2 +- .../types/beta/task_run_create_params.py | 12 ++++----- .../types/beta/task_run_events_response.py | 6 +++++ 8 files changed, 61 insertions(+), 37 deletions(-) diff --git a/.stats.yml b/.stats.yml index 769462b..727f3a0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 12 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/parallel-web%2Fparallel-sdk-ed59cb6466c038703341e4b1eacb013f08b1907b40a6cba7d39ff5396fb432f3.yml -openapi_spec_hash: 9d983b5f712eb8b5531127543291c6e7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/parallel-web%2Fparallel-sdk-496d0afc77bafdc8f4208d3ddd767c3101d91ffb933b9b6bfcef5f489cc175a6.yml +openapi_spec_hash: 730e697fec302b9310d4495c1f82802d config_hash: f9aa4d901581aaf70789dd0bc1b84597 diff --git a/src/parallel/resources/beta/task_group.py b/src/parallel/resources/beta/task_group.py index 8e3fe02..3ea0f77 100644 --- a/src/parallel/resources/beta/task_group.py +++ b/src/parallel/resources/beta/task_group.py @@ -197,8 +197,8 @@ def events( """ Streams events from a TaskGroup: status updates and run completions. - The connection will remain open for up to 10 minutes as long as at least one run - in the TaskGroup is active. + The connection will remain open for up to an hour as long as at least one run in + the group is still active. Args: extra_headers: Send extra headers @@ -255,6 +255,15 @@ def get_runs( """ Retrieves task runs in a TaskGroup and optionally their inputs and outputs. + All runs within a TaskGroup are returned as a stream. To get the inputs and/or + outputs back in the stream, set the corresponding `include_input` and + `include_output` parameters to `true`. + + The stream is resumable using the `event_id` as the cursor. To resume a stream, + specify the `last_event_id` parameter with the `event_id` of the last event in + the stream. The stream will resume from the next event after the + `last_event_id`. + Args: extra_headers: Send extra headers @@ -453,8 +462,8 @@ async def events( """ Streams events from a TaskGroup: status updates and run completions. - The connection will remain open for up to 10 minutes as long as at least one run - in the TaskGroup is active. + The connection will remain open for up to an hour as long as at least one run in + the group is still active. Args: extra_headers: Send extra headers @@ -511,6 +520,15 @@ async def get_runs( """ Retrieves task runs in a TaskGroup and optionally their inputs and outputs. + All runs within a TaskGroup are returned as a stream. To get the inputs and/or + outputs back in the stream, set the corresponding `include_input` and + `include_output` parameters to `true`. + + The stream is resumable using the `event_id` as the cursor. To resume a stream, + specify the `last_event_id` parameter with the `event_id` of the last event in + the stream. The stream will resume from the next event after the + `last_event_id`. + Args: extra_headers: Send extra headers diff --git a/src/parallel/resources/beta/task_run.py b/src/parallel/resources/beta/task_run.py index 63c1306..0f638ef 100644 --- a/src/parallel/resources/beta/task_run.py +++ b/src/parallel/resources/beta/task_run.py @@ -87,13 +87,13 @@ def create( [Task Run events](https://platform.parallel.ai/api-reference) endpoint. When false, no progress events are tracked. Note that progress tracking cannot be enabled after a run has been created. The flag is set to true by default for - premium processors (pro and above). This feature is not available via the Python - SDK. To enable this feature in your API requests, specify the `parallel-beta` - header with `events-sse-2025-07-24` value. + premium processors (pro and above). To enable this feature in your requests, + specify `events-sse-2025-07-24` as one of the values in `parallel-beta` header + (for API calls) or `betas` param (for the SDKs). - mcp_servers: Optional list of MCP servers to use for the run. This feature is not available - via the Python SDK. To enable this feature in your API requests, specify the - `parallel-beta` header with `mcp-server-2025-07-17` value. + mcp_servers: Optional list of MCP servers to use for the run. To enable this feature in your + requests, specify `mcp-server-2025-07-17` as one of the values in + `parallel-beta` header (for API calls) or `betas` param (for the SDKs). metadata: User-provided metadata stored with the run. Keys and values must be strings with a maximum length of 16 and 512 characters respectively. @@ -290,13 +290,13 @@ async def create( [Task Run events](https://platform.parallel.ai/api-reference) endpoint. When false, no progress events are tracked. Note that progress tracking cannot be enabled after a run has been created. The flag is set to true by default for - premium processors (pro and above). This feature is not available via the Python - SDK. To enable this feature in your API requests, specify the `parallel-beta` - header with `events-sse-2025-07-24` value. + premium processors (pro and above). To enable this feature in your requests, + specify `events-sse-2025-07-24` as one of the values in `parallel-beta` header + (for API calls) or `betas` param (for the SDKs). - mcp_servers: Optional list of MCP servers to use for the run. This feature is not available - via the Python SDK. To enable this feature in your API requests, specify the - `parallel-beta` header with `mcp-server-2025-07-17` value. + mcp_servers: Optional list of MCP servers to use for the run. To enable this feature in your + requests, specify `mcp-server-2025-07-17` as one of the values in + `parallel-beta` header (for API calls) or `betas` param (for the SDKs). metadata: User-provided metadata stored with the run. Keys and values must be strings with a maximum length of 16 and 512 characters respectively. diff --git a/src/parallel/types/beta/beta_run_input.py b/src/parallel/types/beta/beta_run_input.py index 7707711..8bed8c4 100644 --- a/src/parallel/types/beta/beta_run_input.py +++ b/src/parallel/types/beta/beta_run_input.py @@ -25,16 +25,16 @@ class BetaRunInput(BaseModel): [Task Run events](https://platform.parallel.ai/api-reference) endpoint. When false, no progress events are tracked. Note that progress tracking cannot be enabled after a run has been created. The flag is set to true by default for - premium processors (pro and above). This feature is not available via the Python - SDK. To enable this feature in your API requests, specify the `parallel-beta` - header with `events-sse-2025-07-24` value. + premium processors (pro and above). To enable this feature in your requests, + specify `events-sse-2025-07-24` as one of the values in `parallel-beta` header + (for API calls) or `betas` param (for the SDKs). """ mcp_servers: Optional[List[McpServer]] = None """ - Optional list of MCP servers to use for the run. This feature is not available - via the Python SDK. To enable this feature in your API requests, specify the - `parallel-beta` header with `mcp-server-2025-07-17` value. + Optional list of MCP servers to use for the run. To enable this feature in your + requests, specify `mcp-server-2025-07-17` as one of the values in + `parallel-beta` header (for API calls) or `betas` param (for the SDKs). """ metadata: Optional[Dict[str, Union[str, float, bool]]] = None diff --git a/src/parallel/types/beta/beta_run_input_param.py b/src/parallel/types/beta/beta_run_input_param.py index 715f6ed..553fa3c 100644 --- a/src/parallel/types/beta/beta_run_input_param.py +++ b/src/parallel/types/beta/beta_run_input_param.py @@ -27,16 +27,16 @@ class BetaRunInputParam(TypedDict, total=False): [Task Run events](https://platform.parallel.ai/api-reference) endpoint. When false, no progress events are tracked. Note that progress tracking cannot be enabled after a run has been created. The flag is set to true by default for - premium processors (pro and above). This feature is not available via the Python - SDK. To enable this feature in your API requests, specify the `parallel-beta` - header with `events-sse-2025-07-24` value. + premium processors (pro and above). To enable this feature in your requests, + specify `events-sse-2025-07-24` as one of the values in `parallel-beta` header + (for API calls) or `betas` param (for the SDKs). """ mcp_servers: Optional[Iterable[McpServerParam]] """ - Optional list of MCP servers to use for the run. This feature is not available - via the Python SDK. To enable this feature in your API requests, specify the - `parallel-beta` header with `mcp-server-2025-07-17` value. + Optional list of MCP servers to use for the run. To enable this feature in your + requests, specify `mcp-server-2025-07-17` as one of the values in + `parallel-beta` header (for API calls) or `betas` param (for the SDKs). """ metadata: Optional[Dict[str, Union[str, float, bool]]] diff --git a/src/parallel/types/beta/search_result.py b/src/parallel/types/beta/search_result.py index 05c945c..0b94295 100644 --- a/src/parallel/types/beta/search_result.py +++ b/src/parallel/types/beta/search_result.py @@ -13,4 +13,4 @@ class SearchResult(BaseModel): """A list of WebSearchResult objects, ordered by decreasing relevance.""" search_id: str - """Search ID. Example: `search_cad0a6d2-dec0-46bd-95ae-900527d880e7`""" + """Search ID. Example: `search_cad0a6d2dec046bd95ae900527d880e7`""" diff --git a/src/parallel/types/beta/task_run_create_params.py b/src/parallel/types/beta/task_run_create_params.py index 80bd0da..2842939 100644 --- a/src/parallel/types/beta/task_run_create_params.py +++ b/src/parallel/types/beta/task_run_create_params.py @@ -29,16 +29,16 @@ class TaskRunCreateParams(TypedDict, total=False): [Task Run events](https://platform.parallel.ai/api-reference) endpoint. When false, no progress events are tracked. Note that progress tracking cannot be enabled after a run has been created. The flag is set to true by default for - premium processors (pro and above). This feature is not available via the Python - SDK. To enable this feature in your API requests, specify the `parallel-beta` - header with `events-sse-2025-07-24` value. + premium processors (pro and above). To enable this feature in your requests, + specify `events-sse-2025-07-24` as one of the values in `parallel-beta` header + (for API calls) or `betas` param (for the SDKs). """ mcp_servers: Optional[Iterable[McpServerParam]] """ - Optional list of MCP servers to use for the run. This feature is not available - via the Python SDK. To enable this feature in your API requests, specify the - `parallel-beta` header with `mcp-server-2025-07-17` value. + Optional list of MCP servers to use for the run. To enable this feature in your + requests, specify `mcp-server-2025-07-17` as one of the values in + `parallel-beta` header (for API calls) or `betas` param (for the SDKs). """ metadata: Optional[Dict[str, Union[str, float, bool]]] diff --git a/src/parallel/types/beta/task_run_events_response.py b/src/parallel/types/beta/task_run_events_response.py index 27ea82f..e344ef1 100644 --- a/src/parallel/types/beta/task_run_events_response.py +++ b/src/parallel/types/beta/task_run_events_response.py @@ -28,6 +28,12 @@ class TaskRunProgressStatsEventSourceStats(BaseModel): class TaskRunProgressStatsEvent(BaseModel): + progress_meter: float + """Completion percentage of the task run. + + Ranges from 0 to 100 where 0 indicates no progress and 100 indicates completion. + """ + source_stats: TaskRunProgressStatsEventSourceStats """Source stats for a task run.""" From db5980ce6d58ac926eea60d836b36dc8bdd651d7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 11 Oct 2025 02:07:03 +0000 Subject: [PATCH 6/8] chore(internal): detect missing future annotations with ruff --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index f0f5a51..29700e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -225,6 +225,8 @@ select = [ "B", # remove unused imports "F401", + # check for missing future annotations + "FA102", # bare except statements "E722", # unused arguments @@ -247,6 +249,8 @@ unfixable = [ "T203", ] +extend-safe-fixes = ["FA102"] + [tool.ruff.lint.flake8-tidy-imports.banned-api] "functools.lru_cache".msg = "This function does not retain type information for the wrapped function's arguments; The `lru_cache` function from `_utils` should be used instead" From e0723f5fa83cd0b3728d7c471c82dd698788305e Mon Sep 17 00:00:00 2001 From: Kumar Saunack Date: Thu, 16 Oct 2025 15:42:59 -0700 Subject: [PATCH 7/8] update custom code --- src/parallel/lib/_parsing/_task_run_result.py | 5 ++- src/parallel/lib/_parsing/_task_spec.py | 8 ++--- src/parallel/resources/task_run.py | 36 +++++++++---------- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/parallel/lib/_parsing/_task_run_result.py b/src/parallel/lib/_parsing/_task_run_result.py index a5b16d2..bd3c02f 100644 --- a/src/parallel/lib/_parsing/_task_run_result.py +++ b/src/parallel/lib/_parsing/_task_run_result.py @@ -4,14 +4,13 @@ from .._time import timeout_retry_context from ...types import TaskRunResult, ParsedTaskRunResult -from ..._types import NotGiven +from ..._types import Omit from ..._utils import is_str, is_given from ..._compat import model_parse, model_parse_json from ..._models import construct_type_unchecked from .._pydantic import is_basemodel_type from ._task_spec import is_output_schema_param from ...types.task_spec_param import OutputT, OutputSchema -from ...types.parsed_task_run_result import ParsedTaskRunResult def wait_for_result( @@ -37,7 +36,7 @@ async def wait_for_result_async( def task_run_result_parser( - run_result: TaskRunResult, output_format: Union[OutputSchema, Type[OutputT]] | None | NotGiven + run_result: TaskRunResult, output_format: Union[OutputSchema, Type[OutputT]] | Omit | None ) -> TaskRunResult | ParsedTaskRunResult[OutputT]: """Parse a TaskRunResult object into a ParsedTaskRunResult based on output_format.""" if not is_given(output_format) or output_format is None or is_output_schema_param(output_format): diff --git a/src/parallel/lib/_parsing/_task_spec.py b/src/parallel/lib/_parsing/_task_spec.py index d5d3cfb..402e64e 100644 --- a/src/parallel/lib/_parsing/_task_spec.py +++ b/src/parallel/lib/_parsing/_task_spec.py @@ -5,7 +5,7 @@ import pydantic -from ..._types import NOT_GIVEN, NotGiven +from ..._types import Omit from ..._utils import is_str, is_dict, is_given from .._pydantic import to_json_schema, is_basemodel_type from ...types.task_spec_param import ( @@ -81,12 +81,12 @@ def _generate_output_schema(output_format: OutputSchema | Type[OutputT]) -> Outp def build_task_spec_param( - output_format: OutputSchema | Type[OutputT] | None | NotGiven, + output_format: OutputSchema | Type[OutputT] | Omit | None, _: Union[str, object], # placeholder for input -) -> TaskSpecParam | NotGiven: +) -> TaskSpecParam | Omit: """Build a TaskSpecParam from an OutputSchema or Type[OutputT] if provided.""" if not is_given(output_format) or output_format is None: - return NOT_GIVEN + return Omit() # output format has type OutputSchema | Type[OutputT] here output_schema = _generate_output_schema(output_format) # type: ignore[arg-type] diff --git a/src/parallel/resources/task_run.py b/src/parallel/resources/task_run.py index c635620..06af545 100644 --- a/src/parallel/resources/task_run.py +++ b/src/parallel/resources/task_run.py @@ -201,7 +201,7 @@ def _wait_for_result( *, run_id: str, deadline: float, - output: Optional[OutputSchema] | Type[OutputT] | NotGiven = NOT_GIVEN, + output: Optional[OutputSchema] | Type[OutputT] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -229,14 +229,14 @@ def execute( *, input: Union[str, Dict[str, object]], processor: str, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, - output: Optional[OutputSchema] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, + output: Optional[OutputSchema] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRunResult: ... @overload def execute( @@ -244,28 +244,28 @@ def execute( *, input: Union[str, Dict[str, object]], processor: str, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, output: Type[OutputT], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ParsedTaskRunResult[OutputT]: ... def execute( self, *, input: Union[str, Dict[str, object]], processor: str, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, - output: Optional[OutputSchema] | Type[OutputT] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, + output: Optional[OutputSchema] | Type[OutputT] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRunResult | ParsedTaskRunResult[OutputT]: """ Convenience method to create and execute a task run in a single call. @@ -492,7 +492,7 @@ async def _wait_for_result( *, run_id: str, deadline: float, - output: Optional[OutputSchema] | Type[OutputT] | NotGiven = NOT_GIVEN, + output: Optional[OutputSchema] | Type[OutputT] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -520,12 +520,12 @@ async def execute( *, input: Union[str, Dict[str, object]], processor: str, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, - output: Optional[OutputSchema] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, + output: Optional[OutputSchema] | Omit = omit, extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRunResult: ... @overload async def execute( @@ -533,26 +533,26 @@ async def execute( *, input: Union[str, Dict[str, object]], processor: str, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, output: Type[OutputT], extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ParsedTaskRunResult[OutputT]: ... async def execute( self, *, input: Union[str, Dict[str, object]], processor: str, - metadata: Optional[Dict[str, Union[str, float, bool]]] | NotGiven = NOT_GIVEN, - output: Optional[OutputSchema] | Type[OutputT] | NotGiven = NOT_GIVEN, + metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, + output: Optional[OutputSchema] | Type[OutputT] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TaskRunResult | ParsedTaskRunResult[OutputT]: """ Convenience method to create and execute a task run in a single call. From 56dd8031212abd74a7cca609be95902d0b602d97 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:43:23 +0000 Subject: [PATCH 8/8] release: 0.2.2 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 21 +++++++++++++++++++++ pyproject.toml | 2 +- src/parallel/_version.py | 2 +- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b06ba91..d66ca57 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.2.1" + ".": "0.2.2" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 645fea6..e2e909b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## 0.2.2 (2025-10-16) + +Full Changelog: [v0.2.1...v0.2.2](https://github.com/parallel-web/parallel-sdk-python/compare/v0.2.1...v0.2.2) + +### Features + +* **api:** Add progress meter to Task Run events ([176f9d3](https://github.com/parallel-web/parallel-sdk-python/commit/176f9d318d9d9367b61e40fb6f8c27576e75deb4)) + + +### Bug Fixes + +* do not set headers with default to omit ([8989f91](https://github.com/parallel-web/parallel-sdk-python/commit/8989f9120217bba2c95b2b256a2767f885311652)) + + +### Chores + +* do not install brew dependencies in ./scripts/bootstrap by default ([c3250e2](https://github.com/parallel-web/parallel-sdk-python/commit/c3250e26311cc9b767d06a112317b74f73f78644)) +* **internal:** detect missing future annotations with ruff ([db5980c](https://github.com/parallel-web/parallel-sdk-python/commit/db5980ce6d58ac926eea60d836b36dc8bdd651d7)) +* **internal:** update pydantic dependency ([96f50db](https://github.com/parallel-web/parallel-sdk-python/commit/96f50dbffc919f591a149f89b387ebf19bd4deb0)) +* **types:** change optional parameter type from NotGiven to Omit ([0f0fa20](https://github.com/parallel-web/parallel-sdk-python/commit/0f0fa20994ddb2c89d0def2a16a68b9499e1abd4)) + ## 0.2.1 (2025-09-15) Full Changelog: [v0.2.0...v0.2.1](https://github.com/parallel-web/parallel-sdk-python/compare/v0.2.0...v0.2.1) diff --git a/pyproject.toml b/pyproject.toml index 29700e1..50713d4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "parallel-web" -version = "0.2.1" +version = "0.2.2" description = "The official Python library for the Parallel API" dynamic = ["readme"] license = "MIT" diff --git a/src/parallel/_version.py b/src/parallel/_version.py index f47c3ba..dedb7d3 100644 --- a/src/parallel/_version.py +++ b/src/parallel/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "parallel" -__version__ = "0.2.1" # x-release-please-version +__version__ = "0.2.2" # x-release-please-version