paddle-python-sdk 1.7.0__py3-none-any.whl → 1.9.0__py3-none-any.whl

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.
Files changed (37) hide show
  1. paddle_billing/Client.py +3 -1
  2. paddle_billing/Entities/ClientToken.py +33 -0
  3. paddle_billing/Entities/ClientTokens/ClientTokenStatus.py +6 -0
  4. paddle_billing/Entities/ClientTokens/__init__.py +1 -0
  5. paddle_billing/Entities/Collections/ClientTokenCollection.py +14 -0
  6. paddle_billing/Entities/Collections/__init__.py +1 -0
  7. paddle_billing/Entities/Events/EventTypeName.py +4 -0
  8. paddle_billing/Entities/Shared/TransactionPayoutTotals.py +4 -0
  9. paddle_billing/Entities/Shared/TransactionPayoutTotalsAdjusted.py +2 -0
  10. paddle_billing/Notifications/Entities/ClientToken.py +33 -0
  11. paddle_billing/Notifications/Entities/ClientTokens/ClientTokenStatus.py +6 -0
  12. paddle_billing/Notifications/Entities/ClientTokens/__init__.py +1 -0
  13. paddle_billing/Notifications/Entities/Shared/TransactionPayoutTotals.py +4 -0
  14. paddle_billing/Notifications/Entities/Shared/TransactionPayoutTotalsAdjusted.py +2 -0
  15. paddle_billing/Notifications/Entities/Simulations/ClientToken.py +38 -0
  16. paddle_billing/Notifications/Entities/Simulations/__init__.py +1 -0
  17. paddle_billing/Notifications/Events/ClientTokenCreated.py +17 -0
  18. paddle_billing/Notifications/Events/ClientTokenRevoked.py +17 -0
  19. paddle_billing/Notifications/Events/ClientTokenUpdated.py +17 -0
  20. paddle_billing/Notifications/Events/DiscountGroupUpdated.py +17 -0
  21. paddle_billing/Resources/ClientTokens/ClientTokensClient.py +50 -0
  22. paddle_billing/Resources/ClientTokens/Operations/CreateClientToken.py +10 -0
  23. paddle_billing/Resources/ClientTokens/Operations/ListClientTokens.py +35 -0
  24. paddle_billing/Resources/ClientTokens/Operations/UpdateClientToken.py +10 -0
  25. paddle_billing/Resources/ClientTokens/Operations/__init__.py +3 -0
  26. paddle_billing/Resources/ClientTokens/__init__.py +0 -0
  27. paddle_billing/Resources/DiscountGroups/DiscountGroupsClient.py +21 -2
  28. paddle_billing/Resources/DiscountGroups/Operations/UpdateDiscountGroup.py +11 -0
  29. paddle_billing/Resources/DiscountGroups/Operations/__init__.py +1 -0
  30. {paddle_python_sdk-1.7.0.dist-info → paddle_python_sdk-1.9.0.dist-info}/METADATA +3 -3
  31. {paddle_python_sdk-1.7.0.dist-info → paddle_python_sdk-1.9.0.dist-info}/RECORD +37 -16
  32. tests/Functional/Resources/ClientToken/__init__.py +0 -0
  33. tests/Functional/Resources/ClientToken/test_ClientTokensClient.py +298 -0
  34. tests/Functional/Resources/DiscountGroups/test_DiscountGroupsClient.py +150 -2
  35. {paddle_python_sdk-1.7.0.dist-info → paddle_python_sdk-1.9.0.dist-info}/WHEEL +0 -0
  36. {paddle_python_sdk-1.7.0.dist-info → paddle_python_sdk-1.9.0.dist-info}/licenses/LICENSE +0 -0
  37. {paddle_python_sdk-1.7.0.dist-info → paddle_python_sdk-1.9.0.dist-info}/top_level.txt +0 -0
paddle_billing/Client.py CHANGED
@@ -18,6 +18,7 @@ from paddle_billing.Logger.NullHandler import NullHandler
18
18
  from paddle_billing.Resources.Addresses.AddressesClient import AddressesClient
19
19
  from paddle_billing.Resources.Adjustments.AdjustmentsClient import AdjustmentsClient
20
20
  from paddle_billing.Resources.Businesses.BusinessesClient import BusinessesClient
21
+ from paddle_billing.Resources.ClientTokens.ClientTokensClient import ClientTokensClient
21
22
  from paddle_billing.Resources.Customers.CustomersClient import CustomersClient
22
23
  from paddle_billing.Resources.CustomerPortalSessions.CustomerPortalSessionsClient import CustomerPortalSessionsClient
23
24
  from paddle_billing.Resources.DiscountGroups.DiscountGroupsClient import DiscountGroupsClient
@@ -71,6 +72,7 @@ class Client:
71
72
  self.addresses = AddressesClient(self)
72
73
  self.adjustments = AdjustmentsClient(self)
73
74
  self.businesses = BusinessesClient(self)
75
+ self.client_tokens = ClientTokensClient(self)
74
76
  self.customers = CustomersClient(self)
75
77
  self.customer_portal_sessions = CustomerPortalSessionsClient(self)
76
78
  self.discounts = DiscountsClient(self)
@@ -198,7 +200,7 @@ class Client:
198
200
  "Authorization": f"Bearer {self.__api_key}",
199
201
  "Content-Type": "application/json",
200
202
  "Paddle-Version": str(self.use_api_version),
201
- "User-Agent": "PaddleSDK/python 1.7.0",
203
+ "User-Agent": "PaddleSDK/python 1.9.0",
202
204
  }
203
205
  )
204
206
 
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from typing import Any
6
+
7
+ from paddle_billing.Entities.Entity import Entity
8
+ from paddle_billing.Entities.ClientTokens import ClientTokenStatus
9
+
10
+
11
+ @dataclass
12
+ class ClientToken(Entity):
13
+ id: str
14
+ status: ClientTokenStatus
15
+ token: str
16
+ name: str
17
+ description: str | None
18
+ created_at: datetime
19
+ updated_at: datetime
20
+ revoked_at: datetime | None
21
+
22
+ @staticmethod
23
+ def from_dict(data: dict[str, Any]) -> ClientToken:
24
+ return ClientToken(
25
+ id=data["id"],
26
+ status=ClientTokenStatus(data["status"]),
27
+ token=data["token"],
28
+ name=data["name"],
29
+ description=data.get("description"),
30
+ created_at=datetime.fromisoformat(data["created_at"]),
31
+ updated_at=datetime.fromisoformat(data["updated_at"]),
32
+ revoked_at=datetime.fromisoformat(data["revoked_at"]) if data.get("revoked_at") else None,
33
+ )
@@ -0,0 +1,6 @@
1
+ from paddle_billing.PaddleStrEnum import PaddleStrEnum, PaddleStrEnumMeta
2
+
3
+
4
+ class ClientTokenStatus(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
5
+ Active: "ClientTokenStatus" = "active"
6
+ Revoked: "ClientTokenStatus" = "revoked"
@@ -0,0 +1 @@
1
+ from paddle_billing.Entities.ClientTokens.ClientTokenStatus import ClientTokenStatus
@@ -0,0 +1,14 @@
1
+ from __future__ import annotations
2
+ from typing import Any
3
+
4
+ from paddle_billing.Entities.Collections.Collection import Collection
5
+ from paddle_billing.Entities.Collections.Paginator import Paginator
6
+ from paddle_billing.Entities.ClientToken import ClientToken
7
+
8
+
9
+ class ClientTokenCollection(Collection[ClientToken]):
10
+ @classmethod
11
+ def from_list(cls, items_data: list[dict[str, Any]], paginator: Paginator | None = None) -> ClientTokenCollection:
12
+ items: list[ClientToken] = [ClientToken.from_dict(item) for item in items_data]
13
+
14
+ return ClientTokenCollection(items, paginator)
@@ -1,6 +1,7 @@
1
1
  from paddle_billing.Entities.Collections.AddressCollection import AddressCollection
2
2
  from paddle_billing.Entities.Collections.AdjustmentCollection import AdjustmentCollection
3
3
  from paddle_billing.Entities.Collections.BusinessCollection import BusinessCollection
4
+ from paddle_billing.Entities.Collections.ClientTokenCollection import ClientTokenCollection
4
5
  from paddle_billing.Entities.Collections.Collection import Collection
5
6
  from paddle_billing.Entities.Collections.CreditBalanceCollection import CreditBalanceCollection
6
7
  from paddle_billing.Entities.Collections.CustomerCollection import CustomerCollection
@@ -15,6 +15,9 @@ class EventTypeName(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
15
15
  BusinessCreated: "EventTypeName" = "business.created"
16
16
  BusinessImported: "EventTypeName" = "business.imported"
17
17
  BusinessUpdated: "EventTypeName" = "business.updated"
18
+ ClientTokenCreated: "EventTypeName" = "client_token.created"
19
+ ClientTokenRevoked: "EventTypeName" = "client_token.revoked"
20
+ ClientTokenUpdated: "EventTypeName" = "client_token.updated"
18
21
  CustomerCreated: "EventTypeName" = "customer.created"
19
22
  CustomerImported: "EventTypeName" = "customer.imported"
20
23
  CustomerUpdated: "EventTypeName" = "customer.updated"
@@ -22,6 +25,7 @@ class EventTypeName(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
22
25
  DiscountImported: "EventTypeName" = "discount.imported"
23
26
  DiscountUpdated: "EventTypeName" = "discount.updated"
24
27
  DiscountGroupCreated: "EventTypeName" = "discount_group.created"
28
+ DiscountGroupUpdated: "EventTypeName" = "discount_group.updated"
25
29
  InvoiceCanceled: "EventTypeName" = "invoice.canceled"
26
30
  InvoiceCreated: "EventTypeName" = "invoice.created"
27
31
  InvoiceIssued: "EventTypeName" = "invoice.issued"
@@ -18,6 +18,8 @@ class TransactionPayoutTotals:
18
18
  earnings: str | None
19
19
  currency_code: CurrencyCodePayouts
20
20
  credit_to_balance: str
21
+ exchange_rate: str
22
+ fee_rate: str
21
23
 
22
24
  @staticmethod
23
25
  def from_dict(data: dict[str, Any]) -> TransactionPayoutTotals:
@@ -33,4 +35,6 @@ class TransactionPayoutTotals:
33
35
  earnings=data.get("earnings"),
34
36
  currency_code=CurrencyCodePayouts(data["currency_code"]),
35
37
  credit_to_balance=data["credit_to_balance"],
38
+ exchange_rate=data["exchange_rate"],
39
+ fee_rate=data["fee_rate"],
36
40
  )
@@ -15,6 +15,7 @@ class TransactionPayoutTotalsAdjusted:
15
15
  chargeback_fee: ChargebackFee
16
16
  earnings: str
17
17
  currency_code: CurrencyCodePayouts
18
+ exchange_rate: str
18
19
 
19
20
  @staticmethod
20
21
  def from_dict(data: dict[str, Any]) -> TransactionPayoutTotalsAdjusted:
@@ -26,4 +27,5 @@ class TransactionPayoutTotalsAdjusted:
26
27
  chargeback_fee=ChargebackFee.from_dict(data["chargeback_fee"]),
27
28
  earnings=data["earnings"],
28
29
  currency_code=CurrencyCodePayouts(data["currency_code"]),
30
+ exchange_rate=data["exchange_rate"],
29
31
  )
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from typing import Any
6
+
7
+ from paddle_billing.Notifications.Entities.Entity import Entity
8
+ from paddle_billing.Notifications.Entities.ClientTokens import ClientTokenStatus
9
+
10
+
11
+ @dataclass
12
+ class ClientToken(Entity):
13
+ id: str
14
+ status: ClientTokenStatus
15
+ token: str
16
+ name: str
17
+ description: str | None
18
+ created_at: datetime
19
+ updated_at: datetime
20
+ revoked_at: datetime | None
21
+
22
+ @staticmethod
23
+ def from_dict(data: dict[str, Any]) -> ClientToken:
24
+ return ClientToken(
25
+ id=data["id"],
26
+ status=ClientTokenStatus(data["status"]),
27
+ token=data["token"],
28
+ name=data["name"],
29
+ description=data.get("description"),
30
+ created_at=datetime.fromisoformat(data["created_at"]),
31
+ updated_at=datetime.fromisoformat(data["updated_at"]),
32
+ revoked_at=datetime.fromisoformat(data["revoked_at"]) if data.get("revoked_at") else None,
33
+ )
@@ -0,0 +1,6 @@
1
+ from paddle_billing.PaddleStrEnum import PaddleStrEnum, PaddleStrEnumMeta
2
+
3
+
4
+ class ClientTokenStatus(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
5
+ Active: "ClientTokenStatus" = "active"
6
+ Revoked: "ClientTokenStatus" = "revoked"
@@ -0,0 +1 @@
1
+ from paddle_billing.Notifications.Entities.ClientTokens.ClientTokenStatus import ClientTokenStatus
@@ -18,6 +18,8 @@ class TransactionPayoutTotals:
18
18
  earnings: str | None
19
19
  currency_code: CurrencyCodePayouts
20
20
  credit_to_balance: str
21
+ exchange_rate: str | None
22
+ fee_rate: str | None
21
23
 
22
24
  @staticmethod
23
25
  def from_dict(data: dict[str, Any]) -> TransactionPayoutTotals:
@@ -33,4 +35,6 @@ class TransactionPayoutTotals:
33
35
  earnings=data.get("earnings"),
34
36
  currency_code=CurrencyCodePayouts(data["currency_code"]),
35
37
  credit_to_balance=data["credit_to_balance"],
38
+ exchange_rate=data.get("exchange_rate"),
39
+ fee_rate=data.get("fee_rate"),
36
40
  )
@@ -15,6 +15,7 @@ class TransactionPayoutTotalsAdjusted:
15
15
  chargeback_fee: ChargebackFee
16
16
  earnings: str
17
17
  currency_code: CurrencyCodePayouts
18
+ exchange_rate: str | None
18
19
 
19
20
  @staticmethod
20
21
  def from_dict(data: dict[str, Any]) -> TransactionPayoutTotalsAdjusted:
@@ -26,4 +27,5 @@ class TransactionPayoutTotalsAdjusted:
26
27
  chargeback_fee=ChargebackFee.from_dict(data["chargeback_fee"]),
27
28
  earnings=data["earnings"],
28
29
  currency_code=CurrencyCodePayouts(data["currency_code"]),
30
+ exchange_rate=data.get("exchange_rate"),
29
31
  )
