Skip to content

Commit 485dd83

Browse files
authored
feat(ProgressiveBilling) - Add usage_thresholds & progressive_billing_credit_amount_cents (#261)
* Add usage_thresholds & progressive_billing_credit_amount_cents attributes * add ruff and check formatting in CI * Fix all Ruff remarks * Force autoformatting with ruff * allow 120 chars line length * add applied_usage_thresholds to the api * Add INP001 rule to ruff linting
1 parent 65176d5 commit 485dd83

File tree

78 files changed

+2231
-1212
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2231
-1212
lines changed

.github/workflows/ruff.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: Ruff
2+
on: [push, pull_request]
3+
jobs:
4+
ruff:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- uses: actions/checkout@v4
8+
- name: Set up Python 3.11
9+
uses: actions/setup-python@v3
10+
with:
11+
python-version: 3.11
12+
- name: Install dependencies
13+
run: |
14+
python -m pip install .[test]
15+
- name: Validate linter rules with Ruff
16+
uses: chartboost/ruff-action@v1
17+
- name: Validate formatting with Ruff
18+
uses: chartboost/ruff-action@v1
19+
with:
20+
args: 'format --check'

lago_python_client/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
from lago_python_client.client import Client
2-
from lago_python_client.version import LAGO_VERSION
1+
from lago_python_client.client import Client as Client
2+
from lago_python_client.version import LAGO_VERSION as LAGO_VERSION

lago_python_client/add_ons/clients.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
from typing import ClassVar, Type
22

33
from ..base_client import BaseClient
4-
from ..mixins import CreateCommandMixin, DestroyCommandMixin, FindAllCommandMixin, FindCommandMixin, UpdateCommandMixin
4+
from ..mixins import (
5+
CreateCommandMixin,
6+
DestroyCommandMixin,
7+
FindAllCommandMixin,
8+
FindCommandMixin,
9+
UpdateCommandMixin,
10+
)
511
from ..models.add_on import AddOnResponse
612

713

@@ -13,6 +19,6 @@ class AddOnClient(
1319
UpdateCommandMixin[AddOnResponse],
1420
BaseClient,
1521
):
16-
API_RESOURCE: ClassVar[str] = 'add_ons'
22+
API_RESOURCE: ClassVar[str] = "add_ons"
1723
RESPONSE_MODEL: ClassVar[Type[AddOnResponse]] = AddOnResponse
18-
ROOT_NAME: ClassVar[str] = 'add_on'
24+
ROOT_NAME: ClassVar[str] = "add_on"
Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
import sys
2-
from typing import Any, ClassVar, Type, Union
1+
from typing import ClassVar, Type
32

43
from ..base_client import BaseClient
5-
from ..mixins import CreateCommandMixin, DestroyCommandMixin, FindAllCommandMixin, FindCommandMixin, UpdateCommandMixin
4+
from ..mixins import (
5+
CreateCommandMixin,
6+
DestroyCommandMixin,
7+
FindAllCommandMixin,
8+
FindCommandMixin,
9+
UpdateCommandMixin,
10+
)
611
from ..models.billable_metric import BillableMetricResponse
7-
from ..services.request import make_headers, make_url, send_get_request
8-
from ..services.response import get_response_data, prepare_index_response, Response
9-
10-
if sys.version_info >= (3, 9):
11-
from collections.abc import Mapping
12-
else:
13-
from typing import Mapping
1412

1513

1614
class BillableMetricClient(
@@ -21,6 +19,6 @@ class BillableMetricClient(
2119
UpdateCommandMixin[BillableMetricResponse],
2220
BaseClient,
2321
):
24-
API_RESOURCE: ClassVar[str] = 'billable_metrics'
22+
API_RESOURCE: ClassVar[str] = "billable_metrics"
2523
RESPONSE_MODEL: ClassVar[Type[BillableMetricResponse]] = BillableMetricResponse
26-
ROOT_NAME: ClassVar[str] = 'billable_metric'
24+
ROOT_NAME: ClassVar[str] = "billable_metric"

lago_python_client/client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@
3030

3131

3232
class Client:
33-
BASE_URL: Final[str] = 'https://api.getlago.com/'
34-
API_PATH: Final[str] = 'api/v1/'
33+
BASE_URL: Final[str] = "https://api.getlago.com/"
34+
API_PATH: Final[str] = "api/v1/"
3535

36-
def __init__(self, api_key: str = '', api_url: str = '') -> None:
36+
def __init__(self, api_key: str = "", api_url: str = "") -> None:
3737
self.api_key: str = api_key
3838
self.api_url: str = api_url
3939

lago_python_client/coupons/clients.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
from typing import ClassVar, Type
22

33
from ..base_client import BaseClient
4-
from ..mixins import CreateCommandMixin, DestroyCommandMixin, FindAllCommandMixin, FindCommandMixin, UpdateCommandMixin
4+
from ..mixins import (
5+
CreateCommandMixin,
6+
DestroyCommandMixin,
7+
FindAllCommandMixin,
8+
FindCommandMixin,
9+
UpdateCommandMixin,
10+
)
511
from ..models.coupon import CouponResponse
612
from ..models.applied_coupon import AppliedCouponResponse
713
from ..services.request import make_headers, make_url, send_delete_request
@@ -16,21 +22,30 @@ class CouponClient(
1622
UpdateCommandMixin[CouponResponse],
1723
BaseClient,
1824
):
19-
API_RESOURCE: ClassVar[str] = 'coupons'
25+
API_RESOURCE: ClassVar[str] = "coupons"
2026
RESPONSE_MODEL: ClassVar[Type[CouponResponse]] = CouponResponse
21-
ROOT_NAME: ClassVar[str] = 'coupon'
27+
ROOT_NAME: ClassVar[str] = "coupon"
2228

2329

24-
class AppliedCouponClient(CreateCommandMixin[AppliedCouponResponse], FindAllCommandMixin[AppliedCouponResponse], BaseClient):
25-
API_RESOURCE: ClassVar[str] = 'applied_coupons'
30+
class AppliedCouponClient(
31+
CreateCommandMixin[AppliedCouponResponse],
32+
FindAllCommandMixin[AppliedCouponResponse],
33+
BaseClient,
34+
):
35+
API_RESOURCE: ClassVar[str] = "applied_coupons"
2636
RESPONSE_MODEL: ClassVar[Type[AppliedCouponResponse]] = AppliedCouponResponse
27-
ROOT_NAME: ClassVar[str] = 'applied_coupon'
37+
ROOT_NAME: ClassVar[str] = "applied_coupon"
2838

2939
def destroy(self, external_customer_id: str, applied_coupon_id: str) -> AppliedCouponResponse:
3040
api_response: Response = send_delete_request(
3141
url=make_url(
3242
origin=self.base_url,
33-
path_parts=('customers', external_customer_id, self.API_RESOURCE, applied_coupon_id),
43+
path_parts=(
44+
"customers",
45+
external_customer_id,
46+
self.API_RESOURCE,
47+
applied_coupon_id,
48+
),
3449
),
3550
headers=make_headers(api_key=self.api_key),
3651
)

lago_python_client/credit_notes/clients.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
1-
from typing import ClassVar, Optional, Type, Union
1+
from typing import ClassVar, Optional, Type
22

33
from ..base_client import BaseClient
4-
from ..mixins import CreateCommandMixin, FindAllCommandMixin, FindCommandMixin, UpdateCommandMixin
5-
from ..models.credit_note import CreditNoteResponse, CreditNoteEstimatedResponse, CreditNoteEstimate
4+
from ..mixins import (
5+
CreateCommandMixin,
6+
FindAllCommandMixin,
7+
FindCommandMixin,
8+
UpdateCommandMixin,
9+
)
10+
from ..models.credit_note import (
11+
CreditNoteResponse,
12+
CreditNoteEstimatedResponse,
13+
CreditNoteEstimate,
14+
)
615
from ..services.json import to_json
7-
from ..services.request import make_headers, make_url, send_post_request, send_put_request
16+
from ..services.request import (
17+
make_headers,
18+
make_url,
19+
send_post_request,
20+
send_put_request,
21+
)
822
from ..services.response import get_response_data, prepare_object_response, Response
923

1024

@@ -15,16 +29,16 @@ class CreditNoteClient(
1529
UpdateCommandMixin[CreditNoteResponse],
1630
BaseClient,
1731
):
18-
API_RESOURCE: ClassVar[str] = 'credit_notes'
19-
ESTIMATE_API_RESOURCE: ClassVar[str] = 'estimated_credit_note'
32+
API_RESOURCE: ClassVar[str] = "credit_notes"
33+
ESTIMATE_API_RESOURCE: ClassVar[str] = "estimated_credit_note"
2034
RESPONSE_MODEL: ClassVar[Type[CreditNoteResponse]] = CreditNoteResponse
21-
ROOT_NAME: ClassVar[str] = 'credit_note'
35+
ROOT_NAME: ClassVar[str] = "credit_note"
2236

2337
def download(self, resource_id: str) -> Optional[CreditNoteResponse]:
2438
api_response: Response = send_post_request(
2539
url=make_url(
2640
origin=self.base_url,
27-
path_parts=(self.API_RESOURCE, resource_id, 'download'),
41+
path_parts=(self.API_RESOURCE, resource_id, "download"),
2842
),
2943
headers=make_headers(api_key=self.api_key),
3044
)
@@ -42,7 +56,7 @@ def void(self, resource_id: str) -> CreditNoteResponse:
4256
api_response: Response = send_put_request(
4357
url=make_url(
4458
origin=self.base_url,
45-
path_parts=(self.API_RESOURCE, resource_id, 'void'),
59+
path_parts=(self.API_RESOURCE, resource_id, "void"),
4660
),
4761
headers=make_headers(api_key=self.api_key),
4862
)
@@ -56,11 +70,13 @@ def estimate(self, input_object: CreditNoteEstimate) -> CreditNoteEstimatedRespo
5670
api_response: Response = send_post_request(
5771
url=make_url(
5872
origin=self.base_url,
59-
path_parts=(self.API_RESOURCE, 'estimate'),
73+
path_parts=(self.API_RESOURCE, "estimate"),
74+
),
75+
content=to_json(
76+
{
77+
self.ROOT_NAME: input_object.dict(),
78+
}
6079
),
61-
content=to_json({
62-
self.ROOT_NAME: input_object.dict(),
63-
}),
6480
headers=make_headers(api_key=self.api_key),
6581
)
6682

lago_python_client/customers/clients.py

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,26 @@
22
from typing import Any, Mapping, ClassVar, Type, Union
33

44
from ..base_client import BaseClient
5-
from ..mixins import CreateCommandMixin, DestroyCommandMixin, FindAllCommandMixin, FindCommandMixin
5+
from ..mixins import (
6+
CreateCommandMixin,
7+
DestroyCommandMixin,
8+
FindAllCommandMixin,
9+
FindCommandMixin,
10+
)
611
from ..models.customer import CustomerResponse
712
from ..models.customer_usage import CustomerUsageResponse
8-
from ..services.request import make_headers, make_url, send_get_request, send_post_request
9-
from ..services.response import get_response_data, prepare_index_response, prepare_object_response, Response
13+
from ..services.request import (
14+
make_headers,
15+
make_url,
16+
send_get_request,
17+
send_post_request,
18+
)
19+
from ..services.response import (
20+
get_response_data,
21+
prepare_index_response,
22+
prepare_object_response,
23+
Response,
24+
)
1025

1126
if sys.version_info >= (3, 9):
1227
from collections.abc import Mapping
@@ -21,67 +36,71 @@ class CustomerClient(
2136
FindCommandMixin[CustomerResponse],
2237
BaseClient,
2338
):
24-
API_RESOURCE: ClassVar[str] = 'customers'
39+
API_RESOURCE: ClassVar[str] = "customers"
2540
RESPONSE_MODEL: ClassVar[Type[CustomerResponse]] = CustomerResponse
26-
ROOT_NAME: ClassVar[str] = 'customer'
41+
ROOT_NAME: ClassVar[str] = "customer"
2742

2843
def current_usage(self, resource_id: str, external_subscription_id: str) -> CustomerUsageResponse:
2944
api_response: Response = send_get_request(
3045
url=make_url(
3146
origin=self.base_url,
32-
path_parts=(self.API_RESOURCE, resource_id, 'current_usage'),
47+
path_parts=(self.API_RESOURCE, resource_id, "current_usage"),
3348
query_pairs={
34-
'external_subscription_id': external_subscription_id,
49+
"external_subscription_id": external_subscription_id,
3550
},
3651
),
3752
headers=make_headers(api_key=self.api_key),
3853
)
3954

4055
return prepare_object_response(
4156
response_model=CustomerUsageResponse,
42-
data=get_response_data(response=api_response, key='customer_usage'),
57+
data=get_response_data(response=api_response, key="customer_usage"),
4358
)
4459

45-
def past_usage(self, resource_id: str, external_subscription_id: str, options: Mapping[str, Union[int, str]] = {}) -> Mapping[str, Any]:
60+
def past_usage(
61+
self,
62+
resource_id: str,
63+
external_subscription_id: str,
64+
options: Mapping[str, Union[int, str]] = {},
65+
) -> Mapping[str, Any]:
4666
api_response: Response = send_get_request(
4767
url=make_url(
4868
origin=self.base_url,
49-
path_parts=(self.API_RESOURCE, resource_id, 'past_usage'),
69+
path_parts=(self.API_RESOURCE, resource_id, "past_usage"),
5070
query_pairs={
51-
'external_subscription_id': external_subscription_id,
71+
"external_subscription_id": external_subscription_id,
5272
**options,
5373
},
5474
),
5575
headers=make_headers(api_key=self.api_key),
5676
)
5777

5878
return prepare_index_response(
59-
api_resource='usage_periods',
79+
api_resource="usage_periods",
6080
response_model=CustomerUsageResponse,
6181
data=get_response_data(response=api_response),
6282
)
6383

64-
6584
def portal_url(self, resource_id: str) -> str:
6685
api_response: Response = send_get_request(
6786
url=make_url(
6887
origin=self.base_url,
69-
path_parts=(self.API_RESOURCE, resource_id, 'portal_url'),
88+
path_parts=(self.API_RESOURCE, resource_id, "portal_url"),
7089
),
7190
headers=make_headers(api_key=self.api_key),
7291
)
7392

7493
response_data = get_response_data(response=api_response, key=self.ROOT_NAME)
75-
return response_data.get('portal_url', '') if isinstance(response_data, Mapping) else ''
94+
return response_data.get("portal_url", "") if isinstance(response_data, Mapping) else ""
7695

7796
def checkout_url(self, resource_id: str) -> str:
7897
api_response: Response = send_post_request(
7998
url=make_url(
8099
origin=self.base_url,
81-
path_parts=(self.API_RESOURCE, resource_id, 'checkout_url'),
100+
path_parts=(self.API_RESOURCE, resource_id, "checkout_url"),
82101
),
83102
headers=make_headers(api_key=self.api_key),
84103
)
85104

86105
response_data = get_response_data(response=api_response, key=self.ROOT_NAME)
87-
return response_data.get('checkout_url', '') if isinstance(response_data, Mapping) else ''
106+
return response_data.get("checkout_url", "") if isinstance(response_data, Mapping) else ""

0 commit comments

Comments
 (0)