diff --git a/.gitignore b/.gitignore index cd6b06b..0d7a739 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +**/__pycache__/ **/.speakeasy/temp/ **/.speakeasy/logs/ .speakeasy/reports diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index e3bda0e..af9ffef 100644 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: 8618b570-44d2-4c9e-aa91-d78e8fe5330e management: - docChecksum: 5b76b5690abc6b64f298c78bc49b1cb3 + docChecksum: 7cffd6e6c6d1e355d6a2430a6cfc7ba2 docVersion: 1.0.0 speakeasyVersion: 1.542.3 generationVersion: 2.597.9 - releaseVersion: 0.10.0 - configChecksum: a49d81219a116475988c23ee6f1c6e37 + releaseVersion: 0.11.1 + configChecksum: e04dcd700f3af99e13ee26442d72a844 repoURL: https://github.com/unkeyed/unkey-py.git installationURL: https://github.com/unkeyed/unkey-py.git published: true @@ -1012,7 +1012,7 @@ examples: createPermission: speakeasy-default-create-permission: requestBody: - application/json: {"name": "record.write", "description": "record.write can create new dns records for our domains."} + application/json: {"name": "Can write records", "slug": "record.write", "description": "record.write can create new dns records for our domains."} responses: "200": application/json: {"permissionId": "perm_123"} @@ -1062,7 +1062,7 @@ examples: permissionId: "perm_123" responses: "200": - application/json: {"id": "perm_123", "name": "domain.record.manager", "description": "Can manage dns records"} + application/json: {"id": "perm_123", "name": "domain.record.manager", "slug": "domain-record-manager", "description": "Can manage dns records"} "400": application/json: {"error": {"code": "BAD_REQUEST", "docs": "https://unkey.dev/docs/api-reference/errors/code/BAD_REQUEST", "message": "", "requestId": "req_1234"}} "401": @@ -1083,7 +1083,7 @@ examples: speakeasy-default-list-permissions: responses: "200": - application/json: [{"id": "perm_123", "name": "domain.record.manager", "description": "Can manage dns records"}, {"id": "perm_123", "name": "domain.record.manager", "description": "Can manage dns records"}, {"id": "perm_123", "name": "domain.record.manager", "description": "Can manage dns records"}] + application/json: [{"id": "perm_123", "name": "domain.record.manager", "slug": "domain-record-manager", "description": "Can manage dns records"}, {"id": "perm_123", "name": "domain.record.manager", "slug": "domain-record-manager", "description": "Can manage dns records"}, {"id": "perm_123", "name": "domain.record.manager", "slug": "domain-record-manager", "description": "Can manage dns records"}] "400": application/json: {"error": {"code": "BAD_REQUEST", "docs": "https://unkey.dev/docs/api-reference/errors/code/BAD_REQUEST", "message": "", "requestId": "req_1234"}} "401": diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index fa6c636..a47be80 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -7,6 +7,7 @@ generation: maintainOpenAPIOrder: true usageSnippets: optionalPropertyRendering: withExample + sdkInitStyle: constructor useClassNamesForArrayFields: true fixes: nameResolutionDec2023: true @@ -19,12 +20,13 @@ generation: oAuth2ClientCredentialsEnabled: true oAuth2PasswordEnabled: false python: - version: 0.10.0 + version: 0.11.1 additionalDependencies: dev: {} main: {} authors: - Speakeasy + baseErrorName: UnkeyError clientServerStatusCodesAsErrors: true defaultErrorName: SDKError description: Python Client SDK for unkey.com. @@ -47,8 +49,10 @@ python: inputModelSuffix: input maxMethodParams: 4 methodArguments: infer-optional-args + moduleName: "" outputModelSuffix: output packageName: unkey.py + pytestFilterWarnings: [] pytestTimeout: 0 responseFormat: envelope-http templateVersion: v2 diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 2df076c..3007961 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -2,20 +2,20 @@ speakeasyVersion: 1.542.3 sources: Unkey-OAS: sourceNamespace: unkey-oas - sourceRevisionDigest: sha256:c4582b17b5db49f9a45062180f5555a72abef0188ba709e929272c85225abeff - sourceBlobDigest: sha256:1c41faf3ed61f8cd6f660239a0d124730ec6c2b09000b14c05d415c493b17d71 + sourceRevisionDigest: sha256:24cd78bf9f84d2163e75a66c410f9d69fa327704e9a455a2e3d5ec6c0ff54f4a + sourceBlobDigest: sha256:f5a0428d9f61cb250a1bf6f427a70969326fdb119db06f0d9c62e9c9714f957f tags: - latest - - speakeasy-sdk-regen-1739752037 + - speakeasy-sdk-regen-1751069407 - 1.0.0 targets: unkey: source: Unkey-OAS sourceNamespace: unkey-oas - sourceRevisionDigest: sha256:c4582b17b5db49f9a45062180f5555a72abef0188ba709e929272c85225abeff - sourceBlobDigest: sha256:1c41faf3ed61f8cd6f660239a0d124730ec6c2b09000b14c05d415c493b17d71 + sourceRevisionDigest: sha256:24cd78bf9f84d2163e75a66c410f9d69fa327704e9a455a2e3d5ec6c0ff54f4a + sourceBlobDigest: sha256:f5a0428d9f61cb250a1bf6f427a70969326fdb119db06f0d9c62e9c9714f957f codeSamplesNamespace: unkey-oas-python-code-samples - codeSamplesRevisionDigest: sha256:2df834896b75976a16a6ccc505428d2e9553bfdb2d6366942ca24cb389635359 + codeSamplesRevisionDigest: sha256:12ef0b11e5efec939efa05e23d7de67dfa6b781f61c81fe02b111d40586735a5 workflow: workflowVersion: 1.0.0 speakeasyVersion: latest diff --git a/README.md b/README.md index 177b0fa..e344c95 100644 --- a/README.md +++ b/README.md @@ -1 +1,549 @@ This SDK has been moved to our [SDKs Monorepo](https://github.com/unkeyed/sdks). + + +## Summary + + + + + +## Table of Contents + + * [SDK Installation](#sdk-installation) + * [IDE Support](#ide-support) + * [SDK Example Usage](#sdk-example-usage) + * [Authentication](#authentication) + * [Available Resources and Operations](#available-resources-and-operations) + * [Pagination](#pagination) + * [Retries](#retries) + * [Error Handling](#error-handling) + * [Server Selection](#server-selection) + * [Custom HTTP Client](#custom-http-client) + * [Resource Management](#resource-management) + * [Debugging](#debugging) + + + + +## SDK Installation + +> [!NOTE] +> **Python version upgrade policy** +> +> Once a Python version reaches its [official end of life date](https://devguide.python.org/versions/), a 3-month grace period is provided for users to upgrade. Following this grace period, the minimum python version supported in the SDK will be updated. + +The SDK can be installed with either *pip* or *poetry* package managers. + +### PIP + +*PIP* is the default package installer for Python, enabling easy installation and management of packages from PyPI via the command line. + +```bash +pip install unkey.py +``` + +### Poetry + +*Poetry* is a modern tool that simplifies dependency management and package publishing by using a single `pyproject.toml` file to handle project metadata and dependencies. + +```bash +poetry add unkey.py +``` + +### Shell and script usage with `uv` + +You can use this SDK in a Python shell with [uv](https://docs.astral.sh/uv/) and the `uvx` command that comes with it like so: + +```shell +uvx --from unkey.py python +``` + +It's also possible to write a standalone Python script without needing to set up a whole project like so: + +```python +#!/usr/bin/env -S uv run --script +# /// script +# requires-python = ">=3.9" +# dependencies = [ +# "unkey.py", +# ] +# /// + +from unkey_py import Unkey + +sdk = Unkey( + # SDK arguments +) + +# Rest of script here... +``` + +Once that is saved to a file, you can run it with `uv run script.py` where +`script.py` can be replaced with the actual file name. + + + +## IDE Support + +### PyCharm + +Generally, the SDK will work well with most IDEs out of the box. However, when using PyCharm, you can enjoy much better integration with Pydantic by installing an additional plugin. + +- [PyCharm Pydantic Plugin](https://docs.pydantic.dev/latest/integrations/pycharm/) + + + +## SDK Example Usage + +### Example + +```python +# Synchronous Example +from unkey_py import Unkey + + +with Unkey( + bearer_auth="UNKEY_ROOT_KEY", +) as unkey: + + res = unkey.liveness.check() + + assert res.object is not None + + # Handle response + print(res.object) +``` + +
+ +The same SDK client can also be used to make asychronous requests by importing asyncio. +```python +# Asynchronous Example +import asyncio +from unkey_py import Unkey + +async def main(): + + async with Unkey( + bearer_auth="UNKEY_ROOT_KEY", + ) as unkey: + + res = await unkey.liveness.check_async() + + assert res.object is not None + + # Handle response + print(res.object) + +asyncio.run(main()) +``` + + + +## Authentication + +### Per-Client Security Schemes + +This SDK supports the following security scheme globally: + +| Name | Type | Scheme | Environment Variable | +| ------------- | ---- | ----------- | -------------------- | +| `bearer_auth` | http | HTTP Bearer | `UNKEY_BEARER_AUTH` | + +To authenticate with the API the `bearer_auth` parameter must be set when initializing the SDK client instance. For example: +```python +from unkey_py import Unkey + + +with Unkey( + bearer_auth="UNKEY_ROOT_KEY", +) as unkey: + + res = unkey.liveness.check() + + assert res.object is not None + + # Handle response + print(res.object) + +``` + + + +## Available Resources and Operations + +
+Available methods + +### [analytics](docs/sdks/analytics/README.md) + +* [get_verifications](docs/sdks/analytics/README.md#get_verifications) + +### [apis](docs/sdks/apis/README.md) + +* [get](docs/sdks/apis/README.md#get) +* [create](docs/sdks/apis/README.md#create) +* [list_keys](docs/sdks/apis/README.md#list_keys) +* [delete](docs/sdks/apis/README.md#delete) +* [delete_keys](docs/sdks/apis/README.md#delete_keys) + +### [identities](docs/sdks/identities/README.md) + +* [create](docs/sdks/identities/README.md#create) +* [get](docs/sdks/identities/README.md#get) +* [list](docs/sdks/identities/README.md#list) +* [update](docs/sdks/identities/README.md#update) +* [delete](docs/sdks/identities/README.md#delete) + +### [keys](docs/sdks/keys/README.md) + +* [get](docs/sdks/keys/README.md#get) +* [whoami](docs/sdks/keys/README.md#whoami) +* [delete](docs/sdks/keys/README.md#delete) +* [create](docs/sdks/keys/README.md#create) +* [verify](docs/sdks/keys/README.md#verify) +* [update](docs/sdks/keys/README.md#update) +* [update_remaining](docs/sdks/keys/README.md#update_remaining) +* [get_verifications](docs/sdks/keys/README.md#get_verifications) +* [add_permissions](docs/sdks/keys/README.md#add_permissions) +* [remove_permissions](docs/sdks/keys/README.md#remove_permissions) +* [set_permissions](docs/sdks/keys/README.md#set_permissions) +* [add_roles](docs/sdks/keys/README.md#add_roles) +* [remove_roles](docs/sdks/keys/README.md#remove_roles) +* [set_roles](docs/sdks/keys/README.md#set_roles) + +### [liveness](docs/sdks/liveness/README.md) + +* [check](docs/sdks/liveness/README.md#check) + +### [migrations](docs/sdks/migrations/README.md) + +* [create_keys](docs/sdks/migrations/README.md#create_keys) +* [enqueue](docs/sdks/migrations/README.md#enqueue) + +### [permissions](docs/sdks/permissions/README.md) + +* [create](docs/sdks/permissions/README.md#create) +* [delete](docs/sdks/permissions/README.md#delete) +* [get](docs/sdks/permissions/README.md#get) +* [list](docs/sdks/permissions/README.md#list) +* [create_role](docs/sdks/permissions/README.md#create_role) +* [delete_role](docs/sdks/permissions/README.md#delete_role) +* [get_role](docs/sdks/permissions/README.md#get_role) +* [list_roles](docs/sdks/permissions/README.md#list_roles) + +### [ratelimit](docs/sdks/ratelimit/README.md) + +* [set_override](docs/sdks/ratelimit/README.md#set_override) +* [list_overrides](docs/sdks/ratelimit/README.md#list_overrides) +* [get_override](docs/sdks/ratelimit/README.md#get_override) + +### [ratelimits](docs/sdks/ratelimits/README.md) + +* [limit](docs/sdks/ratelimits/README.md#limit) +* [delete_override](docs/sdks/ratelimits/README.md#delete_override) + + +
+ + + +## Pagination + +Some of the endpoints in this SDK support pagination. To use pagination, you make your SDK calls as usual, but the +returned response object will have a `Next` method that can be called to pull down the next group of results. If the +return value of `Next` is `None`, then there are no more pages to be fetched. + +Here's an example of one such pagination call: +```python +from unkey_py import Unkey + + +with Unkey( + bearer_auth="UNKEY_ROOT_KEY", +) as unkey: + + res = unkey.identities.list() + + while res is not None: + # Handle items + + res = res.next() + +``` + + + +## Retries + +Some of the endpoints in this SDK support retries. If you use the SDK without any configuration, it will fall back to the default retry strategy provided by the API. However, the default retry strategy can be overridden on a per-operation basis, or across the entire SDK. + +To change the default retry strategy for a single API call, simply provide a `RetryConfig` object to the call: +```python +from unkey_py import Unkey +from unkey_py.utils import BackoffStrategy, RetryConfig + + +with Unkey( + bearer_auth="UNKEY_ROOT_KEY", +) as unkey: + + res = unkey.liveness.check(, + RetryConfig("backoff", BackoffStrategy(1, 50, 1.1, 100), False)) + + assert res.object is not None + + # Handle response + print(res.object) + +``` + +If you'd like to override the default retry strategy for all operations that support retries, you can use the `retry_config` optional parameter when initializing the SDK: +```python +from unkey_py import Unkey +from unkey_py.utils import BackoffStrategy, RetryConfig + + +with Unkey( + retry_config=RetryConfig("backoff", BackoffStrategy(1, 50, 1.1, 100), False), + bearer_auth="UNKEY_ROOT_KEY", +) as unkey: + + res = unkey.liveness.check() + + assert res.object is not None + + # Handle response + print(res.object) + +``` + + + +## Error Handling + +Handling errors in this SDK should largely match your expectations. All operations return a response object or raise an exception. + +By default, an API error will raise a models.SDKError exception, which has the following properties: + +| Property | Type | Description | +|-----------------|------------------|-----------------------| +| `.status_code` | *int* | The HTTP status code | +| `.message` | *str* | The error message | +| `.raw_response` | *httpx.Response* | The raw HTTP response | +| `.body` | *str* | The response content | + +When custom error responses are specified for an operation, the SDK may also raise their associated exceptions. You can refer to respective *Errors* tables in SDK docs for more details on possible exception types for each operation. For example, the `check_async` method may raise the following exceptions: + +| Error Type | Status Code | Content Type | +| ----------------------------- | ----------- | ---------------- | +| models.ErrBadRequest | 400 | application/json | +| models.ErrUnauthorized | 401 | application/json | +| models.ErrForbidden | 403 | application/json | +| models.ErrNotFound | 404 | application/json | +| models.ErrConflict | 409 | application/json | +| models.ErrPreconditionFailed | 412 | application/json | +| models.ErrTooManyRequests | 429 | application/json | +| models.ErrInternalServerError | 500 | application/json | +| models.SDKError | 4XX, 5XX | \*/\* | + +### Example + +```python +from unkey_py import Unkey, models + + +with Unkey( + bearer_auth="UNKEY_ROOT_KEY", +) as unkey: + res = None + try: + + res = unkey.liveness.check() + + assert res.object is not None + + # Handle response + print(res.object) + + except models.ErrBadRequest as e: + # handle e.data: models.ErrBadRequestData + raise(e) + except models.ErrUnauthorized as e: + # handle e.data: models.ErrUnauthorizedData + raise(e) + except models.ErrForbidden as e: + # handle e.data: models.ErrForbiddenData + raise(e) + except models.ErrNotFound as e: + # handle e.data: models.ErrNotFoundData + raise(e) + except models.ErrConflict as e: + # handle e.data: models.ErrConflictData + raise(e) + except models.ErrPreconditionFailed as e: + # handle e.data: models.ErrPreconditionFailedData + raise(e) + except models.ErrTooManyRequests as e: + # handle e.data: models.ErrTooManyRequestsData + raise(e) + except models.ErrInternalServerError as e: + # handle e.data: models.ErrInternalServerErrorData + raise(e) + except models.SDKError as e: + # handle exception + raise(e) +``` + + + +## Server Selection + +### Override Server URL Per-Client + +The default server can be overridden globally by passing a URL to the `server_url: str` optional parameter when initializing the SDK client instance. For example: +```python +from unkey_py import Unkey + + +with Unkey( + server_url="https://api.unkey.dev", + bearer_auth="UNKEY_ROOT_KEY", +) as unkey: + + res = unkey.liveness.check() + + assert res.object is not None + + # Handle response + print(res.object) + +``` + + + +## Custom HTTP Client + +The Python SDK makes API calls using the [httpx](https://www.python-httpx.org/) HTTP library. In order to provide a convenient way to configure timeouts, cookies, proxies, custom headers, and other low-level configuration, you can initialize the SDK client with your own HTTP client instance. +Depending on whether you are using the sync or async version of the SDK, you can pass an instance of `HttpClient` or `AsyncHttpClient` respectively, which are Protocol's ensuring that the client has the necessary methods to make API calls. +This allows you to wrap the client with your own custom logic, such as adding custom headers, logging, or error handling, or you can just pass an instance of `httpx.Client` or `httpx.AsyncClient` directly. + +For example, you could specify a header for every request that this sdk makes as follows: +```python +from unkey_py import Unkey +import httpx + +http_client = httpx.Client(headers={"x-custom-header": "someValue"}) +s = Unkey(client=http_client) +``` + +or you could wrap the client with your own custom logic: +```python +from unkey_py import Unkey +from unkey_py.httpclient import AsyncHttpClient +import httpx + +class CustomClient(AsyncHttpClient): + client: AsyncHttpClient + + def __init__(self, client: AsyncHttpClient): + self.client = client + + async def send( + self, + request: httpx.Request, + *, + stream: bool = False, + auth: Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault, None + ] = httpx.USE_CLIENT_DEFAULT, + follow_redirects: Union[ + bool, httpx._client.UseClientDefault + ] = httpx.USE_CLIENT_DEFAULT, + ) -> httpx.Response: + request.headers["Client-Level-Header"] = "added by client" + + return await self.client.send( + request, stream=stream, auth=auth, follow_redirects=follow_redirects + ) + + def build_request( + self, + method: str, + url: httpx._types.URLTypes, + *, + content: Optional[httpx._types.RequestContent] = None, + data: Optional[httpx._types.RequestData] = None, + files: Optional[httpx._types.RequestFiles] = None, + json: Optional[Any] = None, + params: Optional[httpx._types.QueryParamTypes] = None, + headers: Optional[httpx._types.HeaderTypes] = None, + cookies: Optional[httpx._types.CookieTypes] = None, + timeout: Union[ + httpx._types.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx.USE_CLIENT_DEFAULT, + extensions: Optional[httpx._types.RequestExtensions] = None, + ) -> httpx.Request: + return self.client.build_request( + method, + url, + content=content, + data=data, + files=files, + json=json, + params=params, + headers=headers, + cookies=cookies, + timeout=timeout, + extensions=extensions, + ) + +s = Unkey(async_client=CustomClient(httpx.AsyncClient())) +``` + + + +## Resource Management + +The `Unkey` class implements the context manager protocol and registers a finalizer function to close the underlying sync and async HTTPX clients it uses under the hood. This will close HTTP connections, release memory and free up other resources held by the SDK. In short-lived Python programs and notebooks that make a few SDK method calls, resource management may not be a concern. However, in longer-lived programs, it is beneficial to create a single SDK instance via a [context manager][context-manager] and reuse it across the application. + +[context-manager]: https://docs.python.org/3/reference/datamodel.html#context-managers + +```python +from unkey_py import Unkey +def main(): + + with Unkey( + bearer_auth="UNKEY_ROOT_KEY", + ) as unkey: + # Rest of application here... + + +# Or when using async: +async def amain(): + + async with Unkey( + bearer_auth="UNKEY_ROOT_KEY", + ) as unkey: + # Rest of application here... +``` + + + +## Debugging + +You can setup your SDK to emit debug logs for SDK requests and responses. + +You can pass your own logger class directly into your SDK. +```python +from unkey_py import Unkey +import logging + +logging.basicConfig(level=logging.DEBUG) +s = Unkey(debug_logger=logging.getLogger("unkey_py")) +``` + +You can also enable a default debug logger by setting an environment variable `UNKEY_DEBUG` to true. + + + diff --git a/RELEASES.md b/RELEASES.md index 3278c37..59abe51 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -58,4 +58,14 @@ Based on: ### Generated - [python v0.10.0] . ### Releases -- [PyPI v0.10.0] https://pypi.org/project/unkey.py/0.10.0 - . \ No newline at end of file +- [PyPI v0.10.0] https://pypi.org/project/unkey.py/0.10.0 - . + +## 2025-07-21 00:11:52 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.542.3 (2.597.9) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v0.11.1] . +### Releases +- [PyPI v0.11.1] https://pypi.org/project/unkey.py/0.11.1 - . \ No newline at end of file diff --git a/docs/models/createpermissionrequestbody.md b/docs/models/createpermissionrequestbody.md index 7c88eba..44e1e08 100644 --- a/docs/models/createpermissionrequestbody.md +++ b/docs/models/createpermissionrequestbody.md @@ -5,5 +5,6 @@ | Field | Type | Required | Description | Example | | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -| `name` | *str* | :heavy_check_mark: | The unique name of your permission. | record.write | +| `name` | *str* | :heavy_check_mark: | The unique name of your permission. | Can write records | +| `slug` | *Optional[str]* | :heavy_minus_sign: | The unique slug of your permission. If not provided, the name is used. | record.write | | `description` | [Optional[models.Description]](../models/description.md) | :heavy_minus_sign: | Explain what this permission does. This is just for your team, your users will not see this. | record.write can create new dns records for our domains. | \ No newline at end of file diff --git a/docs/models/getpermissionresponsebody.md b/docs/models/getpermissionresponsebody.md index df0bbd6..1fd3697 100644 --- a/docs/models/getpermissionresponsebody.md +++ b/docs/models/getpermissionresponsebody.md @@ -9,4 +9,5 @@ The Role | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | `id` | *str* | :heavy_check_mark: | The id of the permission | perm_123 | | `name` | *str* | :heavy_check_mark: | The name of the permission. | domain.record.manager | +| `slug` | *str* | :heavy_check_mark: | The slug of the permission | domain-record-manager | | `description` | *Optional[str]* | :heavy_minus_sign: | The description of what this permission does. This is just for your team, your users will not see this. | Can manage dns records | \ No newline at end of file diff --git a/docs/models/listpermissionsresponsebody.md b/docs/models/listpermissionsresponsebody.md index a02c9bf..78fe740 100644 --- a/docs/models/listpermissionsresponsebody.md +++ b/docs/models/listpermissionsresponsebody.md @@ -7,4 +7,5 @@ | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | `id` | *str* | :heavy_check_mark: | The id of the permission | perm_123 | | `name` | *str* | :heavy_check_mark: | The name of the permission. | domain.record.manager | +| `slug` | *str* | :heavy_check_mark: | The slug of the permission | domain-record-manager | | `description` | *Optional[str]* | :heavy_minus_sign: | The description of what this permission does. This is just for your team, your users will not see this. | Can manage dns records | \ No newline at end of file diff --git a/docs/models/removepermissionspermissions.md b/docs/models/removepermissionspermissions.md index 1d86a14..c936b8b 100644 --- a/docs/models/removepermissionspermissions.md +++ b/docs/models/removepermissionspermissions.md @@ -3,7 +3,8 @@ ## Fields -| Field | Type | Required | Description | -| ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -| `id` | *Optional[str]* | :heavy_minus_sign: | The id of the permission. Provide either `id` or `name`. If both are provided `id` is used. | -| `name` | *Optional[str]* | :heavy_minus_sign: | Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used. | \ No newline at end of file +| Field | Type | Required | Description | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *Optional[str]* | :heavy_minus_sign: | The id of the permission. Provide either `id` or `slug`. If both are provided `id` is used. | +| ~~`name`~~ | *Optional[str]* | :heavy_minus_sign: | : warning: ** DEPRECATED **: This will be removed in a future release, please migrate away from it as soon as possible.

