From e36e1f73c5e5db65a7d8eef4aaa217786c859bc3 Mon Sep 17 00:00:00 2001 From: tiagovla Date: Wed, 19 Jul 2023 03:49:56 -0300 Subject: [PATCH] perf: change structure and simplify --- README.rst | 6 +-- ...check_frequency.py => check_attendency.py} | 6 +-- ppgee/__init__.py | 2 +- ppgee/__main__.py | 6 +-- ppgee/client.py | 35 ++++++------ ppgee/http.py | 4 +- ppgee/pages/__init__.py | 6 +-- ppgee/pages/{frequency.py => attendency.py} | 35 ++++++------ ppgee/parser.py | 46 ---------------- ppgee/parsers/__init__.py | 5 ++ ppgee/parsers/attendency.py | 53 +++++++++++++++++++ ppgee/permissions.py | 11 ++++ pyproject.toml | 2 +- tests/test_ppgee.py | 2 +- 14 files changed, 117 insertions(+), 102 deletions(-) rename demo/{check_frequency.py => check_attendency.py} (68%) rename ppgee/pages/{frequency.py => attendency.py} (50%) delete mode 100644 ppgee/parser.py create mode 100644 ppgee/parsers/__init__.py create mode 100644 ppgee/parsers/attendency.py create mode 100644 ppgee/permissions.py diff --git a/README.rst b/README.rst index bbccaef..2245e5a 100644 --- a/README.rst +++ b/README.rst @@ -11,9 +11,9 @@ async def main() -> None: cpf = "00011122233" async with PPGEE(user=cpf, password=cpf) as ppgee: - frequency_page = await ppgee.frequency() - print(frequency_page.history()) - await frequency_page.confirm() + attendency_page = await ppgee.attendency() + print(attendency_page.history()) + await attendency_page.confirm() await asyncio.sleep(5) diff --git a/demo/check_frequency.py b/demo/check_attendency.py similarity index 68% rename from demo/check_frequency.py rename to demo/check_attendency.py index 0872a96..6d06a83 100644 --- a/demo/check_frequency.py +++ b/demo/check_attendency.py @@ -9,9 +9,9 @@ logging.basicConfig(level=logging.INFO) async def main() -> None: cpf = "00011122233" async with PPGEE(user=cpf, password=cpf) as ppgee: - frequency_page = await ppgee.frequency() - print(frequency_page.history()) - await frequency_page.confirm() + attendency_page = await ppgee.attendency() + print(attendency_page.history()) + await attendency_page.confirm() await asyncio.sleep(5) diff --git a/ppgee/__init__.py b/ppgee/__init__.py index e0f2d46..43df149 100644 --- a/ppgee/__init__.py +++ b/ppgee/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.1.3" +__version__ = "0.1.4" from .client import PPGEE diff --git a/ppgee/__main__.py b/ppgee/__main__.py index e77bf5d..21f913a 100644 --- a/ppgee/__main__.py +++ b/ppgee/__main__.py @@ -21,11 +21,11 @@ async def cli(): user, password = args.username, args.password try: async with PPGEE(user=user, password=password) as ppgee: - frequency_page = await ppgee.frequency() + attendency_page = await ppgee.attendency() await asyncio.sleep(1) - if frequency_page.is_available(): + if attendency_page.is_available(): print("Attendency confirmed.") - await frequency_page.confirm() + await attendency_page.confirm() else: eprint("Attendency not available yet.") await asyncio.sleep(1) diff --git a/ppgee/client.py b/ppgee/client.py index 82de59e..2c5fc7d 100644 --- a/ppgee/client.py +++ b/ppgee/client.py @@ -1,23 +1,16 @@ -import aiohttp import logging -from ppgee.http import HttpClient -from ppgee.pages import FrequencyPage -from functools import wraps + +import aiohttp + from ppgee import errors +from ppgee.http import HttpClient +from ppgee.pages import AttendencyPage, AttendencyHistory, AttendencyHistoryEntry +from ppgee.parsers import AttendencyParser +from ppgee.permissions import is_logged_check logger = logging.getLogger(__name__) -def is_logged_check(method): - @wraps(method) - def wrapper(self, *args, **kwargs): - if not self.is_logged: - raise Exception("You must be logged in to use this method") - return method(self, *args, **kwargs) - - return wrapper - - class PPGEE: def __init__(self, user: str | None = None, password: str | None = None) -> None: self.user = user @@ -56,10 +49,16 @@ class PPGEE: logger.info("Logged in without credentials") @is_logged_check - async def frequency(self) -> FrequencyPage: - logger.info("Requesting frequency page...") - html = await self.http.frequency() - return FrequencyPage(html, self.http.frequency_confirmation) + async def attendency(self) -> AttendencyPage: + logger.info("Requesting attendency page...") + html = await self.http.attendency() + parser = AttendencyParser(html) + history = AttendencyHistory( + (AttendencyHistoryEntry(**item) for item in parser.history()) + ) + return AttendencyPage( + history, self.http.attendency_confirmation, parser.availability() + ) @is_logged_check async def logoff(self) -> None: diff --git a/ppgee/http.py b/ppgee/http.py index 4daf32d..9247e99 100644 --- a/ppgee/http.py +++ b/ppgee/http.py @@ -26,10 +26,10 @@ class HttpClient: data: dict[str, str] = {"login": user, "senha": password} return await self._request("post", f"{URL_BASE}/login.php", data=data) - async def frequency(self) -> str: + async def attendency(self) -> str: return await self._request("get", f"{URL_BASE}/afreq.php") - async def frequency_confirmation(self) -> str: + async def attendency_confirmation(self) -> str: today = date.today() data: dict[str, str] = { "freqano": str(today.year), diff --git a/ppgee/pages/__init__.py b/ppgee/pages/__init__.py index eed88fb..6302a46 100644 --- a/ppgee/pages/__init__.py +++ b/ppgee/pages/__init__.py @@ -1,5 +1,3 @@ -from .frequency import FrequencyPage +from .attendency import AttendencyPage, AttendencyHistory, AttendencyHistoryEntry -__all__ = [ - "FrequencyPage", -] +__all__ = ["AttendencyPage", "AttendencyHistory", "AttendencyHistoryEntry"] diff --git a/ppgee/pages/frequency.py b/ppgee/pages/attendency.py similarity index 50% rename from ppgee/pages/frequency.py rename to ppgee/pages/attendency.py index 4f6c1cd..0e3348a 100644 --- a/ppgee/pages/frequency.py +++ b/ppgee/pages/attendency.py @@ -1,21 +1,20 @@ from dataclasses import dataclass from datetime import datetime +from typing import Callable, Awaitable import logging -from ppgee.parser import parse_frequency_history - logger = logging.getLogger(__name__) @dataclass -class HistoryEntry: +class AttendencyHistoryEntry: year: int month: int asked: datetime confirmed: datetime | None -class History(list[HistoryEntry]): +class AttendencyHistory(list[AttendencyHistoryEntry]): def __str__(self) -> str: out: list[str] = [] for entry in self: @@ -24,28 +23,24 @@ class History(list[HistoryEntry]): return "\n".join(out) -class FrequencyPage: - def __init__(self, html, confirmation_callback): - self.html = html - self._history = History() +class AttendencyPage: + def __init__( + self, + history: AttendencyHistory, + confirmation_callback: Callable[[], Awaitable[str]], + available: bool, + ): + self._history = history + self._available = available self.confirmation_callback = confirmation_callback - def _build_history(self): - result_list = parse_frequency_history(self.html) - for item in result_list: - self._history.append(HistoryEntry(**item)) - - def history(self) -> History: - if not self._history: - self._build_history() + def history(self) -> AttendencyHistory: return self._history def is_available(self): - if "Opção não disponível" in self.html: - return False - return True + return self._available async def confirm(self) -> None: if self.is_available(): - logger.info("Requesting frequency confirmation...") + logger.info("Requesting attendency confirmation...") await self.confirmation_callback() diff --git a/ppgee/parser.py b/ppgee/parser.py deleted file mode 100644 index 370bb5f..0000000 --- a/ppgee/parser.py +++ /dev/null @@ -1,46 +0,0 @@ -from datetime import datetime -import re - -from bs4 import BeautifulSoup - -MONTH_MAP = { - "Janeiro": 1, - "Fevereiro": 2, - "Março": 3, - "Abril": 4, - "Maio": 5, - "Junho": 6, - "Julho": 7, - "Agosto": 8, - "Setembro": 9, - "Outubro": 10, - "Novembro": 11, - "Dezembro": 12, -} - - -def parse_frequency_history(html) -> list[dict]: - history = [] - soup = BeautifulSoup(html, "html.parser") - table = soup.find_all("table")[2].find_all("table")[-1] - rows = table.find_all("tr") - for row in rows[1:]: - cols = row.find_all("td") - data = [ele.text.strip() for ele in cols] - year = int(data[0]) - month = MONTH_MAP[data[1]] - date_asked = datetime.strptime(data[2], "%d/%m/%Y%H:%M") - date_confirmed = re.sub(r"[^[0-9:/]]*", "", data[3]) - if date_confirmed == "": - date_confirmed = None - else: - date_confirmed = datetime.strptime(date_confirmed, "%d/%m/%Y%H:%M") - history.append( - { - "year": year, - "month": month, - "asked": date_asked, - "confirmed": date_confirmed, - } - ) - return history diff --git a/ppgee/parsers/__init__.py b/ppgee/parsers/__init__.py new file mode 100644 index 0000000..06faa16 --- /dev/null +++ b/ppgee/parsers/__init__.py @@ -0,0 +1,5 @@ +from .attendency import AttendencyParser + +__all__ = [ + "AttendencyParser", +] diff --git a/ppgee/parsers/attendency.py b/ppgee/parsers/attendency.py new file mode 100644 index 0000000..a192c30 --- /dev/null +++ b/ppgee/parsers/attendency.py @@ -0,0 +1,53 @@ +from datetime import datetime +import re + +from bs4 import BeautifulSoup + +MONTH_MAP = { + "Janeiro": 1, + "Fevereiro": 2, + "Março": 3, + "Abril": 4, + "Maio": 5, + "Junho": 6, + "Julho": 7, + "Agosto": 8, + "Setembro": 9, + "Outubro": 10, + "Novembro": 11, + "Dezembro": 12, +} + + +class AttendencyParser: + def __init__(self, html: str) -> None: + self._html = html + + def history(self) -> list[dict]: + history = [] + soup = BeautifulSoup(self._html, "html.parser") + table = soup.find_all("table")[2].find_all("table")[-1] + rows = table.find_all("tr") + for row in rows[1:]: + cols = row.find_all("td") + data = [ele.text.strip() for ele in cols] + year = int(data[0]) + month = MONTH_MAP[data[1]] + date_asked = datetime.strptime(data[2], "%d/%m/%Y%H:%M") + date_confirmed = re.sub(r"[^[0-9:/]]*", "", data[3]) + if date_confirmed == "": + date_confirmed = None + else: + date_confirmed = datetime.strptime(date_confirmed, "%d/%m/%Y%H:%M") + history.append( + { + "year": year, + "month": month, + "asked": date_asked, + "confirmed": date_confirmed, + } + ) + return history + + def availability(self) -> bool: + return "Opção não disponível" not in self._html diff --git a/ppgee/permissions.py b/ppgee/permissions.py new file mode 100644 index 0000000..d79c2d3 --- /dev/null +++ b/ppgee/permissions.py @@ -0,0 +1,11 @@ +from functools import wraps + + +def is_logged_check(method): + @wraps(method) + def wrapper(self, *args, **kwargs): + if not self.is_logged: + raise Exception("You must be logged in to use this method") + return method(self, *args, **kwargs) + + return wrapper diff --git a/pyproject.toml b/pyproject.toml index 6f68856..f314b53 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "ppgee" -version = "0.1.3" +version = "0.1.4" description = "" authors = ["tiagovla "] diff --git a/tests/test_ppgee.py b/tests/test_ppgee.py index bd5359d..3890156 100644 --- a/tests/test_ppgee.py +++ b/tests/test_ppgee.py @@ -2,4 +2,4 @@ from ppgee import __version__ def test_version(): - assert __version__ == "0.1.3" + assert __version__ == "0.1.4"