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
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ generate-javascript-sdk: ## Generate JavaScript SDK
.PHONY: gen-api
gen-api: update-openapi generate-javascript-sdk ## Generate API and SDKs
$(call print-target)
# dagger call generate python-sdk -o api/client/python

.PHONY: generate-all
generate-all: update-openapi generate-javascript-sdk ## Execute all code generators
Expand Down
670 changes: 335 additions & 335 deletions api/api.gen.go

Large diffs are not rendered by default.

564 changes: 282 additions & 282 deletions api/client/go/client.gen.go

Large diffs are not rendered by default.

187 changes: 186 additions & 1 deletion api/client/python/README.md

Large diffs are not rendered by default.

16 changes: 15 additions & 1 deletion api/client/python/examples/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
# Examples

## Setup

Install dependencies

```sh
poetry install
```

Run examples
## Running Examples

Run any example with environment variables:

```sh
OPENMETER_ENDPOINT=https://openmeter.cloud \
OPENMETER_TOKEN=om_xxx \
poetry run python ./sync/ingest.py
```

## Type Checking

The examples are type-checked using **Pyright**:

```sh
poetry run pyright
```

**Note**: Mypy is not compatible with the generated SDK models due to how it handles overloaded constructors. Pyright is the recommended type checker for this project.
31 changes: 18 additions & 13 deletions api/client/python/examples/async/customer.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
CustomerCreate,
CustomerReplaceUpdate,
CustomerUsageAttribution,
Metadata,
)
from corehttp.exceptions import HttpResponseError

Expand All @@ -25,41 +26,45 @@ async def main() -> None:
# Create a customer
customer_create = CustomerCreate(
name="Acme Corporation",
key=customer_key,
usage_attribution=CustomerUsageAttribution(subject_keys=[subject_key]),
description="A demo customer for testing",
metadata=Metadata(
{
"industry": "technology",
}
),
key=customer_key,
primary_email="contact@acme-corp.example.com",
currency="EUR",
usage_attribution=CustomerUsageAttribution(subject_keys=[subject_key]),
metadata={
"industry": "technology",
},
)

created_customer = await client.customer.customers.create(customer_create)
created_customer = await client.customers.create(customer_create)
print(f"Customer created successfully with ID: {created_customer.id}")
print(f"Customer name: {created_customer.name}")
print(f"Customer key: {created_customer.key}")

# Get the customer by ID or key
customer = await client.customer.customers.get(created_customer.id)
customer = await client.customers.get(created_customer.id)
print(f"\nRetrieved customer: {customer.name}")
print(f"Primary email: {customer.primary_email}")
print(f"Currency: {customer.currency}")

# Update the customer
customer_update = CustomerReplaceUpdate(
name="Acme Corporation Ltd.",
key=customer_key,
usage_attribution=CustomerUsageAttribution(subject_keys=[subject_key]),
description="Updated demo customer",
metadata=Metadata(
{
"industry": "technology",
}
),
key=customer_key,
primary_email="info@acme-corp.example.com",
currency="USD",
usage_attribution=CustomerUsageAttribution(subject_keys=[subject_key]),
metadata={
"industry": "technology",
},
)

updated_customer = await client.customer.customers.update(created_customer.id, customer_update)
updated_customer = await client.customers.update(created_customer.id, customer_update)
print(f"\nCustomer updated successfully")
print(f"Updated name: {updated_customer.name}")
print(f"Updated email: {updated_customer.primary_email}")
Expand Down
34 changes: 31 additions & 3 deletions api/client/python/examples/async/entitlement.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
ENDPOINT: str = environ.get("OPENMETER_ENDPOINT") or "https://openmeter.cloud"
token: Optional[str] = environ.get("OPENMETER_TOKEN")
customer_key: str = environ.get("OPENMETER_CUSTOMER_KEY") or "acme-corp-1"
feature_key: str = environ.get("OPENMETER_FEATURE_KEY") or "api-access"
feature_key: str = environ.get("OPENMETER_FEATURE_KEY") or "api_access"


