fragment-python 1.3.0__tar.gz → 1.4.1__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.
Files changed (113) hide show
  1. {fragment_python-1.3.0 → fragment_python-1.4.1}/PKG-INFO +1 -2
  2. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/client/async_client.py +7 -7
  3. fragment_python-1.4.1/fragment/client/oauth.py +75 -0
  4. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/client/sync_client.py +7 -5
  5. fragment_python-1.4.1/fragment/exceptions.py +24 -0
  6. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/__init__.py +2 -0
  7. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/async_client.py +7 -7
  8. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/client.py +7 -0
  9. {fragment_python-1.3.0/fragment/sync_sdk → fragment_python-1.4.1/fragment/sdk}/create_payment.py +12 -2
  10. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/enums.py +1 -1
  11. {fragment_python-1.3.0/fragment/sync_sdk → fragment_python-1.4.1/fragment/sdk}/input_types.py +8 -2
  12. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/std_queries/queries.graphql +7 -0
  13. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/__init__.py +2 -0
  14. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/async_client.py +7 -7
  15. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/client.py +7 -0
  16. {fragment_python-1.3.0/fragment/sdk → fragment_python-1.4.1/fragment/sync_sdk}/create_payment.py +12 -2
  17. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/enums.py +1 -1
  18. {fragment_python-1.3.0/fragment/sdk → fragment_python-1.4.1/fragment/sync_sdk}/input_types.py +8 -2
  19. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/sync_client.py +7 -5
  20. {fragment_python-1.3.0 → fragment_python-1.4.1}/pyproject.toml +3 -4
  21. fragment_python-1.3.0/fragment/exceptions.py +0 -12
  22. {fragment_python-1.3.0 → fragment_python-1.4.1}/LICENSE +0 -0
  23. {fragment_python-1.3.0 → fragment_python-1.4.1}/README.md +0 -0
  24. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/__init__.py +0 -0
  25. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/client/__init__.py +0 -0
  26. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/codegen/__init__.py +0 -0
  27. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/codegen/helpers.py +0 -0
  28. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/codegen/main.py +0 -0
  29. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/codegen/plugins/__init__.py +0 -0
  30. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/codegen/plugins/generate_client_method.py +0 -0
  31. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/codegen/plugins/generate_typed_entries.py +0 -0
  32. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/codegen/plugins/get_file_comment.py +0 -0
  33. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/codegen/typed_entries.py +0 -0
  34. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/logger.py +0 -0
  35. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/py.typed +0 -0
  36. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/add_ledger_entries.py +0 -0
  37. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/add_ledger_entry.py +0 -0
  38. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/add_ledger_entry_runtime.py +0 -0
  39. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/base_model.py +0 -0
  40. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/create_custom_currency.py +0 -0
  41. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/create_custom_link.py +0 -0
  42. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/create_ledger.py +0 -0
  43. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/delete_custom_txs.py +0 -0
  44. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/delete_ledger.py +0 -0
  45. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/delete_schema.py +0 -0
  46. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_account_data_migrations.py +0 -0
  47. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_entries_to_migrate_for_ledger_account_data_migration.py +0 -0
  48. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_entries_to_migrate_for_ledger_entry_data_migration.py +0 -0
  49. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_entry_data_migrations.py +0 -0
  50. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_ledger.py +0 -0
  51. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_ledger_account_balance.py +0 -0
  52. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_ledger_account_balance_with_child_rollup.py +0 -0
  53. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_ledger_account_lines.py +0 -0
  54. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_ledger_entry.py +0 -0
  55. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_payment.py +0 -0
  56. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_schema.py +0 -0
  57. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/get_workspace.py +0 -0
  58. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/instantiate_ledger_account.py +0 -0
  59. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/list_ledger_account_balances.py +0 -0
  60. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/list_ledger_accounts.py +0 -0
  61. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/list_ledger_entries.py +0 -0
  62. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/list_ledger_entry_group_balances.py +0 -0
  63. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/list_multi_currency_ledger_account_balances.py +0 -0
  64. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/list_payments.py +0 -0
  65. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/migrate_ledger_entry.py +0 -0
  66. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/reconcile_tx.py +0 -0
  67. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/reconcile_tx_runtime.py +0 -0
  68. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/reverse_ledger_entry.py +0 -0
  69. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/store_schema.py +0 -0
  70. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/sync_custom_accounts.py +0 -0
  71. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/sync_custom_txs.py +0 -0
  72. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/typed_entries.py +0 -0
  73. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/update_ledger.py +0 -0
  74. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sdk/update_ledger_entry.py +0 -0
  75. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/add_ledger_entries.py +0 -0
  76. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/add_ledger_entry.py +0 -0
  77. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/add_ledger_entry_runtime.py +0 -0
  78. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/base_model.py +0 -0
  79. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/create_custom_currency.py +0 -0
  80. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/create_custom_link.py +0 -0
  81. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/create_ledger.py +0 -0
  82. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/delete_custom_txs.py +0 -0
  83. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/delete_ledger.py +0 -0
  84. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/delete_schema.py +0 -0
  85. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_account_data_migrations.py +0 -0
  86. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_entries_to_migrate_for_ledger_account_data_migration.py +0 -0
  87. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_entries_to_migrate_for_ledger_entry_data_migration.py +0 -0
  88. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_entry_data_migrations.py +0 -0
  89. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_ledger.py +0 -0
  90. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_ledger_account_balance.py +0 -0
  91. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_ledger_account_balance_with_child_rollup.py +0 -0
  92. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_ledger_account_lines.py +0 -0
  93. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_ledger_entry.py +0 -0
  94. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_payment.py +0 -0
  95. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_schema.py +0 -0
  96. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/get_workspace.py +0 -0
  97. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/instantiate_ledger_account.py +0 -0
  98. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/list_ledger_account_balances.py +0 -0
  99. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/list_ledger_accounts.py +0 -0
  100. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/list_ledger_entries.py +0 -0
  101. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/list_ledger_entry_group_balances.py +0 -0
  102. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/list_multi_currency_ledger_account_balances.py +0 -0
  103. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/list_payments.py +0 -0
  104. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/migrate_ledger_entry.py +0 -0
  105. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/reconcile_tx.py +0 -0
  106. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/reconcile_tx_runtime.py +0 -0
  107. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/reverse_ledger_entry.py +0 -0
  108. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/store_schema.py +0 -0
  109. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/sync_custom_accounts.py +0 -0
  110. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/sync_custom_txs.py +0 -0
  111. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/typed_entries.py +0 -0
  112. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/update_ledger.py +0 -0
  113. {fragment_python-1.3.0 → fragment_python-1.4.1}/fragment/sync_sdk/update_ledger_entry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fragment-python