@@ -0,0 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from typing import Any
6
+
7
+ from paddle_billing.Notifications.Entities.Simulations.SimulationEntity import SimulationEntity
8
+ from paddle_billing.Notifications.Entities.ClientTokens import ClientTokenStatus
9
+ from paddle_billing.Undefined import Undefined
10
+
11
+
12
+ @dataclass
13
+ class ClientToken(SimulationEntity):
14
+ id: str | Undefined = Undefined()
15
+ status: ClientTokenStatus | Undefined = Undefined()
16
+ token: str | Undefined = Undefined()
17
+ name: str | Undefined = Undefined()
18
+ description: str | None | Undefined = Undefined()
19
+ created_at: datetime | Undefined = Undefined()
20
+ updated_at: datetime | Undefined = Undefined()
21
+ revoked_at: datetime | None | Undefined = Undefined()
22
+
23
+ @staticmethod
24
+ def from_dict(data: dict[str, Any]) -> ClientToken:
25
+ return ClientToken(
26
+ id=data.get("id", Undefined()),
27
+ status=ClientTokenStatus(data["status"]) if data.get("status") else Undefined(),
28
+ token=data.get("token", Undefined()),
29
+ name=data.get("name", Undefined()),
30
+ description=data.get("description", Undefined()),
31
+ created_at=datetime.fromisoformat(data["created_at"]) if data.get("created_at") else Undefined(),
32
+ updated_at=datetime.fromisoformat(data["updated_at"]) if data.get("updated_at") else Undefined(),
33
+ revoked_at=(
34
+ datetime.fromisoformat(data["revoked_at"])
35
+ if data.get("revoked_at")
36
+ else data.get("revoked_at", Undefined())
37
+ ),
38
+ )
@@ -1,6 +1,7 @@
1
1
  from paddle_billing.Notifications.Entities.Simulations.Address import Address
2
2
  from paddle_billing.Notifications.Entities.Simulations.Adjustment import Adjustment
3
3
  from paddle_billing.Notifications.Entities.Simulations.Business import Business
4
+ from paddle_billing.Notifications.Entities.Simulations.ClientToken import ClientToken
4
5
  from paddle_billing.Notifications.Entities.Simulations.Customer import Customer
5
6
  from paddle_billing.Notifications.Entities.Simulations.Discount import Discount
6
7
  from paddle_billing.Notifications.Entities.Simulations.PaymentMethod import PaymentMethod
