Monzo-API 1.2.4__tar.gz → 1.2.6__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.
- {monzo_api-1.2.4 → monzo_api-1.2.6/Monzo_API.egg-info}/PKG-INFO +2 -1
- {monzo_api-1.2.4/Monzo_API.egg-info → monzo_api-1.2.6}/PKG-INFO +2 -1
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/authentication.py +6 -7
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/endpoints/account.py +4 -5
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/endpoints/feed_item.py +8 -10
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/endpoints/monzo.py +1 -1
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/endpoints/pot.py +5 -5
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/endpoints/receipt.py +27 -27
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/endpoints/transaction.py +23 -25
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/endpoints/webhooks.py +2 -4
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/handlers/filesystem.py +1 -2
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/handlers/storage.py +1 -2
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/httpio.py +5 -5
- {monzo_api-1.2.4 → monzo_api-1.2.6}/pyproject.toml +13 -1
- {monzo_api-1.2.4 → monzo_api-1.2.6}/tests/test_authentication.py +1 -1
- {monzo_api-1.2.4 → monzo_api-1.2.6}/tests/test_endpoints.py +12 -12
- {monzo_api-1.2.4 → monzo_api-1.2.6}/tests/test_payload.py +4 -5
- {monzo_api-1.2.4 → monzo_api-1.2.6}/LICENSE +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/Monzo_API.egg-info/SOURCES.txt +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/Monzo_API.egg-info/dependency_links.txt +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/Monzo_API.egg-info/top_level.txt +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/README.rst +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/__init__.py +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/endpoints/__init__.py +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/endpoints/attachment.py +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/endpoints/balance.py +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/endpoints/whoami.py +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/exceptions.py +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/handlers/__init__.py +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/monzo/helpers.py +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/setup.cfg +0 -0
- {monzo_api-1.2.4 → monzo_api-1.2.6}/tests/test_httpio_errors.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Monzo-API
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
4
4
|
Summary: Package to interact with the API provided by Monzo bank
|
|
5
5
|
Author-email: Peter McDonald <git@petermcdonald.co.uk>
|
|
6
6
|
License: MIT License
|
|
@@ -37,6 +37,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
37
37
|
Classifier: Programming Language :: Python :: 3.13
|
|
38
38
|
Classifier: Programming Language :: Python :: 3.14
|
|
39
39
|
Classifier: Programming Language :: Python :: 3.15
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.16
|
|
40
41
|
Classifier: Topic :: Office/Business :: Financial
|
|
41
42
|
Classifier: Typing :: Typed
|
|
42
43
|
Requires-Python: >=3.12
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Monzo-API
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
4
4
|
Summary: Package to interact with the API provided by Monzo bank
|
|
5
5
|
Author-email: Peter McDonald <git@petermcdonald.co.uk>
|
|
6
6
|
License: MIT License
|
|
@@ -37,6 +37,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
37
37
|
Classifier: Programming Language :: Python :: 3.13
|
|
38
38
|
Classifier: Programming Language :: Python :: 3.14
|
|
39
39
|
Classifier: Programming Language :: Python :: 3.15
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.16
|
|
40
41
|
Classifier: Topic :: Office/Business :: Financial
|
|
41
42
|
Classifier: Typing :: Typed
|
|
42
43
|
Requires-Python: >=3.12
|
|
@@ -6,7 +6,6 @@ import secrets
|
|
|
6
6
|
from pathlib import Path, PurePath
|
|
7
7
|
from tempfile import gettempdir
|
|
8
8
|
from time import time
|
|
9
|
-
from typing import List
|
|
10
9
|
|
|
11
10
|
from monzo.exceptions import MonzoAuthenticationError, MonzoError, MonzoHTTPError
|
|
12
11
|
from monzo.handlers.storage import Storage
|
|
@@ -16,7 +15,7 @@ MONZO_AUTH_URL = "https://auth.monzo.com"
|
|
|
16
15
|
MONZO_API_URL = "https://api.monzo.com"
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
class Authentication
|
|
18
|
+
class Authentication:
|
|
20
19
|
"""
|
|
21
20
|
Class to manage authentication.
|
|
22
21
|
|
|
@@ -58,7 +57,7 @@ class Authentication(object):
|
|
|
58
57
|
self._access_token_expiry: int = access_token_expiry
|
|
59
58
|
self._client_id: str = client_id
|
|
60
59
|
self._client_secret: str = client_secret
|
|
61
|
-
self._handlers:
|
|
60
|
+
self._handlers: list[Storage] = []
|
|
62
61
|
self._redirect_url: str = redirect_url
|
|
63
62
|
self._refresh_token: str = refresh_token
|
|
64
63
|
|
|
@@ -68,7 +67,7 @@ class Authentication(object):
|
|
|
68
67
|
|
|
69
68
|
Args:
|
|
70
69
|
authorization_token: Authorization code provided by Monzo
|
|
71
|
-
state_token: Pre
|
|
70
|
+
state_token: Pre-agreed state token to validate against
|
|
72
71
|
|
|
73
72
|
Raises:
|
|
74
73
|
MonzoAuthenticationError On missing authorization token or mismatching state tokens
|
|
@@ -111,10 +110,10 @@ class Authentication(object):
|
|
|
111
110
|
timeout: Timeout in seconds for the request
|
|
112
111
|
|
|
113
112
|
Returns:
|
|
114
|
-
Dictionary containing headers and data from query response
|
|
113
|
+
Dictionary containing headers and data from a query response
|
|
115
114
|
|
|
116
115
|
Raises:
|
|
117
|
-
MonzoHTTPError: On using invalid method
|
|
116
|
+
MonzoHTTPError: On using an invalid method
|
|
118
117
|
"""
|
|
119
118
|
if self._access_token and self._access_token_expiry - time() < 0:
|
|
120
119
|
self.refresh_access()
|
|
@@ -182,7 +181,7 @@ class Authentication(object):
|
|
|
182
181
|
@access_token_expiry.setter
|
|
183
182
|
def access_token_expiry(self, expires_in: int) -> None:
|
|
184
183
|
"""
|
|
185
|
-
Setter for access token expiry property.
|
|
184
|
+
Setter for the access token expiry property.
|
|
186
185
|
|
|
187
186
|
Args:
|
|
188
187
|
expires_in: number of seconds until the token expires
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from datetime import datetime
|
|
6
|
-
from typing import List, Optional
|
|
7
6
|
|
|
8
7
|
from monzo.authentication import Authentication
|
|
9
8
|
from monzo.endpoints.balance import Balance
|
|
@@ -62,7 +61,7 @@ class Account(Monzo):
|
|
|
62
61
|
"""
|
|
63
62
|
self._auth: Authentication = auth
|
|
64
63
|
self._account_id: str = account_id
|
|
65
|
-
self._balance:
|
|
64
|
+
self._balance: Balance | None = None
|
|
66
65
|
self._created: datetime = created
|
|
67
66
|
self._description: str = description
|
|
68
67
|
self._has_balance: bool = True
|
|
@@ -95,7 +94,7 @@ class Account(Monzo):
|
|
|
95
94
|
"UNKNOWN",
|
|
96
95
|
)
|
|
97
96
|
|
|
98
|
-
def fetch_balance(self) ->
|
|
97
|
+
def fetch_balance(self) -> Balance | None:
|
|
99
98
|
"""
|
|
100
99
|
Fetch the live balance.
|
|
101
100
|
|
|
@@ -113,7 +112,7 @@ class Account(Monzo):
|
|
|
113
112
|
return self._balance
|
|
114
113
|
|
|
115
114
|
@property
|
|
116
|
-
def balance(self) ->
|
|
115
|
+
def balance(self) -> Balance | None:
|
|
117
116
|
"""
|
|
118
117
|
Property for balance.
|
|
119
118
|
|
|
@@ -158,7 +157,7 @@ class Account(Monzo):
|
|
|
158
157
|
return self._closed
|
|
159
158
|
|
|
160
159
|
@classmethod
|
|
161
|
-
def fetch(cls, auth: Authentication, account_type: str = "") ->
|
|
160
|
+
def fetch(cls, auth: Authentication, account_type: str = "") -> list[Account]:
|
|
162
161
|
"""
|
|
163
162
|
Implement and instantiates an Account object.
|
|
164
163
|
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import Dict, Optional
|
|
6
|
-
|
|
7
5
|
from monzo.authentication import Authentication
|
|
8
6
|
from monzo.endpoints.monzo import Monzo
|
|
9
7
|
from monzo.exceptions import MonzoArgumentError
|
|
@@ -46,7 +44,7 @@ class FeedItem(Monzo):
|
|
|
46
44
|
auth: Authentication,
|
|
47
45
|
account_id: str,
|
|
48
46
|
feed_type: str,
|
|
49
|
-
params:
|
|
47
|
+
params: dict[str, str],
|
|
50
48
|
url: str = "",
|
|
51
49
|
):
|
|
52
50
|
"""
|
|
@@ -57,15 +55,15 @@ class FeedItem(Monzo):
|
|
|
57
55
|
account_id: ID for the account to create the feed item for
|
|
58
56
|
feed_type: Type of feed item to create (must be in FEED_ITEM_TYPES)
|
|
59
57
|
params: Parameters for the feed item.
|
|
60
|
-
url: Optional URL for feed item
|
|
58
|
+
url: Optional URL for a feed item
|
|
61
59
|
"""
|
|
62
60
|
self._account_id: str = account_id
|
|
63
61
|
self._feed_type: str = feed_type
|
|
64
|
-
self._params:
|
|
65
|
-
self._url:
|
|
62
|
+
self._params: dict[str, str] = params
|
|
63
|
+
self._url: str | None = url
|
|
66
64
|
super().__init__(auth=auth)
|
|
67
65
|
|
|
68
|
-
def _validate_feed_params(self) ->
|
|
66
|
+
def _validate_feed_params(self) -> dict[str, str]:
|
|
69
67
|
"""
|
|
70
68
|
Clean the params dictionary with the valid params for the feed type.
|
|
71
69
|
|
|
@@ -73,7 +71,7 @@ class FeedItem(Monzo):
|
|
|
73
71
|
MonzoArgumentError: On missing required parameters
|
|
74
72
|
|
|
75
73
|
Returns:
|
|
76
|
-
Dictionary of parameters only
|
|
74
|
+
Dictionary of parameters only contains valid keys
|
|
77
75
|
"""
|
|
78
76
|
if self._feed_type.lower() not in FEED_ITEM_TYPES:
|
|
79
77
|
raise MonzoArgumentError("Feed type appears invalid")
|
|
@@ -110,7 +108,7 @@ class FeedItem(Monzo):
|
|
|
110
108
|
auth: Authentication,
|
|
111
109
|
account_id: str,
|
|
112
110
|
feed_type: str,
|
|
113
|
-
params:
|
|
111
|
+
params: dict[str, str],
|
|
114
112
|
url: str = "",
|
|
115
113
|
) -> FeedItem:
|
|
116
114
|
"""
|
|
@@ -121,7 +119,7 @@ class FeedItem(Monzo):
|
|
|
121
119
|
account_id: ID for the account to create the feed item for
|
|
122
120
|
feed_type: Type of feed item to create (must be in FEED_ITEM_TYPES)
|
|
123
121
|
params: Parameters for the feed item.
|
|
124
|
-
url: Optional URL for feed item
|
|
122
|
+
url: Optional URL for a feed item
|
|
125
123
|
"""
|
|
126
124
|
feed_item = FeedItem(
|
|
127
125
|
auth=auth,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from datetime import datetime
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
from monzo.authentication import Authentication
|
|
9
9
|
from monzo.endpoints.balance import Balance
|
|
@@ -186,7 +186,7 @@ class Pot(Monzo):
|
|
|
186
186
|
Property for the pot round up multiplier.
|
|
187
187
|
|
|
188
188
|
Returns:
|
|
189
|
-
int object for the
|
|
189
|
+
int object for the pot round up multiplier else None object if roundup is disabled
|
|
190
190
|
"""
|
|
191
191
|
return self._round_up_multiplier
|
|
192
192
|
|
|
@@ -270,7 +270,7 @@ class Pot(Monzo):
|
|
|
270
270
|
return cls._update_pot(pot=pot, data=res["data"])
|
|
271
271
|
|
|
272
272
|
@classmethod
|
|
273
|
-
def fetch(cls, auth: Authentication, account_id: str) ->
|
|
273
|
+
def fetch(cls, auth: Authentication, account_id: str) -> list[Pot]:
|
|
274
274
|
"""
|
|
275
275
|
Fetch a list of pots associated with an account.
|
|
276
276
|
|
|
@@ -309,7 +309,7 @@ class Pot(Monzo):
|
|
|
309
309
|
return pot_list
|
|
310
310
|
|
|
311
311
|
@classmethod
|
|
312
|
-
def fetch_single(cls, auth: Authentication, account_id: str, pot_id: str) ->
|
|
312
|
+
def fetch_single(cls, auth: Authentication, account_id: str, pot_id: str) -> Pot | None:
|
|
313
313
|
"""
|
|
314
314
|
Fetch a pot associated with an account with the given pot id.
|
|
315
315
|
|
|
@@ -361,7 +361,7 @@ class Pot(Monzo):
|
|
|
361
361
|
return cls._update_pot(pot=pot, data=res["data"])
|
|
362
362
|
|
|
363
363
|
@classmethod
|
|
364
|
-
def _update_pot(cls, pot: Pot, data:
|
|
364
|
+
def _update_pot(cls, pot: Pot, data: dict[str, Any]) -> Pot:
|
|
365
365
|
"""
|
|
366
366
|
Update a provided pot from a result received from a request.
|
|
367
367
|
|
|
@@ -3,23 +3,23 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from json import dumps
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
from monzo.authentication import Authentication
|
|
9
9
|
from monzo.endpoints.monzo import Monzo
|
|
10
10
|
|
|
11
11
|
RECEIPTS_PATH = "/transaction-receipts"
|
|
12
12
|
|
|
13
|
-
ITEM_TYPE =
|
|
13
|
+
ITEM_TYPE = dict[
|
|
14
14
|
str,
|
|
15
|
-
|
|
15
|
+
float | int | None | str | list[dict[str, float | int | str | None]],
|
|
16
16
|
]
|
|
17
|
-
MERCHANT_TYPE =
|
|
18
|
-
PAYMENT_TYPE =
|
|
19
|
-
TAX_TYPE =
|
|
17
|
+
MERCHANT_TYPE = dict[str, bool | str]
|
|
18
|
+
PAYMENT_TYPE = dict[str, int | str]
|
|
19
|
+
TAX_TYPE = dict[str, int | str]
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class ReceiptItem
|
|
22
|
+
class ReceiptItem:
|
|
23
23
|
"""
|
|
24
24
|
Class for Receipt Items.
|
|
25
25
|
|
|
@@ -62,7 +62,7 @@ class ReceiptItem(object):
|
|
|
62
62
|
self._quantity = quantity
|
|
63
63
|
self._tax = tax
|
|
64
64
|
self._unit = unit
|
|
65
|
-
self._sub_items:
|
|
65
|
+
self._sub_items: list[ReceiptItem] = []
|
|
66
66
|
|
|
67
67
|
def add_sub_item(self, sub_item: ReceiptItem):
|
|
68
68
|
"""
|
|
@@ -88,7 +88,7 @@ class ReceiptItem(object):
|
|
|
88
88
|
"tax": self._tax,
|
|
89
89
|
"unit": self._unit,
|
|
90
90
|
}
|
|
91
|
-
sub_item_list:
|
|
91
|
+
sub_item_list: list[Any] = [sub_item.as_dict() for sub_item in self._sub_items]
|
|
92
92
|
|
|
93
93
|
item["sub_items"] = sub_item_list
|
|
94
94
|
|
|
@@ -99,7 +99,7 @@ class Receipt(Monzo):
|
|
|
99
99
|
"""
|
|
100
100
|
Class to manage Receipts.
|
|
101
101
|
|
|
102
|
-
Class provides methods to create, fetch and delete receipts.
|
|
102
|
+
Class provides methods to create, fetch, and delete receipts.
|
|
103
103
|
"""
|
|
104
104
|
|
|
105
105
|
__slots__ = (
|
|
@@ -120,7 +120,7 @@ class Receipt(Monzo):
|
|
|
120
120
|
external_id: str,
|
|
121
121
|
transaction_total: int,
|
|
122
122
|
transaction_currency: str,
|
|
123
|
-
items:
|
|
123
|
+
items: list[ReceiptItem],
|
|
124
124
|
):
|
|
125
125
|
"""
|
|
126
126
|
Initialize Receipt.
|
|
@@ -137,9 +137,9 @@ class Receipt(Monzo):
|
|
|
137
137
|
self._transaction_id: str = transaction_id
|
|
138
138
|
self._total = transaction_total
|
|
139
139
|
self._currency = transaction_currency
|
|
140
|
-
self._items:
|
|
141
|
-
self._taxes:
|
|
142
|
-
self._payments:
|
|
140
|
+
self._items: list[ReceiptItem] = items
|
|
141
|
+
self._taxes: list[TAX_TYPE] = []
|
|
142
|
+
self._payments: list[PAYMENT_TYPE] = []
|
|
143
143
|
self._merchant: MERCHANT_TYPE = {}
|
|
144
144
|
|
|
145
145
|
super().__init__(auth=auth)
|
|
@@ -148,11 +148,11 @@ class Receipt(Monzo):
|
|
|
148
148
|
self,
|
|
149
149
|
name: str,
|
|
150
150
|
online: bool,
|
|
151
|
-
phone:
|
|
152
|
-
email:
|
|
153
|
-
store_name:
|
|
154
|
-
store_address:
|
|
155
|
-
store_postcode:
|
|
151
|
+
phone: str | None = None,
|
|
152
|
+
email: str | None = None,
|
|
153
|
+
store_name: str | None = None,
|
|
154
|
+
store_address: str | None = None,
|
|
155
|
+
store_postcode: str | None = None,
|
|
156
156
|
):
|
|
157
157
|
"""
|
|
158
158
|
Set the merchant for the receipt.
|
|
@@ -188,7 +188,7 @@ class Receipt(Monzo):
|
|
|
188
188
|
description: str,
|
|
189
189
|
amount: int,
|
|
190
190
|
currency: str,
|
|
191
|
-
tax_number:
|
|
191
|
+
tax_number: str | None = None,
|
|
192
192
|
):
|
|
193
193
|
"""
|
|
194
194
|
Add receipt tax item.
|
|
@@ -210,7 +210,7 @@ class Receipt(Monzo):
|
|
|
210
210
|
|
|
211
211
|
def _create(self) -> None:
|
|
212
212
|
"""Create the receipt."""
|
|
213
|
-
data = {
|
|
213
|
+
data: dict[str, Any] = {
|
|
214
214
|
"transaction_id": self._transaction_id,
|
|
215
215
|
"external_id": self._external_id,
|
|
216
216
|
"total": self._total,
|
|
@@ -219,7 +219,7 @@ class Receipt(Monzo):
|
|
|
219
219
|
"payments": self._payments,
|
|
220
220
|
"merchant": self._merchant,
|
|
221
221
|
}
|
|
222
|
-
receipt_items:
|
|
222
|
+
receipt_items: list[ITEM_TYPE] = [item.as_dict() for item in self._items]
|
|
223
223
|
|
|
224
224
|
data["items"] = receipt_items
|
|
225
225
|
|
|
@@ -261,7 +261,7 @@ class Receipt(Monzo):
|
|
|
261
261
|
return self._currency
|
|
262
262
|
|
|
263
263
|
@property
|
|
264
|
-
def receipt_items(self) ->
|
|
264
|
+
def receipt_items(self) -> list[ReceiptItem]:
|
|
265
265
|
"""
|
|
266
266
|
Property for the items in a receipt.
|
|
267
267
|
|
|
@@ -281,7 +281,7 @@ class Receipt(Monzo):
|
|
|
281
281
|
return self._merchant
|
|
282
282
|
|
|
283
283
|
@property
|
|
284
|
-
def receipt_payments(self) ->
|
|
284
|
+
def receipt_payments(self) -> list[PAYMENT_TYPE]:
|
|
285
285
|
"""
|
|
286
286
|
Property for the payments in a receipt.
|
|
287
287
|
|
|
@@ -291,7 +291,7 @@ class Receipt(Monzo):
|
|
|
291
291
|
return self._payments
|
|
292
292
|
|
|
293
293
|
@property
|
|
294
|
-
def receipt_taxes(self) ->
|
|
294
|
+
def receipt_taxes(self) -> list[TAX_TYPE]:
|
|
295
295
|
"""
|
|
296
296
|
Property for the taxes in a receipt.
|
|
297
297
|
|
|
@@ -347,7 +347,7 @@ class Receipt(Monzo):
|
|
|
347
347
|
receipt._delete()
|
|
348
348
|
|
|
349
349
|
@classmethod
|
|
350
|
-
def fetch(cls, auth: Authentication, external_id: str) ->
|
|
350
|
+
def fetch(cls, auth: Authentication, external_id: str) -> list[Receipt]:
|
|
351
351
|
"""
|
|
352
352
|
Fetch the receipt with the given external ID.
|
|
353
353
|
|
|
@@ -361,7 +361,7 @@ class Receipt(Monzo):
|
|
|
361
361
|
data = {"external_id": external_id}
|
|
362
362
|
res = auth.make_request(path=RECEIPTS_PATH, data=data)
|
|
363
363
|
receipt_data = res["data"]["receipt"]
|
|
364
|
-
receipt_items:
|
|
364
|
+
receipt_items: list[ReceiptItem] = []
|
|
365
365
|
for item in receipt_data["items"]:
|
|
366
366
|
quantity = float(item["quantity"]) if "quantity" in item else 0.0
|
|
367
367
|
tax = item["tax"] if "tax" in item else 0
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from datetime import datetime
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
from monzo.authentication import Authentication
|
|
9
9
|
from monzo.endpoints.monzo import Monzo
|
|
@@ -56,7 +56,7 @@ class Transaction(Monzo):
|
|
|
56
56
|
"_user_id",
|
|
57
57
|
]
|
|
58
58
|
|
|
59
|
-
def __init__(self, auth: Authentication, transaction_data:
|
|
59
|
+
def __init__(self, auth: Authentication, transaction_data: dict[str, Any]):
|
|
60
60
|
"""
|
|
61
61
|
Initialize Transaction.
|
|
62
62
|
|
|
@@ -76,7 +76,7 @@ class Transaction(Monzo):
|
|
|
76
76
|
"can_match_transactions_in_categorization"
|
|
77
77
|
]
|
|
78
78
|
self._can_split_the_bill: bool = transaction_data["can_split_the_bill"]
|
|
79
|
-
self._categories:
|
|
79
|
+
self._categories: dict[str, int | str] = transaction_data["categories"]
|
|
80
80
|
self._category: str = transaction_data["category"]
|
|
81
81
|
self._counterparty = transaction_data["counterparty"]
|
|
82
82
|
self._created: datetime = create_date(transaction_data["created"])
|
|
@@ -84,19 +84,19 @@ class Transaction(Monzo):
|
|
|
84
84
|
self._dedupe_id: str = transaction_data["dedupe_id"]
|
|
85
85
|
self._decline_reason: str = transaction_data.get("decline_reason", "")
|
|
86
86
|
self._description: str = transaction_data["description"]
|
|
87
|
-
self._fees:
|
|
87
|
+
self._fees: dict[str, Any] = transaction_data["fees"]
|
|
88
88
|
self._include_in_spending: bool = transaction_data["include_in_spending"]
|
|
89
|
-
self._international:
|
|
89
|
+
self._international: str | None = transaction_data["international"]
|
|
90
90
|
self._is_load: bool = transaction_data["is_load"]
|
|
91
91
|
self._labels: str = transaction_data["labels"]
|
|
92
92
|
self._local_amount: int = transaction_data["local_amount"]
|
|
93
93
|
self._local_currency: str = transaction_data["local_currency"]
|
|
94
94
|
self._merchant: str = transaction_data["merchant"]
|
|
95
|
-
self._metadata:
|
|
95
|
+
self._metadata: dict[str, str] = transaction_data["metadata"]
|
|
96
96
|
self._notes: str = transaction_data["notes"]
|
|
97
97
|
self._originator: bool = transaction_data["originator"]
|
|
98
98
|
self._scheme: str = transaction_data["scheme"]
|
|
99
|
-
self._settled:
|
|
99
|
+
self._settled: datetime | None = None
|
|
100
100
|
if transaction_data["settled"]:
|
|
101
101
|
self._settled = create_date(transaction_data["settled"])
|
|
102
102
|
self._transaction_id: str = transaction_data["id"]
|
|
@@ -131,12 +131,12 @@ class Transaction(Monzo):
|
|
|
131
131
|
Property to identify if the amount is pending.
|
|
132
132
|
|
|
133
133
|
Returns:
|
|
134
|
-
True if transaction is pending
|
|
134
|
+
True if a transaction is pending
|
|
135
135
|
"""
|
|
136
136
|
return self._amount_is_pending
|
|
137
137
|
|
|
138
138
|
@property
|
|
139
|
-
def atm_fees_detailed(self) ->
|
|
139
|
+
def atm_fees_detailed(self) -> str | None:
|
|
140
140
|
"""
|
|
141
141
|
Property for detailed atm fees.
|
|
142
142
|
|
|
@@ -146,7 +146,7 @@ class Transaction(Monzo):
|
|
|
146
146
|
return self._atm_fees_detailed
|
|
147
147
|
|
|
148
148
|
@property
|
|
149
|
-
def attachments(self) ->
|
|
149
|
+
def attachments(self) -> str | None:
|
|
150
150
|
"""
|
|
151
151
|
Property for attachments.
|
|
152
152
|
|
|
@@ -206,7 +206,7 @@ class Transaction(Monzo):
|
|
|
206
206
|
return self._can_split_the_bill
|
|
207
207
|
|
|
208
208
|
@property
|
|
209
|
-
def categories(self) ->
|
|
209
|
+
def categories(self) -> dict[str, int | str]:
|
|
210
210
|
"""
|
|
211
211
|
Property to identify categories a transaction is a member of.
|
|
212
212
|
|
|
@@ -226,7 +226,7 @@ class Transaction(Monzo):
|
|
|
226
226
|
return self._category
|
|
227
227
|
|
|
228
228
|
@property
|
|
229
|
-
def counterparty(self) ->
|
|
229
|
+
def counterparty(self) -> dict[str, str]:
|
|
230
230
|
"""
|
|
231
231
|
Property to identify counterparty.
|
|
232
232
|
|
|
@@ -288,7 +288,7 @@ class Transaction(Monzo):
|
|
|
288
288
|
return self._description
|
|
289
289
|
|
|
290
290
|
@property
|
|
291
|
-
def fees(self) ->
|
|
291
|
+
def fees(self) -> dict[str, Any]:
|
|
292
292
|
"""
|
|
293
293
|
Property for transaction fees.
|
|
294
294
|
|
|
@@ -308,7 +308,7 @@ class Transaction(Monzo):
|
|
|
308
308
|
return self._include_in_spending
|
|
309
309
|
|
|
310
310
|
@property
|
|
311
|
-
def international(self) ->
|
|
311
|
+
def international(self) -> str | None:
|
|
312
312
|
"""
|
|
313
313
|
UNCLEAR.
|
|
314
314
|
|
|
@@ -370,7 +370,7 @@ class Transaction(Monzo):
|
|
|
370
370
|
return self._merchant
|
|
371
371
|
|
|
372
372
|
@property
|
|
373
|
-
def metadata(self) ->
|
|
373
|
+
def metadata(self) -> dict[str, str]:
|
|
374
374
|
"""
|
|
375
375
|
Property for metadata associated with a transaction.
|
|
376
376
|
|
|
@@ -395,7 +395,7 @@ class Transaction(Monzo):
|
|
|
395
395
|
Property to identify if you are the originator of a transaction.
|
|
396
396
|
|
|
397
397
|
Returns:
|
|
398
|
-
True if you are the originator of a transaction otherwise False
|
|
398
|
+
True if you are the originator of a transaction, otherwise False
|
|
399
399
|
"""
|
|
400
400
|
return self._originator
|
|
401
401
|
|
|
@@ -412,7 +412,7 @@ class Transaction(Monzo):
|
|
|
412
412
|
return self._scheme
|
|
413
413
|
|
|
414
414
|
@property
|
|
415
|
-
def settled(self) ->
|
|
415
|
+
def settled(self) -> datetime | None:
|
|
416
416
|
"""
|
|
417
417
|
Property for when a transaction was settled.
|
|
418
418
|
|
|
@@ -432,7 +432,7 @@ class Transaction(Monzo):
|
|
|
432
432
|
return self._transaction_id
|
|
433
433
|
|
|
434
434
|
@property
|
|
435
|
-
def updated(self) ->
|
|
435
|
+
def updated(self) -> datetime | None:
|
|
436
436
|
"""
|
|
437
437
|
Property for when a transaction was updated.
|
|
438
438
|
|
|
@@ -477,9 +477,7 @@ class Transaction(Monzo):
|
|
|
477
477
|
self._metadata = res["data"]["transaction"]["metadata"]
|
|
478
478
|
|
|
479
479
|
@classmethod
|
|
480
|
-
def fetch_single(
|
|
481
|
-
cls, auth: Authentication, transaction_id: str, expand_on: str = "merchant"
|
|
482
|
-
) -> Optional[Transaction]:
|
|
480
|
+
def fetch_single(cls, auth: Authentication, transaction_id: str, expand_on: str = "merchant") -> Transaction | None:
|
|
483
481
|
"""
|
|
484
482
|
Fetch a transaction with a specific ID.
|
|
485
483
|
|
|
@@ -507,11 +505,11 @@ class Transaction(Monzo):
|
|
|
507
505
|
cls,
|
|
508
506
|
auth: Authentication,
|
|
509
507
|
account_id: str,
|
|
510
|
-
since:
|
|
511
|
-
before:
|
|
508
|
+
since: datetime | str | None = None,
|
|
509
|
+
before: datetime | None = None,
|
|
512
510
|
expand=None,
|
|
513
511
|
limit=30,
|
|
514
|
-
) ->
|
|
512
|
+
) -> list[Transaction]:
|
|
515
513
|
"""
|
|
516
514
|
Fetch a list of transaction.
|
|
517
515
|
|
|
@@ -524,7 +522,7 @@ class Transaction(Monzo):
|
|
|
524
522
|
limit: Number of transactions to return per request, max 100, default 30.
|
|
525
523
|
|
|
526
524
|
Returns:
|
|
527
|
-
List of
|
|
525
|
+
List of transactions
|
|
528
526
|
"""
|
|
529
527
|
if expand is None:
|
|
530
528
|
expand = []
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import List
|
|
6
|
-
|
|
7
5
|
from monzo.authentication import Authentication
|
|
8
6
|
from monzo.endpoints.monzo import Monzo
|
|
9
7
|
|
|
@@ -12,7 +10,7 @@ class Webhook(Monzo):
|
|
|
12
10
|
"""
|
|
13
11
|
Class to manage webhooks.
|
|
14
12
|
|
|
15
|
-
Class provides methods to create, fetch and delete webhooks.
|
|
13
|
+
Class provides methods to create, fetch, and delete webhooks.
|
|
16
14
|
"""
|
|
17
15
|
|
|
18
16
|
__slots__ = ["_account_id", "_url", "_webhook_id"]
|
|
@@ -104,7 +102,7 @@ class Webhook(Monzo):
|
|
|
104
102
|
webhook._delete()
|
|
105
103
|
|
|
106
104
|
@classmethod
|
|
107
|
-
def fetch(cls, auth: Authentication, account_id: str) ->
|
|
105
|
+
def fetch(cls, auth: Authentication, account_id: str) -> list[Webhook]:
|
|
108
106
|
"""
|
|
109
107
|
Fetch webhooks for an account.
|
|
110
108
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Class to store credentials on the file system."""
|
|
2
2
|
|
|
3
3
|
from json import dumps, loads
|
|
4
|
-
from typing import Dict, Union
|
|
5
4
|
|
|
6
5
|
from monzo.handlers.storage import Storage
|
|
7
6
|
|
|
@@ -20,7 +19,7 @@ class FileSystem(Storage):
|
|
|
20
19
|
"""
|
|
21
20
|
self._file = file
|
|
22
21
|
|
|
23
|
-
def fetch(self) ->
|
|
22
|
+
def fetch(self) -> dict[str, int | str]:
|
|
24
23
|
"""
|
|
25
24
|
Fetch Monzo credentials previously stored.
|
|
26
25
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Abstract class for credential storage."""
|
|
2
2
|
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
|
-
from typing import Dict, Union
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
class Storage(ABC):
|
|
@@ -13,7 +12,7 @@ class Storage(ABC):
|
|
|
13
12
|
"""
|
|
14
13
|
|
|
15
14
|
@abstractmethod
|
|
16
|
-
def fetch(self) ->
|
|
15
|
+
def fetch(self) -> dict[str, int | str]:
|
|
17
16
|
"""
|
|
18
17
|
Abstract method that needs to be implemented to Fetch Monzo credentials previously stored.
|
|
19
18
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Class that handles HTTP requests."""
|
|
2
2
|
|
|
3
3
|
from json import loads
|
|
4
|
-
from typing import Any
|
|
4
|
+
from typing import Any
|
|
5
5
|
from urllib.error import HTTPError
|
|
6
6
|
from urllib.parse import urlencode
|
|
7
7
|
from urllib.request import Request, urlopen
|
|
@@ -17,7 +17,7 @@ from monzo.exceptions import (
|
|
|
17
17
|
|
|
18
18
|
DEFAULT_TIMEOUT = 10
|
|
19
19
|
|
|
20
|
-
REQUEST_RESPONSE_TYPE =
|
|
20
|
+
REQUEST_RESPONSE_TYPE = dict[str, Any]
|
|
21
21
|
|
|
22
22
|
MONZO_ERROR_MAP = {
|
|
23
23
|
400: MonzoHTTPError,
|
|
@@ -32,7 +32,7 @@ MONZO_ERROR_MAP = {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
class HttpIO
|
|
35
|
+
class HttpIO:
|
|
36
36
|
"""
|
|
37
37
|
Class to facilitate http requests.
|
|
38
38
|
|
|
@@ -164,8 +164,8 @@ class HttpIO(object):
|
|
|
164
164
|
self,
|
|
165
165
|
method: str,
|
|
166
166
|
path: str,
|
|
167
|
-
data:
|
|
168
|
-
headers:
|
|
167
|
+
data: bytes | None,
|
|
168
|
+
headers: dict[str, Any],
|
|
169
169
|
timeout,
|
|
170
170
|
) -> REQUEST_RESPONSE_TYPE:
|
|
171
171
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "Monzo-API"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.6"
|
|
4
4
|
authors = [{ name = "Peter McDonald", email = "git@petermcdonald.co.uk"}]
|
|
5
5
|
description = "Package to interact with the API provided by Monzo bank"
|
|
6
6
|
keywords = ["monzo", "bank", "api"]
|
|
@@ -16,6 +16,7 @@ classifiers = [
|
|
|
16
16
|
"Programming Language :: Python :: 3.13",
|
|
17
17
|
"Programming Language :: Python :: 3.14",
|
|
18
18
|
"Programming Language :: Python :: 3.15",
|
|
19
|
+
"Programming Language :: Python :: 3.16",
|
|
19
20
|
"Topic :: Office/Business :: Financial",
|
|
20
21
|
"Typing :: Typed",
|
|
21
22
|
]
|
|
@@ -28,7 +29,9 @@ documentation = "https://monzo-api.readthedocs.io"
|
|
|
28
29
|
|
|
29
30
|
[dependency-groups]
|
|
30
31
|
dev = [
|
|
32
|
+
"cosmic-ray>=8.4.6",
|
|
31
33
|
"idna>=3.16", # To resolve security vulnerabilities in dependencies pip-audit
|
|
34
|
+
"pip-audit>=2.9.0",
|
|
32
35
|
"pygments>=2.20.0", # To resolve security vulnerabilities in dependencies pytest sphinx
|
|
33
36
|
"pytest>=9.0.3",
|
|
34
37
|
"pytest-cov>=7.1.0",
|
|
@@ -46,3 +49,12 @@ addopts = "--cov=monzo --cov-report term-missing --cov-report xml:coverage.xml"
|
|
|
46
49
|
|
|
47
50
|
[tool.ruff]
|
|
48
51
|
line-length = 120
|
|
52
|
+
|
|
53
|
+
[cosmic-ray]
|
|
54
|
+
module-path = "monzo"
|
|
55
|
+
timeout = 10.0
|
|
56
|
+
excluded-modules = []
|
|
57
|
+
test-command = "uv run pytest"
|
|
58
|
+
|
|
59
|
+
[cosmic-ray.distributor]
|
|
60
|
+
name = "local"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Tests for endpoints."""
|
|
2
2
|
|
|
3
3
|
from datetime import datetime
|
|
4
|
-
from typing import Any
|
|
4
|
+
from typing import Any
|
|
5
5
|
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
@@ -15,7 +15,7 @@ from monzo.endpoints.whoami import WhoAmI
|
|
|
15
15
|
from tests.helpers import Handler, load_data
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
class TestEndPoints
|
|
18
|
+
class TestEndPoints:
|
|
19
19
|
"""Tests for the endpoints."""
|
|
20
20
|
|
|
21
21
|
@pytest.mark.parametrize(
|
|
@@ -146,8 +146,8 @@ class TestEndPoints(object):
|
|
|
146
146
|
expected_external_id: str,
|
|
147
147
|
expected_receipt_currency: str,
|
|
148
148
|
expected_receipt_merchant: MERCHANT_TYPE,
|
|
149
|
-
expected_receipt_payments:
|
|
150
|
-
expected_receipt_taxes:
|
|
149
|
+
expected_receipt_payments: list[PAYMENT_TYPE],
|
|
150
|
+
expected_receipt_taxes: list[TAX_TYPE],
|
|
151
151
|
expected_receipt_total: int,
|
|
152
152
|
expected_transaction_id: str,
|
|
153
153
|
mocker,
|
|
@@ -270,7 +270,7 @@ class TestEndPoints(object):
|
|
|
270
270
|
expected_can_be_made_subscription: bool,
|
|
271
271
|
expected_can_match_transactions_in_categorization: bool,
|
|
272
272
|
expected_can_split_the_bill: bool,
|
|
273
|
-
expected_categories:
|
|
273
|
+
expected_categories: dict[str, int | str],
|
|
274
274
|
expected_category: str,
|
|
275
275
|
expected_counterparty: str,
|
|
276
276
|
expected_created: datetime,
|
|
@@ -278,21 +278,21 @@ class TestEndPoints(object):
|
|
|
278
278
|
expected_dedupe_id: str,
|
|
279
279
|
expected_decline_reason: str,
|
|
280
280
|
expected_description: str,
|
|
281
|
-
expected_fees:
|
|
281
|
+
expected_fees: dict[str, Any],
|
|
282
282
|
expected_include_in_spending: bool,
|
|
283
|
-
expected_international:
|
|
283
|
+
expected_international: str | None,
|
|
284
284
|
expected_is_load: bool,
|
|
285
285
|
expected_labels: str,
|
|
286
286
|
expected_local_amount: int,
|
|
287
287
|
expected_local_currency: str,
|
|
288
288
|
expected_merchant: str,
|
|
289
|
-
expected_metadata:
|
|
289
|
+
expected_metadata: dict[str, str],
|
|
290
290
|
expected_notes: str,
|
|
291
291
|
expected_originator: bool,
|
|
292
292
|
expected_scheme: str,
|
|
293
|
-
expected_settled:
|
|
293
|
+
expected_settled: datetime | None,
|
|
294
294
|
expected_transaction_id: str,
|
|
295
|
-
expected_updated:
|
|
295
|
+
expected_updated: datetime | None,
|
|
296
296
|
expected_user_id: bool,
|
|
297
297
|
mocker,
|
|
298
298
|
):
|
|
@@ -414,8 +414,8 @@ class TestEndPoints(object):
|
|
|
414
414
|
self,
|
|
415
415
|
mock_file: str,
|
|
416
416
|
expected_account_id: str,
|
|
417
|
-
expected_url:
|
|
418
|
-
expected_webhook_id:
|
|
417
|
+
expected_url: str | None,
|
|
418
|
+
expected_webhook_id: str | None,
|
|
419
419
|
expected_count: int,
|
|
420
420
|
mocker,
|
|
421
421
|
):
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Tests for HttpIO."""
|
|
2
2
|
|
|
3
3
|
from json import dumps
|
|
4
|
-
from typing import Dict
|
|
5
4
|
|
|
6
5
|
import pytest
|
|
7
6
|
|
|
@@ -16,7 +15,7 @@ from monzo.endpoints.whoami import WhoAmI
|
|
|
16
15
|
from tests.helpers import Handler, load_data
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
class TestHttpIO
|
|
18
|
+
class TestHttpIO:
|
|
20
19
|
"""Tests for the HttpIO class."""
|
|
21
20
|
|
|
22
21
|
@pytest.mark.parametrize(
|
|
@@ -54,7 +53,7 @@ class TestHttpIO(object):
|
|
|
54
53
|
http_method: str,
|
|
55
54
|
data_filename: str,
|
|
56
55
|
response_filename: str,
|
|
57
|
-
extra_data:
|
|
56
|
+
extra_data: dict[str, str],
|
|
58
57
|
mocker,
|
|
59
58
|
):
|
|
60
59
|
"""
|
|
@@ -194,7 +193,7 @@ class TestHttpIO(object):
|
|
|
194
193
|
http_method: str,
|
|
195
194
|
data_filename: str,
|
|
196
195
|
response_filename: str,
|
|
197
|
-
extra_data:
|
|
196
|
+
extra_data: dict[str, str],
|
|
198
197
|
mocker,
|
|
199
198
|
):
|
|
200
199
|
"""
|
|
@@ -258,7 +257,7 @@ class TestHttpIO(object):
|
|
|
258
257
|
http_method: str,
|
|
259
258
|
data_filename: str,
|
|
260
259
|
response_filename: str,
|
|
261
|
-
extra_data:
|
|
260
|
+
extra_data: dict[str, str],
|
|
262
261
|
mocker,
|
|
263
262
|
):
|
|
264
263
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|