From f453222bf7c1be71c4224359bddef6982ecf6caa Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Thu, 24 Apr 2025 01:05:49 -0700 Subject: [PATCH] linter &c --- .pre-commit-config.yaml | 25 +++++++++++++++++++++++++ model.py | 5 +++-- parsers.py | 23 ++++++++++++++--------- setup.cfg | 2 ++ watcher.py | 40 +++++++++++++++++++++++++++------------- 5 files changed, 71 insertions(+), 24 deletions(-) create mode 100644 .pre-commit-config.yaml create mode 100644 setup.cfg diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..e8cc02a --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,25 @@ +# .pre-commit-config.yaml +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.5 # Check for the latest version + hooks: + - id: ruff + - id: ruff-format + + - repo: https://github.com/asottile/reorder-python-imports + rev: v3.11.0 # Check for the latest version + hooks: + - id: reorder-python-imports + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 # Check for the latest version + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - id: requirements-txt-fixer + + - repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 # Check for the latest version + hooks: + - id: flake8 diff --git a/model.py b/model.py index 2bab199..79a1897 100644 --- a/model.py +++ b/model.py @@ -1,7 +1,8 @@ from dataclasses import dataclass -from uuid import UUID from datetime import date from decimal import Decimal +from uuid import UUID + @dataclass class Transaction: @@ -10,4 +11,4 @@ class Transaction: amount: Decimal payee: str # imported_payee in API notes: str - imported_id: str \ No newline at end of file + imported_id: str diff --git a/parsers.py b/parsers.py index 970c47d..012d483 100644 --- a/parsers.py +++ b/parsers.py @@ -1,16 +1,18 @@ +import re +from abc import ABC +from abc import abstractmethod +from datetime import datetime from decimal import Decimal from email.message import EmailMessage -from model import Transaction -import re +from email.message import Message from uuid import UUID -from datetime import datetime -from logging import debug -from abc import ABC, abstractmethod + +from model import Transaction class TransactionParser(ABC): @abstractmethod - def match(self, msg: EmailMessage) -> bool: + def match(self, msg: Message) -> bool: pass @abstractmethod @@ -30,16 +32,19 @@ class RogersBankParser(TransactionParser): def __init__(self, account_id: UUID): self.account_id = account_id - def match(self, msg: EmailMessage) -> bool: + def match(self, msg: Message) -> bool: return ( msg["From"] == "Rogers Bank " and msg["Subject"] == "Purchase amount alert" ) def extract(self, msg: EmailMessage) -> Transaction: - matches = RogersBankParser.EXTRACT_RE.search(msg.get_body().as_string()) + body = msg.get_body() + if body is None: + raise TransactionParsingFailed("No body of message found") + matches = RogersBankParser.EXTRACT_RE.search(body.as_string()) if matches is None: - return TransactionParsingFailed("No matches for extraction RE") + raise TransactionParsingFailed("No matches for extraction RE") amount = Decimal(matches[1]) date_raw = matches[2] payee = matches[3] diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..51b50a0 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 100 \ No newline at end of file diff --git a/watcher.py b/watcher.py index edd25b8..f8fc680 100644 --- a/watcher.py +++ b/watcher.py @@ -1,17 +1,22 @@ #!/usr/bin/env python - -from email.message import EmailMessage -import logging -import asyncio, ssl, email -from os import getenv -from imaplib import IMAP4 -from logging import info, debug, error, warning -from pprint import pprint -from model import Transaction -from config import PARSERS -from parsers import TransactionParsingFailed +import asyncio import email.policy +import logging import os +import ssl +from email.message import EmailMessage +from imaplib import IMAP4 +from logging import debug +from logging import error +from logging import info +from logging import warning +from os import getenv +from pprint import pprint +from typing import cast + +from config import PARSERS +from model import Transaction +from parsers import TransactionParsingFailed IMAP_SERVER = getenv("IMAP_SERVER") IMAP_PORT = int(getenv("IMAP_PORT", 143)) @@ -32,7 +37,14 @@ async def ticker(interval: float): async def submit_transaction(t: Transaction): - cmd=ACTUAL_PATH + f' -a "{t.account}"' + f' -p "{t.payee}"' + f' -m "{t.amount}"' + f' -d "{t.date}"' f' -n "{t.notes}"' + cmd = ( + ACTUAL_PATH + + f' -a "{t.account}"' + + f' -p "{t.payee}"' + + f' -m "{t.amount}"' + + f' -d "{t.date}"' + f' -n "{t.notes}"' + ) debug("Actual command: %s", cmd) proc = await asyncio.create_subprocess_shell( cmd=cmd, @@ -47,7 +59,9 @@ async def submit_transaction(t: Transaction): async def process_message(msg_b: bytes): debug("parsing message") - msg = email.message_from_bytes(msg_b, policy=email.policy.default) + msg = cast( + EmailMessage, email.message_from_bytes(msg_b, policy=email.policy.default) + ) pprint(msg) info( "Found message from %s to %s subject %s",