@@ -0,0 +1,17 @@
1
+ from datetime import datetime
2
+
3
+ from paddle_billing.Entities.Event import Event
4
+ from paddle_billing.Entities.Events import EventTypeName
5
+
6
+ from paddle_billing.Notifications.Entities.ClientToken import ClientToken
7
+
8
+
9
+ class ClientTokenCreated(Event):
10
+ def __init__(
11
+ self,
12
+ event_id: str,
13
+ event_type: EventTypeName,
14
+ occurred_at: datetime,
15
+ data: ClientToken,
16
+ ):
17
+ super().__init__(event_id, event_type, occurred_at, data)
@@ -0,0 +1,17 @@
1
+ from datetime import datetime
2
+
3
+ from paddle_billing.Entities.Event import Event
4
+ from paddle_billing.Entities.Events import EventTypeName
5
+
6
+ from paddle_billing.Notifications.Entities.ClientToken import ClientToken
7
+
8
+
9
+ class ClientTokenRevoked(Event):
10
+ def __init__(
11
+ self,
12
+ event_id: str,
13
+ event_type: EventTypeName,
14
+ occurred_at: datetime,
15
+ data: ClientToken,
16
+ ):
17
+ super().__init__(event_id, event_type, occurred_at, data)
@@ -0,0 +1,17 @@
1
+ from datetime import datetime
2
+
3
+ from paddle_billing.Entities.Event import Event
4
+ from paddle_billing.Entities.Events import EventTypeName
5
+
6
+ from paddle_billing.Notifications.Entities.ClientToken import ClientToken
7
+
8
+
9
+ class ClientTokenUpdated(Event):
10
+ def __init__(
11
+ self,
12
+ event_id: str,
13
+ event_type: EventTypeName,
14
+ occurred_at: datetime,
15
+ data: ClientToken,
16
+ ):
17
+ super().__init__(event_id, event_type, occurred_at, data)
@@ -0,0 +1,17 @@
1
+ from datetime import datetime
2
+
3
+ from paddle_billing.Entities.Event import Event
4
+ from paddle_billing.Entities.Events import EventTypeName
5
+
6
+ from paddle_billing.Notifications.Entities.DiscountGroup import DiscountGroup
7
+
8
+
9
+ class DiscountGroupUpdated(Event):
10
+ def __init__(
11
+ self,
12
+ event_id: str,
13
+ event_type: EventTypeName,
14
+ occurred_at: datetime,
15
+ data: DiscountGroup,
16
+ ):
17
+ super().__init__(event_id, event_type, occurred_at, data)
@@ -0,0 +1,50 @@
1
+ from paddle_billing.ResponseParser import ResponseParser
2
+
3
+ from paddle_billing.Entities.Collections import Paginator, ClientTokenCollection
4
+ from paddle_billing.Entities.ClientToken import ClientToken
5
+ from paddle_billing.Entities.ClientTokens import ClientTokenStatus
6
+
7
+ from paddle_billing.Resources.ClientTokens.Operations import CreateClientToken, ListClientTokens, UpdateClientToken
8
+
9
+ from typing import TYPE_CHECKING
10
+
11
+ if TYPE_CHECKING:
12
+ from paddle_billing.Client import Client
13
+
14
+
15
+ class ClientTokensClient:
16
+ def __init__(self, client: "Client"):
17
+ self.client = client
18
+ self.response = None
19
+
20
+ def list(self, operation: ListClientTokens | None = None) -> ClientTokenCollection:
21
+ if operation is None:
22
+ operation = ListClientTokens()
23
+
24
+ self.response = self.client.get_raw("/client-tokens", operation.get_parameters())
25
+ parser = ResponseParser(self.response)
26
+
27
+ return ClientTokenCollection.from_list(
28
+ parser.get_list(), Paginator(self.client, parser.get_pagination(), ClientTokenCollection)
29
+ )
30
+
31
+ def get(self, client_token_id: str) -> ClientToken:
32
+ self.response = self.client.get_raw(f"/client-tokens/{client_token_id}")
33
+ parser = ResponseParser(self.response)
34
+
35
+ return ClientToken.from_dict(parser.get_dict())
36
+
37
+ def create(self, operation: CreateClientToken) -> ClientToken:
38
+ self.response = self.client.post_raw("/client-tokens", operation)
39
+ parser = ResponseParser(self.response)
40
+
41
+ return ClientToken.from_dict(parser.get_dict())
42
+
43
+ def update(self, client_token_id: str, operation: UpdateClientToken) -> ClientToken:
44
+ self.response = self.client.patch_raw(f"/client-tokens/{client_token_id}", operation)
45
+ parser = ResponseParser(self.response)
46
+
47
+ return ClientToken.from_dict(parser.get_dict())
48
+
49
+ def revoke(self, client_token_id: str) -> ClientToken:
50
+ return self.update(client_token_id, UpdateClientToken(status=ClientTokenStatus.Revoked))
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass
2
+
3
+ from paddle_billing.Operation import Operation
4
+ from paddle_billing.Undefined import Undefined
5
+
6
+
7
+ @dataclass
8
+ class CreateClientToken(Operation):
9
+ name: str
10
+ description: str | None | Undefined = Undefined()
@@ -0,0 +1,35 @@
1
+ from paddle_billing.Entities.ClientToken import ClientTokenStatus
2
+ from paddle_billing.EnumStringify import enum_stringify
3
+ from paddle_billing.HasParameters import HasParameters
4
+
5
+ from paddle_billing.Exceptions.SdkExceptions.InvalidArgumentException import InvalidArgumentException
6
+ from paddle_billing.Resources.Shared.Operations import Pager
7
+
8
+
9
+ class ListClientTokens(HasParameters):
10
+ def __init__(
11
+ self,
12
+ pager: Pager | None = None,
13
+ statuses: list[ClientTokenStatus] | None = None,
14
+ ):
15
+ self.pager = pager
16
+ self.statuses = statuses if statuses is not None else []
17
+
18
+ # Validation
19
+ for field_name, field_value, field_type in [
20
+ ("statuses", self.statuses, ClientTokenStatus),
21
+ ]:
22
+ invalid_items = [item for item in field_value if not isinstance(item, field_type)]
23
+ if invalid_items:
24
+ raise InvalidArgumentException.array_contains_invalid_types(
25
+ field_name, field_type.__name__, invalid_items
26
+ )
27
+
28
+ def get_parameters(self) -> dict[str, str]:
29
+ parameters = {}
30
+ if self.pager:
31
+ parameters.update(self.pager.get_parameters())
32
+ if self.statuses:
33
+ parameters["status"] = ",".join(map(enum_stringify, self.statuses))
34
+
35
+ return parameters
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass
2
+
3
+ from paddle_billing.Operation import Operation
4
+ from paddle_billing.Undefined import Undefined
5
+ from paddle_billing.Entities.ClientTokens import ClientTokenStatus
6
+
7
+
8
+ @dataclass
9
+ class UpdateClientToken(Operation):
10
+ status: ClientTokenStatus | Undefined = Undefined()
@@ -0,0 +1,3 @@
1
+ from paddle_billing.Resources.ClientTokens.Operations.CreateClientToken import CreateClientToken
2
+ from paddle_billing.Resources.ClientTokens.Operations.ListClientTokens import ListClientTokens
3
+ from paddle_billing.Resources.ClientTokens.Operations.UpdateClientToken import UpdateClientToken
File without changes
@@ -1,8 +1,12 @@
1
- from paddle_billing.Resources.DiscountGroups.Operations import CreateDiscountGroup, ListDiscountGroups
1
+ from paddle_billing.Resources.DiscountGroups.Operations import (
2
+ CreateDiscountGroup,
3
+ ListDiscountGroups,
4
+ UpdateDiscountGroup,
5
+ )
2
6
  from paddle_billing.ResponseParser import ResponseParser
3
7
 
4
8
  from paddle_billing.Entities.Collections import Paginator, DiscountGroupCollection
5
- from paddle_billing.Entities.DiscountGroup import DiscountGroup
9
+ from paddle_billing.Entities.DiscountGroup import DiscountGroup, DiscountGroupStatus
6
10
 
7
11
  from typing import TYPE_CHECKING
8
12
 
@@ -26,8 +30,23 @@ class DiscountGroupsClient:
26
30
  parser.get_list(), Paginator(self.client, parser.get_pagination(), DiscountGroupCollection)
27
31
  )
28
32
 
33
+ def get(self, discount_group_id: str) -> DiscountGroup:
34
+ self.response = self.client.get_raw(f"/discount-groups/{discount_group_id}")
35
+ parser = ResponseParser(self.response)
36
+
37
+ return DiscountGroup.from_dict(parser.get_dict())
38
+
29
39
  def create(self, operation: CreateDiscountGroup) -> DiscountGroup:
30
40
  self.response = self.client.post_raw("/discount-groups", operation)
31
41
  parser = ResponseParser(self.response)
32
42
 
33
43
  return DiscountGroup.from_dict(parser.get_dict())
44
+
45
+ def update(self, discount_group_id: str, operation: UpdateDiscountGroup) -> DiscountGroup:
46
+ self.response = self.client.patch_raw(f"/discount-groups/{discount_group_id}", operation)
47
+ parser = ResponseParser(self.response)
48
+
49
+ return DiscountGroup.from_dict(parser.get_dict())
50
+
51
+ def archive(self, discount_group_id: str) -> DiscountGroup:
52
+ return self.update(discount_group_id, UpdateDiscountGroup(status=DiscountGroupStatus.Archived))
@@ -0,0 +1,11 @@
1
+ from dataclasses import dataclass
2
+
3
+ from paddle_billing.Undefined import Undefined
4
+ from paddle_billing.Entities.DiscountGroup import DiscountGroupStatus
5
+ from paddle_billing.Operation import Operation
6
+
7
+
8
+ @dataclass
9
+ class UpdateDiscountGroup(Operation):
10
+ name: str | Undefined = Undefined()
11
+ status: DiscountGroupStatus | Undefined = Undefined()
@@ -1,2 +1,3 @@
1
1
  from paddle_billing.Resources.DiscountGroups.Operations.CreateDiscountGroup import CreateDiscountGroup
2
2
  from paddle_billing.Resources.DiscountGroups.Operations.ListDiscountGroups import ListDiscountGroups
3
+ from paddle_billing.Resources.DiscountGroups.Operations.UpdateDiscountGroup import UpdateDiscountGroup
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paddle-python-sdk
3
- Version: 1.7.0
3
+ Version: 1.9.0
4
4
  Summary: Paddle's Python SDK for Paddle Billing
5
5
  Home-page: https://developer.paddle.com/api-reference/overview
6
6
  Author: Paddle and contributors
@@ -19,8 +19,8 @@ License-File: LICENSE
19
19
  Requires-Dist: requests>=2.31
20
20
  Requires-Dist: urllib3>=1.26.18
21
21
  Provides-Extra: dev
22
- Requires-Dist: pytest<8.4.0,>=7.4.4; extra == "dev"
23
- Requires-Dist: pytest-cov<6.1,>=4.1; extra == "dev"
22
+ Requires-Dist: pytest<8.5.0,>=7.4.4; extra == "dev"
23
+ Requires-Dist: pytest-cov<6.3,>=4.1; extra == "dev"
24
24
  Requires-Dist: requests-mock~=1.11.0; extra == "dev"
25
25
  Requires-Dist: setuptools>=69.0.3; extra == "dev"
26
26
  Requires-Dist: pre-commit>=3.8.0; extra == "dev"
@@ -5,7 +5,7 @@ examples/event_polling.py,sha256=580dg_8CFrSCA89Mr1ny4V1gtB3-hk-LfePTbI7DT5w,217
5
5
  examples/get_products.py,sha256=4V7ZG1SH6Oxojufbtzm_TMySw4cOBMQ99mgQK_hlwFQ,1875
6
6
  examples/logger.py,sha256=AxmQmMrsM0ZqMIUnh6iARiczL4S4F9OqQcOu-67owNg,1042
7
7
  examples/webhook_verification.py,sha256=qkNscNdNZUAgxEIk83tCiljN2VmfePZ_k8zTliKz2QY,1205
8
- paddle_billing/Client.py,sha256=sn-7HZQ75m0NkXx6odBcYNZvDSDl3217mKQfkK4KpFs,9128
8
+ paddle_billing/Client.py,sha256=295xfeguUuIjVCrSgQUgAjXhT_PYABvFzNr97LR0Viw,9270
9
9
  paddle_billing/EnumStringify.py,sha256=iDvKULZat3jx9A-_PhvoN6CbFGf2pyxrQeYZxqX9n8M,48
10
10
  paddle_billing/Environment.py,sha256=sY4nrJUwlTugsZKncieAnvfCojqCcKWi4X7rFzjFeSQ,417
11
11
  paddle_billing/FiltersNone.py,sha256=ErOjaTfxtELXrXdxUvFF9DJI_Yl31iseO4K56qTDR54,303
@@ -22,6 +22,7 @@ paddle_billing/Entities/Address.py,sha256=FPyX7sBXkcbDv0ZbZkaNgidWPB1XbBZKzw01X3
22
22
  paddle_billing/Entities/Adjustment.py,sha256=zOtGdcbn2jS-s-3zF0vwyFgOTwp7pnOiRC5ZKmbdFZ4,2133
23
23
  paddle_billing/Entities/AdjustmentCreditNote.py,sha256=pZ48foCPlRLwZFETTDNRs7M-K_0ZqoZIKjWenQA7-50,338
