Skip to content

Commit

Permalink
add authenticate_request method to sdk client & regenerate
Browse files Browse the repository at this point in the history
  • Loading branch information
walker-tx committed Jan 27, 2025
1 parent 337c470 commit 00a32bc
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 28 deletions.
27 changes: 14 additions & 13 deletions .speakeasy/gen.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions .speakeasy/gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ generation:
oAuth2ClientCredentialsEnabled: true
oAuth2PasswordEnabled: false
python:
version: 1.7.0
version: 1.7.1
additionalDependencies:
dev:
pytest: ^8.3.3
Expand All @@ -26,7 +26,7 @@ python:
clientServerStatusCodesAsErrors: true
defaultErrorName: SDKError
description: Python Client SDK for clerk.dev
enableCustomCodeRegions: false
enableCustomCodeRegions: true
enumFormat: enum
fixFlags:
responseRequiredSep2024: false
Expand Down
36 changes: 33 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ More information about the API can be found at https://clerk.com/docs
* [Error Handling](#error-handling)
* [Server Selection](#server-selection)
* [Custom HTTP Client](#custom-http-client)
* [Resource Management](#resource-management)
* [Debugging](#debugging)
* [Development](#development)
* [Maturity](#maturity)
Expand All @@ -55,6 +56,11 @@ More information about the API can be found at https://clerk.com/docs
<!-- Start SDK Installation [installation] -->
## 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
Expand Down Expand Up @@ -157,7 +163,7 @@ with Clerk(

## Request Authentication

Use the [authenticate_request](https://github.com/clerk/clerk-sdk-python/blob/main/src/clerk_backend_api/jwks_helpers/authenticaterequest.py) method to authenticate a request from your app's frontend (when using a Clerk frontend SDK) to a Python backend (Django, Flask, and other Python web frameworks). For example the following utility function checks if the user is effectively signed in:
Use the client's `authenticate_request` method to authenticate a request from your app's frontend (when using a Clerk frontend SDK) to a Python backend (Django, Flask, and other Python web frameworks). For example the following utility function checks if the user is effectively signed in:

```python
import os
Expand All @@ -167,8 +173,7 @@ from clerk_backend_api.jwks_helpers import authenticate_request, AuthenticateReq

def is_signed_in(request: httpx.Request):
sdk = Clerk(bearer_auth=os.getenv('CLERK_SECRET_KEY'))
request_state = authenticate_request(
sdk,
request_state = sdk.authenticate_request(
request,
AuthenticateRequestOptions(
authorized_parties=['https://example.com']
Expand Down Expand Up @@ -637,6 +642,31 @@ s = Clerk(async_client=CustomClient(httpx.AsyncClient()))
```
<!-- End Custom HTTP Client [http-client] -->

<!-- Start Resource Management [resource-management] -->
## Resource Management

The `Clerk` 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 clerk_backend_api import Clerk
def main():
with Clerk(
bearer_auth="<YOUR_BEARER_TOKEN_HERE>",
) as clerk:
# Rest of application here...


# Or when using async:
async def amain():
async with Clerk(
bearer_auth="<YOUR_BEARER_TOKEN_HERE>",
) as clerk:
# Rest of application here...
```
<!-- End Resource Management [resource-management] -->

<!-- Start Debugging [debug] -->
## Debugging

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 = "clerk-backend-api"
version = "1.7.0"
version = "1.7.1"
description = "Python Client SDK for clerk.dev"
authors = [{ name = "Clerk" },]
readme = "README-PYPI.md"
Expand Down
6 changes: 3 additions & 3 deletions src/clerk_backend_api/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import importlib.metadata

__title__: str = "clerk-backend-api"
__version__: str = "1.7.0"
__version__: str = "1.7.1"
__openapi_doc_version__: str = "v1"
__gen_version__: str = "2.493.34"
__user_agent__: str = "speakeasy-sdk/python 1.7.0 2.493.34 v1 clerk-backend-api"
__gen_version__: str = "2.495.1"
__user_agent__: str = "speakeasy-sdk/python 1.7.1 2.495.1 v1 clerk-backend-api"

try:
if __package__ is not None:
Expand Down
50 changes: 50 additions & 0 deletions src/clerk_backend_api/httpclient.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

# pyright: reportReturnType = false
import asyncio
from concurrent.futures import ThreadPoolExecutor
from typing_extensions import Protocol, runtime_checkable
import httpx
from typing import Any, Optional, Union
Expand Down Expand Up @@ -82,3 +84,51 @@ def build_request(

async def aclose(self) -> None:
pass


class ClientOwner(Protocol):
client: Union[HttpClient, None]
async_client: Union[AsyncHttpClient, None]


def close_clients(
owner: ClientOwner,
sync_client: Union[HttpClient, None],
async_client: Union[AsyncHttpClient, None],
) -> None:
"""
A finalizer function that is meant to be used with weakref.finalize to close
httpx clients used by an SDK so that underlying resources can be garbage
collected.
"""

# Unset the client/async_client properties so there are no more references
# to them from the owning SDK instance and they can be reaped.
owner.client = None
owner.async_client = None

if sync_client is not None:
try:
sync_client.close()
except Exception:
pass

if async_client is not None:
is_async = False
try:
asyncio.get_running_loop()
is_async = True
except RuntimeError:
pass

try:
# If this function is called in an async loop then start another
# loop in a separate thread to close the async http client.
if is_async:
with ThreadPoolExecutor(max_workers=1) as executor:
future = executor.submit(asyncio.run, async_client.aclose())
future.result()
else:
asyncio.run(async_client.aclose())
except Exception:
pass
4 changes: 0 additions & 4 deletions src/clerk_backend_api/jwks_helpers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,3 @@
"VerifyTokenOptions",
"verify_token"
]


# Attach authenticate_request method to the Clerk class
setattr(Clerk, 'authenticate_request', authenticate_request)
21 changes: 19 additions & 2 deletions src/clerk_backend_api/sdk.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from .basesdk import BaseSDK
from .httpclient import AsyncHttpClient, HttpClient
from .httpclient import AsyncHttpClient, ClientOwner, HttpClient, close_clients
from .sdkconfiguration import SDKConfiguration
from .utils.logger import Logger, get_default_logger
from .utils.retries import RetryConfig
Expand Down Expand Up @@ -43,7 +43,12 @@
from clerk_backend_api.waitlist_entries_sdk import WaitlistEntriesSDK
from clerk_backend_api.webhooks import Webhooks
import httpx
from typing import Any, Callable, Dict, Optional, Union
from typing import Any, Callable, Dict, Optional, Union, cast
import weakref

# region imports
from .jwks_helpers.authenticaterequest import authenticate_request
# endregion imports


class Clerk(BaseSDK):
Expand Down Expand Up @@ -194,6 +199,14 @@ def __init__(
# pylint: disable=protected-access
self.sdk_configuration.__dict__["_hooks"] = hooks

weakref.finalize(
self,
close_clients,
cast(ClientOwner, self.sdk_configuration),
self.sdk_configuration.client,
self.sdk_configuration.async_client,
)

self._init_sdks()

def _init_sdks(self):
Expand Down Expand Up @@ -249,3 +262,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):
async def __aexit__(self, exc_type, exc_val, exc_tb):
if self.sdk_configuration.async_client is not None:
await self.sdk_configuration.async_client.aclose()

# region sdk-class-body
authenticate_request = authenticate_request
# endregion sdk-class-body

0 comments on commit 00a32bc

Please sign in to comment.