Skip to content

Commit 94eecf4

Browse files
committed
💥 httpx refactor
replaces requests with httpx. Breaking API Changes: - `LunchMoney.make_http_request()` -> `LunchMoney.request()` - `LunchMoney.lunchmoney_session` -> `LunchMoney.session` Other API Changes: - `LunchMoney._make_request()` -> `LunchMoney.make_request()` - `LunchMoney.process_response()` - handle a raw response - `LunchMoney.async_session` - async session - `LunchMoney.arequest()` - raw async requests - `LunchMoney.process_response()` - handle a raw response
1 parent 2f0af25 commit 94eecf4

Some content is hidden

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

60 files changed

+788
-530
lines changed

‎README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
[![GitHub License](https://img.shields.io/github/license/juftin/lunchable?color=blue&label=License)](https://github.com/juftin/lunchable/blob/main/LICENSE)
1515

1616
**lunchable** is a Python Client for the [Lunch Money Developer API](https://lunchmoney.dev). It's
17-
built on top of [pydantic](https://github.com/pydantic/pydantic), it offers an _intuitive_ API,
18-
a _simple_ CLI, complete coverage of all endpoints, and _plugins_ to other external services.
17+
built on top of [pydantic](https://github.com/pydantic/pydantic) and [httpx](https://github.com/encode/httpx/),
18+
it offers an _intuitive_ API, a _simple_ CLI, complete coverage of all endpoints,
19+
and _plugins_ to other external services.
1920

2021
### Installation
2122

‎docs/source/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99

1010
**lunchable** is a Python Client for the
1111
`Lunch Money Developer API <https://lunchmoney.dev>`_.
12-
It's built on top of `pydantic <https://github.com/samuelcolvin/pydantic>`_,
12+
It's built on top of `pydantic <https://github.com/pydantic/pydantic>`_,
13+
and `httpx <https://github.com/encode/httpx/>`_,
1314
it offers an *intuitive* API, a *simple* CLI,
1415
complete coverage of all endpoints,
1516
and *plugins* to other external services

‎lunchable/_cli.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
from typing import Any, Dict, Optional, Union
1010

1111
import click
12-
import requests
13-
from pydantic.json import pydantic_encoder
12+
import httpx
13+
from pydantic_core import to_jsonable_python
1414
from rich import print, print_json, traceback
1515

1616
import lunchable
@@ -145,7 +145,8 @@ def lunchmoney_transactions(
145145
"""
146146
lunch = LunchMoney(access_token=context.access_token)
147147
transactions = lunch.get_transactions(**kwargs) # type: ignore[arg-type]
148-
print_json(data=transactions, default=pydantic_encoder)
148+
json_data = to_jsonable_python(transactions)
149+
print_json(data=json_data)
149150

150151

151152
@plugins.group()
@@ -198,7 +199,8 @@ def splitlunch_expenses(**kwargs: Union[int, str, bool]) -> None:
198199
if set(kwargs.values()) == {None}:
199200
kwargs["limit"] = 5
200201
expenses = splitlunch.get_expenses(**kwargs) # type: ignore[arg-type]
201-
print_json(data=expenses, default=pydantic_encoder)
202+
json_data = to_jsonable_python(expenses)
203+
print_json(data=json_data)
202204

203205

204206
tag_transactions = click.option(
@@ -237,7 +239,8 @@ def make_splitlunch(**kwargs: Union[int, str, bool]) -> None:
237239

238240
splitlunch = SplitLunch()
239241
results = splitlunch.make_splitlunch(**kwargs) # type: ignore[arg-type]
240-
print_json(data=results, default=pydantic_encoder)
242+
json_data = to_jsonable_python(results)
243+
print_json(data=json_data)
241244

242245

243246
@splitlunch.command("splitlunch-import")
@@ -264,7 +267,8 @@ def make_splitlunch_import(**kwargs: Union[int, str, bool]) -> None:
264267
financial_partner_group_id=financial_partner_group_id,
265268
)
266269
results = splitlunch.make_splitlunch_import(**kwargs) # type: ignore[arg-type]
267-
print_json(data=results, default=pydantic_encoder)
270+
json_data = to_jsonable_python(results)
271+
print_json(data=json_data)
268272

269273

270274
@splitlunch.command("splitlunch-direct-import")
@@ -291,7 +295,8 @@ def make_splitlunch_direct_import(**kwargs: Union[int, str, bool]) -> None:
291295
financial_partner_group_id=financial_partner_group_id,
292296
)
293297
results = splitlunch.make_splitlunch_direct_import(**kwargs) # type: ignore[arg-type]
294-
print_json(data=results, default=pydantic_encoder)
298+
json_data = to_jsonable_python(results)
299+
print_json(data=json_data)
295300

296301

297302
@splitlunch.command("update-balance")
@@ -303,7 +308,8 @@ def update_splitwise_balance() -> None:
303308

304309
splitlunch = SplitLunch()
305310
updated_asset = splitlunch.update_splitwise_balance()
306-
print_json(data=updated_asset, default=pydantic_encoder)
311+
json_data = to_jsonable_python(updated_asset)
312+
print_json(data=json_data)
307313

308314

309315
@splitlunch.command("refresh")
@@ -341,7 +347,8 @@ def refresh_splitwise_transactions(
341347
allow_self_paid=allow_self_paid,
342348
allow_payments=allow_payments,
343349
)
344-
print_json(data=response, default=pydantic_encoder)
350+
json_data = to_jsonable_python(response)
351+
print_json(data=json_data)
345352

346353

347354
@plugins.group()
@@ -397,22 +404,23 @@ def http(context: LunchMoneyContext, url: str, request: str, data: str) -> None:
397404
url_request = f"https://dev.lunchmoney.app/{url}"
398405
else:
399406
url_request = url
400-
resp = lunch.make_http_request(
407+
resp = lunch.request(
401408
method=request,
402409
url=url_request,
403-
data=data,
410+
content=data,
404411
)
405412
try:
406413
resp.raise_for_status()
407-
except requests.HTTPError:
414+
except httpx.HTTPError:
408415
logger.error(resp)
409416
print(resp.text)
410417
sys.exit(1)
411418
try:
412419
response = resp.json()
413420
except JSONDecodeError:
414421
response = resp.text
415-
print_json(data=response, default=pydantic_encoder)
422+
json_data = to_jsonable_python(response)
423+
print_json(data=json_data)
416424

417425

418426
@plugins.group()

‎lunchable/_config/api_config.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing import Dict, List, Optional, Union
88
from urllib import parse
99

10+
from lunchable._version import __version__
1011
from lunchable.exceptions import EnvironmentVariableError, LunchMoneyError
1112

1213
logger = logging.getLogger(__name__)
@@ -69,7 +70,7 @@ def get_access_token(access_token: Optional[str] = None) -> str:
6970
@staticmethod
7071
def get_header(access_token: Optional[str] = None) -> Dict[str, str]:
7172
"""
72-
Get the header dict to pass to requests
73+
Get the header dict to pass to httpx
7374
7475
Parameters
7576
----------
@@ -81,9 +82,12 @@ def get_header(access_token: Optional[str] = None) -> Dict[str, str]:
8182
Dict[str, str]
8283
"""
8384
access_token = APIConfig.get_access_token(access_token=access_token)
84-
auth_header = {"Authorization": f"Bearer {access_token}"}
85-
auth_header.update(APIConfig.LUNCHMONEY_CONTENT_TYPE_HEADERS)
86-
return auth_header
85+
lunchable_header = {
86+
"Authorization": f"Bearer {access_token}",
87+
"User-Agent": f"lunchable/{__version__}",
88+
}
89+
lunchable_header.update(APIConfig.LUNCHMONEY_CONTENT_TYPE_HEADERS)
90+
return lunchable_header
8791

8892
@staticmethod
8993
def make_url(url_path: Union[List[Union[str, int]], str, int]) -> str:

‎lunchable/_config/logging_config.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing import Optional, Tuple, Union
88

99
import click
10+
from rich.console import Console
1011
from rich.logging import RichHandler
1112

1213
LOG_HANDLER = getenv("LOG_HANDLER", "rich").lower()
@@ -36,7 +37,11 @@ def get_log_handler(
3637
omit_repeated_times=False,
3738
show_path=False,
3839
tracebacks_suppress=[click],
40+
console=Console(stderr=True),
3941
)
42+
httpx_logger = logging.getLogger("httpx")
43+
if log_level != logging.DEBUG:
44+
httpx_logger.setLevel(logging.WARNING)
4045
python_handler = logging.StreamHandler()
4146
python_formatter = logging.Formatter("%(asctime)s [%(levelname)8s]: %(message)s")
4247
python_handler.setFormatter(python_formatter)

‎lunchable/exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Lunchmoney Exceptions
33
"""
44

5-
from requests.exceptions import HTTPError
5+
from httpx import HTTPError
66

77

88
class LunchMoneyError(Exception):

0 commit comments

Comments
 (0)