24
24
  paddle_billing/Entities/Business.py,sha256=90T3vhYkdguf_VpXi1HTOsO2rAdR0zwYxYyQ--ql648,1364
25
+ paddle_billing/Entities/ClientToken.py,sha256=br7Asm06YUWAR9tFFx_Qnbb6SH-gFJhMIRO7OUmLayg,1006
25
26
  paddle_billing/Entities/CreditBalance.py,sha256=2ftw3KV2Mew92i1SvZtqFwYzCrgKuYIqWGd8amSGC1k,706
26
27
  paddle_billing/Entities/Customer.py,sha256=aIBbJ3YjsXEUmVHstadm7Jj5EVRIbK6jA1QA-1uvxro,1198
27
28
  paddle_billing/Entities/CustomerAuthToken.py,sha256=735sBPKBnSJu9vEp8hevDDkniXHwjRJFTvyRnVj2tiU,526
@@ -57,9 +58,12 @@ paddle_billing/Entities/Adjustments/AdjustmentItem.py,sha256=oEsz0A6c_k4AsFoyEFy
57
58
  paddle_billing/Entities/Adjustments/AdjustmentTaxRatesUsed.py,sha256=Fq2j54GZ2TinSTQ9fXk_kxMpH5yvcah8YVVMOirDHhg,502
58
59
  paddle_billing/Entities/Adjustments/AdjustmentTotals.py,sha256=QdVxLTJOxhdVF9SK81mHEMxa6W27XIAuEPS7zMIOdI0,399
59
60
  paddle_billing/Entities/Adjustments/__init__.py,sha256=h2dLT_sTySreBTu886fA8F0zjOW16pnyU4FfNAWLAGk,272
61
+ paddle_billing/Entities/ClientTokens/ClientTokenStatus.py,sha256=KnvAHXFsjnrjRPyDSY_82TlrTEVjiSFkI6hhHLWJwYg,233
62
+ paddle_billing/Entities/ClientTokens/__init__.py,sha256=ph1Aqt5NokQMivy67hniNVYI5mGfdo_Cx9z7S1lpCsM,85
60
63
  paddle_billing/Entities/Collections/AddressCollection.py,sha256=IKTlx9PmwmIgMZ4iAH1kRFYIyk4dg_lkCNfkWnvdyYs,561
61
64
  paddle_billing/Entities/Collections/AdjustmentCollection.py,sha256=HsKYx66hyAWwf_WsYUVq9bCCbCMnMjbXmVYPtZcv62g,585
62
65
  paddle_billing/Entities/Collections/BusinessCollection.py,sha256=k5MS3RoE2bcVlb61GcdY58ywBWLmF7IEWNHMiSI3Y0E,570
66
+ paddle_billing/Entities/Collections/ClientTokenCollection.py,sha256=WmZQuAGsGxOw6bKCGfpSW-ozo_O1B-dAfv5JHg93ZqY,593
63
67
  paddle_billing/Entities/Collections/Collection.py,sha256=hbVbZDvRr7_bWOIGA-8t9Twt0mCv5MGY_Qn56W2nS2Y,1276
64
68
  paddle_billing/Entities/Collections/CreditBalanceCollection.py,sha256=9W1VkPz_uDxUXM46JECibC6KAINn7I6-rVXWFxw5-pA,609
65
69
  paddle_billing/Entities/Collections/CustomerCollection.py,sha256=uwIZxlNygFXd9Q_zCnnHysphh7GOdln8gcUv-VLXQ14,569
@@ -84,7 +88,7 @@ paddle_billing/Entities/Collections/SubscriptionPreviewCollection.py,sha256=V1_k
84
88
  paddle_billing/Entities/Collections/TransactionCollection.py,sha256=6yvOLABrD_3TMGKwJtvUjTKzTgSGJ6Edzq_VqBMS7JI,593
85
89
  paddle_billing/Entities/Collections/TransactionPreviewCollection.py,sha256=ZP-xQX9DZE2vHri1Gmb0PcVujWbb4_Orqu2Yu6-B_LE,663
86
90
  paddle_billing/Entities/Collections/TransactionsDataCollection.py,sha256=CaW1GwoXpXSu1ST4Po5pHYF1HlH2WAyu_xzOMmlji8I,642
87
- paddle_billing/Entities/Collections/__init__.py,sha256=5dYiN8A36RadRo-j-dAL5KuOP85uD4Yj74qDpiaYRtI,2466
91
+ paddle_billing/Entities/Collections/__init__.py,sha256=bC6hABSB5NlE9y-dK_GPmM3Y9LJc2wAylwBRvxx342s,2558
88
92
  paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionGeneralUrl.py,sha256=cyN4zrKPD_jDozq5NWqlkIy9HRK4qvFFi-lBnBBZTMc,354
89
93
  paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionSubscriptionUrl.py,sha256=QAk-Ca1Hijg0hVpzFaX6e0WEzMHMU9ZPCmRUzNx0YYo,576
90
94
  paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionUrls.py,sha256=syRIa_vZZ0y0BeLM83jo7EZ3ua4-0MCKM0jdxQiWbTE,895
@@ -95,7 +99,7 @@ paddle_billing/Entities/Discounts/DiscountMode.py,sha256=hzk_00WsxvhJOFfbBywzlSH
95
99
  paddle_billing/Entities/Discounts/DiscountStatus.py,sha256=ss0Btu04U7NEXYgWxlnkUOWINjSXILu67LWEgLb1DaA,304
96
100
  paddle_billing/Entities/Discounts/DiscountType.py,sha256=7JQCM_dN2PGHSiA-jzBHTIRVMVTRFKdHAMKxDxpQgf0,270
97
101
  paddle_billing/Entities/Discounts/__init__.py,sha256=tmYgP8Cw5hVZ_fe1yxeR53AIGmdeXzjYKYxudeqG-SU,220
98
- paddle_billing/Entities/Events/EventTypeName.py,sha256=ltCbjxGMD-NRl2HDpA5Z8kZY9_09T2XMUPFBVUcXnyw,3566
102
+ paddle_billing/Entities/Events/EventTypeName.py,sha256=jnDzmqYyXep3f-vhwPQ6RJRPhwOMBDybc6vd9Q6PUVM,3830
99
103
  paddle_billing/Entities/Events/__init__.py,sha256=DBvU5TZXroY6IACIhh26VV8TWoagJAkne8e9Pz9YdPs,71
100
104
  paddle_billing/Entities/NotificationSettings/NotificationSettingTrafficSource.py,sha256=5jga7qMivQXyU55XOPMGvwsLO1wEPA0Mur40knDgEks,340
101
105
  paddle_billing/Entities/NotificationSettings/NotificationSettingType.py,sha256=zm3kpN5T5QkKp3-3JUpZphUrXCD992OkClAIahqxbns,241
@@ -177,8 +181,8 @@ paddle_billing/Entities/Shared/TransactionDetailsPreview.py,sha256=zyP9-3e5nUxW6
177
181
  paddle_billing/Entities/Shared/TransactionLineItemPreview.py,sha256=wwJLdac1t2EQ0CTUxamy6cw-qbFa2XUkbrHDhyIytUk,1154
178
182
  paddle_billing/Entities/Shared/TransactionOrigin.py,sha256=ITifdfn7H7a7LWQaztQO3H2jwba1EcDlkQSQHI580_8,525
179
183
  paddle_billing/Entities/Shared/TransactionPaymentAttempt.py,sha256=rGlKVdXk6rbxo8jo0uOyhHSzAYI9R_9M5h384BR5T3c,1421
180
- paddle_billing/Entities/Shared/TransactionPayoutTotals.py,sha256=fHVeMbbdyZbRUll95-Njs2IG3rSVcU6AYle7JvGMXKk,1046
181
- paddle_billing/Entities/Shared/TransactionPayoutTotalsAdjusted.py,sha256=9oH6Lv8kmKDVPJSYszlXVCDyZt6HkatDtcz9Q_-2Ibs,917
184
+ paddle_billing/Entities/Shared/TransactionPayoutTotals.py,sha256=ZnJQee1MkfSl_5bzRe6mEdF446agTIh3ObYtxuldrO0,1175
185
+ paddle_billing/Entities/Shared/TransactionPayoutTotalsAdjusted.py,sha256=1N0ffpZ6d6ewiej7TCuSZD58bsnbiFycA47_cdKSi8E,989
182
186
  paddle_billing/Entities/Shared/TransactionPreviewProduct.py,sha256=dfIJ_rjkUx_6UAo2vzjdYyYsRCUvRA3M65kiE1rr_vg,1439
183
187
  paddle_billing/Entities/Shared/TransactionStatus.py,sha256=k3ul97LauZd7KKIlh4IrL_RMVlzAH2aVScFCJ4WycvU,451
184
188
  paddle_billing/Entities/Shared/TransactionTotals.py,sha256=bHBEVWSRmfN0RBfREMweMRsu1o8RBP-IUORD-8Bi3DI,1011
@@ -288,6 +292,7 @@ paddle_billing/Notifications/Entities/Address.py,sha256=ktgEgWXr6UkpSnJtwTQU8Pog
288
292
  paddle_billing/Notifications/Entities/Adjustment.py,sha256=836qBkGD2Cx5aNwoUmJ39IDSUBa3dEmdSYuEv9E9DUA,2323
289
293
  paddle_billing/Notifications/Entities/ApiKey.py,sha256=5-1Dcp8HXqyskFjKOFfkV9u6GNhqpdNBjSsyGCm3Ytg,1287
290
294
  paddle_billing/Notifications/Entities/Business.py,sha256=b_QTTvVBS6KlN4S87OY22V2zoZY0lSHHSTrHjJ0Jwg4,1500
295
+ paddle_billing/Notifications/Entities/ClientToken.py,sha256=yXFcx20UVT-CFO1K7NGtujOKOjlpukchKVDkclcdVck,1034
291
296
  paddle_billing/Notifications/Entities/Customer.py,sha256=i3sFQGYQCwvLByREbOAGt_x7Lb5ywg0Efje-hpibUis,1226
292
297
  paddle_billing/Notifications/Entities/DateTime.py,sha256=iJLwbDZwmfHW2TgE8HRPpkw_xZBrwZyVhFaQnKJENu8,1459
