Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: move to loguru for logging #65

Merged
merged 4 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ client = iec.IecClient("123456789")
try:
await client.manual_login() # login with user inputs
except iec.exceptions.IECError as err:
logger.error("Failed Login: (Code %d): %s", err.code, err.error)
logger.error(f"Failed Login: (Code {err.code}): {err.error}")
raise

customer = await client.get_customer()
Expand Down
12 changes: 4 additions & 8 deletions example.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,20 @@
import concurrent.futures
import os
from datetime import datetime, timedelta
from logging import config, getLogger

import aiohttp
from loguru import logger

from iec_api.iec_client import IecClient
from iec_api.login import IECLoginError
from iec_api.models.exceptions import IECError

ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
config.fileConfig(ROOT_DIR + "/" + "logging.conf", disable_existing_loggers=False)
logger = getLogger(__name__)


async def main():
session = aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False), timeout=aiohttp.ClientTimeout(total=10))
try:
# Example of usage
client = IecClient(123456789, session)
client = IecClient(200461929, session)

token_json_file = "token.json"
if os.path.exists(token_json_file):
Expand All @@ -34,7 +30,7 @@ async def main():
await client.verify_otp(otp)
await client.save_token_to_file(token_json_file)
except IECLoginError as err:
logger.error("Failed Login: (Code %d): %s", err.code, err.error)
logger.error(f"Failed Login: (Code {err.code}): {err.error}")
raise

# refresh token example
Expand Down Expand Up @@ -84,7 +80,7 @@ async def main():
print(await client.get_device_type())
print(await client.get_billing_invoices())
except IECError as err:
logger.error("IEC Error: (Code %d): %s", err.code, err.error)
logger.error(f"IEC Error: (Code {err.code}): {err.error}")
finally:
await session.close()

Expand Down
30 changes: 13 additions & 17 deletions iec_api/commons.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@
import re
from concurrent.futures import ThreadPoolExecutor
from json import JSONDecodeError
from logging import getLogger
from typing import Any, Optional

from aiohttp import ClientError, ClientSession
from loguru import logger

from iec_api.models.exceptions import IECError
from iec_api.models.response_descriptor import RESPONSE_DESCRIPTOR_FIELD, ErrorResponseDescriptor

logger = getLogger(__name__)