3
- Version: 1.3.0
3
+ Version: 1.4.1
4
4
  Summary: Python SDK for https://fragment.dev/
5
5
  License: Apache 2.0
6
6
  License-File: LICENSE
@@ -15,7 +15,6 @@ Classifier: Programming Language :: Python :: 3.13
15
15
  Classifier: Programming Language :: Python :: 3.14
16
16
  Classifier: Programming Language :: Python :: 3.15
17
17
  Requires-Dist: ariadne-codegen (>=0.17.2,<0.18.0)
18
- Requires-Dist: authlib (>=1.6.12,<2.0.0)
19
18
  Requires-Dist: click (>=8.1.7,<9.0.0)
20
19
  Requires-Dist: graphql-core (>=3.2.3,<4.0.0)
21
20
  Requires-Dist: httpx (>=0.28.1,<0.29.0)
@@ -1,5 +1,3 @@
1
- # Ignore untyped authlib
2
- # mypy: disable-error-code="import-untyped"
3
1
  import time
4
2
  from typing import Any, Dict, Optional
5
3
 
@@ -7,8 +5,8 @@ import httpx
7
5
  from ariadne_codegen.client_generators.dependencies.async_base_client import (
8
6
  AsyncBaseClient,
9
7
  )
10
- from authlib.integrations.httpx_client import AsyncOAuth2Client
11
8
 
9
+ from fragment.client.oauth import fetch_token_async
12
10
  from fragment.exceptions import MissingArgumentException, MissingTokenException
13
11
 
14
12
 
@@ -37,16 +35,18 @@ class AsyncFragmentClient(AsyncBaseClient):
37
35
  self.auth_url = auth_url