293
298
  paddle_billing/Notifications/Entities/Discount.py,sha256=PHpQTgf_BbVX31FipD_p9lh6R3VFSOZLi72xp7c8Eys,2312
@@ -314,6 +319,8 @@ paddle_billing/Notifications/Entities/ApiKeys/ApiKeyStatus.py,sha256=cKtyxWgPhR5
314
319
  paddle_billing/Notifications/Entities/ApiKeys/__init__.py,sha256=Q7mE3NFLffKO1XkMJroIOrrYiW6S3iVpUoI9wC5zP6Y,176
315
320
  paddle_billing/Notifications/Entities/Businesses/BusinessesContacts.py,sha256=Z-vW8cDGeynSREQ00wd4UxyA463EB4LtkqWGtNS58xQ,351
316
321
  paddle_billing/Notifications/Entities/Businesses/__init__.py,sha256=157wIn7fKwrE3Wuu1-RctcJjpjX83m77BAe_YIYwjXs,99
322
+ paddle_billing/Notifications/Entities/ClientTokens/ClientTokenStatus.py,sha256=KnvAHXFsjnrjRPyDSY_82TlrTEVjiSFkI6hhHLWJwYg,233
323
+ paddle_billing/Notifications/Entities/ClientTokens/__init__.py,sha256=OHeqcAXPavCYOsCFyDJ3SN27R1R1fYU6IjdkcQI4EqM,99
317
324
  paddle_billing/Notifications/Entities/DiscountGroups/DiscountGroupStatus.py,sha256=tFrxDCkoTf0ya_bO1EQOg1y4EcICFWTm6qu1divua_E,241
318
325
  paddle_billing/Notifications/Entities/DiscountGroups/__init__.py,sha256=qU8unAr_wipUP9fpR0DROsBhH44HUVcmntQ9JqQ9DSY,91
319
326
  paddle_billing/Notifications/Entities/Discounts/DiscountMode.py,sha256=hzk_00WsxvhJOFfbBywzlSHOWOgd9GqTIiBFU7Xbtu8,220
@@ -374,8 +381,8 @@ paddle_billing/Notifications/Entities/Shared/TimePeriod.py,sha256=XimCvD9XGWISic
374
381
  paddle_billing/Notifications/Entities/Shared/Totals.py,sha256=TgZeniIflgtxvl2-5LOx3Ujpqz3jW0walV6y0I5xfgM,426
375
382
  paddle_billing/Notifications/Entities/Shared/TransactionOrigin.py,sha256=ITifdfn7H7a7LWQaztQO3H2jwba1EcDlkQSQHI580_8,525
376
383
  paddle_billing/Notifications/Entities/Shared/TransactionPaymentAttempt.py,sha256=QQhNm8USTjbwtj5fl2fN4Ab9CAqthEHV4VLqKTW8BtY,1452
377
- paddle_billing/Notifications/Entities/Shared/TransactionPayoutTotals.py,sha256=yc5MRWhOTMnCpbSbAVRusaPI62DsowCpehWe9ed-UAg,1060
378
- paddle_billing/Notifications/Entities/Shared/TransactionPayoutTotalsAdjusted.py,sha256=KKgISz10OhXS-hid9lZzQgAhIgw574OfI_IcOQO90Zk,945
384
+ paddle_billing/Notifications/Entities/Shared/TransactionPayoutTotals.py,sha256=WiVxTP8LUv20DXYrb7Kmv5p2dJVYHeG7l_nyv2Wrdmc,1211
385
+ paddle_billing/Notifications/Entities/Shared/TransactionPayoutTotalsAdjusted.py,sha256=7VfJxFklM91utJ7AF1HoZXKT50ZIaH-ZBJHMn_r9UlQ,1028
379
386
  paddle_billing/Notifications/Entities/Shared/TransactionStatus.py,sha256=k3ul97LauZd7KKIlh4IrL_RMVlzAH2aVScFCJ4WycvU,451
380
387
  paddle_billing/Notifications/Entities/Shared/TransactionTotals.py,sha256=trWwH-OL4J3FJ2qEsynyDGlJ7i2P0n2McKKntO-6PrU,1025
381
388
  paddle_billing/Notifications/Entities/Shared/TransactionTotalsAdjusted.py,sha256=Y8MEwpWycMcVfCLo5Gj5qtyMu_octISku6-p4cGwpHY,792
@@ -386,6 +393,7 @@ paddle_billing/Notifications/Entities/Simulations/Address.py,sha256=mBcPnHBtwBVK
386
393
  paddle_billing/Notifications/Entities/Simulations/Adjustment.py,sha256=vbcB_VEwRUg6du_pGwkT5tCRdC1DgqdxGVkKR1FW36I,3369
387
394
  paddle_billing/Notifications/Entities/Simulations/ApiKey.py,sha256=neTDaFyVFkqC17YFajSQl6NuykuyY1w5pTeTKZnCWo4,2125
388
395
  paddle_billing/Notifications/Entities/Simulations/Business.py,sha256=Z7_Y-LH5pfJ9iyIA3TbZ-N3YOTMInQAnk6ZDOO95vFM,2385
396
+ paddle_billing/Notifications/Entities/Simulations/ClientToken.py,sha256=CicRvRcQWtzNzPGeB_QEAmGisobICwHdEaAawcMHb6Y,1615
389
397
  paddle_billing/Notifications/Entities/Simulations/Customer.py,sha256=WMnw37Zbh0CKfKWKWYMgDmp9rpilvPP-5SX2jlBMQJg,1995
390
398
  paddle_billing/Notifications/Entities/Simulations/Discount.py,sha256=H34NlXnvLDqo6hsKLKEh1TW4WFG3e5TDLiGHp6iKNSg,3623
391
399
  paddle_billing/Notifications/Entities/Simulations/DiscountGroup.py,sha256=_1sskFllpDRWpEqypPKUm5bfO8Fjow5jLg_qvFawKJE,1500
@@ -399,7 +407,7 @@ paddle_billing/Notifications/Entities/Simulations/SimulationEntity.py,sha256=Wr1
399
407
  paddle_billing/Notifications/Entities/Simulations/Subscription.py,sha256=TTmXAPLTR7XeqZnbzLEN4JNnQRmLE-ptQ3MHOYPeb2g,5559
400
408
  paddle_billing/Notifications/Entities/Simulations/SubscriptionCreated.py,sha256=EfneXY1fDNhq1FG6qZukEqDVCOUQKMTYxpSIrmXP7lo,5705
401
409
  paddle_billing/Notifications/Entities/Simulations/Transaction.py,sha256=SsOHXu-fefeex5_pqXOYNQ4seHoD8lQ9L2R1LXyjbLQ,5007
402
- paddle_billing/Notifications/Entities/Simulations/__init__.py,sha256=tHFS3tOJjn_xwnOLxltc1K3OtpNR1-XfKd7G53JxTwg,1176
410
+ paddle_billing/Notifications/Entities/Simulations/__init__.py,sha256=TYdqWHJ6KWX8kUonxDTcxBGFKSh-yFFMA2esvM-pGPU,1262
403
411
  paddle_billing/Notifications/Entities/Subscriptions/SubscriptionAdjustmentItem.py,sha256=3tHwWipV7K_xISgsN60FnH5BDt0ZEYoh0OT4M-dxxA0,763
404
412
  paddle_billing/Notifications/Entities/Subscriptions/SubscriptionCharge.py,sha256=EqI4qBmFQavDjwRPeJWqVEjba_cA4H5H3Hp_7wEw9EE,475
405
413
  paddle_billing/Notifications/Entities/Subscriptions/SubscriptionCredit.py,sha256=iferu7zSOBHskqHAW6fvKBacS07GT0gIK2-kLNJT1Ow,475
@@ -431,10 +439,14 @@ paddle_billing/Notifications/Events/ApiKeyRevoked.py,sha256=iXeyWaoZxDc7uHuCiZtQ
431
439
  paddle_billing/Notifications/Events/ApiKeyUpdated.py,sha256=Y9LXxNx6p3DdN8vynE6Q73uQW7hpmg0GCf8tu1Yuexw,447
432
440
  paddle_billing/Notifications/Events/BusinessCreated.py,sha256=OujioUI949ZGAIO0575TvYE_YWQw-fin6D-1X8BG89I,455
433
441
  paddle_billing/Notifications/Events/BusinessUpdated.py,sha256=_5HhTE6LWpQCKuA9jBRbJ7R4yj1kdq9b-rq9Yeo6mzo,455
442
+ paddle_billing/Notifications/Events/ClientTokenCreated.py,sha256=I79gnc4X9bGUTL87RVtrEdznIIHs5xKFnIHjJSkeQHg,467
443
+ paddle_billing/Notifications/Events/ClientTokenRevoked.py,sha256=e8WyJlxgZ7Ls7wg1p0i4G_ucpUO5zsbrKdcowYhdwE4,467
444
+ paddle_billing/Notifications/Events/ClientTokenUpdated.py,sha256=y3FU06onCzIB0WN9DTqWsXmZJ-4L3q4V-NPI6laIzzU,467
434
445
  paddle_billing/Notifications/Events/CustomerCreated.py,sha256=vmbI3yn2jL2fVDamOYuHsVNe2-8lJBqlvvrykkuIWcA,455
435
446
  paddle_billing/Notifications/Events/CustomerUpdated.py,sha256=nC7X_bCLb7j4uo_ZJ_HQcHKUiYp554rHwkDzurLwFqE,455
436
447
  paddle_billing/Notifications/Events/DiscountCreated.py,sha256=w8r8aMdrPPMT4VKWq-S4S07QLFPUvT2QdO98i3TbXHE,455
437
448
  paddle_billing/Notifications/Events/DiscountGroupCreated.py,sha256=jRujwHNE3l-fYyCQLlHWY9pv5cA7IJo6Trs4kHRRth4,475
449
+ paddle_billing/Notifications/Events/DiscountGroupUpdated.py,sha256=UclrTzlsntmvLVssA-7AmyIn87yKYhFHmfQl1Eu74-c,475
438
450
  paddle_billing/Notifications/Events/DiscountImported.py,sha256=u3YbYPBIiKRly7f8KMiWGVkvzjo4lA4lDNM6kIinxv0,456
