From 11a7427530a285d2e2df2b3aa59964777015db01 Mon Sep 17 00:00:00 2001 From: Stainless Bot Date: Tue, 3 Dec 2024 15:22:31 +0000 Subject: [PATCH 01/11] chore(internal): version bump (#451) From f92f37709f85b33a1f4aa3667bdd58601405be6c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 02:14:22 +0000 Subject: [PATCH 02/11] chore: make the `Omit` type public (#454) --- src/orb/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/orb/__init__.py b/src/orb/__init__.py index 801a1e71..61ab6a9b 100644 --- a/src/orb/__init__.py +++ b/src/orb/__init__.py @@ -1,7 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from . import types -from ._types import NOT_GIVEN, NoneType, NotGiven, Transport, ProxiesTypes +from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes from ._utils import file_from_path from ._client import Orb, Client, Stream, Timeout, AsyncOrb, Transport, AsyncClient, AsyncStream, RequestOptions from ._models import BaseModel @@ -48,6 +48,7 @@ "ProxiesTypes", "NotGiven", "NOT_GIVEN", + "Omit", "OrbError", "APIError", "APIStatusError", From da23d38f97aa2f474f56c25a2c2f5fc08a2dea3d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:37:56 +0000 Subject: [PATCH 03/11] chore(internal): bump pydantic dependency (#455) --- requirements-dev.lock | 4 ++-- requirements.lock | 4 ++-- src/orb/_types.py | 6 ++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index 637727ec..8e5f3b94 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -62,9 +62,9 @@ platformdirs==3.11.0 # via virtualenv pluggy==1.5.0 # via pytest -pydantic==2.9.2 +pydantic==2.10.3 # via orb-billing -pydantic-core==2.23.4 +pydantic-core==2.27.1 # via pydantic pygments==2.18.0 # via rich diff --git a/requirements.lock b/requirements.lock index f452fd2d..844a8552 100644 --- a/requirements.lock +++ b/requirements.lock @@ -30,9 +30,9 @@ httpx==0.25.2 idna==3.4 # via anyio # via httpx -pydantic==2.9.2 +pydantic==2.10.3 # via orb-billing -pydantic-core==2.23.4 +pydantic-core==2.27.1 # via pydantic sniffio==1.3.0 # via anyio diff --git a/src/orb/_types.py b/src/orb/_types.py index de4bcc59..a7f6c8ac 100644 --- a/src/orb/_types.py +++ b/src/orb/_types.py @@ -194,10 +194,8 @@ def get(self, __key: str) -> str | None: ... StrBytesIntFloat = Union[str, bytes, int, float] # Note: copied from Pydantic -# https://github.com/pydantic/pydantic/blob/32ea570bf96e84234d2992e1ddf40ab8a565925a/pydantic/main.py#L49 -IncEx: TypeAlias = Union[ - Set[int], Set[str], Mapping[int, Union["IncEx", Literal[True]]], Mapping[str, Union["IncEx", Literal[True]]] -] +# https://github.com/pydantic/pydantic/blob/6f31f8f68ef011f84357330186f603ff295312fd/pydantic/main.py#L79 +IncEx: TypeAlias = Union[Set[int], Set[str], Mapping[int, Union["IncEx", bool]], Mapping[str, Union["IncEx", bool]]] PostParser = Callable[[Any], Any] From db48031ec6b0de13d04ab872eee657dbffcff556 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 18:17:09 +0000 Subject: [PATCH 04/11] docs(readme): fix http client proxies example (#456) --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0870cd51..acf67a22 100644 --- a/README.md +++ b/README.md @@ -397,18 +397,19 @@ can also get all the extra fields on the Pydantic model as a dict with You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including: -- Support for proxies -- Custom transports +- Support for [proxies](https://www.python-httpx.org/advanced/proxies/) +- Custom [transports](https://www.python-httpx.org/advanced/transports/) - Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality ```python +import httpx from orb import Orb, DefaultHttpxClient client = Orb( # Or use the `ORB_BASE_URL` env var base_url="http://my.test.server.example.com:8083", http_client=DefaultHttpxClient( - proxies="http://my.test.proxy.example.com", + proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0"), ), ) From 00cae306687fcb4d206078f048558ddc3b006ffc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 00:10:50 +0000 Subject: [PATCH 05/11] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index fb63efe6..aaba5809 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 97 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-77e2e50c9fb438b08736da759f722f9d062ed3fad3183fb951eb1eee93fa93f5.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-16e9b5c2b884f624e9b1f3dddf584353822295512ead0b72ffb574e6b1780570.yml From 06b16877991041fd6ae53fbf71a6691b22b9bc4d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 02:14:20 +0000 Subject: [PATCH 06/11] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index aaba5809..fb63efe6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 97 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-16e9b5c2b884f624e9b1f3dddf584353822295512ead0b72ffb574e6b1780570.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-77e2e50c9fb438b08736da759f722f9d062ed3fad3183fb951eb1eee93fa93f5.yml From a3d0cda65b9a4cef3d1a81d5b42120bd3582b180 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 02:15:07 +0000 Subject: [PATCH 07/11] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index fb63efe6..aaba5809 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 97 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-77e2e50c9fb438b08736da759f722f9d062ed3fad3183fb951eb1eee93fa93f5.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-16e9b5c2b884f624e9b1f3dddf584353822295512ead0b72ffb574e6b1780570.yml From 2a4d14a279018d5e5a8cffcbadddf347e567641d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 12:11:38 +0000 Subject: [PATCH 08/11] chore(internal): bump pyright (#457) --- requirements-dev.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index 8e5f3b94..a9f3cea1 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -68,7 +68,7 @@ pydantic-core==2.27.1 # via pydantic pygments==2.18.0 # via rich -pyright==1.1.389 +pyright==1.1.390 pytest==8.3.3 # via pytest-asyncio pytest-asyncio==0.24.0 From b03a8ef06e4207f2051fe9a073078a125ce3f1d6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 12:37:48 +0000 Subject: [PATCH 09/11] chore(internal): add support for TypeAliasType (#458) --- pyproject.toml | 2 +- src/orb/_legacy_response.py | 20 ++++++++++---------- src/orb/_models.py | 3 +++ src/orb/_response.py | 20 ++++++++++---------- src/orb/_utils/__init__.py | 1 + src/orb/_utils/_typing.py | 31 ++++++++++++++++++++++++++++++- tests/test_models.py | 18 +++++++++++++++++- tests/utils.py | 4 ++++ 8 files changed, 76 insertions(+), 23 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d8d75047..08d3e65b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ authors = [ dependencies = [ "httpx>=0.23.0, <1", "pydantic>=1.9.0, <3", - "typing-extensions>=4.7, <5", + "typing-extensions>=4.10, <5", "anyio>=3.5.0, <5", "distro>=1.7.0, <2", "sniffio", diff --git a/src/orb/_legacy_response.py b/src/orb/_legacy_response.py index 02edaa22..4cbb4ddf 100644 --- a/src/orb/_legacy_response.py +++ b/src/orb/_legacy_response.py @@ -24,7 +24,7 @@ import pydantic from ._types import NoneType -from ._utils import is_given, extract_type_arg, is_annotated_type +from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type from ._models import BaseModel, is_basemodel from ._constants import RAW_RESPONSE_HEADER from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type @@ -188,9 +188,15 @@ def elapsed(self) -> datetime.timedelta: return self.http_response.elapsed def _parse(self, *, to: type[_T] | None = None) -> R | _T: + cast_to = to if to is not None else self._cast_to + + # unwrap `TypeAlias('Name', T)` -> `T` + if is_type_alias_type(cast_to): + cast_to = cast_to.__value__ # type: ignore[unreachable] + # unwrap `Annotated[T, ...]` -> `T` - if to and is_annotated_type(to): - to = extract_type_arg(to, 0) + if cast_to and is_annotated_type(cast_to): + cast_to = extract_type_arg(cast_to, 0) if self._stream: if to: @@ -226,18 +232,12 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: return cast( R, stream_cls( - cast_to=self._cast_to, + cast_to=cast_to, response=self.http_response, client=cast(Any, self._client), ), ) - cast_to = to if to is not None else self._cast_to - - # unwrap `Annotated[T, ...]` -> `T` - if is_annotated_type(cast_to): - cast_to = extract_type_arg(cast_to, 0) - if cast_to is NoneType: return cast(R, None) diff --git a/src/orb/_models.py b/src/orb/_models.py index 6cb469e2..7a547ce5 100644 --- a/src/orb/_models.py +++ b/src/orb/_models.py @@ -46,6 +46,7 @@ strip_not_given, extract_type_arg, is_annotated_type, + is_type_alias_type, strip_annotated_type, ) from ._compat import ( @@ -428,6 +429,8 @@ def construct_type(*, value: object, type_: object) -> object: # we allow `object` as the input type because otherwise, passing things like # `Literal['value']` will be reported as a type error by type checkers type_ = cast("type[object]", type_) + if is_type_alias_type(type_): + type_ = type_.__value__ # type: ignore[unreachable] # unwrap `Annotated[T, ...]` -> `T` if is_annotated_type(type_): diff --git a/src/orb/_response.py b/src/orb/_response.py index 5b17754b..20f3cd4d 100644 --- a/src/orb/_response.py +++ b/src/orb/_response.py @@ -25,7 +25,7 @@ import pydantic from ._types import NoneType -from ._utils import is_given, extract_type_arg, is_annotated_type, extract_type_var_from_base +from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type, extract_type_var_from_base from ._models import BaseModel, is_basemodel from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type @@ -126,9 +126,15 @@ def __repr__(self) -> str: ) def _parse(self, *, to: type[_T] | None = None) -> R | _T: + cast_to = to if to is not None else self._cast_to + + # unwrap `TypeAlias('Name', T)` -> `T` + if is_type_alias_type(cast_to): + cast_to = cast_to.__value__ # type: ignore[unreachable] + # unwrap `Annotated[T, ...]` -> `T` - if to and is_annotated_type(to): - to = extract_type_arg(to, 0) + if cast_to and is_annotated_type(cast_to): + cast_to = extract_type_arg(cast_to, 0) if self._is_sse_stream: if to: @@ -164,18 +170,12 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: return cast( R, stream_cls( - cast_to=self._cast_to, + cast_to=cast_to, response=self.http_response, client=cast(Any, self._client), ), ) - cast_to = to if to is not None else self._cast_to - - # unwrap `Annotated[T, ...]` -> `T` - if is_annotated_type(cast_to): - cast_to = extract_type_arg(cast_to, 0) - if cast_to is NoneType: return cast(R, None) diff --git a/src/orb/_utils/__init__.py b/src/orb/_utils/__init__.py index a7cff3c0..d4fda26f 100644 --- a/src/orb/_utils/__init__.py +++ b/src/orb/_utils/__init__.py @@ -39,6 +39,7 @@ is_iterable_type as is_iterable_type, is_required_type as is_required_type, is_annotated_type as is_annotated_type, + is_type_alias_type as is_type_alias_type, strip_annotated_type as strip_annotated_type, extract_type_var_from_base as extract_type_var_from_base, ) diff --git a/src/orb/_utils/_typing.py b/src/orb/_utils/_typing.py index c036991f..278749b1 100644 --- a/src/orb/_utils/_typing.py +++ b/src/orb/_utils/_typing.py @@ -1,8 +1,17 @@ from __future__ import annotations +import sys +import typing +import typing_extensions from typing import Any, TypeVar, Iterable, cast from collections import abc as _c_abc -from typing_extensions import Required, Annotated, get_args, get_origin +from typing_extensions import ( + TypeIs, + Required, + Annotated, + get_args, + get_origin, +) from .._types import InheritsGeneric from .._compat import is_union as _is_union @@ -36,6 +45,26 @@ def is_typevar(typ: type) -> bool: return type(typ) == TypeVar # type: ignore +_TYPE_ALIAS_TYPES: tuple[type[typing_extensions.TypeAliasType], ...] = (typing_extensions.TypeAliasType,) +if sys.version_info >= (3, 12): + _TYPE_ALIAS_TYPES = (*_TYPE_ALIAS_TYPES, typing.TypeAliasType) + + +def is_type_alias_type(tp: Any, /) -> TypeIs[typing_extensions.TypeAliasType]: + """Return whether the provided argument is an instance of `TypeAliasType`. + + ```python + type Int = int + is_type_alias_type(Int) + # > True + Str = TypeAliasType("Str", str) + is_type_alias_type(Str) + # > True + ``` + """ + return isinstance(tp, _TYPE_ALIAS_TYPES) + + # Extracts T from Annotated[T, ...] or from Required[Annotated[T, ...]] def strip_annotated_type(typ: type) -> type: if is_required_type(typ) or is_annotated_type(typ): diff --git a/tests/test_models.py b/tests/test_models.py index 6c5a7624..52caebb2 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,7 +1,7 @@ import json from typing import Any, Dict, List, Union, Optional, cast from datetime import datetime, timezone -from typing_extensions import Literal, Annotated +from typing_extensions import Literal, Annotated, TypeAliasType import pytest import pydantic @@ -828,3 +828,19 @@ class B(BaseModel): # if the discriminator details object stays the same between invocations then # we hit the cache assert UnionType.__discriminator__ is discriminator + + +@pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1") +def test_type_alias_type() -> None: + Alias = TypeAliasType("Alias", str) + + class Model(BaseModel): + alias: Alias + union: Union[int, Alias] + + m = construct_type(value={"alias": "foo", "union": "bar"}, type_=Model) + assert isinstance(m, Model) + assert isinstance(m.alias, str) + assert m.alias == "foo" + assert isinstance(m.union, str) + assert m.union == "bar" diff --git a/tests/utils.py b/tests/utils.py index 1fa786ba..b9278ac2 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -16,6 +16,7 @@ is_union_type, extract_type_arg, is_annotated_type, + is_type_alias_type, ) from orb._compat import PYDANTIC_V2, field_outer_type, get_model_fields from orb._models import BaseModel @@ -51,6 +52,9 @@ def assert_matches_type( path: list[str], allow_none: bool = False, ) -> None: + if is_type_alias_type(type_): + type_ = type_.__value__ + # unwrap `Annotated[T, ...]` -> `T` if is_annotated_type(type_): type_ = extract_type_arg(type_, 0) From 6bc521d596131d092db8ec463ef3f19fd6460006 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 20:46:44 +0000 Subject: [PATCH 10/11] feat(api): api update (#459) --- .stats.yml | 2 +- api.md | 4 +- src/orb/resources/alerts.py | 50 +++++++++++++++++---- src/orb/types/__init__.py | 2 + src/orb/types/alert_disable_params.py | 13 ++++++ src/orb/types/alert_enable_params.py | 13 ++++++ tests/api_resources/test_alerts.py | 64 ++++++++++++++++++++------- 7 files changed, 121 insertions(+), 27 deletions(-) create mode 100644 src/orb/types/alert_disable_params.py create mode 100644 src/orb/types/alert_enable_params.py diff --git a/.stats.yml b/.stats.yml index aaba5809..26721953 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 97 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-16e9b5c2b884f624e9b1f3dddf584353822295512ead0b72ffb574e6b1780570.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-908960f165205e2874dd29322cc974df5ab10c7634ab9a342ab22047013de1b4.yml diff --git a/api.md b/api.md index a387852d..f9a7248e 100644 --- a/api.md +++ b/api.md @@ -385,5 +385,5 @@ Methods: - client.alerts.create_for_customer(customer_id, \*\*params) -> Alert - client.alerts.create_for_external_customer(external_customer_id, \*\*params) -> Alert - client.alerts.create_for_subscription(subscription_id, \*\*params) -> Alert -- client.alerts.disable(alert_configuration_id) -> Alert -- client.alerts.enable(alert_configuration_id) -> Alert +- client.alerts.disable(alert_configuration_id, \*\*params) -> Alert +- client.alerts.enable(alert_configuration_id, \*\*params) -> Alert diff --git a/src/orb/resources/alerts.py b/src/orb/resources/alerts.py index 36f800fa..14e32c00 100644 --- a/src/orb/resources/alerts.py +++ b/src/orb/resources/alerts.py @@ -11,7 +11,9 @@ from .. import _legacy_response from ..types import ( alert_list_params, + alert_enable_params, alert_update_params, + alert_disable_params, alert_create_for_customer_params, alert_create_for_subscription_params, alert_create_for_external_customer_params, @@ -431,6 +433,7 @@ def disable( self, alert_configuration_id: str, *, + subscription_id: Optional[str] | NotGiven = NOT_GIVEN, # 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, @@ -439,10 +442,15 @@ def disable( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, idempotency_key: str | None = None, ) -> Alert: - """ - This endpoint can be used to disable an alert. + """This endpoint allows you to disable an alert. + + To disable a plan-level alert for + a specific subscription, you must include the `subscription_id`. The + `subscription_id` is not required for customer or subscription level alerts. Args: + subscription_id: Used to update the status of a plan alert scoped to this subscription_id + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -465,6 +473,7 @@ def disable( extra_body=extra_body, timeout=timeout, idempotency_key=idempotency_key, + query=maybe_transform({"subscription_id": subscription_id}, alert_disable_params.AlertDisableParams), ), cast_to=Alert, ) @@ -473,6 +482,7 @@ def enable( self, alert_configuration_id: str, *, + subscription_id: Optional[str] | NotGiven = NOT_GIVEN, # 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, @@ -481,10 +491,15 @@ def enable( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, idempotency_key: str | None = None, ) -> Alert: - """ - This endpoint can be used to enable an alert. + """This endpoint allows you to enable an alert. + + To enable a plan-level alert for a + specific subscription, you must include the `subscription_id`. The + `subscription_id` is not required for customer or subscription level alerts. Args: + subscription_id: Used to update the status of a plan alert scoped to this subscription_id + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -507,6 +522,7 @@ def enable( extra_body=extra_body, timeout=timeout, idempotency_key=idempotency_key, + query=maybe_transform({"subscription_id": subscription_id}, alert_enable_params.AlertEnableParams), ), cast_to=Alert, ) @@ -912,6 +928,7 @@ async def disable( self, alert_configuration_id: str, *, + subscription_id: Optional[str] | NotGiven = NOT_GIVEN, # 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, @@ -920,10 +937,15 @@ async def disable( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, idempotency_key: str | None = None, ) -> Alert: - """ - This endpoint can be used to disable an alert. + """This endpoint allows you to disable an alert. + + To disable a plan-level alert for + a specific subscription, you must include the `subscription_id`. The + `subscription_id` is not required for customer or subscription level alerts. Args: + subscription_id: Used to update the status of a plan alert scoped to this subscription_id + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -946,6 +968,9 @@ async def disable( extra_body=extra_body, timeout=timeout, idempotency_key=idempotency_key, + query=await async_maybe_transform( + {"subscription_id": subscription_id}, alert_disable_params.AlertDisableParams + ), ), cast_to=Alert, ) @@ -954,6 +979,7 @@ async def enable( self, alert_configuration_id: str, *, + subscription_id: Optional[str] | NotGiven = NOT_GIVEN, # 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, @@ -962,10 +988,15 @@ async def enable( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, idempotency_key: str | None = None, ) -> Alert: - """ - This endpoint can be used to enable an alert. + """This endpoint allows you to enable an alert. + + To enable a plan-level alert for a + specific subscription, you must include the `subscription_id`. The + `subscription_id` is not required for customer or subscription level alerts. Args: + subscription_id: Used to update the status of a plan alert scoped to this subscription_id + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -988,6 +1019,9 @@ async def enable( extra_body=extra_body, timeout=timeout, idempotency_key=idempotency_key, + query=await async_maybe_transform( + {"subscription_id": subscription_id}, alert_enable_params.AlertEnableParams + ), ), cast_to=Alert, ) diff --git a/src/orb/types/__init__.py b/src/orb/types/__init__.py index bbccb109..18c8b027 100644 --- a/src/orb/types/__init__.py +++ b/src/orb/types/__init__.py @@ -33,6 +33,7 @@ from .plan_create_params import PlanCreateParams as PlanCreateParams from .plan_update_params import PlanUpdateParams as PlanUpdateParams from .subscription_usage import SubscriptionUsage as SubscriptionUsage +from .alert_enable_params import AlertEnableParams as AlertEnableParams from .alert_update_params import AlertUpdateParams as AlertUpdateParams from .event_ingest_params import EventIngestParams as EventIngestParams from .event_search_params import EventSearchParams as EventSearchParams @@ -40,6 +41,7 @@ from .invoice_list_params import InvoiceListParams as InvoiceListParams from .price_create_params import PriceCreateParams as PriceCreateParams from .price_update_params import PriceUpdateParams as PriceUpdateParams +from .alert_disable_params import AlertDisableParams as AlertDisableParams from .coupon_create_params import CouponCreateParams as CouponCreateParams from .customer_list_params import CustomerListParams as CustomerListParams from .evaluate_price_group import EvaluatePriceGroup as EvaluatePriceGroup diff --git a/src/orb/types/alert_disable_params.py b/src/orb/types/alert_disable_params.py new file mode 100644 index 00000000..dc4a9847 --- /dev/null +++ b/src/orb/types/alert_disable_params.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import TypedDict + +__all__ = ["AlertDisableParams"] + + +class AlertDisableParams(TypedDict, total=False): + subscription_id: Optional[str] + """Used to update the status of a plan alert scoped to this subscription_id""" diff --git a/src/orb/types/alert_enable_params.py b/src/orb/types/alert_enable_params.py new file mode 100644 index 00000000..b607505a --- /dev/null +++ b/src/orb/types/alert_enable_params.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import TypedDict + +__all__ = ["AlertEnableParams"] + + +class AlertEnableParams(TypedDict, total=False): + subscription_id: Optional[str] + """Used to update the status of a plan alert scoped to this subscription_id""" diff --git a/tests/api_resources/test_alerts.py b/tests/api_resources/test_alerts.py index cb07e015..568aa4ea 100644 --- a/tests/api_resources/test_alerts.py +++ b/tests/api_resources/test_alerts.py @@ -318,14 +318,22 @@ def test_path_params_create_for_subscription(self, client: Orb) -> None: @parametrize def test_method_disable(self, client: Orb) -> None: alert = client.alerts.disable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", + ) + assert_matches_type(Alert, alert, path=["response"]) + + @parametrize + def test_method_disable_with_all_params(self, client: Orb) -> None: + alert = client.alerts.disable( + alert_configuration_id="alert_configuration_id", + subscription_id="subscription_id", ) assert_matches_type(Alert, alert, path=["response"]) @parametrize def test_raw_response_disable(self, client: Orb) -> None: response = client.alerts.with_raw_response.disable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", ) assert response.is_closed is True @@ -336,7 +344,7 @@ def test_raw_response_disable(self, client: Orb) -> None: @parametrize def test_streaming_response_disable(self, client: Orb) -> None: with client.alerts.with_streaming_response.disable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -352,20 +360,28 @@ def test_path_params_disable(self, client: Orb) -> None: ValueError, match=r"Expected a non-empty value for `alert_configuration_id` but received ''" ): client.alerts.with_raw_response.disable( - "", + alert_configuration_id="", ) @parametrize def test_method_enable(self, client: Orb) -> None: alert = client.alerts.enable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", + ) + assert_matches_type(Alert, alert, path=["response"]) + + @parametrize + def test_method_enable_with_all_params(self, client: Orb) -> None: + alert = client.alerts.enable( + alert_configuration_id="alert_configuration_id", + subscription_id="subscription_id", ) assert_matches_type(Alert, alert, path=["response"]) @parametrize def test_raw_response_enable(self, client: Orb) -> None: response = client.alerts.with_raw_response.enable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", ) assert response.is_closed is True @@ -376,7 +392,7 @@ def test_raw_response_enable(self, client: Orb) -> None: @parametrize def test_streaming_response_enable(self, client: Orb) -> None: with client.alerts.with_streaming_response.enable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -392,7 +408,7 @@ def test_path_params_enable(self, client: Orb) -> None: ValueError, match=r"Expected a non-empty value for `alert_configuration_id` but received ''" ): client.alerts.with_raw_response.enable( - "", + alert_configuration_id="", ) @@ -696,14 +712,22 @@ async def test_path_params_create_for_subscription(self, async_client: AsyncOrb) @parametrize async def test_method_disable(self, async_client: AsyncOrb) -> None: alert = await async_client.alerts.disable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", + ) + assert_matches_type(Alert, alert, path=["response"]) + + @parametrize + async def test_method_disable_with_all_params(self, async_client: AsyncOrb) -> None: + alert = await async_client.alerts.disable( + alert_configuration_id="alert_configuration_id", + subscription_id="subscription_id", ) assert_matches_type(Alert, alert, path=["response"]) @parametrize async def test_raw_response_disable(self, async_client: AsyncOrb) -> None: response = await async_client.alerts.with_raw_response.disable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", ) assert response.is_closed is True @@ -714,7 +738,7 @@ async def test_raw_response_disable(self, async_client: AsyncOrb) -> None: @parametrize async def test_streaming_response_disable(self, async_client: AsyncOrb) -> None: async with async_client.alerts.with_streaming_response.disable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -730,20 +754,28 @@ async def test_path_params_disable(self, async_client: AsyncOrb) -> None: ValueError, match=r"Expected a non-empty value for `alert_configuration_id` but received ''" ): await async_client.alerts.with_raw_response.disable( - "", + alert_configuration_id="", ) @parametrize async def test_method_enable(self, async_client: AsyncOrb) -> None: alert = await async_client.alerts.enable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", + ) + assert_matches_type(Alert, alert, path=["response"]) + + @parametrize + async def test_method_enable_with_all_params(self, async_client: AsyncOrb) -> None: + alert = await async_client.alerts.enable( + alert_configuration_id="alert_configuration_id", + subscription_id="subscription_id", ) assert_matches_type(Alert, alert, path=["response"]) @parametrize async def test_raw_response_enable(self, async_client: AsyncOrb) -> None: response = await async_client.alerts.with_raw_response.enable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", ) assert response.is_closed is True @@ -754,7 +786,7 @@ async def test_raw_response_enable(self, async_client: AsyncOrb) -> None: @parametrize async def test_streaming_response_enable(self, async_client: AsyncOrb) -> None: async with async_client.alerts.with_streaming_response.enable( - "alert_configuration_id", + alert_configuration_id="alert_configuration_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -770,5 +802,5 @@ async def test_path_params_enable(self, async_client: AsyncOrb) -> None: ValueError, match=r"Expected a non-empty value for `alert_configuration_id` but received ''" ): await async_client.alerts.with_raw_response.enable( - "", + alert_configuration_id="", ) From bc4afe716472a98925c4803317eb9156389c21da Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 20:47:28 +0000 Subject: [PATCH 11/11] release: 2.19.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 22 ++++++++++++++++++++++ pyproject.toml | 2 +- src/orb/_version.py | 2 +- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7723ed4f..89652a35 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.18.0" + ".": "2.19.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e83b691..9082e3f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 2.19.0 (2024-12-12) + +Full Changelog: [v2.18.0...v2.19.0](https://github.com/orbcorp/orb-python/compare/v2.18.0...v2.19.0) + +### Features + +* **api:** api update ([#459](https://github.com/orbcorp/orb-python/issues/459)) ([6bc521d](https://github.com/orbcorp/orb-python/commit/6bc521d596131d092db8ec463ef3f19fd6460006)) + + +### Chores + +* **internal:** add support for TypeAliasType ([#458](https://github.com/orbcorp/orb-python/issues/458)) ([b03a8ef](https://github.com/orbcorp/orb-python/commit/b03a8ef06e4207f2051fe9a073078a125ce3f1d6)) +* **internal:** bump pydantic dependency ([#455](https://github.com/orbcorp/orb-python/issues/455)) ([da23d38](https://github.com/orbcorp/orb-python/commit/da23d38f97aa2f474f56c25a2c2f5fc08a2dea3d)) +* **internal:** bump pyright ([#457](https://github.com/orbcorp/orb-python/issues/457)) ([2a4d14a](https://github.com/orbcorp/orb-python/commit/2a4d14a279018d5e5a8cffcbadddf347e567641d)) +* **internal:** version bump ([#451](https://github.com/orbcorp/orb-python/issues/451)) ([11a7427](https://github.com/orbcorp/orb-python/commit/11a7427530a285d2e2df2b3aa59964777015db01)) +* make the `Omit` type public ([#454](https://github.com/orbcorp/orb-python/issues/454)) ([f92f377](https://github.com/orbcorp/orb-python/commit/f92f37709f85b33a1f4aa3667bdd58601405be6c)) + + +### Documentation + +* **readme:** fix http client proxies example ([#456](https://github.com/orbcorp/orb-python/issues/456)) ([db48031](https://github.com/orbcorp/orb-python/commit/db48031ec6b0de13d04ab872eee657dbffcff556)) + ## 2.18.0 (2024-12-03) Full Changelog: [v2.17.0...v2.18.0](https://github.com/orbcorp/orb-python/compare/v2.17.0...v2.18.0) diff --git a/pyproject.toml b/pyproject.toml index 08d3e65b..80cdb12d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "orb-billing" -version = "2.18.0" +version = "2.19.0" description = "The official Python library for the orb API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/orb/_version.py b/src/orb/_version.py index f9bd1bfb..9e5ea44f 100644 --- a/src/orb/_version.py +++ b/src/orb/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "orb" -__version__ = "2.18.0" # x-release-please-version +__version__ = "2.19.0" # x-release-please-version