Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "1.18.1"
".": "1.19.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 89
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/knock%2Fknock-1584eaacf779edacf947595928550c8914bd5f39e68c9ef7d8af8dd65e36187a.yml
openapi_spec_hash: 1e56a42e6985e71dfe1a58ff352b57cd
config_hash: 1470ae08f436e4d00dd096cb585b41fd
configured_endpoints: 90
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/knock%2Fknock-ce72fff9b44a47ab7e0425e496f09c61cde5b4258feb20cb5dbef6fa615a57e4.yml
openapi_spec_hash: 3054ea299cf43dc89b68266818fecfe4
config_hash: 2b42d138d85c524e65fa7e205d36cc4a
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## 1.19.0 (2025-11-20)

Full Changelog: [v1.18.1...v1.19.0](https://github.com/knocklabs/knock-python/compare/v1.18.1...v1.19.0)

### Features

* **api:** Add bulk delete subscriptions ([19e98c2](https://github.com/knocklabs/knock-python/commit/19e98c23c849f558c931993cf4b4b51c8aa6cba9))
* **api:** api update ([fd69af2](https://github.com/knocklabs/knock-python/commit/fd69af2d0bceb8268ffe5332d27f164ba8d9cc40))
* **api:** api update ([73a3ba3](https://github.com/knocklabs/knock-python/commit/73a3ba3c1d5e370f31d781f13b211c18c0ba2b25))


### Bug Fixes

* **compat:** update signatures of `model_dump` and `model_dump_json` for Pydantic v1 ([8800c2d](https://github.com/knocklabs/knock-python/commit/8800c2da8a3bd29950d784f87c60d9725a5657b6))

## 1.18.1 (2025-11-10)

Full Changelog: [v1.18.0...v1.18.1](https://github.com/knocklabs/knock-python/compare/v1.18.0...v1.18.1)
Expand Down
3 changes: 2 additions & 1 deletion api.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ Methods:

- <code title="post /v1/objects/{collection}/bulk/delete">client.objects.bulk.<a href="./src/knockapi/resources/objects/bulk.py">delete</a>(collection, \*\*<a href="src/knockapi/types/objects/bulk_delete_params.py">params</a>) -> <a href="./src/knockapi/types/bulk_operation.py">BulkOperation</a></code>
- <code title="post /v1/objects/{collection}/bulk/subscriptions/add">client.objects.bulk.<a href="./src/knockapi/resources/objects/bulk.py">add_subscriptions</a>(collection, \*\*<a href="src/knockapi/types/objects/bulk_add_subscriptions_params.py">params</a>) -> <a href="./src/knockapi/types/bulk_operation.py">BulkOperation</a></code>
- <code title="post /v1/objects/{collection}/bulk/subscriptions/delete">client.objects.bulk.<a href="./src/knockapi/resources/objects/bulk.py">delete_subscriptions</a>(collection, \*\*<a href="src/knockapi/types/objects/bulk_delete_subscriptions_params.py">params</a>) -> <a href="./src/knockapi/types/bulk_operation.py">BulkOperation</a></code>
- <code title="post /v1/objects/{collection}/bulk/set">client.objects.bulk.<a href="./src/knockapi/resources/objects/bulk.py">set</a>(collection, \*\*<a href="src/knockapi/types/objects/bulk_set_params.py">params</a>) -> <a href="./src/knockapi/types/bulk_operation.py">BulkOperation</a></code>

# Tenants
Expand All @@ -178,7 +179,7 @@ Methods:

- <code title="get /v1/tenants">client.tenants.<a href="./src/knockapi/resources/tenants/tenants.py">list</a>(\*\*<a href="src/knockapi/types/tenant_list_params.py">params</a>) -> <a href="./src/knockapi/types/tenant.py">SyncEntriesCursor[Tenant]</a></code>
- <code title="delete /v1/tenants/{id}">client.tenants.<a href="./src/knockapi/resources/tenants/tenants.py">delete</a>(id) -> None</code>
- <code title="get /v1/tenants/{id}">client.tenants.<a href="./src/knockapi/resources/tenants/tenants.py">get</a>(id) -> <a href="./src/knockapi/types/tenant.py">Tenant</a></code>
- <code title="get /v1/tenants/{id}">client.tenants.<a href="./src/knockapi/resources/tenants/tenants.py">get</a>(id, \*\*<a href="src/knockapi/types/tenant_get_params.py">params</a>) -> <a href="./src/knockapi/types/tenant.py">Tenant</a></code>
- <code title="put /v1/tenants/{id}">client.tenants.<a href="./src/knockapi/resources/tenants/tenants.py">set</a>(id, \*\*<a href="src/knockapi/types/tenant_set_params.py">params</a>) -> <a href="./src/knockapi/types/tenant.py">Tenant</a></code>

## Bulk
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "knockapi"
version = "1.18.1"
version = "1.19.0"
description = "The official Python library for the knock API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
41 changes: 29 additions & 12 deletions src/knockapi/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,32 +257,41 @@ def model_dump(
mode: Literal["json", "python"] | str = "python",
include: IncEx | None = None,
exclude: IncEx | None = None,
context: Any | None = None,
by_alias: bool | None = None,
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
exclude_computed_fields: bool = False,
round_trip: bool = False,
warnings: bool | Literal["none", "warn", "error"] = True,
context: dict[str, Any] | None = None,
serialize_as_any: bool = False,
fallback: Callable[[Any], Any] | None = None,
serialize_as_any: bool = False,
) -> dict[str, Any]:
"""Usage docs: https://docs.pydantic.dev/2.4/concepts/serialization/#modelmodel_dump

Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.

Args:
mode: The mode in which `to_python` should run.
If mode is 'json', the dictionary will only contain JSON serializable types.
If mode is 'python', the dictionary may contain any Python objects.
include: A list of fields to include in the output.
exclude: A list of fields to exclude from the output.
If mode is 'json', the output will only contain JSON serializable types.
If mode is 'python', the output may contain non-JSON-serializable Python objects.
include: A set of fields to include in the output.
exclude: A set of fields to exclude from the output.
context: Additional context to pass to the serializer.
by_alias: Whether to use the field's alias in the dictionary key if defined.
exclude_unset: Whether to exclude fields that are unset or None from the output.
exclude_defaults: Whether to exclude fields that are set to their default value from the output.
exclude_none: Whether to exclude fields that have a value of `None` from the output.
round_trip: Whether to enable serialization and deserialization round-trip support.
warnings: Whether to log warnings when invalid fields are encountered.
exclude_unset: Whether to exclude fields that have not been explicitly set.
exclude_defaults: Whether to exclude fields that are set to their default value.
exclude_none: Whether to exclude fields that have a value of `None`.
exclude_computed_fields: Whether to exclude computed fields.
While this can be useful for round-tripping, it is usually recommended to use the dedicated
`round_trip` parameter instead.
round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].
warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors,
"error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError].
fallback: A function to call when an unknown value is encountered. If not provided,
a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised.
serialize_as_any: Whether to serialize fields with duck-typing serialization behavior.

Returns:
A dictionary representation of the model.
Expand All @@ -299,6 +308,8 @@ def model_dump(
raise ValueError("serialize_as_any is only supported in Pydantic v2")
if fallback is not None:
raise ValueError("fallback is only supported in Pydantic v2")
if exclude_computed_fields != False:
raise ValueError("exclude_computed_fields is only supported in Pydantic v2")
dumped = super().dict( # pyright: ignore[reportDeprecated]
include=include,
exclude=exclude,
Expand All @@ -315,15 +326,17 @@ def model_dump_json(
self,
*,
indent: int | None = None,
ensure_ascii: bool = False,
include: IncEx | None = None,
exclude: IncEx | None = None,
context: Any | None = None,
by_alias: bool | None = None,
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
exclude_computed_fields: bool = False,
round_trip: bool = False,
warnings: bool | Literal["none", "warn", "error"] = True,
context: dict[str, Any] | None = None,
fallback: Callable[[Any], Any] | None = None,
serialize_as_any: bool = False,
) -> str:
Expand Down Expand Up @@ -355,6 +368,10 @@ def model_dump_json(
raise ValueError("serialize_as_any is only supported in Pydantic v2")
if fallback is not None:
raise ValueError("fallback is only supported in Pydantic v2")
if ensure_ascii != False:
raise ValueError("ensure_ascii is only supported in Pydantic v2")
if exclude_computed_fields != False:
raise ValueError("exclude_computed_fields is only supported in Pydantic v2")
return super().json( # type: ignore[reportDeprecated]
indent=indent,
include=include,
Expand Down
2 changes: 1 addition & 1 deletion src/knockapi/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "knockapi"
__version__ = "1.18.1" # x-release-please-version
__version__ = "1.19.0" # x-release-please-version
119 changes: 116 additions & 3 deletions src/knockapi/resources/objects/bulk.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
async_to_streamed_response_wrapper,
)
from ..._base_client import make_request_options
from ...types.objects import bulk_set_params, bulk_delete_params, bulk_add_subscriptions_params
from ...types.objects import (
bulk_set_params,
bulk_delete_params,
bulk_add_subscriptions_params,
bulk_delete_subscriptions_params,
)
from ...types.bulk_operation import BulkOperation

__all__ = ["BulkResource", "AsyncBulkResource"]
Expand Down Expand Up @@ -109,7 +114,7 @@ def add_subscriptions(
for the `recipient` field.

Args:
subscriptions: A list of subscriptions.
subscriptions: A nested list of subscriptions.

extra_headers: Send extra headers

Expand Down Expand Up @@ -138,6 +143,54 @@ def add_subscriptions(
cast_to=BulkOperation,
)

def delete_subscriptions(
self,
collection: str,
*,
subscriptions: Iterable[bulk_delete_subscriptions_params.Subscription],
# 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,
idempotency_key: str | None = None,
) -> BulkOperation:
"""Delete subscriptions for many objects in a single collection type.

If a
subscription for an object in the collection doesn't exist, it will be skipped.

Args:
subscriptions: A nested list of subscriptions.

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

idempotency_key: Specify a custom idempotency key for this request
"""
if not collection:
raise ValueError(f"Expected a non-empty value for `collection` but received {collection!r}")
return self._post(
f"/v1/objects/{collection}/bulk/subscriptions/delete",
body=maybe_transform(
{"subscriptions": subscriptions}, bulk_delete_subscriptions_params.BulkDeleteSubscriptionsParams
),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
idempotency_key=idempotency_key,
),
cast_to=BulkOperation,
)

def set(
self,
collection: str,
Expand Down Expand Up @@ -269,7 +322,7 @@ async def add_subscriptions(
for the `recipient` field.

Args:
subscriptions: A list of subscriptions.
subscriptions: A nested list of subscriptions.

extra_headers: Send extra headers

Expand Down Expand Up @@ -298,6 +351,54 @@ async def add_subscriptions(
cast_to=BulkOperation,
)

async def delete_subscriptions(
self,
collection: str,
*,
subscriptions: Iterable[bulk_delete_subscriptions_params.Subscription],
# 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,
idempotency_key: str | None = None,
) -> BulkOperation:
"""Delete subscriptions for many objects in a single collection type.

If a
subscription for an object in the collection doesn't exist, it will be skipped.

Args:
subscriptions: A nested list of subscriptions.

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

idempotency_key: Specify a custom idempotency key for this request
"""
if not collection:
raise ValueError(f"Expected a non-empty value for `collection` but received {collection!r}")
return await self._post(
f"/v1/objects/{collection}/bulk/subscriptions/delete",
body=await async_maybe_transform(
{"subscriptions": subscriptions}, bulk_delete_subscriptions_params.BulkDeleteSubscriptionsParams
),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
idempotency_key=idempotency_key,
),
cast_to=BulkOperation,
)

async def set(
self,
collection: str,
Expand Down Expand Up @@ -353,6 +454,9 @@ def __init__(self, bulk: BulkResource) -> None:
self.add_subscriptions = to_raw_response_wrapper(
bulk.add_subscriptions,
)
self.delete_subscriptions = to_raw_response_wrapper(
bulk.delete_subscriptions,
)
self.set = to_raw_response_wrapper(
bulk.set,
)
Expand All @@ -368,6 +472,9 @@ def __init__(self, bulk: AsyncBulkResource) -> None:
self.add_subscriptions = async_to_raw_response_wrapper(
bulk.add_subscriptions,
)
self.delete_subscriptions = async_to_raw_response_wrapper(
bulk.delete_subscriptions,
)
self.set = async_to_raw_response_wrapper(
bulk.set,
)
Expand All @@ -383,6 +490,9 @@ def __init__(self, bulk: BulkResource) -> None:
self.add_subscriptions = to_streamed_response_wrapper(
bulk.add_subscriptions,
)
self.delete_subscriptions = to_streamed_response_wrapper(
bulk.delete_subscriptions,
)
self.set = to_streamed_response_wrapper(
bulk.set,
)
Expand All @@ -398,6 +508,9 @@ def __init__(self, bulk: AsyncBulkResource) -> None:
self.add_subscriptions = async_to_streamed_response_wrapper(
bulk.add_subscriptions,
)
self.delete_subscriptions = async_to_streamed_response_wrapper(
bulk.delete_subscriptions,
)
self.set = async_to_streamed_response_wrapper(
bulk.set,
)
Loading
Loading