439
451
  paddle_billing/Notifications/Events/DiscountUpdated.py,sha256=aWd3IiyiuxtpxkkPhmGmZe56h0LsAGPAu800miODoR4,455
440
452
  paddle_billing/Notifications/Events/PaymentMethodDeleted.py,sha256=nSkwVe3qVZP0CGPfN_al7e8TGW-NZqNy-eEQp1qlfW4,470
@@ -491,6 +503,12 @@ paddle_billing/Resources/Businesses/Operations/CreateBusiness.py,sha256=zDQ-V7El
491
503
  paddle_billing/Resources/Businesses/Operations/ListBusinesses.py,sha256=ImMW68azO87CWpi2ODnN8xeRL25yIhvJfOyaqOCqWgg,1619
492
504
  paddle_billing/Resources/Businesses/Operations/UpdateBusiness.py,sha256=fzijE9x9ru58jOW5Rq-ZvV_LtFc7m6rksyJQiSNwyLA,562
493
505
  paddle_billing/Resources/Businesses/Operations/__init__.py,sha256=mctosPK-Kdb4n_AmdIqVFKeldZxcjw8e4k4iWWoRml0,267
506
+ paddle_billing/Resources/ClientTokens/ClientTokensClient.py,sha256=b6n3KzG1SZ3OQESupAyrbUwRmf1mVLgks4mr4IVbTRs,2003
507
+ paddle_billing/Resources/ClientTokens/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
508
+ paddle_billing/Resources/ClientTokens/Operations/CreateClientToken.py,sha256=wTEzFcBHcbg_m_Nfraf_s8McYObRM0hI0DwsZ0KslSw,246
509
+ paddle_billing/Resources/ClientTokens/Operations/ListClientTokens.py,sha256=T26QcrRWbY7u-_y3tysyG9JFZ3o1_DsUXiKSURYeFm8,1327
510
+ paddle_billing/Resources/ClientTokens/Operations/UpdateClientToken.py,sha256=4yXwl65YUKExXQtRfBcgnzx9PE51j4rfZT6h1FWzRIA,301
511
+ paddle_billing/Resources/ClientTokens/Operations/__init__.py,sha256=8yBr7tF_OOuANW-bK7ZgwqQQaeBIVp2Fw3ML0rPgZgM,289
494
512
  paddle_billing/Resources/CustomerPortalSessions/CustomerPortalSessionsClient.py,sha256=u6Ix9aUkzodU2FYz_SqygWmUCKZkmxBhCBqMjdmrQJI,804
495
513
  paddle_billing/Resources/CustomerPortalSessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
496
514
  paddle_billing/Resources/CustomerPortalSessions/Operations/CreateCustomerPortalSession.py,sha256=EvIwrW-2fmC4xgh3XCJJmjya52aAj0YvkFOJk-yzNto,246
@@ -502,11 +520,12 @@ paddle_billing/Resources/Customers/Operations/ListCreditBalances.py,sha256=xJ5mV
502
520
  paddle_billing/Resources/Customers/Operations/ListCustomers.py,sha256=Aqt-Y_71PYqJrR_zcBkoXbWmUQOk2jMi6J56Wlw6giE,1840
503
521
  paddle_billing/Resources/Customers/Operations/UpdateCustomer.py,sha256=fgbr9FsvdU3x8aFiQ_d-tA6GFmHOCCttJF_TC6LzmC0,473
504
522
  paddle_billing/Resources/Customers/Operations/__init__.py,sha256=-ue0-Etc7TgWe-ShIGaK428Uj_6Joj-33h9SHEa49Jg,358
505
- paddle_billing/Resources/DiscountGroups/DiscountGroupsClient.py,sha256=F9I8ff7wY8_0y3twPWS70rdcQhSF3CrG1FE5PHPkMQU,1263
523
+ paddle_billing/Resources/DiscountGroups/DiscountGroupsClient.py,sha256=RkQ246ad41jtmNPdwsVZQv-19x-kkhcGVeLUY5n9bVw,2043
506
524
  paddle_billing/Resources/DiscountGroups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
507
525
  paddle_billing/Resources/DiscountGroups/Operations/CreateDiscountGroup.py,sha256=w9GVFW3E7S7HLGUNW71LOcz3su0Z1RSamS60LcXXuaE,147
508
526
  paddle_billing/Resources/DiscountGroups/Operations/ListDiscountGroups.py,sha256=Rtf5UPkmKEcVftkulr97qnio2By1smURV6XeaR_iX-g,1115
509
- paddle_billing/Resources/DiscountGroups/Operations/__init__.py,sha256=0VXVvynwJP2dM2qMX3NbtO0TiTDwSV5UIKzFo2lAlls,204
527
+ paddle_billing/Resources/DiscountGroups/Operations/UpdateDiscountGroup.py,sha256=FR8KcgXUGDfrve7YTBG7OoCXdnSFL0NmTXqjk9UoWOA,348
528
+ paddle_billing/Resources/DiscountGroups/Operations/__init__.py,sha256=yWI79jp80fZXlwI_8eCzdmQ6k-83UVonUNbExWM-4po,307
510
529
  paddle_billing/Resources/Discounts/DiscountsClient.py,sha256=XvLZXAeubdg3dprUSiTGzOqnjk7L1cjm6fxYlnvtUYc,2035
511
530
  paddle_billing/Resources/Discounts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
512
531
  paddle_billing/Resources/Discounts/Operations/CreateDiscount.py,sha256=3qn0o_sovdwY_n8SNARRv2mPPSeb_4jYtjYCaVdwJKA,975
@@ -696,7 +715,7 @@ paddle_billing/Resources/Transactions/Operations/Update/TransactionUpdateItem.py
696
715
  paddle_billing/Resources/Transactions/Operations/Update/TransactionUpdateItemWithPrice.py,sha256=3MIhPl85ZTen-9RLLlrX-s9pktno3Eb32X8tW6hyXSg,490
697
716
  paddle_billing/Resources/Transactions/Operations/Update/UpdateBillingDetails.py,sha256=NAfwUJrT3slphzWfVQjDMElwjljde72wwMBX25Qe9YA,447
698
717
  paddle_billing/Resources/Transactions/Operations/Update/__init__.py,sha256=VL03L8n4r2ZuxGI6l7kpHksSYJSmZL6cKaO9ToTu2jo,361
699
- paddle_python_sdk-1.7.0.dist-info/licenses/LICENSE,sha256=e5Sn9mzCdpjnqCLxXpGHNKdYB6JlRSTLhN_CD4WSO6w,10770
718
+ paddle_python_sdk-1.9.0.dist-info/licenses/LICENSE,sha256=e5Sn9mzCdpjnqCLxXpGHNKdYB6JlRSTLhN_CD4WSO6w,10770
700
719
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
701
720
  tests/conftest.py,sha256=K_rWFm4jOBGVpoQP9llOwQwyYrXThbF3CBvood_hNRU,127
702
721
  tests/Functional/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -709,12 +728,14 @@ tests/Functional/Resources/Adjustments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JC
709
728
  tests/Functional/Resources/Adjustments/test_AdjustmentsClient.py,sha256=s47ShnZyiW4dnFHG_NBM7ecYnmnYLFBTLNEz_2bg7CQ,19278
710
729
  tests/Functional/Resources/Businesses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
711
730
  tests/Functional/Resources/Businesses/test_BusinessesClient.py,sha256=uUAydFqmXq3snmu--gGVI5nNrpg6oySQM_Ulg9q-G1Q,12727
731
+ tests/Functional/Resources/ClientToken/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
732
+ tests/Functional/Resources/ClientToken/test_ClientTokensClient.py,sha256=EKI95cvkt7KR63f_6cZ8RmEmbJk9q4nx0uifjStZ2KA,12046
712
733
  tests/Functional/Resources/CustomerPortalSessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
713
734
  tests/Functional/Resources/CustomerPortalSessions/test_CustomerPortalSessionsClient.py,sha256=n33TXcOD0c6twPECsebfJA_AxLDJV_XV8WixWzvcSvw,7430
714
735
  tests/Functional/Resources/Customers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
715
736
  tests/Functional/Resources/Customers/test_CustomersClient.py,sha256=tWDmre025VMQuUGcK6UE12Ulh7Ju_BeprKon2bM-OLk,14755
716
737
  tests/Functional/Resources/DiscountGroups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
717
- tests/Functional/Resources/DiscountGroups/test_DiscountGroupsClient.py,sha256=cW69VzzoLfkcMqmceXw-cIfVhKafILVlljYzHBBXsco,5145
738
+ tests/Functional/Resources/DiscountGroups/test_DiscountGroupsClient.py,sha256=CwKUB-ibgfxaB8h0ibo1pqOStfb3dg_pYqq_VkwF4T4,11212
718
739
  tests/Functional/Resources/Discounts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
719
740
  tests/Functional/Resources/Discounts/test_DiscountsClient.py,sha256=vldZ40MaYw_jtyEJulbhf2bu2zdZoxo5LFndygqg6EA,17416
720
741
  tests/Functional/Resources/EventTypes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -763,7 +784,7 @@ tests/Utils/ReadsFixture.py,sha256=3CQ_8XHji3kuR28Ktlmw1Kip565UycocUytldWtuAyw,1
763
784
  tests/Utils/TestClient.py,sha256=-wc7hJMuR6WC-ukw0c7I59b5-8hj_-nzq__-2M81elg,1453
764
785
  tests/Utils/TestLogger.py,sha256=pFO9x711buRmg-8DAqpzIJP_hr21JPty1_ZQRcwoGKk,554
765
786
  tests/Utils/__init__.py,sha256=JtqJNPKqbNZ9exlpXlF3yj_9cfylPGlvopjQYi7yYTA,37