38
36
  self.expiration_time: Optional[float] = None
39
37
  self.token: Optional[Dict[str, Any]] = None
40
- self.oauth2_client = AsyncOAuth2Client(
41
- client_id, client_secret, scope=auth_scope
42
- )
38
+ self.client_id = client_id
39
+ self.client_secret = client_secret
40
+ self.auth_scope = auth_scope
43
41
 
44
42
  async def refresh_token(self) -> None:
45
43
  now = time.time()
46
44
  if self.expiration_time is None or self.expiration_time <= now:
47
45
  # Held in a local because `self.token` is declared `dict | None`,
48
46
  # so reading the attribute back is not narrowed by the assignment.
49
- token = await self.oauth2_client.fetch_token(self.auth_url)
47
+ token = await fetch_token_async(
48
+ self.auth_url, self.client_id, self.client_secret, self.auth_scope
49
+ )
50
50
  self.token = token
51
51
  self.expiration_time = now + token["expires_in"]
52
52
 
@@ -0,0 +1,75 @@
1
+ """OAuth2 client-credentials token request against the Fragment auth endpoint.
2
+
3
+ The SDK needs exactly one OAuth2 call: exchange a client ID and secret for an
4
+ access token. That is a single form POST, so it is made with httpx directly
5
+ rather than through an OAuth library, whose much larger surface (JOSE, OIDC,
6
+ server-side grants) customers would otherwise inherit, along with its
7
+ advisories.
8
+
9
+ The request matches what authlib's httpx `OAuth2Client.fetch_token` sent:
10
+ HTTP Basic client authentication (`client_secret_basic`) and a form body of
11
+ `grant_type=client_credentials` and `scope`.
12
+ """
13
+
14
+ from typing import Any, Dict
15
+
16
+ import httpx
17
+
18
+ from fragment.exceptions import TokenRequestException
19
+
20
+ _HEADERS = {
21
+ "Accept": "application/json",
22
+ "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
23
+ }
24
+
25
+
26
+ def _token_request_kwargs(
27
+ client_id: str, client_secret: str, scope: str
28
+ ) -> Dict[str, Any]:
29
+ return dict(
30
+ data={"grant_type": "client_credentials", "scope": scope},
31
+ auth=httpx.BasicAuth(client_id, client_secret),
32
+ headers=_HEADERS,
33
+ )
34
+
35
+
36
+ def _parse_token_response(response: httpx.Response) -> Dict[str, Any]:
37
+ if response.status_code >= 500:
38
+ response.raise_for_status()
39
+ try:
40
+ token = response.json()
41
+ except ValueError as e:
42
+ raise TokenRequestException(
43
+ f"token endpoint returned a non-JSON response "
44
+ f"(HTTP {response.status_code})"
45
+ ) from e
46
+ if not isinstance(token, dict):
47
+ raise TokenRequestException("token endpoint returned a non-object response")
48
+ if "error" in token:
49
+ raise TokenRequestException(token["error"], token.get("error_description"))
50
+ if "access_token" not in token or "expires_in" not in token:
51
+ raise TokenRequestException(
52
+ f"token endpoint response is missing access_token or expires_in "
53
+ f"(HTTP {response.status_code})"
54
+ )
55
+ return token
56
+
57
+
58
+ def fetch_token(
59
+ auth_url: str, client_id: str, client_secret: str, scope: str
60
+ ) -> Dict[str, Any]:
61
+ with httpx.Client() as client:
62
+ response = client.post(
63
+ auth_url, **_token_request_kwargs(client_id, client_secret, scope)
64
+ )
65
+ return _parse_token_response(response)
66
+
67
+
68
+ async def fetch_token_async(
69
+ auth_url: str, client_id: str, client_secret: str, scope: str
70
+ ) -> Dict[str, Any]:
71
+ async with httpx.AsyncClient() as client:
72
+ response = await client.post(
73
+ auth_url, **_token_request_kwargs(client_id, client_secret, scope)
74
+ )
75
+ return _parse_token_response(response)
@@ -1,12 +1,10 @@
1
- # Ignore untyped authlib
2
- # mypy: disable-error-code="import-untyped"
3
1
  import time