def add_auth_bearer_to_headers(headers: dict[str, str], token: str) -> dict[str, str]:
"""
Expand All @@ -27,10 +25,10 @@ def add_auth_bearer_to_headers(headers: dict[str, str], token: str) -> dict[str,
return headers


PHONE_REGEX: str = "^(+972|0)5[0-9]{8}$"
PHONE_REGEX = "^(+972|0)5[0-9]{8}$"


def check_phone(phone):
def check_phone(phone: str):
"""
Check if the phone number is valid.
Args:
Expand Down Expand Up @@ -80,7 +78,7 @@ async def send_get_request(
if not timeout:
timeout = session.timeout

logger.debug("HTTP GET: %s", url)
logger.debug(f"HTTP GET: {url}")
resp = await session.get(url=url, headers=headers, timeout=timeout)
json_resp: dict = await resp.json(content_type=None)
except TimeoutError as ex:
Expand All @@ -90,7 +88,7 @@ async def send_get_request(
except JSONDecodeError as ex:
raise IECError(-1, f"Received invalid response from IEC API: {str(ex)}")

logger.debug("HTTP GET Response: %s", json_resp)
logger.debug(f"HTTP GET Response: {json_resp}")
if resp.status != http.HTTPStatus.OK:
logger.warning(f"Failed call: (Code {resp.status}): {resp.reason}")
if len(json_resp) > 0 and json_resp.get(RESPONSE_DESCRIPTOR_FIELD) is not None:
Expand All @@ -116,7 +114,9 @@ async def send_non_json_get_request(
if not timeout:
timeout = session.timeout

logger.debug("HTTP GET: %s", url)
logger.debug(
f"HTTP GET: {url}",
)
resp = await session.get(url=url, headers=headers, timeout=timeout)
resp_content = await resp.text(encoding=encoding)
except TimeoutError as ex:
Expand All @@ -126,7 +126,7 @@ async def send_non_json_get_request(
except JSONDecodeError as ex:
raise IECError(-1, f"Received invalid response from IEC API: {str(ex)}")

logger.debug("HTTP GET Response: %s", resp_content)
logger.debug(f"HTTP GET Response: {resp_content}")

return resp_content

Expand All @@ -146,14 +146,10 @@ async def send_post_request(
if not timeout:
headers = session.timeout

logger.debug("HTTP POST: %s", url)
logger.debug("HTTP Content: %s", data or json_data)
logger.debug(f"HTTP POST: {url}")
logger.debug(f"HTTP Content: {data or json_data}")

if data:
resp = await session.post(url=url, data=data, headers=headers, timeout=timeout)
else:
if json_data:
resp = await session.post(url=url, json=json_data, headers=headers, timeout=timeout)
resp = await session.post(url=url, data=data, json=json_data, headers=headers, timeout=timeout)

json_resp: dict = await resp.json(content_type=None)
except TimeoutError as ex:
Expand All @@ -163,7 +159,7 @@ async def send_post_request(
except JSONDecodeError as ex:
raise IECError(-1, f"Received invalid response from IEC API: {str(ex)}")

logger.debug("HTTP POST Response: %s", json_resp)
logger.debug(f"HTTP POST Response: {json_resp}")

if resp.status != http.HTTPStatus.OK:
logger.warning(f"Failed call: (Code {resp.status}): {resp.reason}")
Expand Down
9 changes: 3 additions & 6 deletions iec_api/data.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import logging
from datetime import datetime
from typing import Optional, TypeVar

from aiohttp import ClientSession
from loguru import logger
from mashumaro.codecs import BasicDecoder

from iec_api import commons
Expand Down Expand Up @@ -40,8 +40,6 @@
from iec_api.models.remote_reading import ReadingResolution, RemoteReadingRequest, RemoteReadingResponse
from iec_api.models.response_descriptor import ResponseWithDescriptor

logger = logging.getLogger(__name__)

T = TypeVar("T")


Expand Down Expand Up @@ -82,7 +80,7 @@ async def get_customer(session: ClientSession, token: JWT) -> Optional[Customer]
# sending get request and saving the response as response object
response = await commons.send_get_request(session=session, url=GET_CONSUMER_URL, headers=headers)

logger.debug("Response: %s", response)
logger.debug(f"Response: {response}")
return Customer.from_dict(response)


Expand All @@ -106,7 +104,6 @@ async def get_remote_reading(

url = GET_REQUEST_READING_URL.format(contract_id=contract_id)
headers = commons.add_auth_bearer_to_headers(HEADERS_WITH_AUTH, token.id_token)
logger.debug(f"HTTP POST: {url}\nData:{req.to_dict()}")

response = await commons.send_post_request(session=session, url=url, headers=headers, json_data=req.to_dict())

Expand Down Expand Up @@ -155,7 +152,7 @@ async def get_devices(session: ClientSession, token: JWT, contract_id: str) -> l
session=session, url=GET_DEVICES_URL.format(contract_id=contract_id), headers=headers
)

logger.debug("Response: %s", response)
logger.debug(f"Response: {response}")
return [Device.from_dict(device) for device in response]


Expand Down
6 changes: 2 additions & 4 deletions iec_api/iec_client.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import asyncio
import atexit
import datetime
from logging import getLogger
from typing import Optional

import aiohttp
import jwt
from aiohttp import ClientSession
from loguru import logger

from iec_api import data, login
from iec_api.commons import is_valid_israeli_id
Expand All @@ -21,8 +21,6 @@
from iec_api.models.meter_reading import MeterReadings
from iec_api.models.remote_reading import ReadingResolution, RemoteReadingResponse

logger = getLogger(__name__)


class IecClient:
"""IEC API Client."""
Expand Down Expand Up @@ -382,7 +380,7 @@ async def override_id_token(self, id_token):
:param id_token: The new token to be set.
:return: None
"""
logger.debug("Overriding jwt.py token: %s", id_token)
logger.debug(f"Overriding jwt.py token: {id_token}")
self._token = JWT(access_token="", refresh_token="", token_type="", expires_in=0, scope="", id_token=id_token)
self._token.id_token = id_token
self.logged_in = True
Expand Down
12 changes: 5 additions & 7 deletions iec_api/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
import re
import string
import time
from logging import getLogger
from typing import Optional, Tuple

import aiofiles
import jwt
import pkce
from aiohttp import ClientSession
from loguru import logger

from iec_api import commons
from iec_api.models.exceptions import IECLoginError
Expand All @@ -30,8 +30,6 @@
"&sessionToken={sessionToken}&code_challenge={challenge}"
)

logger = getLogger(__name__)


async def authorize_session(session: ClientSession, session_token) -> str:
"""
Expand Down Expand Up @@ -145,8 +143,8 @@ async def first_login(session: ClientSession, id_number: str) -> Tuple[str, str,

return state_token, factor_id, session_token
except Exception as error:
logger.warning("Failed at first login: %s", error)
raise IECLoginError(-1, "Failed at first login")
logger.warning(f"Failed at first login: {error}")
raise IECLoginError(-1, "Failed at first login") from error


async def verify_otp_code(session: ClientSession, factor_id: str, state_token: str, otp_code: str) -> JWT:
Expand All @@ -168,8 +166,8 @@ async def verify_otp_code(session: ClientSession, factor_id: str, state_token: s
jwt_token = await get_access_token(session, code)
return jwt_token
except Exception as error:
logger.warning("Failed at OTP verification: %s", error)
raise IECLoginError(-1, "Failed at OTP verification")
logger.warning(f"Failed at OTP verification: {error}")
raise IECLoginError(-1, "Failed at OTP verification") from error


async def manual_authorization(session: ClientSession, id_number) -> Optional[JWT]: # pragma: no cover
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ requests = "^2.31.0"
pkce = "^1.0.3"
aiohttp = "^3.9.1"
aiofiles = "^23.2.1"
loguru = "^0.7.2"

[tool.poetry.dev-dependencies]
pytest = "8.0.2"
Expand Down