766
- paddle_python_sdk-1.7.0.dist-info/METADATA,sha256=JUuyznJ78G01_03W-TP7Ru_ppswUhhSL5eRcwGJX1Io,8045
767
- paddle_python_sdk-1.7.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
768
- paddle_python_sdk-1.7.0.dist-info/top_level.txt,sha256=9a07VPng7o5wK8VAXkl6NC30xrNbW9zff_02jHyHi4c,30
769
- paddle_python_sdk-1.7.0.dist-info/RECORD,,
787
+ paddle_python_sdk-1.9.0.dist-info/METADATA,sha256=JzoNkuVGZVzQsTcEvmQ_RyDgnoKjtBXdn-1yTsp26r8,8045
788
+ paddle_python_sdk-1.9.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
789
+ paddle_python_sdk-1.9.0.dist-info/top_level.txt,sha256=9a07VPng7o5wK8VAXkl6NC30xrNbW9zff_02jHyHi4c,30
790
+ paddle_python_sdk-1.9.0.dist-info/RECORD,,
File without changes
@@ -0,0 +1,298 @@
1
+ from json import loads
2
+ from pytest import mark
3
+ from urllib.parse import unquote
4
+
5
+ from build.lib.paddle_billing.Json import PayloadEncoder
6
+ from paddle_billing.Entities.Collections import ClientTokenCollection
7
+ from paddle_billing.Entities.ClientToken import ClientToken
8
+ from paddle_billing.Entities.ClientTokens import ClientTokenStatus
9
+
10
+ from paddle_billing.Resources.ClientTokens.Operations import CreateClientToken, ListClientTokens, UpdateClientToken
11
+ from paddle_billing.Resources.Shared.Operations import Pager
12
+
13
+ from tests.Utils.ReadsFixture import ReadsFixtures
14
+
15
+
16
+ class TestClientTokensClient:
17
+ @mark.parametrize(
18
+ "operation, expected_request_body, expected_response_status, expected_response_body, expected_url",
19
+ [
20
+ (
21
+ CreateClientToken(
22
+ "Pricing page integration",
23
+ None,
24
+ ),
25
+ ReadsFixtures.read_raw_json_fixture("request/create_basic"),
26
+ 200,
27
+ ReadsFixtures.read_raw_json_fixture("response/minimal_entity"),
28
+ "/client-tokens",
29
+ ),
30
+ (
31
+ CreateClientToken(
32
+ "Pricing page integration",
33
+ None,
34
+ ),
35
+ ReadsFixtures.read_raw_json_fixture("request/create_null_description"),
36
+ 200,
37
+ ReadsFixtures.read_raw_json_fixture("response/minimal_entity"),
38
+ "/client-tokens",
39
+ ),
40
+ (
41
+ CreateClientToken(
42
+ "Pricing page integration",
43
+ "Used to display prices and open checkout within our pricing page on our marketing domain.",
44
+ ),
45
+ ReadsFixtures.read_raw_json_fixture("request/create_full"),
46
+ 200,
47
+ ReadsFixtures.read_raw_json_fixture("response/full_entity"),
48
+ "/client-tokens",
49
+ ),
50
+ ],
51
+ ids=[
52
+ "Create client token with basic data",
53
+ "Create client token with basic data - null description",
54
+ "Create client token with full data",
55
+ ],
56
+ )
57
+ def test_create_client_token_uses_expected_payload(
58
+ self,
59
+ test_client,
60
+ mock_requests,
61
+ operation,
62
+ expected_request_body,
63
+ expected_response_status,
64
+ expected_response_body,
65
+ expected_url,
66
+ ):
67
+ expected_url = f"{test_client.base_url}{expected_url}"
68
+ mock_requests.post(expected_url, status_code=expected_response_status, text=expected_response_body)
69
+
70
+ response = test_client.client.client_tokens.create(operation)
71
+ response_json = test_client.client.client_tokens.response.json()
72
+ request_json = test_client.client.payload
73
+ last_request = mock_requests.last_request
74
+
75
+ assert isinstance(response, ClientToken)
76
+ assert last_request is not None
77
+ assert last_request.method == "POST"
78
+ assert test_client.client.status_code == expected_response_status
79
+ assert (
80
+ unquote(last_request.url) == expected_url
81
+ ), "The URL does not match the expected URL, verify the query string is correct"
82
+ assert loads(request_json) == loads(
83
+ expected_request_body
84
+ ), "The request JSON doesn't match the expected fixture JSON"
85
+ assert response_json == loads(
86
+ str(expected_response_body)
87
+ ), "The response JSON doesn't match the expected fixture JSON"
88
+
89
+ @mark.parametrize(
90
+ "client_token_id, operation, expected_request_body, expected_response_status, expected_response_body, expected_url",
91
+ [
92
+ (
93
+ "ctkn_01ghbkd0frb9k95cnhwd1bxpvk",
94
+ UpdateClientToken(status=ClientTokenStatus.Revoked),
95
+ ReadsFixtures.read_raw_json_fixture("request/revoke"),
96
+ 200,
97
+ ReadsFixtures.read_raw_json_fixture("response/revoked_entity"),
98
+ "/client-tokens/ctkn_01ghbkd0frb9k95cnhwd1bxpvk",
99
+ ),
100
+ ],
101
+ ids=["Revoke client token"],
102
+ )
103
+ def test_update_client_token_uses_expected_payload(
104
+ self,
105
+ test_client,
106
+ mock_requests,
107
+ client_token_id,
108
+ operation,
109
+ expected_request_body,
110
+ expected_response_status,
111
+ expected_response_body,
112
+ expected_url,
113
+ ):
114
+ expected_url = f"{test_client.base_url}{expected_url}"
115
+ mock_requests.patch(expected_url, status_code=expected_response_status, text=expected_response_body)
116
+
117
+ response = test_client.client.client_tokens.update(client_token_id, operation)
118
+ response_json = test_client.client.client_tokens.response.json()
119
+ request_json = test_client.client.payload
120
+ last_request = mock_requests.last_request
121
+
122
+ assert isinstance(response, ClientToken)
123
+ assert last_request is not None
124
+ assert last_request.method == "PATCH"
125
+ assert test_client.client.status_code == expected_response_status
126
+ assert (
127
+ unquote(last_request.url) == expected_url
128
+ ), "The URL does not match the expected URL, verify the query string is correct"
129
+ assert loads(request_json) == loads(
130
+ expected_request_body
131
+ ), "The request JSON doesn't match the expected fixture JSON"
132
+ assert response_json == loads(
133
+ str(expected_response_body)
134
+ ), "The response JSON doesn't match the expected fixture JSON"
135
+
136
+ def test_revoke_client_token_uses_expected_payload(
137
+ self,
138
+ test_client,
139
+ mock_requests,
140
+ ):
141
+ client_token_id = "ctkn_01ghbkd0frb9k95cnhwd1bxpvk"
142
+ expected_request_body = ReadsFixtures.read_raw_json_fixture("request/revoke")
143
+ expected_response_body = ReadsFixtures.read_raw_json_fixture("response/revoked_entity")
144
+ expected_url = "/client-tokens/ctkn_01ghbkd0frb9k95cnhwd1bxpvk"
145
+
146
+ expected_url = f"{test_client.base_url}{expected_url}"
147
+ mock_requests.patch(expected_url, status_code=200, text=expected_response_body)
148
+
149
+ response = test_client.client.client_tokens.revoke(client_token_id)
150
+ response_json = test_client.client.client_tokens.response.json()
151
+ request_json = test_client.client.payload
152
+ last_request = mock_requests.last_request
153
+
154
+ assert isinstance(response, ClientToken)
155
+ assert last_request is not None
156
+ assert last_request.method == "PATCH"
157
+ assert test_client.client.status_code == 200
158
+ assert (
159
+ unquote(last_request.url) == expected_url
160
+ ), "The URL does not match the expected URL, verify the query string is correct"
161
+ assert loads(request_json) == loads(
162
+ expected_request_body
163
+ ), "The request JSON doesn't match the expected fixture JSON"
164
+ assert response_json == loads(
165
+ str(expected_response_body)
166
+ ), "The response JSON doesn't match the expected fixture JSON"
167
+
168
+ @mark.parametrize(
169
+ "operation, expected_response_status, expected_response_body, expected_url",
170
+ [
171
+ (
172
+ ListClientTokens(),
173
+ 200,
174
+ ReadsFixtures.read_raw_json_fixture("response/list_page_one"),
175
+ "/client-tokens",
176
+ ),
177
+ (
178
+ ListClientTokens(Pager()),
179
+ 200,
180
+ ReadsFixtures.read_raw_json_fixture("response/list_page_one"),
181
+ "/client-tokens?order_by=id[asc]&per_page=50",
182
+ ),
183
+ (
184
+ ListClientTokens(Pager(after="ctkn_01ghbkd0frb9k95cnhwd1bxpvk")),
185
+ 200,
186
+ ReadsFixtures.read_raw_json_fixture("response/list_page_one"),
187
+ "/client-tokens?after=ctkn_01ghbkd0frb9k95cnhwd1bxpvk&order_by=id[asc]&per_page=50",
188
+ ),
189
+ (
190
+ ListClientTokens(statuses=[ClientTokenStatus.Active]),
191
+ 200,
192
+ ReadsFixtures.read_raw_json_fixture("response/list_page_one"),
193
+ "/client-tokens?status=active",
194
+ ),
195
+ (
196
+ ListClientTokens(statuses=[ClientTokenStatus.Revoked]),
197
+ 200,
198
+ ReadsFixtures.read_raw_json_fixture("response/list_page_one"),
199
+ "/client-tokens?status=revoked",
200
+ ),
201
+ ],
202
+ ids=[
203
+ "List client tokens without pagination",
204
+ "List client tokens with default pagination",
205
+ "List paginated client tokens after specified client token id",
206
+ "List client tokens filtered by active status",
207
+ "List client tokens filtered by revoked status",
208
+ ],
209
+ )
210
+ def test_list_client_tokens_returns_expected_response(
211
+ self,
212
+ test_client,
213
+ mock_requests,
214
+ operation,
215
+ expected_response_status,
216
+ expected_response_body,
217
+ expected_url,
218
+ ):
219
+ expected_url = f"{test_client.base_url}{expected_url}"
220
+ mock_requests.get(expected_url, status_code=expected_response_status, text=expected_response_body)
221
+
222
+ response = test_client.client.client_tokens.list(operation)
223
+ last_request = mock_requests.last_request
224
+
225
+ assert isinstance(response, ClientTokenCollection)
226
+ assert last_request is not None
227
+ assert last_request.method == "GET"
228
+ assert test_client.client.status_code == expected_response_status
229
+ assert (
230
+ unquote(last_request.url) == expected_url
231
+ ), "The URL does not match the expected URL, verify the query string is correct"
232
+ assert loads(PayloadEncoder().encode(response.items[0])) == loads(expected_response_body)["data"][0]
233
+
234
+ def test_list_client_tokens_can_paginate(
235
+ self,
236
+ test_client,
237
+ mock_requests,
238
+ ):
239
+ mock_requests.get(
240
+ f"{test_client.base_url}/client-tokens",
241
+ status_code=200,
242
+ text=ReadsFixtures.read_raw_json_fixture("response/list_page_one"),
243
+ )
244
+
245
+ mock_requests.get(
246
+ f"{test_client.base_url}/client-tokens?after=ctkn_03ghbkd0frb9k95cnhwd1bxpvk",
247
+ status_code=200,
248
+ text=ReadsFixtures.read_raw_json_fixture("response/list_page_two"),
249
+ )
250
+
251
+ response = test_client.client.client_tokens.list()
252
+
253
+ assert isinstance(response, ClientTokenCollection)
254
+
255
+ all = []
256
+ for client_token in response:
257
+ all.append(client_token)
258
+
259
+ assert len(all) == 6
260
+
261
+ @mark.parametrize(
262
+ "client_token_id, expected_response_status, expected_response_body, expected_url",
263
+ [
264
+ (
265
+ "dsc_01h83xenpcfjyhkqr4x214m02x",
266
+ 200,
267
+ ReadsFixtures.read_raw_json_fixture("response/full_entity"),
268
+ "/client-tokens/dsc_01h83xenpcfjyhkqr4x214m02x",
269
+ )
270
+ ],
271
+ ids=["Get client token"],
272
+ )
273
+ def test_get_client_tokens_returns_expected_response(
274
+ self,
275
+ test_client,
276
+ mock_requests,
277
+ client_token_id,
278
+ expected_response_status,
279
+ expected_response_body,
280
+ expected_url,
281
+ ):
282
+ expected_url = f"{test_client.base_url}{expected_url}"
283
+ mock_requests.get(expected_url, status_code=expected_response_status, text=expected_response_body)
284
+
285
+ response = test_client.client.client_tokens.get(client_token_id)
286
+ response_json = test_client.client.client_tokens.response.json()
287
+ last_request = mock_requests.last_request
288
+
289
+ assert isinstance(response, ClientToken)
290
+ assert last_request is not None
291
+ assert last_request.method == "GET"
292
+ assert test_client.client.status_code == expected_response_status
293
+ assert (
294
+ unquote(last_request.url) == expected_url
295
+ ), "The URL does not match the expected URL, verify the query string is correct"
296
+ assert response_json == loads(
297
+ str(expected_response_body)
298
+ ), "The response JSON generated by ResponseParser() doesn't match the expected fixture JSON"
@@ -3,10 +3,14 @@ from pytest import mark
3
3
  from urllib.parse import unquote
