diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f497cd3..0cb37986 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,10 @@ on: - 'integrated/**' - 'stl-preview-head/**' - 'stl-preview-base/**' + pull_request: + branches-ignore: + - 'stl-preview-head/**' + - 'stl-preview-base/**' jobs: lint: diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6a37fe2d..3b4c2d4b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.0.1" + ".": "4.1.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index cb4778c1..0834bdd5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 116 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-d7b617958673f6e5b94781a63ed79caed27014e5ca8bbf7e5e31b8f4d135aecb.yml -openapi_spec_hash: 66e9c2cd22385eed3ed507ee60aed4f5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-9d6e0a988df83c0e2baa559ef57ec96981669a7a294de2188adb2cd6bbc0be8a.yml +openapi_spec_hash: 7f5e7221872d7ee799141f546c394f48 config_hash: 3c3524be9607afb24d2139ce26ce5389 diff --git a/CHANGELOG.md b/CHANGELOG.md index f929bf3d..fb51197d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ # Changelog +## 4.1.0 (2025-06-23) + +Full Changelog: [v4.0.1...v4.1.0](https://github.com/orbcorp/orb-python/compare/v4.0.1...v4.1.0) + +### Features + +* **api:** api update ([145fb49](https://github.com/orbcorp/orb-python/commit/145fb49e263d98b69ebc44766fb21256792fb408)) +* **api:** api update ([3e7554d](https://github.com/orbcorp/orb-python/commit/3e7554d9cb500e444e5e72c39324e8d478842dde)) +* **api:** api update ([54a55d0](https://github.com/orbcorp/orb-python/commit/54a55d0284936e49b95b011203a57c1c844c34f9)) +* **client:** add support for aiohttp ([afa214a](https://github.com/orbcorp/orb-python/commit/afa214aa4a2fc5db65335f063784df2e6e61292e)) + + +### Bug Fixes + +* **tests:** fix: tests which call HTTP endpoints directly with the example parameters ([9e77c70](https://github.com/orbcorp/orb-python/commit/9e77c705608f1f437d3487d1a8f3dbb383a7e533)) + + +### Chores + +* **ci:** enable for pull requests ([897e15e](https://github.com/orbcorp/orb-python/commit/897e15e361e1fd1a5941122f2fcbc025610c231b)) +* **internal:** update conftest.py ([981e413](https://github.com/orbcorp/orb-python/commit/981e41335feb9bc86d7e465b12112854c5277c55)) +* **readme:** update badges ([121b76c](https://github.com/orbcorp/orb-python/commit/121b76c47ed179936c95dd3a4033e25a49d68d8a)) +* **tests:** add tests for httpx client instantiation & proxies ([41f738c](https://github.com/orbcorp/orb-python/commit/41f738c81995546912f43a79c61172557fe2153a)) +* **tests:** skip some failing tests on the latest python versions ([b67c12c](https://github.com/orbcorp/orb-python/commit/b67c12ca7d3e2c860848de2a3018eb6b24a69c4d)) + + +### Documentation + +* **client:** fix httpx.Timeout documentation reference ([3d851a6](https://github.com/orbcorp/orb-python/commit/3d851a625d25c16779644d2bba29e0f8c9e87c7e)) + ## 4.0.1 (2025-06-12) Full Changelog: [v4.0.0...v4.0.1](https://github.com/orbcorp/orb-python/compare/v4.0.0...v4.0.1) diff --git a/README.md b/README.md index b141afdf..2dd348e9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Orb Python API library -[![PyPI version](https://img.shields.io/pypi/v/orb-billing.svg)](https://pypi.org/project/orb-billing/) +[![PyPI version]()](https://pypi.org/project/orb-billing/) The Orb Python library provides convenient access to the Orb REST API from any Python 3.8+ application. The library includes type definitions for all request params and response fields, @@ -68,6 +68,41 @@ asyncio.run(main()) Functionality between the synchronous and asynchronous clients is otherwise identical. +### With aiohttp + +By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend. + +You can enable this by installing `aiohttp`: + +```sh +# install from PyPI +pip install orb-billing[aiohttp] +``` + +Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: + +```python +import os +import asyncio +from orb import DefaultAioHttpClient +from orb import AsyncOrb + + +async def main() -> None: + async with AsyncOrb( + api_key=os.environ.get("ORB_API_KEY"), # This is the default and can be omitted + http_client=DefaultAioHttpClient(), + ) as client: + customer = await client.customers.create( + email="example-customer@withorb.com", + name="My Customer", + ) + print(customer.id) + + +asyncio.run(main()) +``` + ## Using types Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like: @@ -257,7 +292,7 @@ client.with_options(max_retries=5).customers.create( ### Timeouts By default requests time out after 1 minute. You can configure this with a `timeout` option, -which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object: +which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object: ```python from orb import Orb diff --git a/pyproject.toml b/pyproject.toml index 7315a5e0..97098bc6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "orb-billing" -version = "4.0.1" +version = "4.1.0" description = "The official Python library for the orb API" dynamic = ["readme"] license = "Apache-2.0" @@ -37,6 +37,8 @@ classifiers = [ Homepage = "https://github.com/orbcorp/orb-python" Repository = "https://github.com/orbcorp/orb-python" +[project.optional-dependencies] +aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.6"] [tool.rye] managed = true diff --git a/requirements-dev.lock b/requirements-dev.lock index 10dae689..1d85cad8 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -10,6 +10,13 @@ # universal: false -e file:. +aiohappyeyeballs==2.6.1 + # via aiohttp +aiohttp==3.12.8 + # via httpx-aiohttp + # via orb-billing +aiosignal==1.3.2 + # via aiohttp annotated-types==0.6.0 # via pydantic anyio==4.4.0 @@ -17,6 +24,10 @@ anyio==4.4.0 # via orb-billing argcomplete==3.1.2 # via nox +async-timeout==5.0.1 + # via aiohttp +attrs==25.3.0 + # via aiohttp certifi==2023.7.22 # via httpcore # via httpx @@ -34,16 +45,23 @@ execnet==2.1.1 # via pytest-xdist filelock==3.12.4 # via virtualenv +frozenlist==1.6.2 + # via aiohttp + # via aiosignal h11==0.14.0 # via httpcore httpcore==1.0.2 # via httpx httpx==0.28.1 + # via httpx-aiohttp # via orb-billing # via respx +httpx-aiohttp==0.1.6 + # via orb-billing idna==3.4 # via anyio # via httpx + # via yarl importlib-metadata==7.0.0 iniconfig==2.0.0 # via pytest @@ -51,6 +69,9 @@ markdown-it-py==3.0.0 # via rich mdurl==0.1.2 # via markdown-it-py +multidict==6.4.4 + # via aiohttp + # via yarl mypy==1.14.1 mypy-extensions==1.0.0 # via mypy @@ -65,6 +86,9 @@ platformdirs==3.11.0 # via virtualenv pluggy==1.5.0 # via pytest +propcache==0.3.1 + # via aiohttp + # via yarl pydantic==2.10.3 # via orb-billing pydantic-core==2.27.1 @@ -97,6 +121,7 @@ tomli==2.0.2 # via pytest typing-extensions==4.12.2 # via anyio + # via multidict # via mypy # via orb-billing # via pydantic @@ -104,5 +129,7 @@ typing-extensions==4.12.2 # via pyright virtualenv==20.24.5 # via nox +yarl==1.20.0 + # via aiohttp zipp==3.17.0 # via importlib-metadata diff --git a/requirements.lock b/requirements.lock index ce8bf8b3..949da231 100644 --- a/requirements.lock +++ b/requirements.lock @@ -10,11 +10,22 @@ # universal: false -e file:. +aiohappyeyeballs==2.6.1 + # via aiohttp +aiohttp==3.12.8 + # via httpx-aiohttp + # via orb-billing +aiosignal==1.3.2 + # via aiohttp annotated-types==0.6.0 # via pydantic anyio==4.4.0 # via httpx # via orb-billing +async-timeout==5.0.1 + # via aiohttp +attrs==25.3.0 + # via aiohttp certifi==2023.7.22 # via httpcore # via httpx @@ -22,15 +33,28 @@ distro==1.8.0 # via orb-billing exceptiongroup==1.2.2 # via anyio +frozenlist==1.6.2 + # via aiohttp + # via aiosignal h11==0.14.0 # via httpcore httpcore==1.0.2 # via httpx httpx==0.28.1 + # via httpx-aiohttp + # via orb-billing +httpx-aiohttp==0.1.6 # via orb-billing idna==3.4 # via anyio # via httpx + # via yarl +multidict==6.4.4 + # via aiohttp + # via yarl +propcache==0.3.1 + # via aiohttp + # via yarl pydantic==2.10.3 # via orb-billing pydantic-core==2.27.1 @@ -40,6 +64,9 @@ sniffio==1.3.0 # via orb-billing typing-extensions==4.12.2 # via anyio + # via multidict # via orb-billing # via pydantic # via pydantic-core +yarl==1.20.0 + # via aiohttp diff --git a/src/orb/__init__.py b/src/orb/__init__.py index 8e183536..aea8a5cb 100644 --- a/src/orb/__init__.py +++ b/src/orb/__init__.py @@ -38,7 +38,7 @@ DuplicateResourceCreation, APIResponseValidationError, ) -from ._base_client import DefaultHttpxClient, DefaultAsyncHttpxClient +from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient from ._utils._logs import setup_logging as _setup_logging __all__ = [ @@ -92,6 +92,7 @@ "DEFAULT_CONNECTION_LIMITS", "DefaultHttpxClient", "DefaultAsyncHttpxClient", + "DefaultAioHttpClient", ] if not _t.TYPE_CHECKING: diff --git a/src/orb/_base_client.py b/src/orb/_base_client.py index 79258719..0212bd38 100644 --- a/src/orb/_base_client.py +++ b/src/orb/_base_client.py @@ -1304,6 +1304,24 @@ def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) +try: + import httpx_aiohttp +except ImportError: + + class _DefaultAioHttpClient(httpx.AsyncClient): + def __init__(self, **_kwargs: Any) -> None: + raise RuntimeError("To use the aiohttp client you must have installed the package with the `aiohttp` extra") +else: + + class _DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore + def __init__(self, **kwargs: Any) -> None: + kwargs.setdefault("timeout", DEFAULT_TIMEOUT) + kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS) + kwargs.setdefault("follow_redirects", True) + + super().__init__(**kwargs) + + if TYPE_CHECKING: DefaultAsyncHttpxClient = httpx.AsyncClient """An alias to `httpx.AsyncClient` that provides the same defaults that this SDK @@ -1312,8 +1330,12 @@ def __init__(self, **kwargs: Any) -> None: This is useful because overriding the `http_client` with your own instance of `httpx.AsyncClient` will result in httpx's defaults being used, not ours. """ + + DefaultAioHttpClient = httpx.AsyncClient + """An alias to `httpx.AsyncClient` that changes the default HTTP transport to `aiohttp`.""" else: DefaultAsyncHttpxClient = _DefaultAsyncHttpxClient + DefaultAioHttpClient = _DefaultAioHttpClient class AsyncHttpxClientWrapper(DefaultAsyncHttpxClient): diff --git a/src/orb/_version.py b/src/orb/_version.py index f7a7898e..a047a01b 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__ = "4.0.1" # x-release-please-version +__version__ = "4.1.0" # x-release-please-version diff --git a/src/orb/resources/customers/credits/ledger.py b/src/orb/resources/customers/credits/ledger.py index 1e58d476..d68dce31 100644 --- a/src/orb/resources/customers/credits/ledger.py +++ b/src/orb/resources/customers/credits/ledger.py @@ -550,12 +550,12 @@ def create_entry( customer_id: str, *, entry_type: Literal["expiration_change"], - expiry_date: Union[str, datetime, None], target_expiry_date: Union[str, date], amount: Optional[float] | NotGiven = NOT_GIVEN, block_id: Optional[str] | NotGiven = NOT_GIVEN, currency: Optional[str] | NotGiven = NOT_GIVEN, description: Optional[str] | NotGiven = NOT_GIVEN, + expiry_date: Union[str, datetime, None] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, 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. @@ -678,8 +678,6 @@ def create_entry( return to the customer, up to the block's initial balance. Args: - expiry_date: An ISO 8601 format date that identifies the origination credit block to expire - target_expiry_date: A future date (specified in YYYY-MM-DD format) used for expiration change, denoting when credits transferred (as part of a partial block expiration) should expire. @@ -697,6 +695,8 @@ def create_entry( For example, this can be used to note an increment refers to trial credits, or for noting corrections as a result of an incident, etc. + expiry_date: An ISO 8601 format date that identifies the origination credit block to expire + metadata: User-specified key/value pairs for the resource. Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. @@ -1036,11 +1036,7 @@ def create_entry( """ ... - @required_args( - ["amount", "entry_type"], - ["entry_type", "expiry_date", "target_expiry_date"], - ["amount", "block_id", "entry_type"], - ) + @required_args(["amount", "entry_type"], ["entry_type", "target_expiry_date"], ["amount", "block_id", "entry_type"]) def create_entry( self, customer_id: str, @@ -1446,12 +1442,12 @@ def create_entry_by_external_id( external_customer_id: str, *, entry_type: Literal["expiration_change"], - expiry_date: Union[str, datetime, None], target_expiry_date: Union[str, date], amount: Optional[float] | NotGiven = NOT_GIVEN, block_id: Optional[str] | NotGiven = NOT_GIVEN, currency: Optional[str] | NotGiven = NOT_GIVEN, description: Optional[str] | NotGiven = NOT_GIVEN, + expiry_date: Union[str, datetime, None] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, 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. @@ -1574,8 +1570,6 @@ def create_entry_by_external_id( return to the customer, up to the block's initial balance. Args: - expiry_date: An ISO 8601 format date that identifies the origination credit block to expire - target_expiry_date: A future date (specified in YYYY-MM-DD format) used for expiration change, denoting when credits transferred (as part of a partial block expiration) should expire. @@ -1593,6 +1587,8 @@ def create_entry_by_external_id( For example, this can be used to note an increment refers to trial credits, or for noting corrections as a result of an incident, etc. + expiry_date: An ISO 8601 format date that identifies the origination credit block to expire + metadata: User-specified key/value pairs for the resource. Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. @@ -1932,11 +1928,7 @@ def create_entry_by_external_id( """ ... - @required_args( - ["amount", "entry_type"], - ["entry_type", "expiry_date", "target_expiry_date"], - ["amount", "block_id", "entry_type"], - ) + @required_args(["amount", "entry_type"], ["entry_type", "target_expiry_date"], ["amount", "block_id", "entry_type"]) def create_entry_by_external_id( self, external_customer_id: str, @@ -2689,12 +2681,12 @@ async def create_entry( customer_id: str, *, entry_type: Literal["expiration_change"], - expiry_date: Union[str, datetime, None], target_expiry_date: Union[str, date], amount: Optional[float] | NotGiven = NOT_GIVEN, block_id: Optional[str] | NotGiven = NOT_GIVEN, currency: Optional[str] | NotGiven = NOT_GIVEN, description: Optional[str] | NotGiven = NOT_GIVEN, + expiry_date: Union[str, datetime, None] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, 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. @@ -2817,8 +2809,6 @@ async def create_entry( return to the customer, up to the block's initial balance. Args: - expiry_date: An ISO 8601 format date that identifies the origination credit block to expire - target_expiry_date: A future date (specified in YYYY-MM-DD format) used for expiration change, denoting when credits transferred (as part of a partial block expiration) should expire. @@ -2836,6 +2826,8 @@ async def create_entry( For example, this can be used to note an increment refers to trial credits, or for noting corrections as a result of an incident, etc. + expiry_date: An ISO 8601 format date that identifies the origination credit block to expire + metadata: User-specified key/value pairs for the resource. Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. @@ -3175,11 +3167,7 @@ async def create_entry( """ ... - @required_args( - ["amount", "entry_type"], - ["entry_type", "expiry_date", "target_expiry_date"], - ["amount", "block_id", "entry_type"], - ) + @required_args(["amount", "entry_type"], ["entry_type", "target_expiry_date"], ["amount", "block_id", "entry_type"]) async def create_entry( self, customer_id: str, @@ -3585,12 +3573,12 @@ async def create_entry_by_external_id( external_customer_id: str, *, entry_type: Literal["expiration_change"], - expiry_date: Union[str, datetime, None], target_expiry_date: Union[str, date], amount: Optional[float] | NotGiven = NOT_GIVEN, block_id: Optional[str] | NotGiven = NOT_GIVEN, currency: Optional[str] | NotGiven = NOT_GIVEN, description: Optional[str] | NotGiven = NOT_GIVEN, + expiry_date: Union[str, datetime, None] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, 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. @@ -3713,8 +3701,6 @@ async def create_entry_by_external_id( return to the customer, up to the block's initial balance. Args: - expiry_date: An ISO 8601 format date that identifies the origination credit block to expire - target_expiry_date: A future date (specified in YYYY-MM-DD format) used for expiration change, denoting when credits transferred (as part of a partial block expiration) should expire. @@ -3732,6 +3718,8 @@ async def create_entry_by_external_id( For example, this can be used to note an increment refers to trial credits, or for noting corrections as a result of an incident, etc. + expiry_date: An ISO 8601 format date that identifies the origination credit block to expire + metadata: User-specified key/value pairs for the resource. Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. @@ -4071,11 +4059,7 @@ async def create_entry_by_external_id( """ ... - @required_args( - ["amount", "entry_type"], - ["entry_type", "expiry_date", "target_expiry_date"], - ["amount", "block_id", "entry_type"], - ) + @required_args(["amount", "entry_type"], ["entry_type", "target_expiry_date"], ["amount", "block_id", "entry_type"]) async def create_entry_by_external_id( self, external_customer_id: str, diff --git a/src/orb/resources/plans/plans.py b/src/orb/resources/plans/plans.py index 9d99305f..b55fbafe 100644 --- a/src/orb/resources/plans/plans.py +++ b/src/orb/resources/plans/plans.py @@ -60,10 +60,12 @@ def create( currency: str, name: str, prices: Iterable[plan_create_params.Price], + adjustments: Optional[Iterable[plan_create_params.Adjustment]] | NotGiven = NOT_GIVEN, default_invoice_memo: Optional[str] | NotGiven = NOT_GIVEN, external_plan_id: Optional[str] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, Optional[str]]] | NotGiven = NOT_GIVEN, net_terms: Optional[int] | NotGiven = NOT_GIVEN, + plan_phases: Optional[Iterable[plan_create_params.PlanPhase]] | NotGiven = NOT_GIVEN, status: Literal["active", "draft"] | 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. @@ -83,6 +85,9 @@ def create( prices: Prices for this plan. If the plan has phases, this includes prices across all phases of the plan. + adjustments: Adjustments for this plan. If the plan has phases, this includes adjustments + across all phases of the plan. + default_invoice_memo: Free-form text which is available on the invoice PDF and the Orb invoice portal. metadata: User-specified key/value pairs for the resource. Individual keys can be removed @@ -93,6 +98,9 @@ def create( date for the invoice. If you intend the invoice to be due on issue, set this to 0. + plan_phases: Configuration of pre-defined phases, each with their own prices and adjustments. + Leave unspecified for plans with a single phase. + status: The status of the plan to create (either active or draft). If not specified, this defaults to active. @@ -113,10 +121,12 @@ def create( "currency": currency, "name": name, "prices": prices, + "adjustments": adjustments, "default_invoice_memo": default_invoice_memo, "external_plan_id": external_plan_id, "metadata": metadata, "net_terms": net_terms, + "plan_phases": plan_phases, "status": status, }, plan_create_params.PlanCreateParams, @@ -335,10 +345,12 @@ async def create( currency: str, name: str, prices: Iterable[plan_create_params.Price], + adjustments: Optional[Iterable[plan_create_params.Adjustment]] | NotGiven = NOT_GIVEN, default_invoice_memo: Optional[str] | NotGiven = NOT_GIVEN, external_plan_id: Optional[str] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, Optional[str]]] | NotGiven = NOT_GIVEN, net_terms: Optional[int] | NotGiven = NOT_GIVEN, + plan_phases: Optional[Iterable[plan_create_params.PlanPhase]] | NotGiven = NOT_GIVEN, status: Literal["active", "draft"] | 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. @@ -358,6 +370,9 @@ async def create( prices: Prices for this plan. If the plan has phases, this includes prices across all phases of the plan. + adjustments: Adjustments for this plan. If the plan has phases, this includes adjustments + across all phases of the plan. + default_invoice_memo: Free-form text which is available on the invoice PDF and the Orb invoice portal. metadata: User-specified key/value pairs for the resource. Individual keys can be removed @@ -368,6 +383,9 @@ async def create( date for the invoice. If you intend the invoice to be due on issue, set this to 0. + plan_phases: Configuration of pre-defined phases, each with their own prices and adjustments. + Leave unspecified for plans with a single phase. + status: The status of the plan to create (either active or draft). If not specified, this defaults to active. @@ -388,10 +406,12 @@ async def create( "currency": currency, "name": name, "prices": prices, + "adjustments": adjustments, "default_invoice_memo": default_invoice_memo, "external_plan_id": external_plan_id, "metadata": metadata, "net_terms": net_terms, + "plan_phases": plan_phases, "status": status, }, plan_create_params.PlanCreateParams, diff --git a/src/orb/types/customers/credits/ledger_create_entry_by_external_id_params.py b/src/orb/types/customers/credits/ledger_create_entry_by_external_id_params.py index 07e8217c..d3e8d544 100644 --- a/src/orb/types/customers/credits/ledger_create_entry_by_external_id_params.py +++ b/src/orb/types/customers/credits/ledger_create_entry_by_external_id_params.py @@ -132,9 +132,6 @@ class AddDecrementCreditLedgerEntryRequestParams(TypedDict, total=False): class AddExpirationChangeCreditLedgerEntryRequestParams(TypedDict, total=False): entry_type: Required[Literal["expiration_change"]] - expiry_date: Required[Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]] - """An ISO 8601 format date that identifies the origination credit block to expire""" - target_expiry_date: Required[Annotated[Union[str, date], PropertyInfo(format="iso8601")]] """ A future date (specified in YYYY-MM-DD format) used for expiration change, @@ -168,6 +165,9 @@ class AddExpirationChangeCreditLedgerEntryRequestParams(TypedDict, total=False): for noting corrections as a result of an incident, etc. """ + expiry_date: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """An ISO 8601 format date that identifies the origination credit block to expire""" + metadata: Optional[Dict[str, Optional[str]]] """User-specified key/value pairs for the resource. diff --git a/src/orb/types/customers/credits/ledger_create_entry_params.py b/src/orb/types/customers/credits/ledger_create_entry_params.py index 46ce0a9e..de066be6 100644 --- a/src/orb/types/customers/credits/ledger_create_entry_params.py +++ b/src/orb/types/customers/credits/ledger_create_entry_params.py @@ -132,9 +132,6 @@ class AddDecrementCreditLedgerEntryRequestParams(TypedDict, total=False): class AddExpirationChangeCreditLedgerEntryRequestParams(TypedDict, total=False): entry_type: Required[Literal["expiration_change"]] - expiry_date: Required[Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]] - """An ISO 8601 format date that identifies the origination credit block to expire""" - target_expiry_date: Required[Annotated[Union[str, date], PropertyInfo(format="iso8601")]] """ A future date (specified in YYYY-MM-DD format) used for expiration change, @@ -168,6 +165,9 @@ class AddExpirationChangeCreditLedgerEntryRequestParams(TypedDict, total=False): for noting corrections as a result of an incident, etc. """ + expiry_date: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """An ISO 8601 format date that identifies the origination credit block to expire""" + metadata: Optional[Dict[str, Optional[str]]] """User-specified key/value pairs for the resource. diff --git a/src/orb/types/invoice_fetch_upcoming_response.py b/src/orb/types/invoice_fetch_upcoming_response.py index 80871dcd..71f10a9b 100644 --- a/src/orb/types/invoice_fetch_upcoming_response.py +++ b/src/orb/types/invoice_fetch_upcoming_response.py @@ -172,6 +172,7 @@ class LineItem(BaseModel): """The number of prepaid credits applied.""" discount: Optional[Discount] = None + """This field is deprecated in favor of `adjustments`""" end_date: datetime """The end date of the range of time applied for this line item's price.""" diff --git a/src/orb/types/invoice_line_item_create_response.py b/src/orb/types/invoice_line_item_create_response.py index 194573da..fb3cfa03 100644 --- a/src/orb/types/invoice_line_item_create_response.py +++ b/src/orb/types/invoice_line_item_create_response.py @@ -65,6 +65,7 @@ class InvoiceLineItemCreateResponse(BaseModel): """The number of prepaid credits applied.""" discount: Optional[Discount] = None + """This field is deprecated in favor of `adjustments`""" end_date: datetime """The end date of the range of time applied for this line item's price.""" diff --git a/src/orb/types/plan_create_params.py b/src/orb/types/plan_create_params.py index 1c08ef49..d1619d7c 100644 --- a/src/orb/types/plan_create_params.py +++ b/src/orb/types/plan_create_params.py @@ -5,12 +5,18 @@ from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict +from .shared_params.new_maximum import NewMaximum +from .shared_params.new_minimum import NewMinimum from .shared_params.new_plan_bps_price import NewPlanBPSPrice +from .shared_params.new_usage_discount import NewUsageDiscount +from .shared_params.new_amount_discount import NewAmountDiscount from .shared_params.new_plan_bulk_price import NewPlanBulkPrice from .shared_params.new_plan_unit_price import NewPlanUnitPrice +from .shared_params.new_allocation_price import NewAllocationPrice from .shared_params.new_plan_matrix_price import NewPlanMatrixPrice from .shared_params.new_plan_tiered_price import NewPlanTieredPrice from .shared_params.new_plan_package_price import NewPlanPackagePrice +from .shared_params.new_percentage_discount import NewPercentageDiscount from .shared_params.new_plan_bulk_bps_price import NewPlanBulkBPSPrice from .shared_params.new_plan_tiered_bps_price import NewPlanTieredBPSPrice from .shared_params.new_plan_grouped_tiered_price import NewPlanGroupedTieredPrice @@ -36,7 +42,7 @@ NewPlanScalableMatrixWithTieredPricingPrice, ) -__all__ = ["PlanCreateParams", "Price"] +__all__ = ["PlanCreateParams", "Price", "PricePrice", "Adjustment", "AdjustmentAdjustment", "PlanPhase"] class PlanCreateParams(TypedDict, total=False): @@ -54,6 +60,12 @@ class PlanCreateParams(TypedDict, total=False): If the plan has phases, this includes prices across all phases of the plan. """ + adjustments: Optional[Iterable[Adjustment]] + """Adjustments for this plan. + + If the plan has phases, this includes adjustments across all phases of the plan. + """ + default_invoice_memo: Optional[str] """ Free-form text which is available on the invoice PDF and the Orb invoice portal. @@ -75,6 +87,12 @@ class PlanCreateParams(TypedDict, total=False): to 0. """ + plan_phases: Optional[Iterable[PlanPhase]] + """Configuration of pre-defined phases, each with their own prices and adjustments. + + Leave unspecified for plans with a single phase. + """ + status: Literal["active", "draft"] """The status of the plan to create (either active or draft). @@ -82,7 +100,7 @@ class PlanCreateParams(TypedDict, total=False): """ -Price: TypeAlias = Union[ +PricePrice: TypeAlias = Union[ NewPlanUnitPrice, NewPlanPackagePrice, NewPlanMatrixPrice, @@ -112,3 +130,43 @@ class PlanCreateParams(TypedDict, total=False): NewPlanMatrixWithAllocationPrice, NewPlanGroupedTieredPrice, ] + + +class Price(TypedDict, total=False): + allocation_price: Optional[NewAllocationPrice] + """The allocation price to add to the plan.""" + + plan_phase_order: Optional[int] + """The phase to add this price to.""" + + price: Optional[PricePrice] + """The price to add to the plan""" + + +AdjustmentAdjustment: TypeAlias = Union[ + NewPercentageDiscount, NewUsageDiscount, NewAmountDiscount, NewMinimum, NewMaximum +] + + +class Adjustment(TypedDict, total=False): + adjustment: Required[AdjustmentAdjustment] + """The definition of a new adjustment to create and add to the plan.""" + + plan_phase_order: Optional[int] + """The phase to add this adjustment to.""" + + +class PlanPhase(TypedDict, total=False): + order: Required[int] + """Determines the ordering of the phase in a plan's lifecycle. 1 = first phase.""" + + align_billing_with_phase_start_date: Optional[bool] + """Align billing cycle day with phase start date.""" + + duration: Optional[int] + """How many terms of length `duration_unit` this phase is active for. + + If null, this phase is evergreen and active indefinitely + """ + + duration_unit: Optional[Literal["daily", "monthly", "quarterly", "semi_annual", "annual"]] diff --git a/src/orb/types/shared/invoice.py b/src/orb/types/shared/invoice.py index c25e9812..eb568d34 100644 --- a/src/orb/types/shared/invoice.py +++ b/src/orb/types/shared/invoice.py @@ -172,6 +172,7 @@ class LineItem(BaseModel): """The number of prepaid credits applied.""" discount: Optional[Discount] = None + """This field is deprecated in favor of `adjustments`""" end_date: datetime """The end date of the range of time applied for this line item's price.""" diff --git a/src/orb/types/shared/new_plan_bps_price.py b/src/orb/types/shared/new_plan_bps_price.py index 451dd197..1a0d6f79 100644 --- a/src/orb/types/shared/new_plan_bps_price.py +++ b/src/orb/types/shared/new_plan_bps_price.py @@ -92,3 +92,9 @@ class NewPlanBPSPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_bulk_bps_price.py b/src/orb/types/shared/new_plan_bulk_bps_price.py index 145b1f76..d0d5d648 100644 --- a/src/orb/types/shared/new_plan_bulk_bps_price.py +++ b/src/orb/types/shared/new_plan_bulk_bps_price.py @@ -92,3 +92,9 @@ class NewPlanBulkBPSPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_bulk_price.py b/src/orb/types/shared/new_plan_bulk_price.py index 6aab73c9..aaf53526 100644 --- a/src/orb/types/shared/new_plan_bulk_price.py +++ b/src/orb/types/shared/new_plan_bulk_price.py @@ -92,3 +92,9 @@ class NewPlanBulkPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_bulk_with_proration_price.py b/src/orb/types/shared/new_plan_bulk_with_proration_price.py index 62f90b5a..21e34766 100644 --- a/src/orb/types/shared/new_plan_bulk_with_proration_price.py +++ b/src/orb/types/shared/new_plan_bulk_with_proration_price.py @@ -91,3 +91,9 @@ class NewPlanBulkWithProrationPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_cumulative_grouped_bulk_price.py b/src/orb/types/shared/new_plan_cumulative_grouped_bulk_price.py index 3e48f366..30aef3f5 100644 --- a/src/orb/types/shared/new_plan_cumulative_grouped_bulk_price.py +++ b/src/orb/types/shared/new_plan_cumulative_grouped_bulk_price.py @@ -91,3 +91,9 @@ class NewPlanCumulativeGroupedBulkPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_grouped_allocation_price.py b/src/orb/types/shared/new_plan_grouped_allocation_price.py index a3a9c138..91cb4428 100644 --- a/src/orb/types/shared/new_plan_grouped_allocation_price.py +++ b/src/orb/types/shared/new_plan_grouped_allocation_price.py @@ -91,3 +91,9 @@ class NewPlanGroupedAllocationPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_grouped_tiered_package_price.py b/src/orb/types/shared/new_plan_grouped_tiered_package_price.py index bd6b9920..82521871 100644 --- a/src/orb/types/shared/new_plan_grouped_tiered_package_price.py +++ b/src/orb/types/shared/new_plan_grouped_tiered_package_price.py @@ -91,3 +91,9 @@ class NewPlanGroupedTieredPackagePrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_grouped_tiered_price.py b/src/orb/types/shared/new_plan_grouped_tiered_price.py index 0286abe8..1be2b1e3 100644 --- a/src/orb/types/shared/new_plan_grouped_tiered_price.py +++ b/src/orb/types/shared/new_plan_grouped_tiered_price.py @@ -91,3 +91,9 @@ class NewPlanGroupedTieredPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_grouped_with_metered_minimum_price.py b/src/orb/types/shared/new_plan_grouped_with_metered_minimum_price.py index 29f97a50..6dce8c0b 100644 --- a/src/orb/types/shared/new_plan_grouped_with_metered_minimum_price.py +++ b/src/orb/types/shared/new_plan_grouped_with_metered_minimum_price.py @@ -91,3 +91,9 @@ class NewPlanGroupedWithMeteredMinimumPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_grouped_with_prorated_minimum_price.py b/src/orb/types/shared/new_plan_grouped_with_prorated_minimum_price.py index af882d7e..ba366557 100644 --- a/src/orb/types/shared/new_plan_grouped_with_prorated_minimum_price.py +++ b/src/orb/types/shared/new_plan_grouped_with_prorated_minimum_price.py @@ -91,3 +91,9 @@ class NewPlanGroupedWithProratedMinimumPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_matrix_price.py b/src/orb/types/shared/new_plan_matrix_price.py index 23ce8dcd..c0464de0 100644 --- a/src/orb/types/shared/new_plan_matrix_price.py +++ b/src/orb/types/shared/new_plan_matrix_price.py @@ -92,3 +92,9 @@ class NewPlanMatrixPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_matrix_with_allocation_price.py b/src/orb/types/shared/new_plan_matrix_with_allocation_price.py index 32df42d7..d42f93fa 100644 --- a/src/orb/types/shared/new_plan_matrix_with_allocation_price.py +++ b/src/orb/types/shared/new_plan_matrix_with_allocation_price.py @@ -92,3 +92,9 @@ class NewPlanMatrixWithAllocationPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_matrix_with_display_name_price.py b/src/orb/types/shared/new_plan_matrix_with_display_name_price.py index cb787cca..0af3224c 100644 --- a/src/orb/types/shared/new_plan_matrix_with_display_name_price.py +++ b/src/orb/types/shared/new_plan_matrix_with_display_name_price.py @@ -91,3 +91,9 @@ class NewPlanMatrixWithDisplayNamePrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_max_group_tiered_package_price.py b/src/orb/types/shared/new_plan_max_group_tiered_package_price.py index b299cba5..219fc4ea 100644 --- a/src/orb/types/shared/new_plan_max_group_tiered_package_price.py +++ b/src/orb/types/shared/new_plan_max_group_tiered_package_price.py @@ -91,3 +91,9 @@ class NewPlanMaxGroupTieredPackagePrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_package_price.py b/src/orb/types/shared/new_plan_package_price.py index 6f541aca..eeb5ca46 100644 --- a/src/orb/types/shared/new_plan_package_price.py +++ b/src/orb/types/shared/new_plan_package_price.py @@ -92,3 +92,9 @@ class NewPlanPackagePrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_package_with_allocation_price.py b/src/orb/types/shared/new_plan_package_with_allocation_price.py index ca4f9b7f..4fe90474 100644 --- a/src/orb/types/shared/new_plan_package_with_allocation_price.py +++ b/src/orb/types/shared/new_plan_package_with_allocation_price.py @@ -91,3 +91,9 @@ class NewPlanPackageWithAllocationPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_scalable_matrix_with_tiered_pricing_price.py b/src/orb/types/shared/new_plan_scalable_matrix_with_tiered_pricing_price.py index fb242856..b4fbf30c 100644 --- a/src/orb/types/shared/new_plan_scalable_matrix_with_tiered_pricing_price.py +++ b/src/orb/types/shared/new_plan_scalable_matrix_with_tiered_pricing_price.py @@ -91,3 +91,9 @@ class NewPlanScalableMatrixWithTieredPricingPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_scalable_matrix_with_unit_pricing_price.py b/src/orb/types/shared/new_plan_scalable_matrix_with_unit_pricing_price.py index d79eaf54..ab8f3500 100644 --- a/src/orb/types/shared/new_plan_scalable_matrix_with_unit_pricing_price.py +++ b/src/orb/types/shared/new_plan_scalable_matrix_with_unit_pricing_price.py @@ -91,3 +91,9 @@ class NewPlanScalableMatrixWithUnitPricingPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_threshold_total_amount_price.py b/src/orb/types/shared/new_plan_threshold_total_amount_price.py index 0f49e3fc..3a5a63b0 100644 --- a/src/orb/types/shared/new_plan_threshold_total_amount_price.py +++ b/src/orb/types/shared/new_plan_threshold_total_amount_price.py @@ -91,3 +91,9 @@ class NewPlanThresholdTotalAmountPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_tier_with_proration_price.py b/src/orb/types/shared/new_plan_tier_with_proration_price.py index abb1bec1..252fbde0 100644 --- a/src/orb/types/shared/new_plan_tier_with_proration_price.py +++ b/src/orb/types/shared/new_plan_tier_with_proration_price.py @@ -91,3 +91,9 @@ class NewPlanTierWithProrationPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_tiered_bps_price.py b/src/orb/types/shared/new_plan_tiered_bps_price.py index e35450ce..28d84f68 100644 --- a/src/orb/types/shared/new_plan_tiered_bps_price.py +++ b/src/orb/types/shared/new_plan_tiered_bps_price.py @@ -92,3 +92,9 @@ class NewPlanTieredBPSPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_tiered_package_price.py b/src/orb/types/shared/new_plan_tiered_package_price.py index c3398125..91fe49fd 100644 --- a/src/orb/types/shared/new_plan_tiered_package_price.py +++ b/src/orb/types/shared/new_plan_tiered_package_price.py @@ -91,3 +91,9 @@ class NewPlanTieredPackagePrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_tiered_package_with_minimum_price.py b/src/orb/types/shared/new_plan_tiered_package_with_minimum_price.py index d40bef69..860e32fb 100644 --- a/src/orb/types/shared/new_plan_tiered_package_with_minimum_price.py +++ b/src/orb/types/shared/new_plan_tiered_package_with_minimum_price.py @@ -91,3 +91,9 @@ class NewPlanTieredPackageWithMinimumPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_tiered_price.py b/src/orb/types/shared/new_plan_tiered_price.py index 5b483c2d..3e1607c6 100644 --- a/src/orb/types/shared/new_plan_tiered_price.py +++ b/src/orb/types/shared/new_plan_tiered_price.py @@ -92,3 +92,9 @@ class NewPlanTieredPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_tiered_with_minimum_price.py b/src/orb/types/shared/new_plan_tiered_with_minimum_price.py index abdcf6a8..6a2f9db4 100644 --- a/src/orb/types/shared/new_plan_tiered_with_minimum_price.py +++ b/src/orb/types/shared/new_plan_tiered_with_minimum_price.py @@ -91,3 +91,9 @@ class NewPlanTieredWithMinimumPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_unit_price.py b/src/orb/types/shared/new_plan_unit_price.py index 39f5521e..e1d3f1e7 100644 --- a/src/orb/types/shared/new_plan_unit_price.py +++ b/src/orb/types/shared/new_plan_unit_price.py @@ -92,3 +92,9 @@ class NewPlanUnitPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_unit_with_percent_price.py b/src/orb/types/shared/new_plan_unit_with_percent_price.py index fad2b748..a04f79e7 100644 --- a/src/orb/types/shared/new_plan_unit_with_percent_price.py +++ b/src/orb/types/shared/new_plan_unit_with_percent_price.py @@ -91,3 +91,9 @@ class NewPlanUnitWithPercentPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared/new_plan_unit_with_proration_price.py b/src/orb/types/shared/new_plan_unit_with_proration_price.py index e04a4153..fcea45f2 100644 --- a/src/orb/types/shared/new_plan_unit_with_proration_price.py +++ b/src/orb/types/shared/new_plan_unit_with_proration_price.py @@ -91,3 +91,9 @@ class NewPlanUnitWithProrationPrice(BaseModel): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] = None + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_bps_price.py b/src/orb/types/shared_params/new_plan_bps_price.py index fcabd457..c4f7ebcd 100644 --- a/src/orb/types/shared_params/new_plan_bps_price.py +++ b/src/orb/types/shared_params/new_plan_bps_price.py @@ -87,3 +87,9 @@ class NewPlanBPSPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_bulk_bps_price.py b/src/orb/types/shared_params/new_plan_bulk_bps_price.py index 531e7371..79321ef3 100644 --- a/src/orb/types/shared_params/new_plan_bulk_bps_price.py +++ b/src/orb/types/shared_params/new_plan_bulk_bps_price.py @@ -87,3 +87,9 @@ class NewPlanBulkBPSPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_bulk_price.py b/src/orb/types/shared_params/new_plan_bulk_price.py index 3edb1584..436cb117 100644 --- a/src/orb/types/shared_params/new_plan_bulk_price.py +++ b/src/orb/types/shared_params/new_plan_bulk_price.py @@ -87,3 +87,9 @@ class NewPlanBulkPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_bulk_with_proration_price.py b/src/orb/types/shared_params/new_plan_bulk_with_proration_price.py index c30f7e39..d316caa0 100644 --- a/src/orb/types/shared_params/new_plan_bulk_with_proration_price.py +++ b/src/orb/types/shared_params/new_plan_bulk_with_proration_price.py @@ -86,3 +86,9 @@ class NewPlanBulkWithProrationPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_cumulative_grouped_bulk_price.py b/src/orb/types/shared_params/new_plan_cumulative_grouped_bulk_price.py index af851f4a..35baaf81 100644 --- a/src/orb/types/shared_params/new_plan_cumulative_grouped_bulk_price.py +++ b/src/orb/types/shared_params/new_plan_cumulative_grouped_bulk_price.py @@ -86,3 +86,9 @@ class NewPlanCumulativeGroupedBulkPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_grouped_allocation_price.py b/src/orb/types/shared_params/new_plan_grouped_allocation_price.py index 873a9bc6..19a387c9 100644 --- a/src/orb/types/shared_params/new_plan_grouped_allocation_price.py +++ b/src/orb/types/shared_params/new_plan_grouped_allocation_price.py @@ -86,3 +86,9 @@ class NewPlanGroupedAllocationPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_grouped_tiered_package_price.py b/src/orb/types/shared_params/new_plan_grouped_tiered_package_price.py index 98de19ff..fbb0d525 100644 --- a/src/orb/types/shared_params/new_plan_grouped_tiered_package_price.py +++ b/src/orb/types/shared_params/new_plan_grouped_tiered_package_price.py @@ -86,3 +86,9 @@ class NewPlanGroupedTieredPackagePrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_grouped_tiered_price.py b/src/orb/types/shared_params/new_plan_grouped_tiered_price.py index 2fbc66d5..bee29ec2 100644 --- a/src/orb/types/shared_params/new_plan_grouped_tiered_price.py +++ b/src/orb/types/shared_params/new_plan_grouped_tiered_price.py @@ -86,3 +86,9 @@ class NewPlanGroupedTieredPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_grouped_with_metered_minimum_price.py b/src/orb/types/shared_params/new_plan_grouped_with_metered_minimum_price.py index 8627f703..24147e08 100644 --- a/src/orb/types/shared_params/new_plan_grouped_with_metered_minimum_price.py +++ b/src/orb/types/shared_params/new_plan_grouped_with_metered_minimum_price.py @@ -86,3 +86,9 @@ class NewPlanGroupedWithMeteredMinimumPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_grouped_with_prorated_minimum_price.py b/src/orb/types/shared_params/new_plan_grouped_with_prorated_minimum_price.py index 2bdf29ff..c32d54a9 100644 --- a/src/orb/types/shared_params/new_plan_grouped_with_prorated_minimum_price.py +++ b/src/orb/types/shared_params/new_plan_grouped_with_prorated_minimum_price.py @@ -86,3 +86,9 @@ class NewPlanGroupedWithProratedMinimumPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_matrix_price.py b/src/orb/types/shared_params/new_plan_matrix_price.py index b65a8f4b..d3f4452d 100644 --- a/src/orb/types/shared_params/new_plan_matrix_price.py +++ b/src/orb/types/shared_params/new_plan_matrix_price.py @@ -87,3 +87,9 @@ class NewPlanMatrixPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_matrix_with_allocation_price.py b/src/orb/types/shared_params/new_plan_matrix_with_allocation_price.py index bfd0cab7..112a5a3c 100644 --- a/src/orb/types/shared_params/new_plan_matrix_with_allocation_price.py +++ b/src/orb/types/shared_params/new_plan_matrix_with_allocation_price.py @@ -87,3 +87,9 @@ class NewPlanMatrixWithAllocationPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_matrix_with_display_name_price.py b/src/orb/types/shared_params/new_plan_matrix_with_display_name_price.py index 43bb73ee..dd420961 100644 --- a/src/orb/types/shared_params/new_plan_matrix_with_display_name_price.py +++ b/src/orb/types/shared_params/new_plan_matrix_with_display_name_price.py @@ -86,3 +86,9 @@ class NewPlanMatrixWithDisplayNamePrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_max_group_tiered_package_price.py b/src/orb/types/shared_params/new_plan_max_group_tiered_package_price.py index c9100746..3d05613a 100644 --- a/src/orb/types/shared_params/new_plan_max_group_tiered_package_price.py +++ b/src/orb/types/shared_params/new_plan_max_group_tiered_package_price.py @@ -86,3 +86,9 @@ class NewPlanMaxGroupTieredPackagePrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_package_price.py b/src/orb/types/shared_params/new_plan_package_price.py index b315f03b..5d67fda5 100644 --- a/src/orb/types/shared_params/new_plan_package_price.py +++ b/src/orb/types/shared_params/new_plan_package_price.py @@ -87,3 +87,9 @@ class NewPlanPackagePrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_package_with_allocation_price.py b/src/orb/types/shared_params/new_plan_package_with_allocation_price.py index 1eef2c0e..db47c1e0 100644 --- a/src/orb/types/shared_params/new_plan_package_with_allocation_price.py +++ b/src/orb/types/shared_params/new_plan_package_with_allocation_price.py @@ -86,3 +86,9 @@ class NewPlanPackageWithAllocationPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_scalable_matrix_with_tiered_pricing_price.py b/src/orb/types/shared_params/new_plan_scalable_matrix_with_tiered_pricing_price.py index d9121714..4bb3987f 100644 --- a/src/orb/types/shared_params/new_plan_scalable_matrix_with_tiered_pricing_price.py +++ b/src/orb/types/shared_params/new_plan_scalable_matrix_with_tiered_pricing_price.py @@ -86,3 +86,9 @@ class NewPlanScalableMatrixWithTieredPricingPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_scalable_matrix_with_unit_pricing_price.py b/src/orb/types/shared_params/new_plan_scalable_matrix_with_unit_pricing_price.py index b58738f8..650a6882 100644 --- a/src/orb/types/shared_params/new_plan_scalable_matrix_with_unit_pricing_price.py +++ b/src/orb/types/shared_params/new_plan_scalable_matrix_with_unit_pricing_price.py @@ -86,3 +86,9 @@ class NewPlanScalableMatrixWithUnitPricingPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_threshold_total_amount_price.py b/src/orb/types/shared_params/new_plan_threshold_total_amount_price.py index a7f1f3db..9bd75b47 100644 --- a/src/orb/types/shared_params/new_plan_threshold_total_amount_price.py +++ b/src/orb/types/shared_params/new_plan_threshold_total_amount_price.py @@ -86,3 +86,9 @@ class NewPlanThresholdTotalAmountPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_tier_with_proration_price.py b/src/orb/types/shared_params/new_plan_tier_with_proration_price.py index 243fb99c..a9414209 100644 --- a/src/orb/types/shared_params/new_plan_tier_with_proration_price.py +++ b/src/orb/types/shared_params/new_plan_tier_with_proration_price.py @@ -86,3 +86,9 @@ class NewPlanTierWithProrationPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_tiered_bps_price.py b/src/orb/types/shared_params/new_plan_tiered_bps_price.py index d96e07ee..b6854a82 100644 --- a/src/orb/types/shared_params/new_plan_tiered_bps_price.py +++ b/src/orb/types/shared_params/new_plan_tiered_bps_price.py @@ -87,3 +87,9 @@ class NewPlanTieredBPSPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_tiered_package_price.py b/src/orb/types/shared_params/new_plan_tiered_package_price.py index 0ef773ac..00e50d44 100644 --- a/src/orb/types/shared_params/new_plan_tiered_package_price.py +++ b/src/orb/types/shared_params/new_plan_tiered_package_price.py @@ -86,3 +86,9 @@ class NewPlanTieredPackagePrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_tiered_package_with_minimum_price.py b/src/orb/types/shared_params/new_plan_tiered_package_with_minimum_price.py index 251fc01d..fef575b7 100644 --- a/src/orb/types/shared_params/new_plan_tiered_package_with_minimum_price.py +++ b/src/orb/types/shared_params/new_plan_tiered_package_with_minimum_price.py @@ -86,3 +86,9 @@ class NewPlanTieredPackageWithMinimumPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_tiered_price.py b/src/orb/types/shared_params/new_plan_tiered_price.py index 598c0d48..37d03944 100644 --- a/src/orb/types/shared_params/new_plan_tiered_price.py +++ b/src/orb/types/shared_params/new_plan_tiered_price.py @@ -87,3 +87,9 @@ class NewPlanTieredPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_tiered_with_minimum_price.py b/src/orb/types/shared_params/new_plan_tiered_with_minimum_price.py index 61b8636f..946bd174 100644 --- a/src/orb/types/shared_params/new_plan_tiered_with_minimum_price.py +++ b/src/orb/types/shared_params/new_plan_tiered_with_minimum_price.py @@ -86,3 +86,9 @@ class NewPlanTieredWithMinimumPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_unit_price.py b/src/orb/types/shared_params/new_plan_unit_price.py index ec3b698c..1fd39a1a 100644 --- a/src/orb/types/shared_params/new_plan_unit_price.py +++ b/src/orb/types/shared_params/new_plan_unit_price.py @@ -87,3 +87,9 @@ class NewPlanUnitPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_unit_with_percent_price.py b/src/orb/types/shared_params/new_plan_unit_with_percent_price.py index 6db2bcb6..9999bd7b 100644 --- a/src/orb/types/shared_params/new_plan_unit_with_percent_price.py +++ b/src/orb/types/shared_params/new_plan_unit_with_percent_price.py @@ -86,3 +86,9 @@ class NewPlanUnitWithPercentPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/src/orb/types/shared_params/new_plan_unit_with_proration_price.py b/src/orb/types/shared_params/new_plan_unit_with_proration_price.py index 4cf6159a..d7ffe5ff 100644 --- a/src/orb/types/shared_params/new_plan_unit_with_proration_price.py +++ b/src/orb/types/shared_params/new_plan_unit_with_proration_price.py @@ -86,3 +86,9 @@ class NewPlanUnitWithProrationPrice(TypedDict, total=False): Individual keys can be removed by setting the value to `null`, and the entire metadata mapping can be cleared by setting `metadata` to `null`. """ + + reference_id: Optional[str] + """ + A transient ID that can be used to reference this price when adding adjustments + in the same API call. + """ diff --git a/tests/api_resources/beta/test_external_plan_id.py b/tests/api_resources/beta/test_external_plan_id.py index fe98d6fc..920332bf 100644 --- a/tests/api_resources/beta/test_external_plan_id.py +++ b/tests/api_resources/beta/test_external_plan_id.py @@ -96,6 +96,7 @@ def test_method_create_plan_version_with_all_params(self, client: Orb) -> None: "duration_unit": "day", }, "metadata": {"foo": "string"}, + "reference_id": "reference_id", }, } ], @@ -179,6 +180,7 @@ def test_method_create_plan_version_with_all_params(self, client: Orb) -> None: "duration_unit": "day", }, "metadata": {"foo": "string"}, + "reference_id": "reference_id", }, } ], @@ -312,7 +314,9 @@ def test_path_params_set_default_plan_version(self, client: Orb) -> None: class TestAsyncExternalPlanID: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create_plan_version(self, async_client: AsyncOrb) -> None: @@ -393,6 +397,7 @@ async def test_method_create_plan_version_with_all_params(self, async_client: As "duration_unit": "day", }, "metadata": {"foo": "string"}, + "reference_id": "reference_id", }, } ], @@ -476,6 +481,7 @@ async def test_method_create_plan_version_with_all_params(self, async_client: As "duration_unit": "day", }, "metadata": {"foo": "string"}, + "reference_id": "reference_id", }, } ], diff --git a/tests/api_resources/coupons/test_subscriptions.py b/tests/api_resources/coupons/test_subscriptions.py index 4c190521..cbf1e1d2 100644 --- a/tests/api_resources/coupons/test_subscriptions.py +++ b/tests/api_resources/coupons/test_subscriptions.py @@ -67,7 +67,9 @@ def test_path_params_list(self, client: Orb) -> None: class TestAsyncSubscriptions: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_list(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/customers/credits/test_ledger.py b/tests/api_resources/customers/credits/test_ledger.py index ff759955..255b0e65 100644 --- a/tests/api_resources/customers/credits/test_ledger.py +++ b/tests/api_resources/customers/credits/test_ledger.py @@ -209,7 +209,6 @@ def test_method_create_entry_overload_3(self, client: Orb) -> None: ledger = client.customers.credits.ledger.create_entry( customer_id="customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) assert_matches_type(LedgerCreateEntryResponse, ledger, path=["response"]) @@ -219,12 +218,12 @@ def test_method_create_entry_with_all_params_overload_3(self, client: Orb) -> No ledger = client.customers.credits.ledger.create_entry( customer_id="customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), amount=0, block_id="block_id", currency="currency", description="description", + expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), metadata={"foo": "string"}, ) assert_matches_type(LedgerCreateEntryResponse, ledger, path=["response"]) @@ -234,7 +233,6 @@ def test_raw_response_create_entry_overload_3(self, client: Orb) -> None: response = client.customers.credits.ledger.with_raw_response.create_entry( customer_id="customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) @@ -248,7 +246,6 @@ def test_streaming_response_create_entry_overload_3(self, client: Orb) -> None: with client.customers.credits.ledger.with_streaming_response.create_entry( customer_id="customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) as response: assert not response.is_closed @@ -265,7 +262,6 @@ def test_path_params_create_entry_overload_3(self, client: Orb) -> None: client.customers.credits.ledger.with_raw_response.create_entry( customer_id="", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) @@ -526,7 +522,6 @@ def test_method_create_entry_by_external_id_overload_3(self, client: Orb) -> Non ledger = client.customers.credits.ledger.create_entry_by_external_id( external_customer_id="external_customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) assert_matches_type(LedgerCreateEntryByExternalIDResponse, ledger, path=["response"]) @@ -536,12 +531,12 @@ def test_method_create_entry_by_external_id_with_all_params_overload_3(self, cli ledger = client.customers.credits.ledger.create_entry_by_external_id( external_customer_id="external_customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), amount=0, block_id="block_id", currency="currency", description="description", + expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), metadata={"foo": "string"}, ) assert_matches_type(LedgerCreateEntryByExternalIDResponse, ledger, path=["response"]) @@ -551,7 +546,6 @@ def test_raw_response_create_entry_by_external_id_overload_3(self, client: Orb) response = client.customers.credits.ledger.with_raw_response.create_entry_by_external_id( external_customer_id="external_customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) @@ -565,7 +559,6 @@ def test_streaming_response_create_entry_by_external_id_overload_3(self, client: with client.customers.credits.ledger.with_streaming_response.create_entry_by_external_id( external_customer_id="external_customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) as response: assert not response.is_closed @@ -582,7 +575,6 @@ def test_path_params_create_entry_by_external_id_overload_3(self, client: Orb) - client.customers.credits.ledger.with_raw_response.create_entry_by_external_id( external_customer_id="", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) @@ -770,7 +762,9 @@ def test_path_params_list_by_external_id(self, client: Orb) -> None: class TestAsyncLedger: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_list(self, async_client: AsyncOrb) -> None: @@ -957,7 +951,6 @@ async def test_method_create_entry_overload_3(self, async_client: AsyncOrb) -> N ledger = await async_client.customers.credits.ledger.create_entry( customer_id="customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) assert_matches_type(LedgerCreateEntryResponse, ledger, path=["response"]) @@ -967,12 +960,12 @@ async def test_method_create_entry_with_all_params_overload_3(self, async_client ledger = await async_client.customers.credits.ledger.create_entry( customer_id="customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), amount=0, block_id="block_id", currency="currency", description="description", + expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), metadata={"foo": "string"}, ) assert_matches_type(LedgerCreateEntryResponse, ledger, path=["response"]) @@ -982,7 +975,6 @@ async def test_raw_response_create_entry_overload_3(self, async_client: AsyncOrb response = await async_client.customers.credits.ledger.with_raw_response.create_entry( customer_id="customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) @@ -996,7 +988,6 @@ async def test_streaming_response_create_entry_overload_3(self, async_client: As async with async_client.customers.credits.ledger.with_streaming_response.create_entry( customer_id="customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) as response: assert not response.is_closed @@ -1013,7 +1004,6 @@ async def test_path_params_create_entry_overload_3(self, async_client: AsyncOrb) await async_client.customers.credits.ledger.with_raw_response.create_entry( customer_id="", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) @@ -1274,7 +1264,6 @@ async def test_method_create_entry_by_external_id_overload_3(self, async_client: ledger = await async_client.customers.credits.ledger.create_entry_by_external_id( external_customer_id="external_customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) assert_matches_type(LedgerCreateEntryByExternalIDResponse, ledger, path=["response"]) @@ -1284,12 +1273,12 @@ async def test_method_create_entry_by_external_id_with_all_params_overload_3(sel ledger = await async_client.customers.credits.ledger.create_entry_by_external_id( external_customer_id="external_customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), amount=0, block_id="block_id", currency="currency", description="description", + expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), metadata={"foo": "string"}, ) assert_matches_type(LedgerCreateEntryByExternalIDResponse, ledger, path=["response"]) @@ -1299,7 +1288,6 @@ async def test_raw_response_create_entry_by_external_id_overload_3(self, async_c response = await async_client.customers.credits.ledger.with_raw_response.create_entry_by_external_id( external_customer_id="external_customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) @@ -1313,7 +1301,6 @@ async def test_streaming_response_create_entry_by_external_id_overload_3(self, a async with async_client.customers.credits.ledger.with_streaming_response.create_entry_by_external_id( external_customer_id="external_customer_id", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) as response: assert not response.is_closed @@ -1330,7 +1317,6 @@ async def test_path_params_create_entry_by_external_id_overload_3(self, async_cl await async_client.customers.credits.ledger.with_raw_response.create_entry_by_external_id( external_customer_id="", entry_type="expiration_change", - expiry_date=parse_datetime("2019-12-27T18:11:19.117Z"), target_expiry_date=parse_date("2019-12-27"), ) diff --git a/tests/api_resources/customers/credits/test_top_ups.py b/tests/api_resources/customers/credits/test_top_ups.py index 03281ee1..728f90b7 100644 --- a/tests/api_resources/customers/credits/test_top_ups.py +++ b/tests/api_resources/customers/credits/test_top_ups.py @@ -396,7 +396,9 @@ def test_path_params_list_by_external_id(self, client: Orb) -> None: class TestAsyncTopUps: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/customers/test_balance_transactions.py b/tests/api_resources/customers/test_balance_transactions.py index 77d23372..054ffd79 100644 --- a/tests/api_resources/customers/test_balance_transactions.py +++ b/tests/api_resources/customers/test_balance_transactions.py @@ -131,7 +131,9 @@ def test_path_params_list(self, client: Orb) -> None: class TestAsyncBalanceTransactions: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/customers/test_costs.py b/tests/api_resources/customers/test_costs.py index 17d95e60..dfab25e6 100644 --- a/tests/api_resources/customers/test_costs.py +++ b/tests/api_resources/customers/test_costs.py @@ -121,7 +121,9 @@ def test_path_params_list_by_external_id(self, client: Orb) -> None: class TestAsyncCosts: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_list(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/customers/test_credits.py b/tests/api_resources/customers/test_credits.py index 19de5732..90d60907 100644 --- a/tests/api_resources/customers/test_credits.py +++ b/tests/api_resources/customers/test_credits.py @@ -121,7 +121,9 @@ def test_path_params_list_by_external_id(self, client: Orb) -> None: class TestAsyncCredits: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_list(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/dimensional_price_groups/test_external_dimensional_price_group_id.py b/tests/api_resources/dimensional_price_groups/test_external_dimensional_price_group_id.py index e4d7118f..2cb38c45 100644 --- a/tests/api_resources/dimensional_price_groups/test_external_dimensional_price_group_id.py +++ b/tests/api_resources/dimensional_price_groups/test_external_dimensional_price_group_id.py @@ -61,7 +61,9 @@ def test_path_params_retrieve(self, client: Orb) -> None: class TestAsyncExternalDimensionalPriceGroupID: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_retrieve(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/events/test_backfills.py b/tests/api_resources/events/test_backfills.py index bed65b8c..9cabc90c 100644 --- a/tests/api_resources/events/test_backfills.py +++ b/tests/api_resources/events/test_backfills.py @@ -221,7 +221,9 @@ def test_path_params_revert(self, client: Orb) -> None: class TestAsyncBackfills: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/events/test_volume.py b/tests/api_resources/events/test_volume.py index 7de82b57..87ef4772 100644 --- a/tests/api_resources/events/test_volume.py +++ b/tests/api_resources/events/test_volume.py @@ -61,7 +61,9 @@ def test_streaming_response_list(self, client: Orb) -> None: class TestAsyncVolume: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_list(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/plans/test_external_plan_id.py b/tests/api_resources/plans/test_external_plan_id.py index 0adbc341..3c77aa9c 100644 --- a/tests/api_resources/plans/test_external_plan_id.py +++ b/tests/api_resources/plans/test_external_plan_id.py @@ -106,7 +106,9 @@ def test_path_params_fetch(self, client: Orb) -> None: class TestAsyncExternalPlanID: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_update(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/prices/test_external_price_id.py b/tests/api_resources/prices/test_external_price_id.py index 24ad301a..1c995858 100644 --- a/tests/api_resources/prices/test_external_price_id.py +++ b/tests/api_resources/prices/test_external_price_id.py @@ -103,7 +103,9 @@ def test_path_params_fetch(self, client: Orb) -> None: class TestAsyncExternalPriceID: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_update(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_alerts.py b/tests/api_resources/test_alerts.py index b12409c4..bcae7a6b 100644 --- a/tests/api_resources/test_alerts.py +++ b/tests/api_resources/test_alerts.py @@ -413,7 +413,9 @@ def test_path_params_enable(self, client: Orb) -> None: class TestAsyncAlerts: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_retrieve(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_beta.py b/tests/api_resources/test_beta.py index 6d0e3e8e..5b2987f2 100644 --- a/tests/api_resources/test_beta.py +++ b/tests/api_resources/test_beta.py @@ -96,6 +96,7 @@ def test_method_create_plan_version_with_all_params(self, client: Orb) -> None: "duration_unit": "day", }, "metadata": {"foo": "string"}, + "reference_id": "reference_id", }, } ], @@ -179,6 +180,7 @@ def test_method_create_plan_version_with_all_params(self, client: Orb) -> None: "duration_unit": "day", }, "metadata": {"foo": "string"}, + "reference_id": "reference_id", }, } ], @@ -312,7 +314,9 @@ def test_path_params_set_default_plan_version(self, client: Orb) -> None: class TestAsyncBeta: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create_plan_version(self, async_client: AsyncOrb) -> None: @@ -393,6 +397,7 @@ async def test_method_create_plan_version_with_all_params(self, async_client: As "duration_unit": "day", }, "metadata": {"foo": "string"}, + "reference_id": "reference_id", }, } ], @@ -476,6 +481,7 @@ async def test_method_create_plan_version_with_all_params(self, async_client: As "duration_unit": "day", }, "metadata": {"foo": "string"}, + "reference_id": "reference_id", }, } ], diff --git a/tests/api_resources/test_coupons.py b/tests/api_resources/test_coupons.py index 8d59baa8..7b888a5e 100644 --- a/tests/api_resources/test_coupons.py +++ b/tests/api_resources/test_coupons.py @@ -187,7 +187,9 @@ def test_path_params_fetch(self, client: Orb) -> None: class TestAsyncCoupons: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_credit_notes.py b/tests/api_resources/test_credit_notes.py index 3b6322de..198527c6 100644 --- a/tests/api_resources/test_credit_notes.py +++ b/tests/api_resources/test_credit_notes.py @@ -159,7 +159,9 @@ def test_path_params_fetch(self, client: Orb) -> None: class TestAsyncCreditNotes: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_customers.py b/tests/api_resources/test_customers.py index a3cb552e..2a712518 100644 --- a/tests/api_resources/test_customers.py +++ b/tests/api_resources/test_customers.py @@ -531,7 +531,9 @@ def test_path_params_update_by_external_id(self, client: Orb) -> None: class TestAsyncCustomers: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_dimensional_price_groups.py b/tests/api_resources/test_dimensional_price_groups.py index d371b7c5..9ea7e958 100644 --- a/tests/api_resources/test_dimensional_price_groups.py +++ b/tests/api_resources/test_dimensional_price_groups.py @@ -141,7 +141,9 @@ def test_streaming_response_list(self, client: Orb) -> None: class TestAsyncDimensionalPriceGroups: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_events.py b/tests/api_resources/test_events.py index e4b98158..6aab2662 100644 --- a/tests/api_resources/test_events.py +++ b/tests/api_resources/test_events.py @@ -235,7 +235,9 @@ def test_streaming_response_search(self, client: Orb) -> None: class TestAsyncEvents: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_update(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_invoice_line_items.py b/tests/api_resources/test_invoice_line_items.py index 55411e85..0c9c4ab8 100644 --- a/tests/api_resources/test_invoice_line_items.py +++ b/tests/api_resources/test_invoice_line_items.py @@ -66,7 +66,9 @@ def test_streaming_response_create(self, client: Orb) -> None: class TestAsyncInvoiceLineItems: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_invoices.py b/tests/api_resources/test_invoices.py index d1082981..d3b5bfee 100644 --- a/tests/api_resources/test_invoices.py +++ b/tests/api_resources/test_invoices.py @@ -471,7 +471,9 @@ def test_path_params_void(self, client: Orb) -> None: class TestAsyncInvoices: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_items.py b/tests/api_resources/test_items.py index 43beecc1..220d2c17 100644 --- a/tests/api_resources/test_items.py +++ b/tests/api_resources/test_items.py @@ -221,7 +221,9 @@ def test_path_params_fetch(self, client: Orb) -> None: class TestAsyncItems: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_metrics.py b/tests/api_resources/test_metrics.py index f111499e..5b58742a 100644 --- a/tests/api_resources/test_metrics.py +++ b/tests/api_resources/test_metrics.py @@ -193,7 +193,9 @@ def test_path_params_fetch(self, client: Orb) -> None: class TestAsyncMetrics: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_plans.py b/tests/api_resources/test_plans.py index abecb8a2..590f1e77 100644 --- a/tests/api_resources/test_plans.py +++ b/tests/api_resources/test_plans.py @@ -24,15 +24,7 @@ def test_method_create(self, client: Orb) -> None: plan = client.plans.create( currency="currency", name="name", - prices=[ - { - "cadence": "annual", - "item_id": "item_id", - "model_type": "unit", - "name": "Annual fee", - "unit_config": {"unit_amount": "unit_amount"}, - } - ], + prices=[{}], ) assert_matches_type(Plan, plan, path=["response"]) @@ -43,42 +35,86 @@ def test_method_create_with_all_params(self, client: Orb) -> None: name="name", prices=[ { - "cadence": "annual", - "item_id": "item_id", - "model_type": "unit", - "name": "Annual fee", - "unit_config": {"unit_amount": "unit_amount"}, - "billable_metric_id": "billable_metric_id", - "billed_in_advance": True, - "billing_cycle_configuration": { - "duration": 0, - "duration_unit": "day", + "allocation_price": { + "amount": "10.00", + "cadence": "monthly", + "currency": "USD", + "custom_expiration": { + "duration": 0, + "duration_unit": "day", + }, + "expires_at_end_of_cadence": True, }, - "conversion_rate": 0, - "conversion_rate_config": { - "conversion_rate_type": "unit", + "plan_phase_order": 0, + "price": { + "cadence": "annual", + "item_id": "item_id", + "model_type": "unit", + "name": "Annual fee", "unit_config": {"unit_amount": "unit_amount"}, + "billable_metric_id": "billable_metric_id", + "billed_in_advance": True, + "billing_cycle_configuration": { + "duration": 0, + "duration_unit": "day", + }, + "conversion_rate": 0, + "conversion_rate_config": { + "conversion_rate_type": "unit", + "unit_config": {"unit_amount": "unit_amount"}, + }, + "currency": "currency", + "dimensional_price_configuration": { + "dimension_values": ["string"], + "dimensional_price_group_id": "dimensional_price_group_id", + "external_dimensional_price_group_id": "external_dimensional_price_group_id", + }, + "external_price_id": "external_price_id", + "fixed_price_quantity": 0, + "invoice_grouping_key": "x", + "invoicing_cycle_configuration": { + "duration": 0, + "duration_unit": "day", + }, + "metadata": {"foo": "string"}, + "reference_id": "reference_id", }, - "currency": "currency", - "dimensional_price_configuration": { - "dimension_values": ["string"], - "dimensional_price_group_id": "dimensional_price_group_id", - "external_dimensional_price_group_id": "external_dimensional_price_group_id", - }, - "external_price_id": "external_price_id", - "fixed_price_quantity": 0, - "invoice_grouping_key": "x", - "invoicing_cycle_configuration": { - "duration": 0, - "duration_unit": "day", + } + ], + adjustments=[ + { + "adjustment": { + "adjustment_type": "percentage_discount", + "percentage_discount": 0, + "applies_to_all": True, + "applies_to_item_ids": ["item_1", "item_2"], + "applies_to_price_ids": ["price_1", "price_2"], + "currency": "currency", + "filters": [ + { + "field": "price_id", + "operator": "includes", + "values": ["string"], + } + ], + "is_invoice_level": True, + "price_type": "usage", }, - "metadata": {"foo": "string"}, + "plan_phase_order": 0, } ], default_invoice_memo="default_invoice_memo", external_plan_id="external_plan_id", metadata={"foo": "string"}, net_terms=0, + plan_phases=[ + { + "order": 0, + "align_billing_with_phase_start_date": True, + "duration": 1, + "duration_unit": "daily", + } + ], status="active", ) assert_matches_type(Plan, plan, path=["response"]) @@ -88,15 +124,7 @@ def test_raw_response_create(self, client: Orb) -> None: response = client.plans.with_raw_response.create( currency="currency", name="name", - prices=[ - { - "cadence": "annual", - "item_id": "item_id", - "model_type": "unit", - "name": "Annual fee", - "unit_config": {"unit_amount": "unit_amount"}, - } - ], + prices=[{}], ) assert response.is_closed is True @@ -109,15 +137,7 @@ def test_streaming_response_create(self, client: Orb) -> None: with client.plans.with_streaming_response.create( currency="currency", name="name", - prices=[ - { - "cadence": "annual", - "item_id": "item_id", - "model_type": "unit", - "name": "Annual fee", - "unit_config": {"unit_amount": "unit_amount"}, - } - ], + prices=[{}], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -252,22 +272,16 @@ def test_path_params_fetch(self, client: Orb) -> None: class TestAsyncPlans: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: plan = await async_client.plans.create( currency="currency", name="name", - prices=[ - { - "cadence": "annual", - "item_id": "item_id", - "model_type": "unit", - "name": "Annual fee", - "unit_config": {"unit_amount": "unit_amount"}, - } - ], + prices=[{}], ) assert_matches_type(Plan, plan, path=["response"]) @@ -278,42 +292,86 @@ async def test_method_create_with_all_params(self, async_client: AsyncOrb) -> No name="name", prices=[ { - "cadence": "annual", - "item_id": "item_id", - "model_type": "unit", - "name": "Annual fee", - "unit_config": {"unit_amount": "unit_amount"}, - "billable_metric_id": "billable_metric_id", - "billed_in_advance": True, - "billing_cycle_configuration": { - "duration": 0, - "duration_unit": "day", + "allocation_price": { + "amount": "10.00", + "cadence": "monthly", + "currency": "USD", + "custom_expiration": { + "duration": 0, + "duration_unit": "day", + }, + "expires_at_end_of_cadence": True, }, - "conversion_rate": 0, - "conversion_rate_config": { - "conversion_rate_type": "unit", + "plan_phase_order": 0, + "price": { + "cadence": "annual", + "item_id": "item_id", + "model_type": "unit", + "name": "Annual fee", "unit_config": {"unit_amount": "unit_amount"}, + "billable_metric_id": "billable_metric_id", + "billed_in_advance": True, + "billing_cycle_configuration": { + "duration": 0, + "duration_unit": "day", + }, + "conversion_rate": 0, + "conversion_rate_config": { + "conversion_rate_type": "unit", + "unit_config": {"unit_amount": "unit_amount"}, + }, + "currency": "currency", + "dimensional_price_configuration": { + "dimension_values": ["string"], + "dimensional_price_group_id": "dimensional_price_group_id", + "external_dimensional_price_group_id": "external_dimensional_price_group_id", + }, + "external_price_id": "external_price_id", + "fixed_price_quantity": 0, + "invoice_grouping_key": "x", + "invoicing_cycle_configuration": { + "duration": 0, + "duration_unit": "day", + }, + "metadata": {"foo": "string"}, + "reference_id": "reference_id", }, - "currency": "currency", - "dimensional_price_configuration": { - "dimension_values": ["string"], - "dimensional_price_group_id": "dimensional_price_group_id", - "external_dimensional_price_group_id": "external_dimensional_price_group_id", - }, - "external_price_id": "external_price_id", - "fixed_price_quantity": 0, - "invoice_grouping_key": "x", - "invoicing_cycle_configuration": { - "duration": 0, - "duration_unit": "day", + } + ], + adjustments=[ + { + "adjustment": { + "adjustment_type": "percentage_discount", + "percentage_discount": 0, + "applies_to_all": True, + "applies_to_item_ids": ["item_1", "item_2"], + "applies_to_price_ids": ["price_1", "price_2"], + "currency": "currency", + "filters": [ + { + "field": "price_id", + "operator": "includes", + "values": ["string"], + } + ], + "is_invoice_level": True, + "price_type": "usage", }, - "metadata": {"foo": "string"}, + "plan_phase_order": 0, } ], default_invoice_memo="default_invoice_memo", external_plan_id="external_plan_id", metadata={"foo": "string"}, net_terms=0, + plan_phases=[ + { + "order": 0, + "align_billing_with_phase_start_date": True, + "duration": 1, + "duration_unit": "daily", + } + ], status="active", ) assert_matches_type(Plan, plan, path=["response"]) @@ -323,15 +381,7 @@ async def test_raw_response_create(self, async_client: AsyncOrb) -> None: response = await async_client.plans.with_raw_response.create( currency="currency", name="name", - prices=[ - { - "cadence": "annual", - "item_id": "item_id", - "model_type": "unit", - "name": "Annual fee", - "unit_config": {"unit_amount": "unit_amount"}, - } - ], + prices=[{}], ) assert response.is_closed is True @@ -344,15 +394,7 @@ async def test_streaming_response_create(self, async_client: AsyncOrb) -> None: async with async_client.plans.with_streaming_response.create( currency="currency", name="name", - prices=[ - { - "cadence": "annual", - "item_id": "item_id", - "model_type": "unit", - "name": "Annual fee", - "unit_config": {"unit_amount": "unit_amount"}, - } - ], + prices=[{}], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/api_resources/test_prices.py b/tests/api_resources/test_prices.py index 4cc40d19..c27f8d1b 100644 --- a/tests/api_resources/test_prices.py +++ b/tests/api_resources/test_prices.py @@ -2838,7 +2838,9 @@ def test_path_params_fetch(self, client: Orb) -> None: class TestAsyncPrices: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create_overload_1(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_subscription_changes.py b/tests/api_resources/test_subscription_changes.py index c362679e..68137cca 100644 --- a/tests/api_resources/test_subscription_changes.py +++ b/tests/api_resources/test_subscription_changes.py @@ -152,7 +152,9 @@ def test_path_params_cancel(self, client: Orb) -> None: class TestAsyncSubscriptionChanges: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_retrieve(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_subscriptions.py b/tests/api_resources/test_subscriptions.py index 0d241eef..6607f896 100644 --- a/tests/api_resources/test_subscriptions.py +++ b/tests/api_resources/test_subscriptions.py @@ -1345,7 +1345,9 @@ def test_path_params_update_trial(self, client: Orb) -> None: class TestAsyncSubscriptions: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_create(self, async_client: AsyncOrb) -> None: diff --git a/tests/api_resources/test_top_level.py b/tests/api_resources/test_top_level.py index 6971f1e7..217fbeef 100644 --- a/tests/api_resources/test_top_level.py +++ b/tests/api_resources/test_top_level.py @@ -44,7 +44,9 @@ def test_streaming_response_ping(self, client: Orb) -> None: class TestAsyncTopLevel: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) @parametrize async def test_method_ping(self, async_client: AsyncOrb) -> None: diff --git a/tests/conftest.py b/tests/conftest.py index 42a2de02..1d22f0ef 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,13 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + from __future__ import annotations import os import logging from typing import TYPE_CHECKING, Iterator, AsyncIterator +import httpx import pytest from pytest_asyncio import is_async_test -from orb import Orb, AsyncOrb +from orb import Orb, AsyncOrb, DefaultAioHttpClient +from orb._utils import is_dict if TYPE_CHECKING: from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage] @@ -25,6 +29,19 @@ def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: for async_test in pytest_asyncio_tests: async_test.add_marker(session_scope_marker, append=False) + # We skip tests that use both the aiohttp client and respx_mock as respx_mock + # doesn't support custom transports. + for item in items: + if "async_client" not in item.fixturenames or "respx_mock" not in item.fixturenames: + continue + + if not hasattr(item, "callspec"): + continue + + async_client_param = item.callspec.params.get("async_client") + if is_dict(async_client_param) and async_client_param.get("http_client") == "aiohttp": + item.add_marker(pytest.mark.skip(reason="aiohttp client is not compatible with respx_mock")) + base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -43,9 +60,25 @@ def client(request: FixtureRequest) -> Iterator[Orb]: @pytest.fixture(scope="session") async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncOrb]: - strict = getattr(request, "param", True) - if not isinstance(strict, bool): - raise TypeError(f"Unexpected fixture parameter type {type(strict)}, expected {bool}") - - async with AsyncOrb(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: + param = getattr(request, "param", True) + + # defaults + strict = True + http_client: None | httpx.AsyncClient = None + + if isinstance(param, bool): + strict = param + elif is_dict(param): + strict = param.get("strict", True) + assert isinstance(strict, bool) + + http_client_type = param.get("http_client", "httpx") + if http_client_type == "aiohttp": + http_client = DefaultAioHttpClient() + else: + raise TypeError(f"Unexpected fixture parameter type {type(param)}, expected bool or dict") + + async with AsyncOrb( + base_url=base_url, api_key=api_key, _strict_response_validation=strict, http_client=http_client + ) as client: yield client diff --git a/tests/test_client.py b/tests/test_client.py index 88928ef0..b2a4334b 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -23,12 +23,16 @@ from orb import Orb, AsyncOrb, APIResponseValidationError from orb._types import Omit -from orb._utils import maybe_transform from orb._models import BaseModel, FinalRequestOptions -from orb._constants import RAW_RESPONSE_HEADER from orb._exceptions import OrbError, APIStatusError, APITimeoutError, APIResponseValidationError -from orb._base_client import DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, BaseClient, make_request_options -from orb.types.customer_create_params import CustomerCreateParams +from orb._base_client import ( + DEFAULT_TIMEOUT, + HTTPX_DEFAULT_TIMEOUT, + BaseClient, + DefaultHttpxClient, + DefaultAsyncHttpxClient, + make_request_options, +) from .utils import update_env @@ -185,6 +189,7 @@ def test_copy_signature(self) -> None: copy_param = copy_signature.parameters.get(name) assert copy_param is not None, f"copy() signature is missing the {name} param" + @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") def test_copy_build_request(self) -> None: options = FinalRequestOptions(method="get", url="/foo") @@ -729,42 +734,21 @@ def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str @mock.patch("orb._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: + def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, client: Orb) -> None: respx_mock.post("/customers").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - self.client.post( - "/customers", - body=cast( - object, - maybe_transform( - dict(email="example-customer@withorb.com", name="My Customer"), CustomerCreateParams - ), - ), - cast_to=httpx.Response, - options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, - ) + client.customers.with_streaming_response.create(email="dev@stainless.com", name="x").__enter__() assert _get_open_connections(self.client) == 0 @mock.patch("orb._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: + def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client: Orb) -> None: respx_mock.post("/customers").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - self.client.post( - "/customers", - body=cast( - object, - maybe_transform( - dict(email="example-customer@withorb.com", name="My Customer"), CustomerCreateParams - ), - ), - cast_to=httpx.Response, - options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, - ) - + client.customers.with_streaming_response.create(email="dev@stainless.com", name="x").__enter__() assert _get_open_connections(self.client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @@ -869,6 +853,28 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success + def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: + # Test that the proxy environment variables are set correctly + monkeypatch.setenv("HTTPS_PROXY", "https://example.org") + + client = DefaultHttpxClient() + + mounts = tuple(client._mounts.items()) + assert len(mounts) == 1 + assert mounts[0][0].pattern == "https://" + + @pytest.mark.filterwarnings("ignore:.*deprecated.*:DeprecationWarning") + def test_default_client_creation(self) -> None: + # Ensure that the client can be initialized without any exceptions + DefaultHttpxClient( + verify=True, + cert=None, + trust_env=True, + http1=True, + http2=False, + limits=httpx.Limits(max_connections=100, max_keepalive_connections=20), + ) + @pytest.mark.respx(base_url=base_url) def test_follow_redirects(self, respx_mock: MockRouter) -> None: # Test that the default follow_redirects=True allows following redirects @@ -1032,6 +1038,7 @@ def test_copy_signature(self) -> None: copy_param = copy_signature.parameters.get(name) assert copy_param is not None, f"copy() signature is missing the {name} param" + @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") def test_copy_build_request(self) -> None: options = FinalRequestOptions(method="get", url="/foo") @@ -1588,42 +1595,25 @@ async def test_parse_retry_after_header(self, remaining_retries: int, retry_afte @mock.patch("orb._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: + async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, async_client: AsyncOrb) -> None: respx_mock.post("/customers").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - await self.client.post( - "/customers", - body=cast( - object, - maybe_transform( - dict(email="example-customer@withorb.com", name="My Customer"), CustomerCreateParams - ), - ), - cast_to=httpx.Response, - options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, - ) + await async_client.customers.with_streaming_response.create( + email="dev@stainless.com", name="x" + ).__aenter__() assert _get_open_connections(self.client) == 0 @mock.patch("orb._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: + async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, async_client: AsyncOrb) -> None: respx_mock.post("/customers").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - await self.client.post( - "/customers", - body=cast( - object, - maybe_transform( - dict(email="example-customer@withorb.com", name="My Customer"), CustomerCreateParams - ), - ), - cast_to=httpx.Response, - options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, - ) - + await async_client.customers.with_streaming_response.create( + email="dev@stainless.com", name="x" + ).__aenter__() assert _get_open_connections(self.client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @@ -1779,6 +1769,28 @@ async def test_main() -> None: time.sleep(0.1) + async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: + # Test that the proxy environment variables are set correctly + monkeypatch.setenv("HTTPS_PROXY", "https://example.org") + + client = DefaultAsyncHttpxClient() + + mounts = tuple(client._mounts.items()) + assert len(mounts) == 1 + assert mounts[0][0].pattern == "https://" + + @pytest.mark.filterwarnings("ignore:.*deprecated.*:DeprecationWarning") + async def test_default_client_creation(self) -> None: + # Ensure that the client can be initialized without any exceptions + DefaultAsyncHttpxClient( + verify=True, + cert=None, + trust_env=True, + http1=True, + http2=False, + limits=httpx.Limits(max_connections=100, max_keepalive_connections=20), + ) + @pytest.mark.respx(base_url=base_url) async def test_follow_redirects(self, respx_mock: MockRouter) -> None: # Test that the default follow_redirects=True allows following redirects