diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index e4cc178..e8175f5 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "7.11.0"
+ ".": "7.11.1"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 035a6ed..37cb440 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 103
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-d891c800ffe6b7eddce179c225367cedcb49dab758ebc03e352d945240918d96.yml
-openapi_spec_hash: 852d55192b8d7ad96c1f85cd9070ef64
-config_hash: a730d0e598dc108e89c016802008c9b3
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-f0ac5c2fa86eabda773c549f5809d3e2d109e3e1d5a07f6fe1ace18355e4680a.yml
+openapi_spec_hash: b25dc0b42dd9386ab4a025bb2143bde6
+config_hash: 6037e4a9909efb8b2edac2dcc907b84f
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1e306dc..12e7bb5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+## 7.11.1 (2026-04-13)
+
+Full Changelog: [v7.11.0...v7.11.1](https://github.com/trycourier/courier-python/compare/v7.11.0...v7.11.1)
+
+### Bug Fixes
+
+* **api:** correct providers update method, notifications/routing_strategies return types ([069bf70](https://github.com/trycourier/courier-python/commit/069bf70791042c6ac0233022a8066cf1724a173c))
+* ensure file data are only sent as 1 parameter ([ca4b529](https://github.com/trycourier/courier-python/commit/ca4b529bf902fa70de9776bd66154d9bb5783b2b))
+
## 7.11.0 (2026-04-08)
Full Changelog: [v7.10.0...v7.11.0](https://github.com/trycourier/courier-python/compare/v7.10.0...v7.11.0)
diff --git a/api.md b/api.md
index c1d4cde..80d82a8 100644
--- a/api.md
+++ b/api.md
@@ -127,7 +127,7 @@ Methods:
- client.providers.create(\*\*params) -> Provider
- client.providers.retrieve(id) -> Provider
-- client.providers.update(id, \*\*params) -> Provider
+- client.providers.update(id, \*\*params) -> Provider
- client.providers.list(\*\*params) -> ProviderListResponse
- client.providers.delete(id) -> None
@@ -352,7 +352,6 @@ from courier.types import (
NotificationLocalePutRequest,
NotificationTemplateCreateRequest,
NotificationTemplateGetResponse,
- NotificationTemplateMutationResponse,
NotificationTemplatePayload,
NotificationTemplatePublishRequest,
NotificationTemplateState,
@@ -367,7 +366,7 @@ from courier.types import (
Methods:
-- client.notifications.create(\*\*params) -> NotificationTemplateMutationResponse
+- client.notifications.create(\*\*params) -> NotificationTemplateGetResponse
- client.notifications.retrieve(id, \*\*params) -> NotificationTemplateGetResponse
- client.notifications.list(\*\*params) -> NotificationListResponse
- client.notifications.archive(id) -> None
@@ -376,7 +375,7 @@ Methods:
- client.notifications.put_content(id, \*\*params) -> NotificationContentMutationResponse
- client.notifications.put_element(element_id, \*, id, \*\*params) -> NotificationContentMutationResponse
- client.notifications.put_locale(locale_id, \*, id, \*\*params) -> NotificationContentMutationResponse
-- client.notifications.replace(id, \*\*params) -> NotificationTemplateMutationResponse
+- client.notifications.replace(id, \*\*params) -> NotificationTemplateGetResponse
- client.notifications.retrieve_content(id, \*\*params) -> NotificationRetrieveContentResponse
## Checks
@@ -403,7 +402,6 @@ from courier.types import (
RoutingStrategyCreateRequest,
RoutingStrategyGetResponse,
RoutingStrategyListResponse,
- RoutingStrategyMutationResponse,
RoutingStrategyReplaceRequest,
RoutingStrategySummary,
)
@@ -411,12 +409,12 @@ from courier.types import (
Methods:
-- client.routing_strategies.create(\*\*params) -> RoutingStrategyMutationResponse
+- client.routing_strategies.create(\*\*params) -> RoutingStrategyGetResponse
- client.routing_strategies.retrieve(id) -> RoutingStrategyGetResponse
- client.routing_strategies.list(\*\*params) -> RoutingStrategyListResponse
- client.routing_strategies.archive(id) -> None
- client.routing_strategies.list_notifications(id, \*\*params) -> AssociatedNotificationListResponse
-- client.routing_strategies.replace(id, \*\*params) -> RoutingStrategyMutationResponse
+- client.routing_strategies.replace(id, \*\*params) -> RoutingStrategyGetResponse
# Profiles
diff --git a/pyproject.toml b/pyproject.toml
index e5428f9..f23035e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "trycourier"
-version = "7.11.0"
+version = "7.11.1"
description = "The official Python library for the Courier API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/courier/_utils/_utils.py b/src/courier/_utils/_utils.py
index eec7f4a..63b8cd6 100644
--- a/src/courier/_utils/_utils.py
+++ b/src/courier/_utils/_utils.py
@@ -86,8 +86,9 @@ def _extract_items(
index += 1
if is_dict(obj):
try:
- # We are at the last entry in the path so we must remove the field
- if (len(path)) == index:
+ # Remove the field if there are no more dict keys in the path,
+ # only "" traversal markers or end.
+ if all(p == "" for p in path[index:]):
item = obj.pop(key)
else:
item = obj[key]
diff --git a/src/courier/_version.py b/src/courier/_version.py
index 7f12b90..a93f7c7 100644
--- a/src/courier/_version.py
+++ b/src/courier/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "courier"
-__version__ = "7.11.0" # x-release-please-version
+__version__ = "7.11.1" # x-release-please-version
diff --git a/src/courier/resources/notifications/notifications.py b/src/courier/resources/notifications/notifications.py
index 37a1f1b..93ac470 100644
--- a/src/courier/resources/notifications/notifications.py
+++ b/src/courier/resources/notifications/notifications.py
@@ -45,7 +45,6 @@
from ...types.notification_template_payload_param import NotificationTemplatePayloadParam
from ...types.notification_content_mutation_response import NotificationContentMutationResponse
from ...types.notification_retrieve_content_response import NotificationRetrieveContentResponse
-from ...types.notification_template_mutation_response import NotificationTemplateMutationResponse
from ...types.notification_template_version_list_response import NotificationTemplateVersionListResponse
__all__ = ["NotificationsResource", "AsyncNotificationsResource"]
@@ -86,7 +85,7 @@ def create(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> NotificationTemplateMutationResponse:
+ ) -> NotificationTemplateGetResponse:
"""Create a notification template.
Requires all fields in the notification object.
@@ -119,7 +118,7 @@ def create(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NotificationTemplateMutationResponse,
+ cast_to=NotificationTemplateGetResponse,
)
def retrieve(
@@ -512,7 +511,7 @@ def replace(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> NotificationTemplateMutationResponse:
+ ) -> NotificationTemplateGetResponse:
"""Replace a notification template.
All fields are required.
@@ -546,7 +545,7 @@ def replace(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NotificationTemplateMutationResponse,
+ cast_to=NotificationTemplateGetResponse,
)
def retrieve_content(
@@ -637,7 +636,7 @@ async def create(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> NotificationTemplateMutationResponse:
+ ) -> NotificationTemplateGetResponse:
"""Create a notification template.
Requires all fields in the notification object.
@@ -670,7 +669,7 @@ async def create(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NotificationTemplateMutationResponse,
+ cast_to=NotificationTemplateGetResponse,
)
async def retrieve(
@@ -1067,7 +1066,7 @@ async def replace(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> NotificationTemplateMutationResponse:
+ ) -> NotificationTemplateGetResponse:
"""Replace a notification template.
All fields are required.
@@ -1101,7 +1100,7 @@ async def replace(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NotificationTemplateMutationResponse,
+ cast_to=NotificationTemplateGetResponse,
)
async def retrieve_content(
diff --git a/src/courier/resources/providers/providers.py b/src/courier/resources/providers/providers.py
index bdd369d..57bc9da 100644
--- a/src/courier/resources/providers/providers.py
+++ b/src/courier/resources/providers/providers.py
@@ -160,14 +160,17 @@ def update(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> Provider:
- """Update an existing provider configuration.
+ """Replace an existing provider configuration.
- The `provider` key is required. All
- other fields are optional — omitted fields are cleared from the stored
- configuration (this is a full replacement, not a partial merge).
+ The `provider` key is required and
+ determines which provider-specific settings schema is applied. All other fields
+ are optional — omitted fields are cleared from the stored configuration (this is
+ a full replacement, not a partial merge). Changing the provider type for an
+ existing configuration is not supported.
Args:
- provider: The provider key identifying the type.
+ provider: The provider key identifying the type. Required on every request because it
+ selects the provider-specific settings schema for validation.
alias: Updated alias. Omit to clear.
@@ -187,7 +190,7 @@ def update(
"""
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
- return self._post(
+ return self._put(
path_template("/providers/{id}", id=id),
body=maybe_transform(
{
@@ -408,14 +411,17 @@ async def update(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> Provider:
- """Update an existing provider configuration.
+ """Replace an existing provider configuration.
- The `provider` key is required. All
- other fields are optional — omitted fields are cleared from the stored
- configuration (this is a full replacement, not a partial merge).
+ The `provider` key is required and
+ determines which provider-specific settings schema is applied. All other fields
+ are optional — omitted fields are cleared from the stored configuration (this is
+ a full replacement, not a partial merge). Changing the provider type for an
+ existing configuration is not supported.
Args:
- provider: The provider key identifying the type.
+ provider: The provider key identifying the type. Required on every request because it
+ selects the provider-specific settings schema for validation.
alias: Updated alias. Omit to clear.
@@ -435,7 +441,7 @@ async def update(
"""
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
- return await self._post(
+ return await self._put(
path_template("/providers/{id}", id=id),
body=await async_maybe_transform(
{
diff --git a/src/courier/resources/routing_strategies.py b/src/courier/resources/routing_strategies.py
index fbbbd1c..9991097 100644
--- a/src/courier/resources/routing_strategies.py
+++ b/src/courier/resources/routing_strategies.py
@@ -28,7 +28,6 @@
from ..types.routing_strategy_list_response import RoutingStrategyListResponse
from ..types.shared_params.message_channels import MessageChannels
from ..types.shared_params.message_providers import MessageProviders
-from ..types.routing_strategy_mutation_response import RoutingStrategyMutationResponse
from ..types.associated_notification_list_response import AssociatedNotificationListResponse
__all__ = ["RoutingStrategiesResource", "AsyncRoutingStrategiesResource"]
@@ -69,7 +68,7 @@ def create(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> RoutingStrategyMutationResponse:
+ ) -> RoutingStrategyGetResponse:
"""Create a routing strategy.
Requires a name and routing configuration at minimum.
@@ -112,7 +111,7 @@ def create(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=RoutingStrategyMutationResponse,
+ cast_to=RoutingStrategyGetResponse,
)
def retrieve(
@@ -302,7 +301,7 @@ def replace(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> RoutingStrategyMutationResponse:
+ ) -> RoutingStrategyGetResponse:
"""Replace a routing strategy.
Full document replacement; the caller must send the
@@ -347,7 +346,7 @@ def replace(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=RoutingStrategyMutationResponse,
+ cast_to=RoutingStrategyGetResponse,
)
@@ -386,7 +385,7 @@ async def create(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> RoutingStrategyMutationResponse:
+ ) -> RoutingStrategyGetResponse:
"""Create a routing strategy.
Requires a name and routing configuration at minimum.
@@ -429,7 +428,7 @@ async def create(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=RoutingStrategyMutationResponse,
+ cast_to=RoutingStrategyGetResponse,
)
async def retrieve(
@@ -619,7 +618,7 @@ async def replace(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> RoutingStrategyMutationResponse:
+ ) -> RoutingStrategyGetResponse:
"""Replace a routing strategy.
Full document replacement; the caller must send the
@@ -664,7 +663,7 @@ async def replace(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=RoutingStrategyMutationResponse,
+ cast_to=RoutingStrategyGetResponse,
)
diff --git a/src/courier/types/__init__.py b/src/courier/types/__init__.py
index 67a0911..92eaece 100644
--- a/src/courier/types/__init__.py
+++ b/src/courier/types/__init__.py
@@ -227,7 +227,6 @@
from .notification_list_versions_params import NotificationListVersionsParams as NotificationListVersionsParams
from .put_subscriptions_recipient_param import PutSubscriptionsRecipientParam as PutSubscriptionsRecipientParam
from .notification_template_get_response import NotificationTemplateGetResponse as NotificationTemplateGetResponse
-from .routing_strategy_mutation_response import RoutingStrategyMutationResponse as RoutingStrategyMutationResponse
from .notification_template_payload_param import NotificationTemplatePayloadParam as NotificationTemplatePayloadParam
from .notification_retrieve_content_params import NotificationRetrieveContentParams as NotificationRetrieveContentParams
from .associated_notification_list_response import (
@@ -243,9 +242,6 @@
from .notification_retrieve_content_response import (
NotificationRetrieveContentResponse as NotificationRetrieveContentResponse,
)
-from .notification_template_mutation_response import (
- NotificationTemplateMutationResponse as NotificationTemplateMutationResponse,
-)
from .routing_strategy_list_notifications_params import (
RoutingStrategyListNotificationsParams as RoutingStrategyListNotificationsParams,
)
diff --git a/src/courier/types/notification_template_mutation_response.py b/src/courier/types/notification_template_mutation_response.py
deleted file mode 100644
index d67e495..0000000
--- a/src/courier/types/notification_template_mutation_response.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import Literal
-
-from .._models import BaseModel
-
-__all__ = ["NotificationTemplateMutationResponse", "Notification"]
-
-
-class Notification(BaseModel):
- id: str
- """The ID of the created or updated template."""
-
-
-class NotificationTemplateMutationResponse(BaseModel):
- """Response returned by POST and PUT operations."""
-
- notification: Notification
-
- state: Literal["DRAFT", "PUBLISHED"]
- """The template state after the operation. Always uppercase."""
diff --git a/src/courier/types/provider_update_params.py b/src/courier/types/provider_update_params.py
index 4516ef1..20699f9 100644
--- a/src/courier/types/provider_update_params.py
+++ b/src/courier/types/provider_update_params.py
@@ -10,7 +10,11 @@
class ProviderUpdateParams(TypedDict, total=False):
provider: Required[str]
- """The provider key identifying the type."""
+ """The provider key identifying the type.
+
+ Required on every request because it selects the provider-specific settings
+ schema for validation.
+ """
alias: str
"""Updated alias. Omit to clear."""
diff --git a/src/courier/types/routing_strategy_mutation_response.py b/src/courier/types/routing_strategy_mutation_response.py
deleted file mode 100644
index 849d7e3..0000000
--- a/src/courier/types/routing_strategy_mutation_response.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .._models import BaseModel
-
-__all__ = ["RoutingStrategyMutationResponse"]
-
-
-class RoutingStrategyMutationResponse(BaseModel):
- """Response returned by create and replace operations."""
-
- id: str
- """The routing strategy ID (rs\\__ prefix)."""
diff --git a/tests/api_resources/test_notifications.py b/tests/api_resources/test_notifications.py
index 68c98ac..145a34b 100644
--- a/tests/api_resources/test_notifications.py
+++ b/tests/api_resources/test_notifications.py
@@ -14,7 +14,6 @@
NotificationTemplateGetResponse,
NotificationContentMutationResponse,
NotificationRetrieveContentResponse,
- NotificationTemplateMutationResponse,
NotificationTemplateVersionListResponse,
)
@@ -40,7 +39,7 @@ def test_method_create(self, client: Courier) -> None:
"tags": ["onboarding", "welcome"],
},
)
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -59,7 +58,7 @@ def test_method_create_with_all_params(self, client: Courier) -> None:
},
state="DRAFT",
)
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -81,7 +80,7 @@ def test_raw_response_create(self, client: Courier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = response.parse()
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -103,7 +102,7 @@ def test_streaming_response_create(self, client: Courier) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = response.parse()
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -558,7 +557,7 @@ def test_method_replace(self, client: Courier) -> None:
"tags": ["updated"],
},
)
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -578,7 +577,7 @@ def test_method_replace_with_all_params(self, client: Courier) -> None:
},
state="PUBLISHED",
)
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -601,7 +600,7 @@ def test_raw_response_replace(self, client: Courier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = response.parse()
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -624,7 +623,7 @@ def test_streaming_response_replace(self, client: Courier) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = response.parse()
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -720,7 +719,7 @@ async def test_method_create(self, async_client: AsyncCourier) -> None:
"tags": ["onboarding", "welcome"],
},
)
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -739,7 +738,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncCourier) -
},
state="DRAFT",
)
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -761,7 +760,7 @@ async def test_raw_response_create(self, async_client: AsyncCourier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = await response.parse()
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -783,7 +782,7 @@ async def test_streaming_response_create(self, async_client: AsyncCourier) -> No
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = await response.parse()
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -1238,7 +1237,7 @@ async def test_method_replace(self, async_client: AsyncCourier) -> None:
"tags": ["updated"],
},
)
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -1258,7 +1257,7 @@ async def test_method_replace_with_all_params(self, async_client: AsyncCourier)
},
state="PUBLISHED",
)
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -1281,7 +1280,7 @@ async def test_raw_response_replace(self, async_client: AsyncCourier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = await response.parse()
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -1304,7 +1303,7 @@ async def test_streaming_response_replace(self, async_client: AsyncCourier) -> N
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = await response.parse()
- assert_matches_type(NotificationTemplateMutationResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_routing_strategies.py b/tests/api_resources/test_routing_strategies.py
index 7f334a5..8d314b6 100644
--- a/tests/api_resources/test_routing_strategies.py
+++ b/tests/api_resources/test_routing_strategies.py
@@ -12,7 +12,6 @@
from courier.types import (
RoutingStrategyGetResponse,
RoutingStrategyListResponse,
- RoutingStrategyMutationResponse,
AssociatedNotificationListResponse,
)
@@ -32,7 +31,7 @@ def test_method_create(self, client: Courier) -> None:
"method": "single",
},
)
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -84,7 +83,7 @@ def test_method_create_with_all_params(self, client: Courier) -> None:
},
tags=["production", "email"],
)
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -100,7 +99,7 @@ def test_raw_response_create(self, client: Courier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
routing_strategy = response.parse()
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -116,7 +115,7 @@ def test_streaming_response_create(self, client: Courier) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
routing_strategy = response.parse()
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -304,7 +303,7 @@ def test_method_replace(self, client: Courier) -> None:
"method": "single",
},
)
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -357,7 +356,7 @@ def test_method_replace_with_all_params(self, client: Courier) -> None:
},
tags=["production", "email", "v2"],
)
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -374,7 +373,7 @@ def test_raw_response_replace(self, client: Courier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
routing_strategy = response.parse()
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -391,7 +390,7 @@ def test_streaming_response_replace(self, client: Courier) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
routing_strategy = response.parse()
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -424,7 +423,7 @@ async def test_method_create(self, async_client: AsyncCourier) -> None:
"method": "single",
},
)
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -476,7 +475,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncCourier) -
},
tags=["production", "email"],
)
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -492,7 +491,7 @@ async def test_raw_response_create(self, async_client: AsyncCourier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
routing_strategy = await response.parse()
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -508,7 +507,7 @@ async def test_streaming_response_create(self, async_client: AsyncCourier) -> No
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
routing_strategy = await response.parse()
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -696,7 +695,7 @@ async def test_method_replace(self, async_client: AsyncCourier) -> None:
"method": "single",
},
)
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -749,7 +748,7 @@ async def test_method_replace_with_all_params(self, async_client: AsyncCourier)
},
tags=["production", "email", "v2"],
)
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -766,7 +765,7 @@ async def test_raw_response_replace(self, async_client: AsyncCourier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
routing_strategy = await response.parse()
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -783,7 +782,7 @@ async def test_streaming_response_replace(self, async_client: AsyncCourier) -> N
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
routing_strategy = await response.parse()
- assert_matches_type(RoutingStrategyMutationResponse, routing_strategy, path=["response"])
+ assert_matches_type(RoutingStrategyGetResponse, routing_strategy, path=["response"])
assert cast(Any, response.is_closed) is True
diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py
index 02fd18b..b1010d7 100644
--- a/tests/test_extract_files.py
+++ b/tests/test_extract_files.py
@@ -35,6 +35,15 @@ def test_multiple_files() -> None:
assert query == {"documents": [{}, {}]}
+def test_top_level_file_array() -> None:
+ query = {"files": [b"file one", b"file two"], "title": "hello"}
+ assert extract_files(query, paths=[["files", ""]]) == [
+ ("files[]", b"file one"),
+ ("files[]", b"file two"),
+ ]
+ assert query == {"title": "hello"}
+
+
@pytest.mark.parametrize(
"query,paths,expected",
[