This field is deprecated and will be removed in a future release. please use `slug` instead. | +| `slug` | *Optional[str]* | :heavy_minus_sign: | Identify the permission via its slug. Provide either `id` or `slug`. If both are provided `id` is used. | \ No newline at end of file diff --git a/docs/models/setpermissionspermissions.md b/docs/models/setpermissionspermissions.md index cb8455d..7f80af5 100644 --- a/docs/models/setpermissionspermissions.md +++ b/docs/models/setpermissionspermissions.md @@ -6,5 +6,6 @@ | Field | Type | Required | Description | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `id` | *Optional[str]* | :heavy_minus_sign: | The id of the permission. Provide either `id` or `name`. If both are provided `id` is used. | -| `name` | *Optional[str]* | :heavy_minus_sign: | Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used. | +| ~~`name`~~ | *Optional[str]* | :heavy_minus_sign: | : warning: ** DEPRECATED **: This will be removed in a future release, please migrate away from it as soon as possible.

This field is deprecated and will be removed in a future release. please use `slug` instead. | +| `slug` | *Optional[str]* | :heavy_minus_sign: | Identify the permission via its slug. Provide either `id` or `slug`. If both are provided `id` is used. | | `create` | *Optional[bool]* | :heavy_minus_sign: | Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`.
Autocreating permissions requires your root key to have the `rbac.*.create_permission` permission, otherwise the request will get rejected | \ No newline at end of file diff --git a/docs/sdks/permissions/README.md b/docs/sdks/permissions/README.md index baad185..3690ce8 100644 --- a/docs/sdks/permissions/README.md +++ b/docs/sdks/permissions/README.md @@ -27,7 +27,8 @@ with Unkey( ) as unkey: res = unkey.permissions.create(request={ - "name": "record.write", + "name": "Can write records", + "slug": "record.write", "description": "record.write can create new dns records for our domains.", }) diff --git a/poetry.lock b/poetry.lock index fb1d091..be8e104 100644 --- a/poetry.lock +++ b/poetry.lock @@ -109,31 +109,31 @@ test = ["pytest (>=6)"] [[package]] name = "h11" -version = "0.14.0" +version = "0.16.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["main"] files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, ] [[package]] name = "httpcore" -version = "1.0.6" +version = "1.0.9" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "httpcore-1.0.6-py3-none-any.whl", hash = "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f"}, - {file = "httpcore-1.0.6.tar.gz", hash = "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f"}, + {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, + {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, ] [package.dependencies] certifi = "*" -h11 = ">=0.13,<0.15" +h11 = ">=0.16" [package.extras] asyncio = ["anyio (>=4.0,<5.0)"] diff --git a/pyproject.toml b/pyproject.toml index e38cde2..c9f866c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "unkey.py" -version = "0.10.0" +version = "0.11.1" description = "Python Client SDK for unkey.com." authors = [{ name = "Speakeasy" },] readme = "README-PYPI.md" diff --git a/src/unkey/py/_hooks/registration.py b/src/unkey/py/_hooks/registration.py new file mode 100644 index 0000000..cab4778 --- /dev/null +++ b/src/unkey/py/_hooks/registration.py @@ -0,0 +1,13 @@ +from .types import Hooks + + +# This file is only ever generated once on the first generation and then is free to be modified. +# Any hooks you wish to add should be registered in the init_hooks function. Feel free to define them +# in this file or in separate files in the hooks folder. + + +def init_hooks(hooks: Hooks): + # pylint: disable=unused-argument + """Add hooks by calling hooks.register{sdk_init/before_request/after_success/after_error}Hook + with an instance of a hook that implements that specific Hook interface + Hooks are registered per SDK instance, and are valid for the lifetime of the SDK instance""" diff --git a/src/unkey_py/_version.py b/src/unkey_py/_version.py index 0629604..b9b617a 100644 --- a/src/unkey_py/_version.py +++ b/src/unkey_py/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "unkey.py" -__version__: str = "0.10.0" +__version__: str = "0.11.1" __openapi_doc_version__: str = "1.0.0" __gen_version__: str = "2.597.9" -__user_agent__: str = "speakeasy-sdk/python 0.10.0 2.597.9 1.0.0 unkey.py" +__user_agent__: str = "speakeasy-sdk/python 0.11.1 2.597.9 1.0.0 unkey.py" try: if __package__ is not None: diff --git a/src/unkey_py/models/createpermissionop.py b/src/unkey_py/models/createpermissionop.py index a598823..667db7e 100644 --- a/src/unkey_py/models/createpermissionop.py +++ b/src/unkey_py/models/createpermissionop.py @@ -24,6 +24,8 @@ class Two(str, Enum): class CreatePermissionRequestBodyTypedDict(TypedDict): name: str r"""The unique name of your permission.""" + slug: NotRequired[str] + r"""The unique slug of your permission. If not provided, the name is used.""" description: NotRequired[DescriptionTypedDict] r"""Explain what this permission does. This is just for your team, your users will not see this.""" @@ -32,6 +34,9 @@ class CreatePermissionRequestBody(BaseModel): name: str r"""The unique name of your permission.""" + slug: Optional[str] = None + r"""The unique slug of your permission. If not provided, the name is used.""" + description: Optional[Description] = None r"""Explain what this permission does. This is just for your team, your users will not see this.""" diff --git a/src/unkey_py/models/getpermissionop.py b/src/unkey_py/models/getpermissionop.py index 2cec2be..e1c536c 100644 --- a/src/unkey_py/models/getpermissionop.py +++ b/src/unkey_py/models/getpermissionop.py @@ -28,6 +28,8 @@ class GetPermissionResponseBodyTypedDict(TypedDict): r"""The id of the permission""" name: str r"""The name of the permission.""" + slug: str + r"""The slug of the permission""" description: NotRequired[str] r"""The description of what this permission does. This is just for your team, your users will not see this.""" @@ -41,6 +43,9 @@ class GetPermissionResponseBody(BaseModel): name: str r"""The name of the permission.""" + slug: str + r"""The slug of the permission""" + description: Optional[str] = None r"""The description of what this permission does. This is just for your team, your users will not see this.""" diff --git a/src/unkey_py/models/getverificationsop.py b/src/unkey_py/models/getverificationsop.py index 8e61d40..d8e5e78 100644 --- a/src/unkey_py/models/getverificationsop.py +++ b/src/unkey_py/models/getverificationsop.py @@ -171,7 +171,7 @@ class GetVerificationsRequest(BaseModel): end: Annotated[ OptionalNullable[int], FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), - ] = 1746664158001 + ] = 1753056757376 group_by: Annotated[ Optional[GroupBy], diff --git a/src/unkey_py/models/listpermissionsop.py b/src/unkey_py/models/listpermissionsop.py index ea1bf05..44ee20f 100644 --- a/src/unkey_py/models/listpermissionsop.py +++ b/src/unkey_py/models/listpermissionsop.py @@ -13,6 +13,8 @@ class ListPermissionsResponseBodyTypedDict(TypedDict): r"""The id of the permission""" name: str r"""The name of the permission.""" + slug: str + r"""The slug of the permission""" description: NotRequired[str] r"""The description of what this permission does. This is just for your team, your users will not see this.""" @@ -24,6 +26,9 @@ class ListPermissionsResponseBody(BaseModel): name: str r"""The name of the permission.""" + slug: str + r"""The slug of the permission""" + description: Optional[str] = None r"""The description of what this permission does. This is just for your team, your users will not see this.""" diff --git a/src/unkey_py/models/removepermissionsop.py b/src/unkey_py/models/removepermissionsop.py index d7f8982..eb53a6b 100644 --- a/src/unkey_py/models/removepermissionsop.py +++ b/src/unkey_py/models/removepermissionsop.py @@ -10,17 +10,27 @@ class RemovePermissionsPermissionsTypedDict(TypedDict): id: NotRequired[str] - r"""The id of the permission. Provide either `id` or `name`. If both are provided `id` is used.""" + r"""The id of the permission. Provide either `id` or `slug`. If both are provided `id` is used.""" name: NotRequired[str] - r"""Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used.""" + r"""This field is deprecated and will be removed in a future release. please use `slug` instead.""" + slug: NotRequired[str] + r"""Identify the permission via its slug. Provide either `id` or `slug`. If both are provided `id` is used.""" class RemovePermissionsPermissions(BaseModel): id: Optional[str] = None - r"""The id of the permission. Provide either `id` or `name`. If both are provided `id` is used.""" - - name: Optional[str] = None - r"""Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used.""" + r"""The id of the permission. Provide either `id` or `slug`. If both are provided `id` is used.""" + + name: Annotated[ + Optional[str], + pydantic.Field( + deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible." + ), + ] = None + r"""This field is deprecated and will be removed in a future release. please use `slug` instead.""" + + slug: Optional[str] = None + r"""Identify the permission via its slug. Provide either `id` or `slug`. If both are provided `id` is used.""" class RemovePermissionsRequestBodyTypedDict(TypedDict): diff --git a/src/unkey_py/models/setpermissionsop.py b/src/unkey_py/models/setpermissionsop.py index dcb2244..70a793e 100644 --- a/src/unkey_py/models/setpermissionsop.py +++ b/src/unkey_py/models/setpermissionsop.py @@ -12,7 +12,9 @@ class SetPermissionsPermissionsTypedDict(TypedDict): id: NotRequired[str] r"""The id of the permission. Provide either `id` or `name`. If both are provided `id` is used.""" name: NotRequired[str] - r"""Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used.""" + r"""This field is deprecated and will be removed in a future release. please use `slug` instead.""" + slug: NotRequired[str] + r"""Identify the permission via its slug. Provide either `id` or `slug`. If both are provided `id` is used.""" create: NotRequired[bool] r"""Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. Autocreating permissions requires your root key to have the `rbac.*.create_permission` permission, otherwise the request will get rejected @@ -23,8 +25,16 @@ class SetPermissionsPermissions(BaseModel): id: Optional[str] = None r"""The id of the permission. Provide either `id` or `name`. If both are provided `id` is used.""" - name: Optional[str] = None - r"""Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used.""" + name: Annotated[ + Optional[str], + pydantic.Field( + deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible." + ), + ] = None + r"""This field is deprecated and will be removed in a future release. please use `slug` instead.""" + + slug: Optional[str] = None + r"""Identify the permission via its slug. Provide either `id` or `slug`. If both are provided `id` is used.""" create: Optional[bool] = None r"""Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`.