From 797719ac713c52ac1abae12df3b3667ee3d536aa Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 1 May 2025 16:23:30 +0000
Subject: [PATCH 1/9] chore(internal): version bump
---
.release-please-manifest.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 37fcefaa..fea34540 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
".": "1.0.0"
-}
+}
\ No newline at end of file
From 07aa7ef945058ad65a8b7586c74dabf156c69cfb Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 2 May 2025 20:23:39 +0000
Subject: [PATCH 2/9] feat(api): api update
---
.stats.yml | 4 ++--
src/knockapi/resources/objects/objects.py | 16 +++++++--------
src/knockapi/resources/users/users.py | 20 +++++++++----------
.../types/audience_add_members_params.py | 1 +
.../types/audience_remove_members_params.py | 1 +
.../inline_identify_user_request_param.py | 15 ++++++++++++++
src/knockapi/types/object_set_params.py | 8 ++++----
src/knockapi/types/user.py | 10 +++++-----
src/knockapi/types/user_update_params.py | 10 +++++-----
9 files changed, 51 insertions(+), 34 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 6a1766d5..46b7dfc9 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 89
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/knock%2Fknock-641970ffdc1043cad290c3384d3d9c55b50cb709016a7513c03b2b84cf24fb31.yml
-openapi_spec_hash: e10e8093bf0dbde38523b98bec436123
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/knock%2Fknock-5176d1bb3a88b127808b197c9ae1cf366fd56599fd8c7b7241ac829e72d69a42.yml
+openapi_spec_hash: 92953a04021af2d0132fd9eebeb844b9
config_hash: 7460c5bd6d1a7041faa274f677789407
diff --git a/src/knockapi/resources/objects/objects.py b/src/knockapi/resources/objects/objects.py
index 8469041f..7cd99792 100644
--- a/src/knockapi/resources/objects/objects.py
+++ b/src/knockapi/resources/objects/objects.py
@@ -708,10 +708,10 @@ def set(
preferences: Inline set preferences for a recipient, where the key is the preference set id.
- timezone: The timezone of the object. Must be a valid
- [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
- Used for
- [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
+ timezone: The timezone of the object. Must be a
+ valid [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
+ Used
+ for [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
extra_headers: Send extra headers
@@ -1544,10 +1544,10 @@ async def set(
preferences: Inline set preferences for a recipient, where the key is the preference set id.
- timezone: The timezone of the object. Must be a valid
- [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
- Used for
- [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
+ timezone: The timezone of the object. Must be a
+ valid [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
+ Used
+ for [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
extra_headers: Send extra headers
diff --git a/src/knockapi/resources/users/users.py b/src/knockapi/resources/users/users.py
index 22d2d2fa..8fee6e79 100644
--- a/src/knockapi/resources/users/users.py
+++ b/src/knockapi/resources/users/users.py
@@ -140,15 +140,15 @@ def update(
name: Display name of the user.
- phone_number: The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the
+ phone_number: The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the
user (required for SMS channels).
preferences: Inline set preferences for a recipient, where the key is the preference set id.
- timezone: The timezone of the user. Must be a valid
- [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
- Used for
- [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
+ timezone: The timezone of the user. Must be a
+ valid [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
+ Used
+ for [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
extra_headers: Send extra headers
@@ -891,15 +891,15 @@ async def update(
name: Display name of the user.
- phone_number: The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the
+ phone_number: The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the
user (required for SMS channels).
preferences: Inline set preferences for a recipient, where the key is the preference set id.
- timezone: The timezone of the user. Must be a valid
- [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
- Used for
- [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
+ timezone: The timezone of the user. Must be a
+ valid [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
+ Used
+ for [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
extra_headers: Send extra headers
diff --git a/src/knockapi/types/audience_add_members_params.py b/src/knockapi/types/audience_add_members_params.py
index 4043ee6a..2baf6174 100644
--- a/src/knockapi/types/audience_add_members_params.py
+++ b/src/knockapi/types/audience_add_members_params.py
@@ -20,6 +20,7 @@ class MemberUser(TypedDict, total=False):
class Member(TypedDict, total=False):
user: Required[MemberUser]
+ """An object containing the user's ID."""
tenant: Optional[str]
"""The unique identifier for the tenant."""
diff --git a/src/knockapi/types/audience_remove_members_params.py b/src/knockapi/types/audience_remove_members_params.py
index f4ef4c3b..4b449606 100644
--- a/src/knockapi/types/audience_remove_members_params.py
+++ b/src/knockapi/types/audience_remove_members_params.py
@@ -20,6 +20,7 @@ class MemberUser(TypedDict, total=False):
class Member(TypedDict, total=False):
user: Required[MemberUser]
+ """An object containing the user's ID."""
tenant: Optional[str]
"""The unique identifier for the tenant."""
diff --git a/src/knockapi/types/inline_identify_user_request_param.py b/src/knockapi/types/inline_identify_user_request_param.py
index 9172195f..75ab532f 100644
--- a/src/knockapi/types/inline_identify_user_request_param.py
+++ b/src/knockapi/types/inline_identify_user_request_param.py
@@ -23,8 +23,23 @@ class InlineIdentifyUserRequestParamTyped(TypedDict, total=False):
created_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
"""The creation date of the user from your system."""
+ email: Optional[str]
+ """The primary email address for the user."""
+
+ name: Optional[str]
+ """Display name of the user."""
+
preferences: Optional[InlinePreferenceSetRequestParam]
"""Inline set preferences for a recipient, where the key is the preference set id."""
+ timezone: Optional[str]
+ """The timezone of the user.
+
+ Must be a
+ valid [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
+ Used
+ for [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
+ """
+
InlineIdentifyUserRequestParam: TypeAlias = Union[InlineIdentifyUserRequestParamTyped, Dict[str, object]]
diff --git a/src/knockapi/types/object_set_params.py b/src/knockapi/types/object_set_params.py
index 6cc33162..5d8b80cc 100644
--- a/src/knockapi/types/object_set_params.py
+++ b/src/knockapi/types/object_set_params.py
@@ -27,8 +27,8 @@ class ObjectSetParams(TypedDict, total=False):
timezone: Optional[str]
"""The timezone of the object.
- Must be a valid
- [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
- Used for
- [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
+ Must be a
+ valid [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
+ Used
+ for [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
"""
diff --git a/src/knockapi/types/user.py b/src/knockapi/types/user.py
index 704d057c..ee5b56b7 100644
--- a/src/knockapi/types/user.py
+++ b/src/knockapi/types/user.py
@@ -34,17 +34,17 @@ class User(BaseModel):
phone_number: Optional[str] = None
"""
- The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the
+ The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the
user (required for SMS channels).
"""
timezone: Optional[str] = None
"""The timezone of the user.
- Must be a valid
- [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
- Used for
- [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
+ Must be a
+ valid [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
+ Used
+ for [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
"""
if TYPE_CHECKING:
diff --git a/src/knockapi/types/user_update_params.py b/src/knockapi/types/user_update_params.py
index 96d6b2ed..3f4814c2 100644
--- a/src/knockapi/types/user_update_params.py
+++ b/src/knockapi/types/user_update_params.py
@@ -37,7 +37,7 @@ class UserUpdateParams(TypedDict, total=False):
phone_number: Optional[str]
"""
- The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the
+ The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the
user (required for SMS channels).
"""
@@ -47,8 +47,8 @@ class UserUpdateParams(TypedDict, total=False):
timezone: Optional[str]
"""The timezone of the user.
- Must be a valid
- [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
- Used for
- [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
+ Must be a
+ valid [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
+ Used
+ for [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
"""
From 49ba46929f05e16a4d134ce201d7a10bbfd09b4b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 9 May 2025 04:07:09 +0000
Subject: [PATCH 3/9] chore(internal): avoid errors for isinstance checks on
proxies
---
src/knockapi/_utils/_proxy.py | 5 ++++-
tests/test_utils/test_proxy.py | 11 +++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/knockapi/_utils/_proxy.py b/src/knockapi/_utils/_proxy.py
index ffd883e9..0f239a33 100644
--- a/src/knockapi/_utils/_proxy.py
+++ b/src/knockapi/_utils/_proxy.py
@@ -46,7 +46,10 @@ def __dir__(self) -> Iterable[str]:
@property # type: ignore
@override
def __class__(self) -> type: # pyright: ignore
- proxied = self.__get_proxied__()
+ try:
+ proxied = self.__get_proxied__()
+ except Exception:
+ return type(self)
if issubclass(type(proxied), LazyProxy):
return type(proxied)
return proxied.__class__
diff --git a/tests/test_utils/test_proxy.py b/tests/test_utils/test_proxy.py
index e57c32c5..82da93a8 100644
--- a/tests/test_utils/test_proxy.py
+++ b/tests/test_utils/test_proxy.py
@@ -21,3 +21,14 @@ def test_recursive_proxy() -> None:
assert dir(proxy) == []
assert type(proxy).__name__ == "RecursiveLazyProxy"
assert type(operator.attrgetter("name.foo.bar.baz")(proxy)).__name__ == "RecursiveLazyProxy"
+
+
+def test_isinstance_does_not_error() -> None:
+ class AlwaysErrorProxy(LazyProxy[Any]):
+ @override
+ def __load__(self) -> Any:
+ raise RuntimeError("Mocking missing dependency")
+
+ proxy = AlwaysErrorProxy()
+ assert not isinstance(proxy, dict)
+ assert isinstance(proxy, LazyProxy)
From 03d835a305fe7024814c863ed902481ec509b439 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 10 May 2025 03:31:18 +0000
Subject: [PATCH 4/9] fix(package): support direct resource imports
---
src/knockapi/__init__.py | 5 +++++
src/knockapi/_utils/_resources_proxy.py | 24 ++++++++++++++++++++++++
2 files changed, 29 insertions(+)
create mode 100644 src/knockapi/_utils/_resources_proxy.py
diff --git a/src/knockapi/__init__.py b/src/knockapi/__init__.py
index f6ac71d7..e72f3cb4 100644
--- a/src/knockapi/__init__.py
+++ b/src/knockapi/__init__.py
@@ -1,5 +1,7 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+import typing as _t
+
from . import types
from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes
from ._utils import file_from_path
@@ -68,6 +70,9 @@
"DefaultAsyncHttpxClient",
]
+if not _t.TYPE_CHECKING:
+ from ._utils._resources_proxy import resources as resources
+
_setup_logging()
# Update the __module__ attribute for exported symbols so that
diff --git a/src/knockapi/_utils/_resources_proxy.py b/src/knockapi/_utils/_resources_proxy.py
new file mode 100644
index 00000000..f85f01c8
--- /dev/null
+++ b/src/knockapi/_utils/_resources_proxy.py
@@ -0,0 +1,24 @@
+from __future__ import annotations
+
+from typing import Any
+from typing_extensions import override
+
+from ._proxy import LazyProxy
+
+
+class ResourcesProxy(LazyProxy[Any]):
+ """A proxy for the `knockapi.resources` module.
+
+ This is used so that we can lazily import `knockapi.resources` only when
+ needed *and* so that users can just import `knockapi` and reference `knockapi.resources`
+ """
+
+ @override
+ def __load__(self) -> Any:
+ import importlib
+
+ mod = importlib.import_module("knockapi.resources")
+ return mod
+
+
+resources = ResourcesProxy().__as_proxied__()
From 5e79f8b6dc84a299099052a204f50c8522671d51 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 14 May 2025 21:40:42 +0000
Subject: [PATCH 5/9] feat(api): removes duplicate activities section
This section is extra since the endpoint is already included in the list of methods above
---
.stats.yml | 2 +-
api.md | 6 -
src/knockapi/resources/messages/__init__.py | 14 --
src/knockapi/resources/messages/activities.py | 216 ------------------
src/knockapi/resources/messages/messages.py | 32 ---
src/knockapi/types/messages/__init__.py | 1 -
.../types/messages/activity_list_params.py | 21 --
.../api_resources/messages/test_activities.py | 151 ------------
8 files changed, 1 insertion(+), 442 deletions(-)
delete mode 100644 src/knockapi/resources/messages/activities.py
delete mode 100644 src/knockapi/types/messages/activity_list_params.py
delete mode 100644 tests/api_resources/messages/test_activities.py
diff --git a/.stats.yml b/.stats.yml
index 46b7dfc9..2c15eaf0 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 89
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/knock%2Fknock-5176d1bb3a88b127808b197c9ae1cf366fd56599fd8c7b7241ac829e72d69a42.yml
openapi_spec_hash: 92953a04021af2d0132fd9eebeb844b9
-config_hash: 7460c5bd6d1a7041faa274f677789407
+config_hash: 2ae8965d371a03bd30c6a56819c04cf2
diff --git a/api.md b/api.md
index f7a45fb2..2a815109 100644
--- a/api.md
+++ b/api.md
@@ -260,12 +260,6 @@ Methods:
- client.messages.batch.mark_as_unseen(\*\*params) -> BatchMarkAsUnseenResponse
- client.messages.batch.unarchive(\*\*params) -> BatchUnarchiveResponse
-## Activities
-
-Methods:
-
-- client.messages.activities.list(message_id, \*\*params) -> SyncItemsCursor[Activity]
-
# Providers
## Slack
diff --git a/src/knockapi/resources/messages/__init__.py b/src/knockapi/resources/messages/__init__.py
index 74a67564..389b8cc1 100644
--- a/src/knockapi/resources/messages/__init__.py
+++ b/src/knockapi/resources/messages/__init__.py
@@ -16,14 +16,6 @@
MessagesResourceWithStreamingResponse,
AsyncMessagesResourceWithStreamingResponse,
)
-from .activities import (
- ActivitiesResource,
- AsyncActivitiesResource,
- ActivitiesResourceWithRawResponse,
- AsyncActivitiesResourceWithRawResponse,
- ActivitiesResourceWithStreamingResponse,
- AsyncActivitiesResourceWithStreamingResponse,
-)
__all__ = [
"BatchResource",
@@ -32,12 +24,6 @@
"AsyncBatchResourceWithRawResponse",
"BatchResourceWithStreamingResponse",
"AsyncBatchResourceWithStreamingResponse",
- "ActivitiesResource",
- "AsyncActivitiesResource",
- "ActivitiesResourceWithRawResponse",
- "AsyncActivitiesResourceWithRawResponse",
- "ActivitiesResourceWithStreamingResponse",
- "AsyncActivitiesResourceWithStreamingResponse",
"MessagesResource",
"AsyncMessagesResource",
"MessagesResourceWithRawResponse",
diff --git a/src/knockapi/resources/messages/activities.py b/src/knockapi/resources/messages/activities.py
deleted file mode 100644
index 36b83205..00000000
--- a/src/knockapi/resources/messages/activities.py
+++ /dev/null
@@ -1,216 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import httpx
-
-from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from ..._utils import maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ...pagination import SyncItemsCursor, AsyncItemsCursor
-from ..._base_client import AsyncPaginator, make_request_options
-from ...types.activity import Activity
-from ...types.messages import activity_list_params
-
-__all__ = ["ActivitiesResource", "AsyncActivitiesResource"]
-
-
-class ActivitiesResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ActivitiesResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/knocklabs/knock-python#accessing-raw-response-data-eg-headers
- """
- return ActivitiesResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ActivitiesResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/knocklabs/knock-python#with_streaming_response
- """
- return ActivitiesResourceWithStreamingResponse(self)
-
- def list(
- self,
- message_id: str,
- *,
- after: str | NotGiven = NOT_GIVEN,
- before: str | NotGiven = NOT_GIVEN,
- page_size: int | NotGiven = NOT_GIVEN,
- trigger_data: str | NotGiven = NOT_GIVEN,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
- ) -> SyncItemsCursor[Activity]:
- """
- Returns a paginated list of activities for the specified message.
-
- Args:
- after: The cursor to fetch entries after.
-
- before: The cursor to fetch entries before.
-
- page_size: The number of items per page.
-
- trigger_data: The trigger data to filter activities by.
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not message_id:
- raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}")
- return self._get_api_list(
- f"/v1/messages/{message_id}/activities",
- page=SyncItemsCursor[Activity],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "after": after,
- "before": before,
- "page_size": page_size,
- "trigger_data": trigger_data,
- },
- activity_list_params.ActivityListParams,
- ),
- ),
- model=Activity,
- )
-
-
-class AsyncActivitiesResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncActivitiesResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/knocklabs/knock-python#accessing-raw-response-data-eg-headers
- """
- return AsyncActivitiesResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncActivitiesResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/knocklabs/knock-python#with_streaming_response
- """
- return AsyncActivitiesResourceWithStreamingResponse(self)
-
- def list(
- self,
- message_id: str,
- *,
- after: str | NotGiven = NOT_GIVEN,
- before: str | NotGiven = NOT_GIVEN,
- page_size: int | NotGiven = NOT_GIVEN,
- trigger_data: str | NotGiven = NOT_GIVEN,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
- ) -> AsyncPaginator[Activity, AsyncItemsCursor[Activity]]:
- """
- Returns a paginated list of activities for the specified message.
-
- Args:
- after: The cursor to fetch entries after.
-
- before: The cursor to fetch entries before.
-
- page_size: The number of items per page.
-
- trigger_data: The trigger data to filter activities by.
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not message_id:
- raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}")
- return self._get_api_list(
- f"/v1/messages/{message_id}/activities",
- page=AsyncItemsCursor[Activity],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "after": after,
- "before": before,
- "page_size": page_size,
- "trigger_data": trigger_data,
- },
- activity_list_params.ActivityListParams,
- ),
- ),
- model=Activity,
- )
-
-
-class ActivitiesResourceWithRawResponse:
- def __init__(self, activities: ActivitiesResource) -> None:
- self._activities = activities
-
- self.list = to_raw_response_wrapper(
- activities.list,
- )
-
-
-class AsyncActivitiesResourceWithRawResponse:
- def __init__(self, activities: AsyncActivitiesResource) -> None:
- self._activities = activities
-
- self.list = async_to_raw_response_wrapper(
- activities.list,
- )
-
-
-class ActivitiesResourceWithStreamingResponse:
- def __init__(self, activities: ActivitiesResource) -> None:
- self._activities = activities
-
- self.list = to_streamed_response_wrapper(
- activities.list,
- )
-
-
-class AsyncActivitiesResourceWithStreamingResponse:
- def __init__(self, activities: AsyncActivitiesResource) -> None:
- self._activities = activities
-
- self.list = async_to_streamed_response_wrapper(
- activities.list,
- )
diff --git a/src/knockapi/resources/messages/messages.py b/src/knockapi/resources/messages/messages.py
index 99f44e79..e3ec1e50 100644
--- a/src/knockapi/resources/messages/messages.py
+++ b/src/knockapi/resources/messages/messages.py
@@ -25,14 +25,6 @@
from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
from ..._utils import maybe_transform, async_maybe_transform
from ..._compat import cached_property
-from .activities import (
- ActivitiesResource,
- AsyncActivitiesResource,
- ActivitiesResourceWithRawResponse,
- AsyncActivitiesResourceWithRawResponse,
- ActivitiesResourceWithStreamingResponse,
- AsyncActivitiesResourceWithStreamingResponse,
-)
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
to_raw_response_wrapper,
@@ -56,10 +48,6 @@ class MessagesResource(SyncAPIResource):
def batch(self) -> BatchResource:
return BatchResource(self._client)
- @cached_property
- def activities(self) -> ActivitiesResource:
- return ActivitiesResource(self._client)
-
@cached_property
def with_raw_response(self) -> MessagesResourceWithRawResponse:
"""
@@ -674,10 +662,6 @@ class AsyncMessagesResource(AsyncAPIResource):
def batch(self) -> AsyncBatchResource:
return AsyncBatchResource(self._client)
- @cached_property
- def activities(self) -> AsyncActivitiesResource:
- return AsyncActivitiesResource(self._client)
-
@cached_property
def with_raw_response(self) -> AsyncMessagesResourceWithRawResponse:
"""
@@ -1335,10 +1319,6 @@ def __init__(self, messages: MessagesResource) -> None:
def batch(self) -> BatchResourceWithRawResponse:
return BatchResourceWithRawResponse(self._messages.batch)
- @cached_property
- def activities(self) -> ActivitiesResourceWithRawResponse:
- return ActivitiesResourceWithRawResponse(self._messages.activities)
-
class AsyncMessagesResourceWithRawResponse:
def __init__(self, messages: AsyncMessagesResource) -> None:
@@ -1388,10 +1368,6 @@ def __init__(self, messages: AsyncMessagesResource) -> None:
def batch(self) -> AsyncBatchResourceWithRawResponse:
return AsyncBatchResourceWithRawResponse(self._messages.batch)
- @cached_property
- def activities(self) -> AsyncActivitiesResourceWithRawResponse:
- return AsyncActivitiesResourceWithRawResponse(self._messages.activities)
-
class MessagesResourceWithStreamingResponse:
def __init__(self, messages: MessagesResource) -> None:
@@ -1441,10 +1417,6 @@ def __init__(self, messages: MessagesResource) -> None:
def batch(self) -> BatchResourceWithStreamingResponse:
return BatchResourceWithStreamingResponse(self._messages.batch)
- @cached_property
- def activities(self) -> ActivitiesResourceWithStreamingResponse:
- return ActivitiesResourceWithStreamingResponse(self._messages.activities)
-
class AsyncMessagesResourceWithStreamingResponse:
def __init__(self, messages: AsyncMessagesResource) -> None:
@@ -1493,7 +1465,3 @@ def __init__(self, messages: AsyncMessagesResource) -> None:
@cached_property
def batch(self) -> AsyncBatchResourceWithStreamingResponse:
return AsyncBatchResourceWithStreamingResponse(self._messages.batch)
-
- @cached_property
- def activities(self) -> AsyncActivitiesResourceWithStreamingResponse:
- return AsyncActivitiesResourceWithStreamingResponse(self._messages.activities)
diff --git a/src/knockapi/types/messages/__init__.py b/src/knockapi/types/messages/__init__.py
index 77bdb73c..8e38f600 100644
--- a/src/knockapi/types/messages/__init__.py
+++ b/src/knockapi/types/messages/__init__.py
@@ -2,7 +2,6 @@
from __future__ import annotations
-from .activity_list_params import ActivityListParams as ActivityListParams
from .batch_archive_params import BatchArchiveParams as BatchArchiveParams
from .batch_archive_response import BatchArchiveResponse as BatchArchiveResponse
from .batch_unarchive_params import BatchUnarchiveParams as BatchUnarchiveParams
diff --git a/src/knockapi/types/messages/activity_list_params.py b/src/knockapi/types/messages/activity_list_params.py
deleted file mode 100644
index c5cc589a..00000000
--- a/src/knockapi/types/messages/activity_list_params.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import TypedDict
-
-__all__ = ["ActivityListParams"]
-
-
-class ActivityListParams(TypedDict, total=False):
- after: str
- """The cursor to fetch entries after."""
-
- before: str
- """The cursor to fetch entries before."""
-
- page_size: int
- """The number of items per page."""
-
- trigger_data: str
- """The trigger data to filter activities by."""
diff --git a/tests/api_resources/messages/test_activities.py b/tests/api_resources/messages/test_activities.py
deleted file mode 100644
index 48f22907..00000000
--- a/tests/api_resources/messages/test_activities.py
+++ /dev/null
@@ -1,151 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from knockapi import Knock, AsyncKnock
-from tests.utils import assert_matches_type
-from knockapi.types import Activity
-from knockapi.pagination import SyncItemsCursor, AsyncItemsCursor
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestActivities:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(
- reason="currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url"
- )
- @parametrize
- def test_method_list(self, client: Knock) -> None:
- activity = client.messages.activities.list(
- message_id="message_id",
- )
- assert_matches_type(SyncItemsCursor[Activity], activity, path=["response"])
-
- @pytest.mark.skip(
- reason="currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url"
- )
- @parametrize
- def test_method_list_with_all_params(self, client: Knock) -> None:
- activity = client.messages.activities.list(
- message_id="message_id",
- after="after",
- before="before",
- page_size=0,
- trigger_data="trigger_data",
- )
- assert_matches_type(SyncItemsCursor[Activity], activity, path=["response"])
-
- @pytest.mark.skip(
- reason="currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url"
- )
- @parametrize
- def test_raw_response_list(self, client: Knock) -> None:
- response = client.messages.activities.with_raw_response.list(
- message_id="message_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- activity = response.parse()
- assert_matches_type(SyncItemsCursor[Activity], activity, path=["response"])
-
- @pytest.mark.skip(
- reason="currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url"
- )
- @parametrize
- def test_streaming_response_list(self, client: Knock) -> None:
- with client.messages.activities.with_streaming_response.list(
- message_id="message_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- activity = response.parse()
- assert_matches_type(SyncItemsCursor[Activity], activity, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(
- reason="currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url"
- )
- @parametrize
- def test_path_params_list(self, client: Knock) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"):
- client.messages.activities.with_raw_response.list(
- message_id="",
- )
-
-
-class TestAsyncActivities:
- parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(
- reason="currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url"
- )
- @parametrize
- async def test_method_list(self, async_client: AsyncKnock) -> None:
- activity = await async_client.messages.activities.list(
- message_id="message_id",
- )
- assert_matches_type(AsyncItemsCursor[Activity], activity, path=["response"])
-
- @pytest.mark.skip(
- reason="currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url"
- )
- @parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncKnock) -> None:
- activity = await async_client.messages.activities.list(
- message_id="message_id",
- after="after",
- before="before",
- page_size=0,
- trigger_data="trigger_data",
- )
- assert_matches_type(AsyncItemsCursor[Activity], activity, path=["response"])
-
- @pytest.mark.skip(
- reason="currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url"
- )
- @parametrize
- async def test_raw_response_list(self, async_client: AsyncKnock) -> None:
- response = await async_client.messages.activities.with_raw_response.list(
- message_id="message_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- activity = await response.parse()
- assert_matches_type(AsyncItemsCursor[Activity], activity, path=["response"])
-
- @pytest.mark.skip(
- reason="currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url"
- )
- @parametrize
- async def test_streaming_response_list(self, async_client: AsyncKnock) -> None:
- async with async_client.messages.activities.with_streaming_response.list(
- message_id="message_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- activity = await response.parse()
- assert_matches_type(AsyncItemsCursor[Activity], activity, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(
- reason="currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url"
- )
- @parametrize
- async def test_path_params_list(self, async_client: AsyncKnock) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"):
- await async_client.messages.activities.with_raw_response.list(
- message_id="",
- )
From 6793aeb32db67c2f41dc3c721c64b25471031c13 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 15 May 2025 04:43:26 +0000
Subject: [PATCH 6/9] chore(ci): upload sdks to package manager
---
.github/workflows/ci.yml | 24 ++++++++++++++++++++++++
scripts/utils/upload-artifact.sh | 25 +++++++++++++++++++++++++
2 files changed, 49 insertions(+)
create mode 100755 scripts/utils/upload-artifact.sh
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 83d1a081..6e9bff9b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -30,6 +30,30 @@ jobs:
- name: Run lints
run: ./scripts/lint
+ upload:
+ if: github.repository == 'stainless-sdks/knock-python'
+ timeout-minutes: 10
+ name: upload
+ permissions:
+ contents: read
+ id-token: write
+ runs-on: depot-ubuntu-24.04
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Get GitHub OIDC Token
+ id: github-oidc
+ uses: actions/github-script@v6
+ with:
+ script: core.setOutput('github_token', await core.getIDToken());
+
+ - name: Upload tarball
+ env:
+ URL: https://pkg.stainless.com/s
+ AUTH: ${{ steps.github-oidc.outputs.github_token }}
+ SHA: ${{ github.sha }}
+ run: ./scripts/utils/upload-artifact.sh
+
test:
timeout-minutes: 10
name: test
diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh
new file mode 100755
index 00000000..c2229e23
--- /dev/null
+++ b/scripts/utils/upload-artifact.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+set -exuo pipefail
+
+RESPONSE=$(curl -X POST "$URL" \
+ -H "Authorization: Bearer $AUTH" \
+ -H "Content-Type: application/json")
+
+SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url')
+
+if [[ "$SIGNED_URL" == "null" ]]; then
+ echo -e "\033[31mFailed to get signed URL.\033[0m"
+ exit 1
+fi
+
+UPLOAD_RESPONSE=$(tar -cz . | curl -v -X PUT \
+ -H "Content-Type: application/gzip" \
+ --data-binary @- "$SIGNED_URL" 2>&1)
+
+if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then
+ echo -e "\033[32mUploaded build to Stainless storage.\033[0m"
+ echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/knock-python/$SHA'\033[0m"
+else
+ echo -e "\033[31mFailed to upload artifact.\033[0m"
+ exit 1
+fi
From e88471a8b9c90f68d9ff6438298754f8b63148cc Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 15 May 2025 22:18:26 +0000
Subject: [PATCH 7/9] feat(api): api update
---
.stats.yml | 4 +--
src/knockapi/resources/schedules/schedules.py | 6 ++---
.../inline_identify_user_request_param.py | 15 +++++++++++
src/knockapi/types/object.py | 9 +++----
src/knockapi/types/recipients/__init__.py | 1 -
.../recipients/channel_data_request_param.py | 27 -------------------
.../inline_channel_data_request_param.py | 20 +++++++++++---
src/knockapi/types/schedule_create_params.py | 6 +----
tests/api_resources/test_objects.py | 4 +--
tests/api_resources/test_tenants.py | 4 +--
tests/api_resources/test_users.py | 4 +--
11 files changed, 45 insertions(+), 55 deletions(-)
delete mode 100644 src/knockapi/types/recipients/channel_data_request_param.py
diff --git a/.stats.yml b/.stats.yml
index 2c15eaf0..9b155a84 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 89
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/knock%2Fknock-5176d1bb3a88b127808b197c9ae1cf366fd56599fd8c7b7241ac829e72d69a42.yml
-openapi_spec_hash: 92953a04021af2d0132fd9eebeb844b9
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/knock%2Fknock-923618cb1489556307ce0be07853170d15516da8fe450578fed856e560ec361c.yml
+openapi_spec_hash: 1406cf9ab287412197a1907f5d66d541
config_hash: 2ae8965d371a03bd30c6a56819c04cf2
diff --git a/src/knockapi/resources/schedules/schedules.py b/src/knockapi/resources/schedules/schedules.py
index 816d1f1d..8e58b442 100644
--- a/src/knockapi/resources/schedules/schedules.py
+++ b/src/knockapi/resources/schedules/schedules.py
@@ -94,8 +94,7 @@ def create(
for the `actor`, `recipient`, and `tenant` fields.
Args:
- recipients: The recipients to trigger the workflow for. Can inline identify users, objects,
- or use a list of user IDs. Limited to 1,000 recipients.
+ recipients: The recipients to set the schedule for. Limited to 100 recipients per request.
repeats: The repeat rule for the schedule.
@@ -354,8 +353,7 @@ async def create(
for the `actor`, `recipient`, and `tenant` fields.
Args:
- recipients: The recipients to trigger the workflow for. Can inline identify users, objects,
- or use a list of user IDs. Limited to 1,000 recipients.
+ recipients: The recipients to set the schedule for. Limited to 100 recipients per request.
repeats: The repeat rule for the schedule.
diff --git a/src/knockapi/types/inline_identify_user_request_param.py b/src/knockapi/types/inline_identify_user_request_param.py
index 75ab532f..c47254f2 100644
--- a/src/knockapi/types/inline_identify_user_request_param.py
+++ b/src/knockapi/types/inline_identify_user_request_param.py
@@ -17,6 +17,9 @@ class InlineIdentifyUserRequestParamTyped(TypedDict, total=False):
id: Required[str]
"""The ID for the user that you set when identifying them in Knock."""
+ avatar: Optional[str]
+ """URL to the user's avatar image."""
+
channel_data: Optional[InlineChannelDataRequestParam]
"""A request to set channel data for a type of channel inline."""
@@ -26,9 +29,21 @@ class InlineIdentifyUserRequestParamTyped(TypedDict, total=False):
email: Optional[str]
"""The primary email address for the user."""
+ locale: Optional[str]
+ """The locale of the user.
+
+ Used for [message localization](/concepts/translations).
+ """
+
name: Optional[str]
"""Display name of the user."""
+ phone_number: Optional[str]
+ """
+ The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the
+ user (required for SMS channels).
+ """
+
preferences: Optional[InlinePreferenceSetRequestParam]
"""Inline set preferences for a recipient, where the key is the preference set id."""
diff --git a/src/knockapi/types/object.py b/src/knockapi/types/object.py
index bcb94643..3d2ed638 100644
--- a/src/knockapi/types/object.py
+++ b/src/knockapi/types/object.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import TYPE_CHECKING, Optional
+from typing import Dict, Optional
from datetime import datetime
from pydantic import Field as FieldInfo
@@ -26,8 +26,5 @@ class Object(BaseModel):
created_at: Optional[datetime] = None
"""Timestamp when the resource was created."""
- if TYPE_CHECKING:
- # Stub to indicate that arbitrary properties are accepted.
- # To access properties that are not valid identifiers you can use `getattr`, e.g.
- # `getattr(obj, '$type')`
- def __getattr__(self, attr: str) -> object: ...
+ properties: Optional[Dict[str, object]] = None
+ """The custom properties associated with the object."""
diff --git a/src/knockapi/types/recipients/__init__.py b/src/knockapi/types/recipients/__init__.py
index e1c0177c..49d62a96 100644
--- a/src/knockapi/types/recipients/__init__.py
+++ b/src/knockapi/types/recipients/__init__.py
@@ -12,7 +12,6 @@
from .one_signal_channel_data import OneSignalChannelData as OneSignalChannelData
from .push_channel_data_param import PushChannelDataParam as PushChannelDataParam
from .slack_channel_data_param import SlackChannelDataParam as SlackChannelDataParam
-from .channel_data_request_param import ChannelDataRequestParam as ChannelDataRequestParam
from .discord_channel_data_param import DiscordChannelDataParam as DiscordChannelDataParam
from .ms_teams_channel_data_param import MsTeamsChannelDataParam as MsTeamsChannelDataParam
from .preference_set_channel_types import PreferenceSetChannelTypes as PreferenceSetChannelTypes
diff --git a/src/knockapi/types/recipients/channel_data_request_param.py b/src/knockapi/types/recipients/channel_data_request_param.py
deleted file mode 100644
index e9af5159..00000000
--- a/src/knockapi/types/recipients/channel_data_request_param.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Union
-from typing_extensions import Required, TypeAlias, TypedDict
-
-from .push_channel_data_param import PushChannelDataParam
-from .slack_channel_data_param import SlackChannelDataParam
-from .discord_channel_data_param import DiscordChannelDataParam
-from .ms_teams_channel_data_param import MsTeamsChannelDataParam
-from .one_signal_channel_data_param import OneSignalChannelDataParam
-
-__all__ = ["ChannelDataRequestParam", "Data"]
-
-Data: TypeAlias = Union[
- PushChannelDataParam,
- OneSignalChannelDataParam,
- SlackChannelDataParam,
- MsTeamsChannelDataParam,
- DiscordChannelDataParam,
-]
-
-
-class ChannelDataRequestParam(TypedDict, total=False):
- data: Required[Data]
- """Channel data for a given channel type."""
diff --git a/src/knockapi/types/recipients/inline_channel_data_request_param.py b/src/knockapi/types/recipients/inline_channel_data_request_param.py
index 33fcc462..df544367 100644
--- a/src/knockapi/types/recipients/inline_channel_data_request_param.py
+++ b/src/knockapi/types/recipients/inline_channel_data_request_param.py
@@ -2,11 +2,23 @@
from __future__ import annotations
-from typing import Dict
+from typing import Dict, Union
from typing_extensions import TypeAlias
-from .channel_data_request_param import ChannelDataRequestParam
+from .push_channel_data_param import PushChannelDataParam
+from .slack_channel_data_param import SlackChannelDataParam
+from .discord_channel_data_param import DiscordChannelDataParam
+from .ms_teams_channel_data_param import MsTeamsChannelDataParam
+from .one_signal_channel_data_param import OneSignalChannelDataParam
-__all__ = ["InlineChannelDataRequestParam"]
+__all__ = ["InlineChannelDataRequestParam", "InlineChannelDataRequestParamItem"]
-InlineChannelDataRequestParam: TypeAlias = Dict[str, ChannelDataRequestParam]
+InlineChannelDataRequestParamItem: TypeAlias = Union[
+ PushChannelDataParam,
+ OneSignalChannelDataParam,
+ SlackChannelDataParam,
+ MsTeamsChannelDataParam,
+ DiscordChannelDataParam,
+]
+
+InlineChannelDataRequestParam: TypeAlias = Dict[str, InlineChannelDataRequestParamItem]
diff --git a/src/knockapi/types/schedule_create_params.py b/src/knockapi/types/schedule_create_params.py
index cd9c9f43..491ee949 100644
--- a/src/knockapi/types/schedule_create_params.py
+++ b/src/knockapi/types/schedule_create_params.py
@@ -16,11 +16,7 @@
class ScheduleCreateParams(TypedDict, total=False):
recipients: Required[List[RecipientRequestParam]]
- """The recipients to trigger the workflow for.
-
- Can inline identify users, objects, or use a list of user IDs. Limited to 1,000
- recipients.
- """
+ """The recipients to set the schedule for. Limited to 100 recipients per request."""
repeats: Required[Iterable[ScheduleRepeatRuleParam]]
"""The repeat rule for the schedule."""
diff --git a/tests/api_resources/test_objects.py b/tests/api_resources/test_objects.py
index e868b4af..b8dde450 100644
--- a/tests/api_resources/test_objects.py
+++ b/tests/api_resources/test_objects.py
@@ -829,7 +829,7 @@ def test_method_set_with_all_params(self, client: Knock) -> None:
object_ = client.objects.set(
collection="collection",
id="id",
- channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"data": {"tokens": ["push_token_123"]}}},
+ channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"tokens": ["push_token_123"]}},
locale="en-US",
preferences={
"default": {
@@ -2032,7 +2032,7 @@ async def test_method_set_with_all_params(self, async_client: AsyncKnock) -> Non
object_ = await async_client.objects.set(
collection="collection",
id="id",
- channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"data": {"tokens": ["push_token_123"]}}},
+ channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"tokens": ["push_token_123"]}},
locale="en-US",
preferences={
"default": {
diff --git a/tests/api_resources/test_tenants.py b/tests/api_resources/test_tenants.py
index 3bc1993a..9dee76b2 100644
--- a/tests/api_resources/test_tenants.py
+++ b/tests/api_resources/test_tenants.py
@@ -183,7 +183,7 @@ def test_method_set(self, client: Knock) -> None:
def test_method_set_with_all_params(self, client: Knock) -> None:
tenant = client.tenants.set(
id="id",
- channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"data": {"tokens": ["push_token_xxx"]}}},
+ channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"tokens": ["push_token_xxx"]}},
preferences={
"default": {
"categories": {
@@ -504,7 +504,7 @@ async def test_method_set(self, async_client: AsyncKnock) -> None:
async def test_method_set_with_all_params(self, async_client: AsyncKnock) -> None:
tenant = await async_client.tenants.set(
id="id",
- channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"data": {"tokens": ["push_token_xxx"]}}},
+ channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"tokens": ["push_token_xxx"]}},
preferences={
"default": {
"categories": {
diff --git a/tests/api_resources/test_users.py b/tests/api_resources/test_users.py
index 18718405..76315573 100644
--- a/tests/api_resources/test_users.py
+++ b/tests/api_resources/test_users.py
@@ -47,7 +47,7 @@ def test_method_update_with_all_params(self, client: Knock) -> None:
user = client.users.update(
user_id="user_id",
avatar="avatar",
- channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"data": {"tokens": ["push_token_123"]}}},
+ channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"tokens": ["push_token_123"]}},
created_at=parse_datetime("2019-12-27T18:11:19.117Z"),
email="ian.malcolm@chaos.theory",
locale="locale",
@@ -1017,7 +1017,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncKnock) ->
user = await async_client.users.update(
user_id="user_id",
avatar="avatar",
- channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"data": {"tokens": ["push_token_123"]}}},
+ channel_data={"97c5837d-c65c-4d54-aa39-080eeb81c69d": {"tokens": ["push_token_123"]}},
created_at=parse_datetime("2019-12-27T18:11:19.117Z"),
email="ian.malcolm@chaos.theory",
locale="locale",
From aad60e07fd672462e4689125a20f4f62a99d18de Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 16 May 2025 03:42:19 +0000
Subject: [PATCH 8/9] chore(ci): fix installation instructions
---
scripts/utils/upload-artifact.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh
index c2229e23..597153be 100755
--- a/scripts/utils/upload-artifact.sh
+++ b/scripts/utils/upload-artifact.sh
@@ -18,7 +18,7 @@ UPLOAD_RESPONSE=$(tar -cz . | curl -v -X PUT \
if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then
echo -e "\033[32mUploaded build to Stainless storage.\033[0m"
- echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/knock-python/$SHA'\033[0m"
+ echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/knock-python/$SHA'\033[0m"
else
echo -e "\033[31mFailed to upload artifact.\033[0m"
exit 1
From 961acf51bcbb8b4ca80e48331c1de33376d40fc1 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 16 May 2025 03:42:36 +0000
Subject: [PATCH 9/9] release: 1.1.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 23 +++++++++++++++++++++++
pyproject.toml | 2 +-
src/knockapi/_version.py | 2 +-
4 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index fea34540..2601677b 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "1.0.0"
+ ".": "1.1.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 22d5a70b..8f3ccea2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,28 @@
# Changelog
+## 1.1.0 (2025-05-16)
+
+Full Changelog: [v1.0.0...v1.1.0](https://github.com/knocklabs/knock-python/compare/v1.0.0...v1.1.0)
+
+### Features
+
+* **api:** api update ([e88471a](https://github.com/knocklabs/knock-python/commit/e88471a8b9c90f68d9ff6438298754f8b63148cc))
+* **api:** api update ([07aa7ef](https://github.com/knocklabs/knock-python/commit/07aa7ef945058ad65a8b7586c74dabf156c69cfb))
+* **api:** removes duplicate activities section ([5e79f8b](https://github.com/knocklabs/knock-python/commit/5e79f8b6dc84a299099052a204f50c8522671d51))
+
+
+### Bug Fixes
+
+* **package:** support direct resource imports ([03d835a](https://github.com/knocklabs/knock-python/commit/03d835a305fe7024814c863ed902481ec509b439))
+
+
+### Chores
+
+* **ci:** fix installation instructions ([aad60e0](https://github.com/knocklabs/knock-python/commit/aad60e07fd672462e4689125a20f4f62a99d18de))
+* **ci:** upload sdks to package manager ([6793aeb](https://github.com/knocklabs/knock-python/commit/6793aeb32db67c2f41dc3c721c64b25471031c13))
+* **internal:** avoid errors for isinstance checks on proxies ([49ba469](https://github.com/knocklabs/knock-python/commit/49ba46929f05e16a4d134ce201d7a10bbfd09b4b))
+* **internal:** version bump ([797719a](https://github.com/knocklabs/knock-python/commit/797719ac713c52ac1abae12df3b3667ee3d536aa))
+
## 1.0.0 (2025-05-01)
Full Changelog: [v0.5.14...v1.0.0](https://github.com/knocklabs/knock-python/compare/v0.5.14...v1.0.0)
diff --git a/pyproject.toml b/pyproject.toml
index fbe1edfd..8124a3ae 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "knockapi"
-version = "1.0.0"
+version = "1.1.0"
description = "The official Python library for the knock API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/knockapi/_version.py b/src/knockapi/_version.py
index b18ad4b7..4cea0bdf 100644
--- a/src/knockapi/_version.py
+++ b/src/knockapi/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "knockapi"
-__version__ = "1.0.0" # x-release-please-version
+__version__ = "1.1.0" # x-release-please-version