async def main() -> None:
Expand All @@ -20,7 +20,7 @@ async def main() -> None:
# Check customer access to a specific feature
print(f"Checking access for customer '{customer_key}' to feature '{feature_key}'...")

entitlement_value = await client.entitlements.customer_entitlement.get_customer_entitlement_value(
entitlement_value = await client.customer_entitlement.get_customer_entitlement_value(
customer_key, feature_key
)

Expand All @@ -39,9 +39,37 @@ async def main() -> None:
if entitlement_value.config is not None:
print(f"Config: {entitlement_value.config}")

# List customer entitlements and demonstrate type-specific handling
print(f"\nListing all entitlements for customer '{customer_key}'...")
entitlements_response = await client.customer_entitlements_v2.list(customer_key)

print(f"\nEntitlements by Type:")
for entitlement in entitlements_response.items_property:
# Note: Due to a deserialization issue in the SDK, items come back as dicts
# Access fields using dict syntax or .get()
print(f"\n Feature: {entitlement.get('featureKey')}")
print(f" ID: {entitlement.get('id')}")

# Handle different entitlement types using discriminator
entitlement_type = entitlement.get("type")
if entitlement_type == "metered":
# Metered entitlement
print(f" Type: Metered")
print(f" Soft Limit: {entitlement.get('isSoftLimit')}")
if entitlement.get("issueAfterReset") is not None:
print(f" Issue After Reset: {entitlement.get('issueAfterReset')}")
elif entitlement_type == "static":
# Static entitlement
print(f" Type: Static")
if entitlement.get("config") is not None:
print(f" Config: {entitlement.get('config')}")
elif entitlement_type == "boolean":
# Boolean entitlement
print(f" Type: Boolean")

# Get overall customer access to all features
print(f"\nGetting overall access for customer '{customer_key}'...")
customer_access = await client.entitlements.customer.get_customer_access(customer_key)
customer_access = await client.customer.get_customer_access(customer_key)

print(f"\nCustomer Access Summary:")
print(f"Total entitlements: {len(customer_access.entitlements)}")
Expand Down
4 changes: 2 additions & 2 deletions api/client/python/examples/async/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import asyncio

from openmeter.aio import Client
from openmeter.models import MeterQueryResult
from openmeter.models import MeterQueryResult, FilterString
from corehttp.exceptions import HttpResponseError

ENDPOINT: str = environ.get("OPENMETER_ENDPOINT") or "https://openmeter.cloud"
Expand Down Expand Up @@ -35,7 +35,7 @@ async def main() -> None:
# Query total values for model=gpt-4o
r = await client.meters.query_json(
meter_id_or_slug="tokens_total",
advanced_meter_group_by_filters={"model": {"$eq": "gpt-4o"}},
advanced_meter_group_by_filters={"model": FilterString(eq="gpt-4o")},
)
if r.data and len(r.data) > 0:
print("Query total values for model=gpt-4o:", r.data[0].value)
Expand Down
19 changes: 11 additions & 8 deletions api/client/python/examples/async/subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from openmeter.aio import Client
from openmeter.models import (
Metadata,
PlanSubscriptionCreate,
PlanReferenceInput,
SubscriptionStatus,
Expand All @@ -26,19 +27,21 @@ async def main() -> None:
print(f"Creating subscription for customer '{customer_key}' with plan '{plan_key}'...")

subscription_create = PlanSubscriptionCreate(
customer_key=customer_key,
plan=PlanReferenceInput(
key=plan_key,
),
name="Free Plan Subscription",
description="Subscription to the free plan for Acme Corporation",
metadata={
"source": "example",
"environment": "development",
},
customer_key=customer_key,
metadata=Metadata(
{
"source": "example",
"environment": "development",
}
),
)

subscription = await client.product_catalog.subscriptions.create(subscription_create)
subscription = await client.subscriptions.create(subscription_create)
print(f"Subscription created successfully with ID: {subscription.id}")
print(f"Subscription name: {subscription.name}")
print(f"Subscription status: {subscription.status}")
Expand All @@ -49,7 +52,7 @@ async def main() -> None:
print(f"Billing cadence: {subscription.billing_cadence}")

# Retrieve the subscription to verify
retrieved_subscription = await client.product_catalog.subscriptions.get_expanded(subscription.id)
retrieved_subscription = await client.subscriptions.get_expanded(subscription.id)
print(f"\nRetrieved subscription: {retrieved_subscription.name}")
print(f"Status: {retrieved_subscription.status}")
if retrieved_subscription.plan:
Expand All @@ -58,7 +61,7 @@ async def main() -> None:

# List subscriptions for the customer
print(f"\nListing subscriptions for customer '{customer_key}'...")
subscriptions_response = await client.customer.customers.list_customer_subscriptions(
subscriptions_response = await client.customers.list_customer_subscriptions(
customer_key, status=[SubscriptionStatus.ACTIVE]
)
for sub in subscriptions_response.items_property:
Expand Down
39 changes: 36 additions & 3 deletions api/client/python/examples/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions api/client/python/examples/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ package-mode = false
[tool.poetry.dependencies]
python = "^3.9"
openmeter = { path = "..", develop = true }

[tool.poetry.group.dev.dependencies]
pyright = "^1.1.407"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
4 changes: 4 additions & 0 deletions api/client/python/examples/pyrightconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"include": ["async", "sync"],
"typeCheckingMode": "basic"
}
31 changes: 18 additions & 13 deletions api/client/python/examples/sync/customer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
CustomerCreate,
CustomerReplaceUpdate,
CustomerUsageAttribution,
Metadata,
)
from corehttp.exceptions import HttpResponseError

Expand All @@ -25,41 +26,45 @@ def main() -> None:
# Create a customer
customer_create = CustomerCreate(
name="Acme Corporation",
key=customer_key,
usage_attribution=CustomerUsageAttribution(subject_keys=[subject_key]),
description="A demo customer for testing",
metadata=Metadata(
{
"industry": "technology",
}
),
key=customer_key,
primary_email="contact@acme-corp.example.com",
currency="EUR",
usage_attribution=CustomerUsageAttribution(subject_keys=[subject_key]),
metadata={
"industry": "technology",
},
)

created_customer = client.customer.customers.create(customer_create)
created_customer = client.customers.create(customer_create)
print(f"Customer created successfully with ID: {created_customer.id}")
print(f"Customer name: {created_customer.name}")
print(f"Customer key: {created_customer.key}")

# Get the customer by ID or key
customer = client.customer.customers.get(created_customer.id)
customer = client.customers.get(created_customer.id)
print(f"\nRetrieved customer: {customer.name}")
print(f"Primary email: {customer.primary_email}")
print(f"Currency: {customer.currency}")

# Update the customer
customer_update = CustomerReplaceUpdate(
name="Acme Corporation Ltd.",
key=customer_key,
usage_attribution=CustomerUsageAttribution(subject_keys=[subject_key]),
description="Updated demo customer",
metadata=Metadata(
{
"industry": "technology",
}
),
key=customer_key,
primary_email="info@acme-corp.example.com",
currency="USD",
usage_attribution=CustomerUsageAttribution(subject_keys=[subject_key]),
metadata={
"industry": "technology",
},
)

updated_customer = client.customer.customers.update(created_customer.id, customer_update)
updated_customer = client.customers.update(created_customer.id, customer_update)
print(f"\nCustomer updated successfully")
print(f"Updated name: {updated_customer.name}")
print(f"Updated email: {updated_customer.primary_email}")
Expand Down
Loading
Loading