4
2
  from typing import Any, Dict, Optional
5
3
 
6
4
  import httpx
7
5
  from ariadne_codegen.client_generators.dependencies.base_client import BaseClient
8
- from authlib.integrations.httpx_client import OAuth2Client
9
6
 
7
+ from fragment.client.oauth import fetch_token
10
8
  from fragment.exceptions import MissingArgumentException, MissingTokenException
11
9
 
12
10
 
@@ -35,14 +33,18 @@ class SyncFragmentClient(BaseClient):
35
33
  self.auth_url = auth_url
36
34
  self.expiration_time: Optional[float] = None
37
35
  self.token: Optional[Dict[str, Any]] = None
38
- self.oauth2_client = OAuth2Client(client_id, client_secret, scope=auth_scope)
36
+ self.client_id = client_id
37
+ self.client_secret = client_secret
38
+ self.auth_scope = auth_scope
39
39
 
40
40
  def refresh_token(self) -> None:
41
41
  now = time.time()
42
42
  if self.expiration_time is None or self.expiration_time <= now:
43
43
  # Held in a local because `self.token` is declared `dict | None`,
44
44
  # so reading the attribute back is not narrowed by the assignment.
45
- token = self.oauth2_client.fetch_token(self.auth_url)
45
+ token = fetch_token(
46
+ self.auth_url, self.client_id, self.client_secret, self.auth_scope
47
+ )
46
48
  self.token = token
47
49
  self.expiration_time = now + token["expires_in"]
48
50
 
@@ -0,0 +1,24 @@
1
+ from typing import Optional
2
+
3
+
4
+ class MissingTokenException(ValueError):
5
+ """Token not found."""
6
+
7
+ def __init__(self) -> None:
8
+ super().__init__("Token is None")
9
+
10
+
11
+ class MissingArgumentException(ValueError):
12
+ """Argument not present."""
13
+
14
+ def __init__(self, argument: str) -> None:
15
+ super().__init__(f"{argument} must be provided")
16
+
17
+
18
+ class TokenRequestException(Exception):
19
+ """The auth endpoint did not return an access token."""
20
+
21
+ def __init__(self, error: str, description: Optional[str] = None) -> None:
22
+ self.error = error
23
+ self.description = description
24
+ super().__init__(f"{error}: {description}" if description else error)
@@ -60,6 +60,7 @@ from .create_payment import (
60
60
  CreatePaymentCreatePaymentBadRequestError,
61
61
  CreatePaymentCreatePaymentCreatePaymentResult,
62
62
  CreatePaymentCreatePaymentCreatePaymentResultPayment,
63
+ CreatePaymentCreatePaymentCreatePaymentResultPaymentCurrency,
63
64
  CreatePaymentCreatePaymentInternalError,
64
65
  )