4
4
 
5
5
  from paddle_billing.Client import PayloadEncoder
6
- from paddle_billing.Entities.DiscountGroup import DiscountGroup
6
+ from paddle_billing.Entities.DiscountGroup import DiscountGroup, DiscountGroupStatus
7
7
  from paddle_billing.Entities.Collections import DiscountGroupCollection
8
8
 
9
- from paddle_billing.Resources.DiscountGroups.Operations import CreateDiscountGroup, ListDiscountGroups
9
+ from paddle_billing.Resources.DiscountGroups.Operations import (
10
+ CreateDiscountGroup,
11
+ ListDiscountGroups,
12
+ UpdateDiscountGroup,
13
+ )
10
14
  from paddle_billing.Resources.Shared.Operations import Pager
11
15
 
12
16
  from tests.Utils.ReadsFixture import ReadsFixtures
@@ -123,3 +127,147 @@ class TestDiscountsClient:
123
127
  assert response_json == loads(
124
128
  str(expected_response_body)
125
129
  ), "The response JSON doesn't match the expected fixture JSON"
130
+
131
+ @mark.parametrize(
132
+ "discount_group_id, operation, expected_request_body, expected_response_status, expected_response_body, expected_url",
133
+ [
134
+ (
135
+ "dsg_01gtf15svsqzgp9325ss4ebmwt",
136
+ UpdateDiscountGroup(name="Some Discount Group"),
137
+ ReadsFixtures.read_raw_json_fixture("request/update_partial"),
138
+ 200,
139
+ ReadsFixtures.read_raw_json_fixture("response/full_entity"),
140
+ "/discount-groups/dsg_01gtf15svsqzgp9325ss4ebmwt",
141
+ ),
142
+ (
143
+ "dsg_01gtf15svsqzgp9325ss4ebmwt",
144
+ UpdateDiscountGroup(name="Some Discount Group", status=DiscountGroupStatus.Archived),
145
+ ReadsFixtures.read_raw_json_fixture("request/update_full"),
146
+ 200,
147
+ ReadsFixtures.read_raw_json_fixture("response/full_entity"),
148
+ "/discount-groups/dsg_01gtf15svsqzgp9325ss4ebmwt",
149
+ ),
150
+ ],
151
+ ids=[
152
+ "Update discount group with minimal",
153
+ "Update discount with with full",
154
+ ],
155
+ )
156
+ def test_update_discount_group_uses_expected_payload(
157
+ self,
158
+ test_client,
159
+ mock_requests,
160
+ discount_group_id,
161
+ operation,
162
+ expected_request_body,
163
+ expected_response_status,
164
+ expected_response_body,
165
+ expected_url,
166
+ ):
167
+ expected_url = f"{test_client.base_url}{expected_url}"
168
+ mock_requests.patch(expected_url, status_code=expected_response_status, text=expected_response_body)
169
+
170
+ response = test_client.client.discount_groups.update(discount_group_id, operation)
171
+ response_json = test_client.client.discount_groups.response.json()
172
+ request_json = test_client.client.payload
173
+ last_request = mock_requests.last_request
174
+
175
+ assert isinstance(response, DiscountGroup)
176
+ assert last_request is not None
177
+ assert last_request.method == "PATCH"
178
+ assert test_client.client.status_code == expected_response_status
179
+ assert (
180
+ unquote(last_request.url) == expected_url
181
+ ), "The URL does not match the expected URL, verify the query string is correct"
182
+ assert loads(request_json) == loads(
183
+ expected_request_body
184
+ ), "The request JSON doesn't match the expected fixture JSON"
185
+ assert response_json == loads(
186
+ str(expected_response_body)
187
+ ), "The response JSON doesn't match the expected fixture JSON"
188
+
189
+ @mark.parametrize(
190
+ "discount_group_id, expected_request_body, expected_response_status, expected_response_body, expected_url",
191
+ [
192
+ (
193
+ "dsg_01gtf15svsqzgp9325ss4ebmwt",
194
+ ReadsFixtures.read_raw_json_fixture("request/archive"),
195
+ 200,
196
+ ReadsFixtures.read_raw_json_fixture("response/full_entity"),
197
+ "/discount-groups/dsg_01gtf15svsqzgp9325ss4ebmwt",
198
+ ),
199
+ ],
200
+ ids=[
201
+ "Archive discount group",
202
+ ],
203
+ )
204
+ def test_archive_discount_group_uses_expected_payload(
205
+ self,
206
+ test_client,
207
+ mock_requests,
208
+ discount_group_id,
209
+ expected_request_body,
210
+ expected_response_status,
211
+ expected_response_body,
212
+ expected_url,
213
+ ):
214
+ expected_url = f"{test_client.base_url}{expected_url}"
215
+ mock_requests.patch(expected_url, status_code=expected_response_status, text=expected_response_body)
216
+
217
+ response = test_client.client.discount_groups.archive(discount_group_id)
218
+ response_json = test_client.client.discount_groups.response.json()
219
+ request_json = test_client.client.payload
220
+ last_request = mock_requests.last_request
221
+
222
+ assert isinstance(response, DiscountGroup)
223
+ assert last_request is not None
224
+ assert last_request.method == "PATCH"
225
+ assert test_client.client.status_code == expected_response_status
226
+ assert (
227
+ unquote(last_request.url) == expected_url
228
+ ), "The URL does not match the expected URL, verify the query string is correct"
229
+ assert loads(request_json) == loads(
230
+ expected_request_body
231
+ ), "The request JSON doesn't match the expected fixture JSON"
232
+ assert response_json == loads(
233
+ str(expected_response_body)
234
+ ), "The response JSON doesn't match the expected fixture JSON"
235
+
236
+ @mark.parametrize(
237
+ "discount_group_id, expected_response_status, expected_response_body, expected_url",
238
+ [
239
+ (
240
+ "dsg_01gtf15svsqzgp9325ss4ebmwt",
241
+ 200,
242
+ ReadsFixtures.read_raw_json_fixture("response/full_entity"),
243
+ "/discount-groups/dsg_01gtf15svsqzgp9325ss4ebmwt",
244
+ )
245
+ ],
246
+ ids=["Get discount group"],
247
+ )
248
+ def test_get_discount_group_returns_expected_response(
249
+ self,
250
+ test_client,
251
+ mock_requests,
252
+ discount_group_id,
253
+ expected_response_status,
254
+ expected_response_body,
255
+ expected_url,
256
+ ):
257
+ expected_url = f"{test_client.base_url}{expected_url}"
258
+ mock_requests.get(expected_url, status_code=expected_response_status, text=expected_response_body)
259
+
260
+ response = test_client.client.discount_groups.get(discount_group_id)
261
+ response_json = test_client.client.discount_groups.response.json()
262
+ last_request = mock_requests.last_request
263
+
264
+ assert isinstance(response, DiscountGroup)
265
+ assert last_request is not None
266
+ assert last_request.method == "GET"
267
+ assert test_client.client.status_code == expected_response_status
268
+ assert (
269
+ unquote(last_request.url) == expected_url
270
+ ), "The URL does not match the expected URL, verify the query string is correct"
271
+ assert response_json == loads(
272
+ str(expected_response_body)
273
+ ), "The response JSON generated by ResponseParser() doesn't match the expected fixture JSON"