Initial work on a full backup option

Creates the Backup command and a general serializer.
This commit is contained in:
Luís Murta 2023-05-02 23:07:44 +01:00
parent 0a0bc1baa0
commit a355ec3642
Signed by: satprog
GPG Key ID: 169EF1BBD7049F94
3 changed files with 67 additions and 0 deletions

View File

@ -51,6 +51,12 @@ class Operation(Enum):
ImportCategoryGroups = auto()
class ExportFormat(Enum):
CSV = auto()
JSON = auto()
pickle = auto()
class TransactionError(Exception):
pass

40
pfbudget/core/command.py Normal file
View File

@ -0,0 +1,40 @@
from abc import ABC, abstractmethod
import csv
import json
from pathlib import Path
import pickle
from typing import Any, Type
from pfbudget.common.types import ExportFormat
from pfbudget.db.client import Client
from pfbudget.utils.serializer import serialize
class Command(ABC):
@abstractmethod
def execute(self) -> None:
raise NotImplementedError
def undo(self) -> None:
raise NotImplementedError
class ExportCommand(Command):
def __init__(self, client: Client, what: Type[Any], fn: Path, format: ExportFormat):
self.__client = client
self.what = what
self.fn = fn
self.format = format
def execute(self) -> None:
values = self.__client.select(self.what)
match self.format:
case ExportFormat.CSV:
with open(self.fn, "w", newline="") as f:
csv.writer(f).writerows([serialize(e) for e in values])
case ExportFormat.JSON:
with open(self.fn, "w", newline="") as f:
json.dump([serialize(e) for e in values], f, indent=4, default=str)
case ExportFormat.pickle:
with open(self.fn, "wb") as f:
pickle.dump([serialize(e) for e in values], f)

View File

@ -0,0 +1,21 @@
from collections.abc import Mapping
from dataclasses import fields
from functools import singledispatch
from typing import Any
from pfbudget.db.model import Transaction, TransactionCategory
@singledispatch
def serialize(obj: Any) -> Mapping[str, Any]:
raise NotImplementedError
@serialize.register
def _(obj: Transaction) -> Mapping[str, Any]:
return dict((field.name, getattr(obj, field.name)) for field in fields(obj))
@serialize.register
def _(obj: TransactionCategory) -> Mapping[str, Any]:
return dict((field.name, getattr(obj, field.name)) for field in fields(obj))