65
66
  from .delete_custom_txs import (
@@ -498,6 +499,7 @@ __all__ = [
498
499
  "CreatePaymentCreatePaymentBadRequestError",
499
500
  "CreatePaymentCreatePaymentCreatePaymentResult",
500
501
  "CreatePaymentCreatePaymentCreatePaymentResultPayment",
502
+ "CreatePaymentCreatePaymentCreatePaymentResultPaymentCurrency",
501
503
  "CreatePaymentCreatePaymentInternalError",
502
504
  "CreatePaymentInput",
503
505
  "CurrencyCode",
@@ -1,7 +1,5 @@
1
1
  # Generated by fragment (with the help of ariadne-codegen)
2
2
 
3
- # Ignore untyped authlib
4
- # mypy: disable-error-code="import-untyped"
5
3
  import time
6
4
  from typing import Any, Dict, Optional
7
5
 
@@ -9,8 +7,8 @@ import httpx
9
7
  from ariadne_codegen.client_generators.dependencies.async_base_client import (
10
8
  AsyncBaseClient,
11
9
  )
12
- from authlib.integrations.httpx_client import AsyncOAuth2Client
13
10
 
11
+ from fragment.client.oauth import fetch_token_async
14
12
  from fragment.exceptions import MissingArgumentException, MissingTokenException
15
13
 
16
14
 
@@ -39,16 +37,18 @@ class AsyncFragmentClient(AsyncBaseClient):
39
37
  self.auth_url = auth_url
40
38
  self.expiration_time: Optional[float] = None
41
39
  self.token: Optional[Dict[str, Any]] = None
42
- self.oauth2_client = AsyncOAuth2Client(
43
- client_id, client_secret, scope=auth_scope
44
- )
40
+ self.client_id = client_id
41
+ self.client_secret = client_secret
42
+ self.auth_scope = auth_scope
45
43
 
46
44
  async def refresh_token(self) -> None:
47
45
  now = time.time()
48
46
  if self.expiration_time is None or self.expiration_time <= now:
49
47
  # Held in a local because `self.token` is declared `dict | None`,
50
48
  # so reading the attribute back is not narrowed by the assignment.
51
- token = await self.oauth2_client.fetch_token(self.auth_url)
49
+ token = await fetch_token_async(
50
+ self.auth_url, self.client_id, self.client_secret, self.auth_scope
51
+ )
52
52
  self.token = token
53
53
  self.expiration_time = now + token["expires_in"]
54
54
 
@@ -1858,8 +1858,15 @@ class Client(AsyncFragmentClient):
1858
1858
  __typename
1859
1859
  ... on CreatePaymentResult {
1860
1860
  payment {
1861
+ id
1862
+ ik
1861
1863
  clientSecret
1862
1864
  status
1865
+ amount
1866
+ mode
1867
+ currency {
1868
+ code
1869
+ }
1863
1870
  }
1864
1871
  }
1865
1872
  ... on BadRequestError {
@@ -1,12 +1,12 @@
1
1
  # Generated by fragment (with the help of ariadne-codegen)
2
2
  # Source: queries/
3
3
 
4
- from typing import Literal, Union
4
+ from typing import Any, Literal, Union
5
5
 
6
6
  from pydantic import Field
7
7
 
8
8
  from .base_model import BaseModel
9
- from .enums import PaymentStatus
9
+ from .enums import PaymentCurrencyCode, PaymentMode, PaymentStatus
10
10
 
11
11
 
12
12
  class CreatePayment(BaseModel):
@@ -30,8 +30,17 @@ class CreatePaymentCreatePaymentCreatePaymentResult(BaseModel):
30
30
 
31
31
 
32
32
  class CreatePaymentCreatePaymentCreatePaymentResultPayment(BaseModel):
33
+ id: str
34
+ ik: Any
33
35
  client_secret: str = Field(alias="clientSecret")
34
36
  status: PaymentStatus
37
+ amount: Any
38
+ mode: PaymentMode
39
+ currency: "CreatePaymentCreatePaymentCreatePaymentResultPaymentCurrency"
40
+
41
+
42
+ class CreatePaymentCreatePaymentCreatePaymentResultPaymentCurrency(BaseModel):
43
+ code: PaymentCurrencyCode
35
44
 
36
45
 
37
46
  class CreatePaymentCreatePaymentInternalError(BaseModel):
@@ -43,3 +52,4 @@ class CreatePaymentCreatePaymentInternalError(BaseModel):
43
52
 
44
53
  CreatePayment.model_rebuild()
45
54
  CreatePaymentCreatePaymentCreatePaymentResult.model_rebuild()
55
+ CreatePaymentCreatePaymentCreatePaymentResultPayment.model_rebuild()
@@ -271,7 +271,7 @@ class PaymentMode(str, Enum):
271
271
 
272
272
 
273
273
  class PaymentStatus(str, Enum):
274
- approved = "approved"
274
+ accepted = "accepted"
275
275
  needs_payment_method = "needs_payment_method"
276
276
  processing = "processing"
277
277
  settled = "settled"
@@ -606,6 +606,8 @@ class LedgerLinesFilterSet(BaseModel):
606
606
  "Filter by the currency of the Ledger Line."
607
607
  date: Optional["DateFilter"] = None
608
608
  "Use this filter to filter Ledger Lines by their `posted` date."
609
+ external_tx_ids: Optional[list[str]] = Field(alias="externalTxIds", default=None)
610
+ "Filter Ledger Lines by the external IDs of their linked transactions. Only supported on `LedgerAccount.lines` for a linked Ledger Account."
609
611
  is_reversal: Optional[bool] = Field(alias="isReversal", default=None)
610
612
  "Use this to filter Ledger Lines that were posted to this Ledger Account, using `reverseLedgerEntry`."
611
613
  is_reversed: Optional[bool] = Field(alias="isReversed", default=None)
@@ -648,7 +650,11 @@ class LedgersFilterSet(BaseModel):
648
650
 
649
651
 
650
652
  class LinkMatchInput(BaseModel):
651
- id: str
653
+ """Specify a Link by ID, or a Custom Link by its creation IK."""
654
+
655
+ id: Optional[str] = None
656
+ ik: Optional[Any] = None
657
+ "The IK passed to createCustomLink. If id is also provided, both must identify the same Link."
652
658
 
653
659
 
654
660
  class MigrateLedgerEntryInput(BaseModel):
@@ -965,7 +971,7 @@ class SchemaPaymentAccountingInput(BaseModel):
965
971
  through its lifecycle, keyed by lifecycle transition."""
966
972
 
967
973
  initiated: Optional["SchemaPaymentEntryInput"] = None
968
- "Posted when the payment is approved. Optional."
974
+ "Posted when the payment is captured. Optional."
969
975
  settled: "SchemaPaymentEntryInput"
970
976
  "Posted when the payment settles. Every Payment Type must define it."
971
977
 
@@ -1291,8 +1291,15 @@ mutation createPayment(
1291
1291
  __typename
1292
1292
  ... on CreatePaymentResult {
1293
1293
  payment {
1294
+ id
1295
+ ik
1294
1296
  clientSecret
1295
1297
  status
1298
+ amount
1299
+ mode
1300
+ currency {
1301
+ code
1302
+ }
1296
1303
  }
1297
1304
  }
1298
1305
  ... on BadRequestError {
@@ -59,6 +59,7 @@ from .create_payment import (
59
59
  CreatePaymentCreatePaymentBadRequestError,
60
60
  CreatePaymentCreatePaymentCreatePaymentResult,
61
61
  CreatePaymentCreatePaymentCreatePaymentResultPayment,
62
+ CreatePaymentCreatePaymentCreatePaymentResultPaymentCurrency,
62
63
  CreatePaymentCreatePaymentInternalError,
63
64
  )
64
65
  from .delete_custom_txs import (
@@ -497,6 +498,7 @@ __all__ = [
497
498
  "CreatePaymentCreatePaymentBadRequestError",
498
499
  "CreatePaymentCreatePaymentCreatePaymentResult",
499
500
  "CreatePaymentCreatePaymentCreatePaymentResultPayment",
501
+ "CreatePaymentCreatePaymentCreatePaymentResultPaymentCurrency",
500
502
  "CreatePaymentCreatePaymentInternalError",
501
503
  "CreatePaymentInput",
502
504
  "CurrencyCode",
@@ -1,7 +1,5 @@
1
1
  # Generated by fragment (with the help of ariadne-codegen)
2
2
 
3
- # Ignore untyped authlib
4
- # mypy: disable-error-code="import-untyped"
5
3
  import time
6
4
  from typing import Any, Dict, Optional
7
5
 
@@ -9,8 +7,8 @@ import httpx
9
7
  from ariadne_codegen.client_generators.dependencies.async_base_client import (
10
8
  AsyncBaseClient,
11
9
  )
12
- from authlib.integrations.httpx_client import AsyncOAuth2Client
13
10
 
11
+ from fragment.client.oauth import fetch_token_async
14
12
  from fragment.exceptions import MissingArgumentException, MissingTokenException
15
13
 
16
14
 
@@ -39,16 +37,18 @@ class AsyncFragmentClient(AsyncBaseClient):
39
37
  self.auth_url = auth_url
40
38
  self.expiration_time: Optional[float] = None
41
39
  self.token: Optional[Dict[str, Any]] = None
42
- self.oauth2_client = AsyncOAuth2Client(
43
- client_id, client_secret, scope=auth_scope
44
- )
40
+ self.client_id = client_id
41
+ self.client_secret = client_secret
42
+ self.auth_scope = auth_scope
45
43
 
46
44
  async def refresh_token(self) -> None:
47
45
  now = time.time()
48
46
  if self.expiration_time is None or self.expiration_time <= now:
49
47
  # Held in a local because `self.token` is declared `dict | None`,
50
48
  # so reading the attribute back is not narrowed by the assignment.
51
- token = await self.oauth2_client.fetch_token(self.auth_url)
49
+ token = await fetch_token_async(
50
+ self.auth_url, self.client_id, self.client_secret, self.auth_scope
51
+ )
52
52
  self.token = token
53
53
  self.expiration_time = now + token["expires_in"]
54
54
 
@@ -1852,8 +1852,15 @@ class Client(SyncFragmentClient):
1852
1852
  __typename
1853
1853
  ... on CreatePaymentResult {
1854
1854
  payment {
1855
+ id
1856
+ ik
1855
1857
  clientSecret
1856
1858
  status
1859
+ amount
1860
+ mode
1861
+ currency {
1862
+ code
1863
+ }
1857
1864
  }
1858
1865
  }
1859
1866
  ... on BadRequestError {
@@ -1,12 +1,12 @@
1
1
  # Generated by fragment (with the help of ariadne-codegen)
2
2
  # Source: queries/
3
3
 
4
- from typing import Literal, Union
4
+ from typing import Any, Literal, Union
5
5
 
6
6
  from pydantic import Field
7
7
 
8
8
  from .base_model import BaseModel
9
- from .enums import PaymentStatus
9
+ from .enums import PaymentCurrencyCode, PaymentMode, PaymentStatus
10
10
 
11
11
 
12
12
  class CreatePayment(BaseModel):
@@ -30,8 +30,17 @@ class CreatePaymentCreatePaymentCreatePaymentResult(BaseModel):
30
30
 
31
31
 
32
32
  class CreatePaymentCreatePaymentCreatePaymentResultPayment(BaseModel):
33
+ id: str
34
+ ik: Any
33
35
  client_secret: str = Field(alias="clientSecret")
34
36
  status: PaymentStatus
37
+ amount: Any
38
+ mode: PaymentMode
39
+ currency: "CreatePaymentCreatePaymentCreatePaymentResultPaymentCurrency"
40
+
41
+
42
+ class CreatePaymentCreatePaymentCreatePaymentResultPaymentCurrency(BaseModel):
43
+ code: PaymentCurrencyCode
35
44
 
36
45
 
37
46
  class CreatePaymentCreatePaymentInternalError(BaseModel):
@@ -43,3 +52,4 @@ class CreatePaymentCreatePaymentInternalError(BaseModel):
43
52
 
44
53
  CreatePayment.model_rebuild()
45
54
  CreatePaymentCreatePaymentCreatePaymentResult.model_rebuild()
55
+ CreatePaymentCreatePaymentCreatePaymentResultPayment.model_rebuild()
@@ -271,7 +271,7 @@ class PaymentMode(str, Enum):
271
271
 
272
272
 
273
273
  class PaymentStatus(str, Enum):
274
- approved = "approved"
274
+ accepted = "accepted"
275
275
  needs_payment_method = "needs_payment_method"
276
276
  processing = "processing"
277
277
  settled = "settled"
@@ -606,6 +606,8 @@ class LedgerLinesFilterSet(BaseModel):
606
606
  "Filter by the currency of the Ledger Line."
607
607
  date: Optional["DateFilter"] = None
608
608
  "Use this filter to filter Ledger Lines by their `posted` date."
609
+ external_tx_ids: Optional[list[str]] = Field(alias="externalTxIds", default=None)
610
+ "Filter Ledger Lines by the external IDs of their linked transactions. Only supported on `LedgerAccount.lines` for a linked Ledger Account."
609
611
  is_reversal: Optional[bool] = Field(alias="isReversal", default=None)
610
612
  "Use this to filter Ledger Lines that were posted to this Ledger Account, using `reverseLedgerEntry`."
611
613
  is_reversed: Optional[bool] = Field(alias="isReversed", default=None)
@@ -648,7 +650,11 @@ class LedgersFilterSet(BaseModel):
648
650
 
649
651
 
650
652
  class LinkMatchInput(BaseModel):
651
- id: str
653
+ """Specify a Link by ID, or a Custom Link by its creation IK."""
654
+
655
+ id: Optional[str] = None
656
+ ik: Optional[Any] = None
657
+ "The IK passed to createCustomLink. If id is also provided, both must identify the same Link."
652
658
 
653
659
 
654
660
  class MigrateLedgerEntryInput(BaseModel):
@@ -965,7 +971,7 @@ class SchemaPaymentAccountingInput(BaseModel):
965
971
  through its lifecycle, keyed by lifecycle transition."""
966
972
 
967
973
  initiated: Optional["SchemaPaymentEntryInput"] = None
968
- "Posted when the payment is approved. Optional."
974
+ "Posted when the payment is captured. Optional."
969
975
  settled: "SchemaPaymentEntryInput"
970
976
  "Posted when the payment settles. Every Payment Type must define it."
971
977
 
@@ -1,14 +1,12 @@
1
1
  # Generated by fragment (with the help of ariadne-codegen)
2
2
 
3
- # Ignore untyped authlib
4
- # mypy: disable-error-code="import-untyped"
5
3
  import time
6
4
  from typing import Any, Dict, Optional
7
5
 
8
6
  import httpx
9
7
  from ariadne_codegen.client_generators.dependencies.base_client import BaseClient
10
- from authlib.integrations.httpx_client import OAuth2Client
11
8
 
9
+ from fragment.client.oauth import fetch_token
12
10
  from fragment.exceptions import MissingArgumentException, MissingTokenException
13
11
 
14
12
 
@@ -37,14 +35,18 @@ class SyncFragmentClient(BaseClient):
37
35
  self.auth_url = auth_url
38
36
  self.expiration_time: Optional[float] = None
39
37
  self.token: Optional[Dict[str, Any]] = None
40
- self.oauth2_client = OAuth2Client(client_id, client_secret, scope=auth_scope)
38
+ self.client_id = client_id
39
+ self.client_secret = client_secret
40
+ self.auth_scope = auth_scope
41
41
 
42
42
  def refresh_token(self) -> None:
43
43
  now = time.time()
44
44
  if self.expiration_time is None or self.expiration_time <= now:
45
45
  # Held in a local because `self.token` is declared `dict | None`,
46
46
  # so reading the attribute back is not narrowed by the assignment.
47
- token = self.oauth2_client.fetch_token(self.auth_url)
47
+ token = fetch_token(
48
+ self.auth_url, self.client_id, self.client_secret, self.auth_scope
49
+ )
48
50
  self.token = token
49
51
  self.expiration_time = now + token["expires_in"]
50
52
 
@@ -5,7 +5,7 @@ target_package_name = "fragment_graphql_client"
5
5
 
6
6
  [tool.poetry]
7
7
  name = "fragment-python"
8
- version = "1.3.0"
8
+ version = "1.4.1"
9
9
  description = "Python SDK for https://fragment.dev/"
10
10
  authors = ["Fragment Foundries Inc"]
11
11
  license = "Apache 2.0"
@@ -18,7 +18,6 @@ ariadne-codegen = "^0.17.2"
18
18
  requests-oauth2client = "^1.6.0"
19
19
  pydantic = "^2.8.0"
20
20
  httpx = "^0.28.1"
21
- authlib = "^1.6.12"
22
21
  graphql-core = "^3.2.3"
23
22
  click = "^8.1.7"
24
23
 
@@ -27,8 +26,8 @@ pylint = "^3.2.6"
27
26
  black = "^26.3.1"
28
27
  isort = "^5.13.2"
29
28
  mypy = "^1.11.2"
30
- pytest = "^8.3.2"
31
- pytest-asyncio = "^0.24.0"
29
+ pytest = "^9.0.3"
30
+ pytest-asyncio = "^1.4.0"
32
31
 
33
32
  [build-system]
34
33
  requires = ["poetry-core"]
@@ -1,12 +0,0 @@
1
- class MissingTokenException(ValueError):
2
- """Token not found."""
3
-
4
- def __init__(self) -> None:
5
- super().__init__("Token is None")
6
-
7
-
8
- class MissingArgumentException(ValueError):
9
- """Argument not present."""
10
-
11
- def __init__(self, argument: str) -> None:
12
- super().__init__(f"{argument} must be provided")
File without changes