lago-python-client 1.45.0__tar.gz → 1.47.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/PKG-INFO +1 -1
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/base_client.py +10 -2
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/client.py +62 -42
- lago_python_client-1.47.0/lago_python_client/exceptions.py +69 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/mixins.py +18 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/fee.py +2 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/invoice_custom_section.py +11 -10
- lago_python_client-1.47.0/lago_python_client/observability.py +67 -0
- lago_python_client-1.47.0/lago_python_client/services/rate_limit.py +235 -0
- lago_python_client-1.47.0/lago_python_client/services/request.py +131 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/services/response.py +10 -1
- lago_python_client-1.47.0/lago_python_client/version.py +1 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client.egg-info/PKG-INFO +1 -1
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client.egg-info/SOURCES.txt +6 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_wallet_client.py +15 -0
- lago_python_client-1.47.0/tests/test_rate_limit.py +602 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_request_services.py +8 -10
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_subscription_client.py +3 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_wallet_client.py +15 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_wallet_transaction_client.py +4 -0
- lago_python_client-1.45.0/lago_python_client/exceptions.py +0 -26
- lago_python_client-1.45.0/lago_python_client/services/request.py +0 -55
- lago_python_client-1.45.0/lago_python_client/version.py +0 -1
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/LICENSE +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/README.md +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/activity_logs/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/activity_logs/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/add_ons/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/add_ons/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/api_logs/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/api_logs/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/base_model.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/billable_metrics/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/billable_metrics/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/billing_entities/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/billing_entities/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/coupons/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/coupons/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/credit_notes/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/credit_notes/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/applied_coupons_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/credit_notes_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/invoices_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/payment_methods_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/payment_requests_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/payments_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/subscriptions_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/wallet_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/wallets/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/wallets/alert_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/wallets/metadata_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/customers/wallets_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/events/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/events/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/fees/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/fees/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/functools_ext.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/gross_revenues/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/gross_revenues/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/invoice_collections/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/invoice_collections/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/invoiced_usages/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/invoiced_usages/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/invoices/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/invoices/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/activity_log.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/add_on.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/alert.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/api_log.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/applied_coupon.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/billable_metric.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/billing_entity.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/billing_period.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/charge.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/coupon.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/credit.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/credit_note.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/customer.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/customer_projected_usage.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/customer_usage.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/error_detail.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/event.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/fixed_charge.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/gross_revenue.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/invoice.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/invoice_collection.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/invoice_item.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/invoiced_usage.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/lifetime_usage.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/minimum_commitment.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/mrr.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/organization.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/overdue_balance.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/payment.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/payment_method.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/payment_receipt.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/payment_request.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/plan.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/subscription.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/tax.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/usage.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/usage_threshold.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/wallet.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/wallet_transaction.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/models/webhook_endpoint.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/mrrs/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/mrrs/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/organizations/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/organizations/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/overdue_balances/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/overdue_balances/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/payment_receipts/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/payment_receipts/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/payment_requests/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/payment_requests/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/payments/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/payments/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/plans/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/plans/charges_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/plans/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/plans/fixed_charges_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/py.typed +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/services/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/services/json.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/subscriptions/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/subscriptions/charges_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/subscriptions/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/subscriptions/fixed_charges_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/taxes/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/taxes/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/usages/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/usages/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/wallets/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/wallets/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/webhook_endpoints/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/webhook_endpoints/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/webhooks/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client/webhooks/clients.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client.egg-info/dependency_links.txt +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client.egg-info/requires.txt +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/lago_python_client.egg-info/top_level.txt +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/pyproject.toml +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/setup.cfg +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_activity_logs_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_add_on_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_api_logs_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_applied_coupon_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_billable_metric_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_billing_entity_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_coupon_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_credit_note_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_applied_coupons_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_credit_notes_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_invoices_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_payment_methods_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_payment_requests_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_payments_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_sbscriptions_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_wallet_alert_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_wallet_metadata_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_customer_wallets_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_event_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_fee_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_functools_ext.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_gross_revenue_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_invoice_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_invoice_collection_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_invoiced_usage_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_json_services.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_mrr_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_organization_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_overdue_balance_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_payment_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_payment_receipt_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_payment_request_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_plan_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_response_services.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_tax_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_usage_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_webhook_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/test_webhook_endpoint_client.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/utils/__init__.py +0 -0
- {lago_python_client-1.45.0 → lago_python_client-1.47.0}/tests/utils/mixin.py +0 -0
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import Type
|
|
2
|
+
from typing import Optional, Type
|
|
3
3
|
|
|
4
4
|
from lago_python_client.base_model import BaseModel
|
|
5
|
+
from lago_python_client.services.rate_limit import RateLimitRetryConfig
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class BaseClient(ABC):
|
|
8
9
|
"""The base class used for each collection client."""
|
|
9
10
|
|
|
10
|
-
def __init__(
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
base_url: str,
|
|
14
|
+
api_key: str,
|
|
15
|
+
base_ingest_url: str = "",
|
|
16
|
+
rate_limit_retry_config: Optional[RateLimitRetryConfig] = None,
|
|
17
|
+
):
|
|
11
18
|
self.base_url = base_url
|
|
12
19
|
self.api_key = api_key
|
|
13
20
|
self.base_ingest_url = base_ingest_url
|
|
21
|
+
self.rate_limit_retry_config = rate_limit_retry_config or RateLimitRetryConfig()
|
|
14
22
|
|
|
15
23
|
@property
|
|
16
24
|
@classmethod
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from typing import Optional
|
|
1
2
|
from urllib.parse import urljoin
|
|
2
3
|
|
|
3
4
|
from .activity_logs.clients import ActivityLogClient
|
|
@@ -32,6 +33,7 @@ from .payments.clients import PaymentClient
|
|
|
32
33
|
from .plans.charges_client import PlanChargesClient
|
|
33
34
|
from .plans.clients import PlanClient
|
|
34
35
|
from .plans.fixed_charges_client import PlanFixedChargesClient
|
|
36
|
+
from .services.rate_limit import RateLimitCallback, RateLimitRetryConfig
|
|
35
37
|
from .subscriptions.charges_client import SubscriptionChargesClient
|
|
36
38
|
from .subscriptions.clients import SubscriptionClient
|
|
37
39
|
from .subscriptions.fixed_charges_client import SubscriptionFixedChargesClient
|
|
@@ -53,12 +55,24 @@ class Client:
|
|
|
53
55
|
API_PATH: Final[str] = "api/v1/"
|
|
54
56
|
|
|
55
57
|
def __init__(
|
|
56
|
-
self,
|
|
58
|
+
self,
|
|
59
|
+
api_key: str = "",
|
|
60
|
+
api_url: str = "",
|
|
61
|
+
use_ingest_service: bool = False,
|
|
62
|
+
ingest_api_url: str = "",
|
|
63
|
+
max_retries: int = 3,
|
|
64
|
+
retry_on_rate_limit: bool = True,
|
|
65
|
+
on_rate_limit_info: Optional[RateLimitCallback] = None,
|
|
57
66
|
) -> None:
|
|
58
67
|
self.api_key: str = api_key
|
|
59
68
|
self.api_url: str = api_url
|
|
60
69
|
self.use_ingest_service: bool = use_ingest_service
|
|
61
70
|
self.ingest_api_url: str = ingest_api_url
|
|
71
|
+
self.rate_limit_retry_config: RateLimitRetryConfig = RateLimitRetryConfig(
|
|
72
|
+
max_retries=max_retries,
|
|
73
|
+
retry_on_rate_limit=retry_on_rate_limit,
|
|
74
|
+
on_rate_limit_info=on_rate_limit_info,
|
|
75
|
+
)
|
|
62
76
|
|
|
63
77
|
@property
|
|
64
78
|
def base_api_url(self) -> str:
|
|
@@ -76,166 +90,172 @@ class Client:
|
|
|
76
90
|
|
|
77
91
|
return urljoin(ingest_url, Client.API_PATH)
|
|
78
92
|
|
|
93
|
+
def _create_client(self, client_class, base_url, api_key, base_ingest_url=""):
|
|
94
|
+
"""Create a client instance with rate limit config."""
|
|
95
|
+
if base_ingest_url:
|
|
96
|
+
return client_class(base_url, api_key, base_ingest_url, self.rate_limit_retry_config)
|
|
97
|
+
return client_class(base_url, api_key, rate_limit_retry_config=self.rate_limit_retry_config)
|
|
98
|
+
|
|
79
99
|
@callable_cached_property
|
|
80
100
|
def add_ons(self) -> AddOnClient:
|
|
81
|
-
return AddOnClient
|
|
101
|
+
return self._create_client(AddOnClient, self.base_api_url, self.api_key)
|
|
82
102
|
|
|
83
103
|
@callable_cached_property
|
|
84
104
|
def billable_metrics(self) -> BillableMetricClient:
|
|
85
|
-
return BillableMetricClient
|
|
105
|
+
return self._create_client(BillableMetricClient, self.base_api_url, self.api_key)
|
|
86
106
|
|
|
87
107
|
@callable_cached_property
|
|
88
108
|
def billing_entities(self) -> BillingEntityClient:
|
|
89
|
-
return BillingEntityClient
|
|
109
|
+
return self._create_client(BillingEntityClient, self.base_api_url, self.api_key)
|
|
90
110
|
|
|
91
111
|
@callable_cached_property
|
|
92
112
|
def coupons(self) -> CouponClient:
|
|
93
|
-
return CouponClient
|
|
113
|
+
return self._create_client(CouponClient, self.base_api_url, self.api_key)
|
|
94
114
|
|
|
95
115
|
@callable_cached_property
|
|
96
116
|
def applied_coupons(self) -> AppliedCouponClient:
|
|
97
|
-
return AppliedCouponClient
|
|
117
|
+
return self._create_client(AppliedCouponClient, self.base_api_url, self.api_key)
|
|
98
118
|
|
|
99
119
|
@callable_cached_property
|
|
100
120
|
def credit_notes(self) -> CreditNoteClient:
|
|
101
|
-
return CreditNoteClient
|
|
121
|
+
return self._create_client(CreditNoteClient, self.base_api_url, self.api_key)
|
|
102
122
|
|
|
103
123
|
@callable_cached_property
|
|
104
124
|
def customers(self) -> CustomerClient:
|
|
105
|
-
return CustomerClient
|
|
125
|
+
return self._create_client(CustomerClient, self.base_api_url, self.api_key)
|
|
106
126
|
|
|
107
127
|
@callable_cached_property
|
|
108
128
|
def customer_applied_coupons(self) -> CustomerAppliedCouponsClient:
|
|
109
|
-
return CustomerAppliedCouponsClient
|
|
129
|
+
return self._create_client(CustomerAppliedCouponsClient, self.base_api_url, self.api_key)
|
|
110
130
|
|
|
111
131
|
@callable_cached_property
|
|
112
132
|
def customer_credit_notes(self) -> CustomerCreditNotesClient:
|
|
113
|
-
return CustomerCreditNotesClient
|
|
133
|
+
return self._create_client(CustomerCreditNotesClient, self.base_api_url, self.api_key)
|
|
114
134
|
|
|
115
135
|
@callable_cached_property
|
|
116
136
|
def customer_invoices(self) -> CustomerInvoicesClient:
|
|
117
|
-
return CustomerInvoicesClient
|
|
137
|
+
return self._create_client(CustomerInvoicesClient, self.base_api_url, self.api_key)
|
|
118
138
|
|
|
119
139
|
@callable_cached_property
|
|
120
140
|
def customer_payment_methods(self) -> CustomerPaymentMethodsClient:
|
|
121
|
-
return CustomerPaymentMethodsClient
|
|
141
|
+
return self._create_client(CustomerPaymentMethodsClient, self.base_api_url, self.api_key)
|
|
122
142
|
|
|
123
143
|
@callable_cached_property
|
|
124
144
|
def customer_payments(self) -> CustomerPaymentsClient:
|
|
125
|
-
return CustomerPaymentsClient
|
|
145
|
+
return self._create_client(CustomerPaymentsClient, self.base_api_url, self.api_key)
|
|
126
146
|
|
|
127
147
|
@callable_cached_property
|
|
128
148
|
def customer_payment_requests(self) -> CustomerPaymentRequestsClient:
|
|
129
|
-
return CustomerPaymentRequestsClient
|
|
149
|
+
return self._create_client(CustomerPaymentRequestsClient, self.base_api_url, self.api_key)
|
|
130
150
|
|
|
131
151
|
@callable_cached_property
|
|
132
152
|
def customer_subscriptions(self) -> CustomerSubscriptionsClient:
|
|
133
|
-
return CustomerSubscriptionsClient
|
|
153
|
+
return self._create_client(CustomerSubscriptionsClient, self.base_api_url, self.api_key)
|
|
134
154
|
|
|
135
155
|
@callable_cached_property
|
|
136
156
|
def customer_wallets(self) -> CustomerWalletsClient:
|
|
137
|
-
return CustomerWalletsClient
|
|
157
|
+
return self._create_client(CustomerWalletsClient, self.base_api_url, self.api_key)
|
|
138
158
|
|
|
139
159
|
@callable_cached_property
|
|
140
160
|
def events(self) -> EventClient:
|
|
141
|
-
return EventClient
|
|
161
|
+
return self._create_client(EventClient, self.base_api_url, self.api_key, self.base_ingest_api_url)
|
|
142
162
|
|
|
143
163
|
@callable_cached_property
|
|
144
164
|
def fees(self) -> FeeClient:
|
|
145
|
-
return FeeClient
|
|
165
|
+
return self._create_client(FeeClient, self.base_api_url, self.api_key)
|
|
146
166
|
|
|
147
167
|
@callable_cached_property
|
|
148
168
|
def gross_revenues(self) -> GrossRevenueClient:
|
|
149
|
-
return GrossRevenueClient
|
|
169
|
+
return self._create_client(GrossRevenueClient, self.base_api_url, self.api_key)
|
|
150
170
|
|
|
151
171
|
@callable_cached_property
|
|
152
172
|
def invoices(self) -> InvoiceClient:
|
|
153
|
-
return InvoiceClient
|
|
173
|
+
return self._create_client(InvoiceClient, self.base_api_url, self.api_key)
|
|
154
174
|
|
|
155
175
|
@callable_cached_property
|
|
156
176
|
def invoiced_usages(self) -> InvoicedUsageClient:
|
|
157
|
-
return InvoicedUsageClient
|
|
177
|
+
return self._create_client(InvoicedUsageClient, self.base_api_url, self.api_key)
|
|
158
178
|
|
|
159
179
|
@callable_cached_property
|
|
160
180
|
def mrrs(self) -> MrrClient:
|
|
161
|
-
return MrrClient
|
|
181
|
+
return self._create_client(MrrClient, self.base_api_url, self.api_key)
|
|
162
182
|
|
|
163
183
|
@callable_cached_property
|
|
164
184
|
def organizations(self) -> OrganizationClient:
|
|
165
|
-
return OrganizationClient
|
|
185
|
+
return self._create_client(OrganizationClient, self.base_api_url, self.api_key)
|
|
166
186
|
|
|
167
187
|
@callable_cached_property
|
|
168
188
|
def overdue_balances(self) -> OverdueBalanceClient:
|
|
169
|
-
return OverdueBalanceClient
|
|
189
|
+
return self._create_client(OverdueBalanceClient, self.base_api_url, self.api_key)
|
|
170
190
|
|
|
171
191
|
@callable_cached_property
|
|
172
192
|
def payment_receipts(self) -> PaymentReceiptClient:
|
|
173
|
-
return PaymentReceiptClient
|
|
193
|
+
return self._create_client(PaymentReceiptClient, self.base_api_url, self.api_key)
|
|
174
194
|
|
|
175
195
|
@callable_cached_property
|
|
176
196
|
def payment_requests(self) -> PaymentRequestClient:
|
|
177
|
-
return PaymentRequestClient
|
|
197
|
+
return self._create_client(PaymentRequestClient, self.base_api_url, self.api_key)
|
|
178
198
|
|
|
179
199
|
@callable_cached_property
|
|
180
200
|
def payments(self) -> PaymentClient:
|
|
181
|
-
return PaymentClient
|
|
201
|
+
return self._create_client(PaymentClient, self.base_api_url, self.api_key)
|
|
182
202
|
|
|
183
203
|
@callable_cached_property
|
|
184
204
|
def invoice_collections(self) -> InvoiceCollectionClient:
|
|
185
|
-
return InvoiceCollectionClient
|
|
205
|
+
return self._create_client(InvoiceCollectionClient, self.base_api_url, self.api_key)
|
|
186
206
|
|
|
187
207
|
@callable_cached_property
|
|
188
208
|
def plans(self) -> PlanClient:
|
|
189
|
-
return PlanClient
|
|
209
|
+
return self._create_client(PlanClient, self.base_api_url, self.api_key)
|
|
190
210
|
|
|
191
211
|
@callable_cached_property
|
|
192
212
|
def plan_charges(self) -> PlanChargesClient:
|
|
193
|
-
return PlanChargesClient
|
|
213
|
+
return self._create_client(PlanChargesClient, self.base_api_url, self.api_key)
|
|
194
214
|
|
|
195
215
|
@callable_cached_property
|
|
196
216
|
def plan_fixed_charges(self) -> PlanFixedChargesClient:
|
|
197
|
-
return PlanFixedChargesClient
|
|
217
|
+
return self._create_client(PlanFixedChargesClient, self.base_api_url, self.api_key)
|
|
198
218
|
|
|
199
219
|
@callable_cached_property
|
|
200
220
|
def subscriptions(self) -> SubscriptionClient:
|
|
201
|
-
return SubscriptionClient
|
|
221
|
+
return self._create_client(SubscriptionClient, self.base_api_url, self.api_key)
|
|
202
222
|
|
|
203
223
|
@callable_cached_property
|
|
204
224
|
def subscription_charges(self) -> SubscriptionChargesClient:
|
|
205
|
-
return SubscriptionChargesClient
|
|
225
|
+
return self._create_client(SubscriptionChargesClient, self.base_api_url, self.api_key)
|
|
206
226
|
|
|
207
227
|
@callable_cached_property
|
|
208
228
|
def subscription_fixed_charges(self) -> SubscriptionFixedChargesClient:
|
|
209
|
-
return SubscriptionFixedChargesClient
|
|
229
|
+
return self._create_client(SubscriptionFixedChargesClient, self.base_api_url, self.api_key)
|
|
210
230
|
|
|
211
231
|
@callable_cached_property
|
|
212
232
|
def taxes(self) -> TaxClient:
|
|
213
|
-
return TaxClient
|
|
233
|
+
return self._create_client(TaxClient, self.base_api_url, self.api_key)
|
|
214
234
|
|
|
215
235
|
@callable_cached_property
|
|
216
236
|
def usages(self) -> UsageClient:
|
|
217
|
-
return UsageClient
|
|
237
|
+
return self._create_client(UsageClient, self.base_api_url, self.api_key)
|
|
218
238
|
|
|
219
239
|
@callable_cached_property
|
|
220
240
|
def wallets(self) -> WalletClient:
|
|
221
|
-
return WalletClient
|
|
241
|
+
return self._create_client(WalletClient, self.base_api_url, self.api_key)
|
|
222
242
|
|
|
223
243
|
@callable_cached_property
|
|
224
244
|
def wallet_transactions(self) -> WalletTransactionClient:
|
|
225
|
-
return WalletTransactionClient
|
|
245
|
+
return self._create_client(WalletTransactionClient, self.base_api_url, self.api_key)
|
|
226
246
|
|
|
227
247
|
@callable_cached_property
|
|
228
248
|
def webhooks(self) -> WebhookClient:
|
|
229
|
-
return WebhookClient
|
|
249
|
+
return self._create_client(WebhookClient, self.base_api_url, self.api_key)
|
|
230
250
|
|
|
231
251
|
@callable_cached_property
|
|
232
252
|
def webhook_endpoints(self) -> WebhookEndpointClient:
|
|
233
|
-
return WebhookEndpointClient
|
|
253
|
+
return self._create_client(WebhookEndpointClient, self.base_api_url, self.api_key)
|
|
234
254
|
|
|
235
255
|
@callable_cached_property
|
|
236
256
|
def activity_logs(self) -> ActivityLogClient:
|
|
237
|
-
return ActivityLogClient
|
|
257
|
+
return self._create_client(ActivityLogClient, self.base_api_url, self.api_key)
|
|
238
258
|
|
|
239
259
|
@callable_cached_property
|
|
240
260
|
def api_logs(self) -> ApiLogClient:
|
|
241
|
-
return ApiLogClient
|
|
261
|
+
return self._create_client(ApiLogClient, self.base_api_url, self.api_key)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from collections.abc import MutableMapping
|
|
2
|
+
from http import HTTPStatus
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LagoApiError(Exception):
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
status_code: int,
|
|
10
|
+
url: Optional[str],
|
|
11
|
+
response: Any,
|
|
12
|
+
detail: Optional[str] = None,
|
|
13
|
+
headers: Optional[MutableMapping[str, str]] = None,
|
|
14
|
+
) -> None:
|
|
15
|
+
if detail is None:
|
|
16
|
+
detail = HTTPStatus(status_code).phrase
|
|
17
|
+
self.status_code = status_code
|
|
18
|
+
self.url = url
|
|
19
|
+
self.response = response
|
|
20
|
+
self.detail = detail
|
|
21
|
+
self.headers = headers
|
|
22
|
+
super().__init__(self.response)
|
|
23
|
+
|
|
24
|
+
def __repr__(self) -> str:
|
|
25
|
+
class_name = self.__class__.__name__
|
|
26
|
+
return f"{class_name}(response={self.response!r}"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class LagoRateLimitError(LagoApiError):
|
|
30
|
+
"""Exception raised when rate limit is exceeded (HTTP 429)."""
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
status_code: int,
|
|
35
|
+
url: Optional[str],
|
|
36
|
+
response: Any,
|
|
37
|
+
detail: Optional[str] = None,
|
|
38
|
+
headers: Optional[MutableMapping[str, str]] = None,
|
|
39
|
+
) -> None:
|
|
40
|
+
super().__init__(
|
|
41
|
+
status_code=status_code,
|
|
42
|
+
url=url,
|
|
43
|
+
response=response,
|
|
44
|
+
detail=detail,
|
|
45
|
+
headers=headers,
|
|
46
|
+
)
|
|
47
|
+
# Parse rate limit headers
|
|
48
|
+
self.limit: Optional[int] = None
|
|
49
|
+
self.remaining: Optional[int] = None
|
|
50
|
+
self.reset: Optional[int] = None
|
|
51
|
+
|
|
52
|
+
if headers:
|
|
53
|
+
try:
|
|
54
|
+
self.limit = int(headers["x-ratelimit-limit"])
|
|
55
|
+
except (KeyError, ValueError, TypeError):
|
|
56
|
+
pass
|
|
57
|
+
try:
|
|
58
|
+
self.remaining = int(headers["x-ratelimit-remaining"])
|
|
59
|
+
except (KeyError, ValueError, TypeError):
|
|
60
|
+
pass
|
|
61
|
+
try:
|
|
62
|
+
self.reset = int(headers["x-ratelimit-reset"])
|
|
63
|
+
except (KeyError, ValueError, TypeError):
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
def __repr__(self) -> str:
|
|
67
|
+
return (
|
|
68
|
+
f"LagoRateLimitError(limit={self.limit}, remaining={self.remaining}, reset={self.reset}, url={self.url!r})"
|
|
69
|
+
)
|
|
@@ -10,6 +10,7 @@ except ImportError: # Python 3.7
|
|
|
10
10
|
from collections.abc import Mapping
|
|
11
11
|
|
|
12
12
|
from lago_python_client.base_model import BaseModel
|
|
13
|
+
from lago_python_client.services.rate_limit import RateLimitRetryConfig
|
|
13
14
|
|
|
14
15
|
from .services.json import to_json
|
|
15
16
|
from .services.request import (
|
|
@@ -47,6 +48,8 @@ class _ClientMixin(Protocol[_PM_co]):
|
|
|
47
48
|
def api_key(self) -> str: ...
|
|
48
49
|
@property
|
|
49
50
|
def base_url(self) -> str: ...
|
|
51
|
+
@property
|
|
52
|
+
def rate_limit_retry_config(self) -> RateLimitRetryConfig: ...
|
|
50
53
|
|
|
51
54
|
|
|
52
55
|
class CreateCommandMixin(Generic[_M]):
|
|
@@ -71,6 +74,7 @@ class CreateCommandMixin(Generic[_M]):
|
|
|
71
74
|
),
|
|
72
75
|
headers=make_headers(api_key=self.api_key),
|
|
73
76
|
timeout=timeout,
|
|
77
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
74
78
|
)
|
|
75
79
|
|
|
76
80
|
# Process response data
|
|
@@ -105,6 +109,7 @@ class DestroyCommandMixin(Generic[_M]):
|
|
|
105
109
|
),
|
|
106
110
|
headers=make_headers(api_key=self.api_key),
|
|
107
111
|
timeout=timeout,
|
|
112
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
108
113
|
)
|
|
109
114
|
|
|
110
115
|
# Process response data
|
|
@@ -134,6 +139,7 @@ class FindAllCommandMixin(Generic[_M]):
|
|
|
134
139
|
),
|
|
135
140
|
headers=make_headers(api_key=self.api_key),
|
|
136
141
|
timeout=timeout,
|
|
142
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
137
143
|
)
|
|
138
144
|
|
|
139
145
|
# Process response data
|
|
@@ -167,6 +173,7 @@ class FindAllChildrenCommandMixin(Generic[_M]):
|
|
|
167
173
|
),
|
|
168
174
|
query_pairs=options,
|
|
169
175
|
),
|
|
176
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
170
177
|
)
|
|
171
178
|
|
|
172
179
|
return prepare_index_response(
|
|
@@ -200,6 +207,7 @@ class FindChildCommandMixin(Generic[_M]):
|
|
|
200
207
|
query_pairs=options,
|
|
201
208
|
),
|
|
202
209
|
headers=make_headers(api_key=self.api_key),
|
|
210
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
203
211
|
)
|
|
204
212
|
|
|
205
213
|
return prepare_object_response(
|
|
@@ -232,6 +240,7 @@ class CreateChildCommandMixin(Generic[_M]):
|
|
|
232
240
|
),
|
|
233
241
|
content=to_json({self.ROOT_NAME: input_object.dict(exclude_none=True)}),
|
|
234
242
|
headers=make_headers(api_key=self.api_key),
|
|
243
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
235
244
|
)
|
|
236
245
|
|
|
237
246
|
return prepare_object_response(
|
|
@@ -266,6 +275,7 @@ class UpdateChildCommandMixin(Generic[_M]):
|
|
|
266
275
|
),
|
|
267
276
|
content=to_json({self.ROOT_NAME: input_object.dict(exclude_none=True)}),
|
|
268
277
|
headers=make_headers(api_key=self.api_key),
|
|
278
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
269
279
|
)
|
|
270
280
|
|
|
271
281
|
return prepare_object_response(
|
|
@@ -298,6 +308,7 @@ class DestroyChildCommandMixin(Generic[_M]):
|
|
|
298
308
|
query_pairs=options,
|
|
299
309
|
),
|
|
300
310
|
headers=make_headers(api_key=self.api_key),
|
|
311
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
301
312
|
)
|
|
302
313
|
|
|
303
314
|
return prepare_object_response(
|
|
@@ -327,6 +338,7 @@ class FindCommandMixin(Generic[_M]):
|
|
|
327
338
|
),
|
|
328
339
|
headers=make_headers(api_key=self.api_key),
|
|
329
340
|
timeout=timeout,
|
|
341
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
330
342
|
)
|
|
331
343
|
|
|
332
344
|
# Process response data
|
|
@@ -359,6 +371,7 @@ class UpdateCommandMixin(Generic[_M]):
|
|
|
359
371
|
),
|
|
360
372
|
headers=make_headers(api_key=self.api_key),
|
|
361
373
|
timeout=timeout,
|
|
374
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
362
375
|
)
|
|
363
376
|
|
|
364
377
|
# Process response data
|
|
@@ -389,6 +402,7 @@ class NestedCreateCommandMixin(Generic[_M]):
|
|
|
389
402
|
),
|
|
390
403
|
headers=make_headers(api_key=self.api_key),
|
|
391
404
|
timeout=timeout,
|
|
405
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
392
406
|
)
|
|
393
407
|
|
|
394
408
|
# Process response data
|
|
@@ -426,6 +440,7 @@ class NestedUpdateCommandMixin(Generic[_M]):
|
|
|
426
440
|
),
|
|
427
441
|
headers=make_headers(api_key=self.api_key),
|
|
428
442
|
timeout=timeout,
|
|
443
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
429
444
|
)
|
|
430
445
|
|
|
431
446
|
# Process response data
|
|
@@ -454,6 +469,7 @@ class NestedDestroyCommandMixin(Generic[_M]):
|
|
|
454
469
|
),
|
|
455
470
|
headers=make_headers(api_key=self.api_key),
|
|
456
471
|
timeout=timeout,
|
|
472
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
457
473
|
)
|
|
458
474
|
|
|
459
475
|
# Process response data
|
|
@@ -482,6 +498,7 @@ class NestedFindCommandMixin(Generic[_M]):
|
|
|
482
498
|
),
|
|
483
499
|
headers=make_headers(api_key=self.api_key),
|
|
484
500
|
timeout=timeout,
|
|
501
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
485
502
|
)
|
|
486
503
|
|
|
487
504
|
# Process response data
|
|
@@ -510,6 +527,7 @@ class NestedFindAllCommandMixin(Generic[_M]):
|
|
|
510
527
|
),
|
|
511
528
|
headers=make_headers(api_key=self.api_key),
|
|
512
529
|
timeout=timeout,
|
|
530
|
+
rate_limit_retry_config=self.rate_limit_retry_config,
|
|
513
531
|
)
|
|
514
532
|
|
|
515
533
|
# Process response data
|
|
@@ -53,6 +53,8 @@ class FeeResponse(BaseResponseModel):
|
|
|
53
53
|
total_amount_cents: Optional[int]
|
|
54
54
|
unit_amount_cents: Optional[int] # deprecated
|
|
55
55
|
precise_unit_amount: Optional[str]
|
|
56
|
+
sub_total_excluding_taxes_amount_cents: Optional[int]
|
|
57
|
+
sub_total_excluding_taxes_precise_amount_cents: Optional[str]
|
|
56
58
|
precise_amount: Optional[str]
|
|
57
59
|
precise_total_amount: Optional[str]
|
|
58
60
|
taxes_precise_amount: Optional[str]
|
|
@@ -10,16 +10,6 @@ class InvoiceCustomSectionInput(BaseModel):
|
|
|
10
10
|
invoice_custom_section_codes: Optional[List[str]]
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class AppliedInvoiceCustomSection(BaseResponseModel):
|
|
14
|
-
lago_id: Optional[str]
|
|
15
|
-
invoice_custom_section_id: Optional[str]
|
|
16
|
-
created_at: Optional[str]
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class AppliedInvoiceCustomSections(BaseResponseModel):
|
|
20
|
-
__root__: List[AppliedInvoiceCustomSection]
|
|
21
|
-
|
|
22
|
-
|
|
23
13
|
class InvoiceCustomSectionResponse(BaseResponseModel):
|
|
24
14
|
lago_id: Optional[str]
|
|
25
15
|
code: Optional[str]
|
|
@@ -30,5 +20,16 @@ class InvoiceCustomSectionResponse(BaseResponseModel):
|
|
|
30
20
|
applied_to_organization: Optional[bool] # Deprecated
|
|
31
21
|
|
|
32
22
|
|
|
23
|
+
class AppliedInvoiceCustomSection(BaseResponseModel):
|
|
24
|
+
lago_id: Optional[str]
|
|
25
|
+
invoice_custom_section_id: Optional[str]
|
|
26
|
+
created_at: Optional[str]
|
|
27
|
+
invoice_custom_section: Optional[InvoiceCustomSectionResponse]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AppliedInvoiceCustomSections(BaseResponseModel):
|
|
31
|
+
__root__: List[AppliedInvoiceCustomSection]
|
|
32
|
+
|
|
33
|
+
|
|
33
34
|
class InvoiceCustomSectionsResponseList(BaseResponseModel):
|
|
34
35
|
__root__: List[InvoiceCustomSectionResponse]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Optional observability helpers for Lago rate limits.
|
|
3
|
+
|
|
4
|
+
Provides ready-to-use ``on_rate_limit_info`` callbacks so callers can opt into
|
|
5
|
+
rate limit observability without writing one themselves.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
from lago_python_client import Client
|
|
9
|
+
from lago_python_client.observability import LoggingRateLimitObserver
|
|
10
|
+
|
|
11
|
+
client = Client(
|
|
12
|
+
api_key="...",
|
|
13
|
+
on_rate_limit_info=LoggingRateLimitObserver(),
|
|
14
|
+
)
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import logging
|
|
18
|
+
from typing import Optional, Sequence
|
|
19
|
+
|
|
20
|
+
from .services.rate_limit import RateLimitInfo
|
|
21
|
+
|
|
22
|
+
DEFAULT_THRESHOLDS: Sequence[float] = (0.80, 0.90, 0.95)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class LoggingRateLimitObserver:
|
|
26
|
+
"""
|
|
27
|
+
Emits a log line each time rate limit usage crosses a configured threshold.
|
|
28
|
+
|
|
29
|
+
Stateless across calls: every response that lands above any threshold logs.
|
|
30
|
+
If you want one-shot crossings, wrap it with your own state.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
thresholds: Usage fractions (0.0 - 1.0) that should produce a log line.
|
|
34
|
+
Defaults to 80%, 90%, 95%.
|
|
35
|
+
logger: Logger to emit on. Defaults to ``lago_python_client.rate_limit``.
|
|
36
|
+
level: Log level used when a threshold is crossed. Defaults to WARNING.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
thresholds: Sequence[float] = DEFAULT_THRESHOLDS,
|
|
42
|
+
logger: Optional[logging.Logger] = None,
|
|
43
|
+
level: int = logging.WARNING,
|
|
44
|
+
) -> None:
|
|
45
|
+
# Sort descending so we report the highest matching threshold first.
|
|
46
|
+
self.thresholds = tuple(sorted(thresholds, reverse=True))
|
|
47
|
+
self.logger = logger or logging.getLogger("lago_python_client.rate_limit")
|
|
48
|
+
self.level = level
|
|
49
|
+
|
|
50
|
+
def __call__(self, info: RateLimitInfo) -> None:
|
|
51
|
+
pct = info.usage_pct
|
|
52
|
+
if pct is None:
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
for threshold in self.thresholds:
|
|
56
|
+
if pct >= threshold:
|
|
57
|
+
self.logger.log(
|
|
58
|
+
self.level,
|
|
59
|
+
"Lago rate limit at %.0f%% (limit=%s, remaining=%s, reset=%ss, %s %s)",
|
|
60
|
+
pct * 100,
|
|
61
|
+
info.limit,
|
|
62
|
+
info.remaining,
|
|
63
|
+
info.reset,
|
|
64
|
+
info.method,
|
|
65
|
+
info.url,
|
|
66
|
+
)
|
|
67
|
+
return
|