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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ jobs:
- name: Sync dependencies
run: |
uv sync --all-groups
- name: Static code check
run: uv run poe ci_checker
- name: Code quality check
run: uv run poe cq-check
- name: Unit tests
run: uv run pytest tests/ -v -m 'not (account or basin or stream or metrics)'
- name: Check docs build
Expand Down
109 changes: 109 additions & 0 deletions examples/docs/account_and_basins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""Documentation examples for Account and Basins page.

These snippets are extracted by the docs build script.

Run with: python examples/docs/account_and_basins.py
Requires: S2_ACCESS_TOKEN, S2_BASIN environment variables

Note: These examples create resources with hardcoded names.
They may fail on repeated runs if resources already exist.
"""

import asyncio
import os
from datetime import datetime, timezone

from s2_sdk import (
S2,
AccessTokenScope,
OperationGroupPermissions,
Permission,
PrefixMatch,
)

access_token = os.environ["S2_ACCESS_TOKEN"]
basin_name = os.environ["S2_BASIN"]


async def main():
async with S2(access_token) as client:
# ANCHOR: basin-operations
# List basins
basins = await client.list_basins()

# Create a basin
await client.create_basin("my-events")

# Get configuration
config = await client.get_basin_config("my-events")

# Delete
await client.delete_basin("my-events")
# ANCHOR_END: basin-operations
print(f"Basins: {len(basins.items)} found, config: {config}")

basin = client.basin(basin_name)

# ANCHOR: stream-operations
# List streams
streams = await basin.list_streams(prefix="user-")

# Create a stream
await basin.create_stream(
"user-actions",
# config=StreamConfig(...) # optional
)

# Get configuration
config = await basin.get_stream_config("user-actions")

# Delete
await basin.delete_stream("user-actions")
# ANCHOR_END: stream-operations
print(f"Streams: {len(streams.items)} found, config: {config}")

# ANCHOR: access-token-basic
# List tokens (returns metadata, not the secret)
tokens = await client.list_access_tokens()

# Issue a token scoped to streams under "users/1234/"
issued_token = await client.issue_access_token(
"user-1234-rw-token",
scope=AccessTokenScope(
basins=PrefixMatch(""), # all basins
streams=PrefixMatch("users/1234/"),
op_groups=OperationGroupPermissions(
stream=Permission.READ_WRITE,
),
),
expires_at=datetime(2027, 1, 1, tzinfo=timezone.utc),
)

# Revoke a token
await client.revoke_access_token("user-1234-rw-token")
# ANCHOR_END: access-token-basic
print(f"Tokens: {len(tokens.items)} found, issued: {bool(issued_token)}")

# ANCHOR: pagination
# Iterate through all streams with automatic pagination
async for stream in basin.list_all_streams():
print(stream.name)
# ANCHOR_END: pagination

# ANCHOR: pagination-filtering
# List streams with a prefix filter
async for stream in basin.list_all_streams(prefix="events/"):
print(stream.name)
# ANCHOR_END: pagination-filtering

# ANCHOR: pagination-deleted
# Include streams that are being deleted
async for stream in basin.list_all_streams(include_deleted=True):
print(stream.name, stream.deleted_at)
# ANCHOR_END: pagination-deleted

print("Account and basins examples completed")


if __name__ == "__main__":
asyncio.run(main())
57 changes: 57 additions & 0 deletions examples/docs/configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""Documentation examples for Configuration page.

These snippets are extracted by the docs build script.

Run with: python examples/docs/configuration.py
Requires: S2_ACCESS_TOKEN environment variable
"""

import asyncio
import os
from datetime import timedelta

from s2_sdk import S2, Endpoints, Retry, Timeout


async def main():
# ANCHOR: custom-endpoints
client = S2(
"local-token",
endpoints=Endpoints(
account="http://localhost:8080",
basin="http://localhost:8080",
),
)
# ANCHOR_END: custom-endpoints
await client.close()

access_token = os.environ["S2_ACCESS_TOKEN"]

# ANCHOR: retry-config
client = S2(
access_token,
retry=Retry(
max_attempts=5,
min_base_delay=timedelta(milliseconds=100),
max_base_delay=timedelta(seconds=2),
),
)
# ANCHOR_END: retry-config
await client.close()

# ANCHOR: timeout-config
client = S2(
access_token,
timeout=Timeout(
connection=timedelta(seconds=5),
request=timedelta(seconds=10),
),
)
# ANCHOR_END: timeout-config
await client.close()

print("Configuration examples loaded")


if __name__ == "__main__":
asyncio.run(main())
63 changes: 63 additions & 0 deletions examples/docs/metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""Documentation examples for Metrics page.

These snippets are extracted by the docs build script.

Run with: python examples/docs/metrics.py
Requires: S2_ACCESS_TOKEN environment variable
"""

import asyncio
import os
import time

from s2_sdk import (
S2,
AccountMetricSet,
BasinMetricSet,
StreamMetricSet,
TimeseriesInterval,
)

access_token = os.environ["S2_ACCESS_TOKEN"]


async def main():
async with S2(access_token) as client:
# ANCHOR: metrics
now = int(time.time())
thirty_days_ago = now - 30 * 24 * 3600
six_hours_ago = now - 6 * 3600
hour_ago = now - 3600

# Account-level: active basins over the last 30 days
account_metrics = await client.account_metrics(
set=AccountMetricSet.ACTIVE_BASINS,
start=thirty_days_ago,
end=now,
)

# Basin-level: storage usage with hourly resolution
basin_metrics = await client.basin_metrics(
"events",
set=BasinMetricSet.STORAGE,
start=six_hours_ago,
end=now,
interval=TimeseriesInterval.HOUR,
)

# Stream-level: storage for a specific stream
stream_metrics = await client.stream_metrics(
"events",
"user-actions",
set=StreamMetricSet.STORAGE,
start=hour_ago,
end=now,
interval=TimeseriesInterval.MINUTE,
)
# ANCHOR_END: metrics

print(account_metrics, basin_metrics, stream_metrics)


if __name__ == "__main__":
asyncio.run(main())
20 changes: 20 additions & 0 deletions examples/docs/overview.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Documentation examples for SDK Overview page.

These snippets are extracted by the docs build script.

Run with: python examples/docs/overview.py
Requires: S2_ACCESS_TOKEN environment variable
"""

# ANCHOR: create-client
import os

from s2_sdk import S2

client = S2(os.environ["S2_ACCESS_TOKEN"])

basin = client.basin("my-basin")
stream = basin.stream("my-stream")
# ANCHOR_END: create-client

print("Client created successfully")
Loading
Loading