summary history files

web/penny/lib/txmeta/txmeta.py
from typing import Optional
import requests
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm.exc import NoResultFound
from penny import models


class TXResponse:
    def __init__(self, body: dict):
        self.body = body

    @property
    def locality_name(self) -> Optional[str]:
        return self.locality.get("name", None)

    @property
    def locality(self) -> dict:
        return self.body.get("locality", {})

    @property
    def postcode(self) -> Optional[int]:
        return self.locality.get("postcode", None)

    @property
    def state(self) -> Optional[str]:
        return self.locality.get("state", None)

    @property
    def organisation(self) -> Optional[str]:
        return self.body.get("organisation", None)

    @property
    def address(self) -> Optional[str]:
        return self.body.get("address", None)

    @property
    def description(self) -> Optional[str]:
        return self.body.get("description", None)


class TXMeta:
    def __init__(self, url: str):
        self.url = url
        self.response: dict
        self.txresponse: TXResponse

    def request(self, memo: str) -> None:
        try:
            response = requests.post(self.url, json={"memo": memo})
            response.raise_for_status()
        except (
            requests.exceptions.HTTPError,
            requests.exceptions.RequestException,
        ) as e:
            raise e

        self.response = response.json()
        self.txresponse = TXResponse(response.json())

    def persist(self, transaction, session):
        for k, v in {
            "locality_name": self.txresponse.locality_name,
            "postcode": self.txresponse.postcode,
            "state": self.txresponse.state,
            "organisation": self.txresponse.organisation,
            "address": self.txresponse.address,
            "description": self.txresponse.description,
        }.items():
            if v is None:
                continue

            try:
                rows = session.execute(
                    select(models.TransactionMetaType).where(
                        models.TransactionMetaType.name == k
                    )
                ).one()
            except NoResultFound as e:
                raise e
            transaction_meta_type = rows[0]

            session.add(
                models.TransactionMeta(
                    tx_id=transaction.id,
                    tx_meta_type_id=transaction_meta_type.id,
                    value=v,
                )
            )

            try:
                session.commit()
            except IntegrityError:
                session.rollback()
                continue