Skip to content

Commit

Permalink
💥 httpx refactor
Browse files Browse the repository at this point in the history
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
  • Loading branch information
juftin committed Dec 16, 2023
1 parent 8225e98 commit 836d13d
Show file tree
Hide file tree
Showing 60 changed files with 788 additions and 530 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
[![GitHub License](https://img.shields.io/github/license/juftin/lunchable?color=blue&label=License)](https://github.com/juftin/lunchable/blob/main/LICENSE)

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

### Installation

Expand Down
3 changes: 2 additions & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

**lunchable** is a Python Client for the
`Lunch Money Developer API <https://lunchmoney.dev>`_.
It's built on top of `pydantic <https://github.com/samuelcolvin/pydantic>`_,
It's built on top of `pydantic <https://github.com/pydantic/pydantic>`_,
and `httpx <https://github.com/encode/httpx/>`_,
it offers an *intuitive* API, a *simple* CLI,
complete coverage of all endpoints,
and *plugins* to other external services
Expand Down
34 changes: 21 additions & 13 deletions lunchable/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from typing import Any, Dict, Optional, Union

import click
import requests
from pydantic.json import pydantic_encoder
import httpx
from pydantic_core import to_jsonable_python
from rich import print, print_json, traceback

import lunchable
Expand Down Expand Up @@ -145,7 +145,8 @@ def lunchmoney_transactions(
"""
lunch = LunchMoney(access_token=context.access_token)
transactions = lunch.get_transactions(**kwargs) # type: ignore[arg-type]
print_json(data=transactions, default=pydantic_encoder)
json_data = to_jsonable_python(transactions)
print_json(data=json_data)


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


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

splitlunch = SplitLunch()
results = splitlunch.make_splitlunch(**kwargs) # type: ignore[arg-type]
print_json(data=results, default=pydantic_encoder)
json_data = to_jsonable_python(results)
print_json(data=json_data)


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


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


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

splitlunch = SplitLunch()
updated_asset = splitlunch.update_splitwise_balance()
print_json(data=updated_asset, default=pydantic_encoder)
json_data = to_jsonable_python(updated_asset)
print_json(data=json_data)


@splitlunch.command("refresh")
Expand Down Expand Up @@ -341,7 +347,8 @@ def refresh_splitwise_transactions(
allow_self_paid=allow_self_paid,
allow_payments=allow_payments,
)
print_json(data=response, default=pydantic_encoder)
json_data = to_jsonable_python(response)
print_json(data=json_data)


@plugins.group()
Expand Down Expand Up @@ -397,22 +404,23 @@ def http(context: LunchMoneyContext, url: str, request: str, data: str) -> None:
url_request = f"https://dev.lunchmoney.app/{url}"
else:
url_request = url
resp = lunch.make_http_request(
resp = lunch.request(
method=request,
url=url_request,
data=data,
content=data,
)
try:
resp.raise_for_status()
except requests.HTTPError:
except httpx.HTTPError:
logger.error(resp)
print(resp.text)
sys.exit(1)
try:
response = resp.json()
except JSONDecodeError:
response = resp.text
print_json(data=response, default=pydantic_encoder)
json_data = to_jsonable_python(response)
print_json(data=json_data)


@plugins.group()
Expand Down
12 changes: 8 additions & 4 deletions lunchable/_config/api_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import Dict, List, Optional, Union
from urllib import parse

from lunchable._version import __version__
from lunchable.exceptions import EnvironmentVariableError, LunchMoneyError

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -69,7 +70,7 @@ def get_access_token(access_token: Optional[str] = None) -> str:
@staticmethod
def get_header(access_token: Optional[str] = None) -> Dict[str, str]:
"""
Get the header dict to pass to requests
Get the header dict to pass to httpx
Parameters
----------
Expand All @@ -81,9 +82,12 @@ def get_header(access_token: Optional[str] = None) -> Dict[str, str]:
Dict[str, str]
"""
access_token = APIConfig.get_access_token(access_token=access_token)
auth_header = {"Authorization": f"Bearer {access_token}"}
auth_header.update(APIConfig.LUNCHMONEY_CONTENT_TYPE_HEADERS)
return auth_header
lunchable_header = {
"Authorization": f"Bearer {access_token}",
"User-Agent": f"lunchable/{__version__}",
}
lunchable_header.update(APIConfig.LUNCHMONEY_CONTENT_TYPE_HEADERS)
return lunchable_header

@staticmethod
def make_url(url_path: Union[List[Union[str, int]], str, int]) -> str:
Expand Down
5 changes: 5 additions & 0 deletions lunchable/_config/logging_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import Optional, Tuple, Union

import click
from rich.console import Console
from rich.logging import RichHandler

LOG_HANDLER = getenv("LOG_HANDLER", "rich").lower()
Expand Down Expand Up @@ -36,7 +37,11 @@ def get_log_handler(
omit_repeated_times=False,
show_path=False,
tracebacks_suppress=[click],
console=Console(stderr=True),
)
httpx_logger = logging.getLogger("httpx")
if log_level != logging.DEBUG:
httpx_logger.setLevel(logging.WARNING)
python_handler = logging.StreamHandler()
python_formatter = logging.Formatter("%(asctime)s [%(levelname)8s]: %(message)s")
python_handler.setFormatter(python_formatter)
Expand Down
2 changes: 1 addition & 1 deletion lunchable/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Lunchmoney Exceptions
"""

from requests.exceptions import HTTPError
from httpx import HTTPError


class LunchMoneyError(Exception):
Expand Down
Loading

0 comments on commit 836d13d

Please sign in to comment.