Pickling directly from a DB object will also save DB related attributes, namely the state of the object. When exporting values from a DB select, they will be in detached state, which means on the import, the session will not insert the object back into the DB, it already assumes they are there.
71 lines
2.0 KiB
Python
71 lines
2.0 KiB
Python
from abc import ABC, abstractmethod
|
|
import json
|
|
from pathlib import Path
|
|
import pickle
|
|
from typing import Type
|
|
|
|
from pfbudget.common.types import ExportFormat
|
|
from pfbudget.db.client import Client
|
|
from pfbudget.db.model import Serializable
|
|
|
|
|
|
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[Serializable], 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.JSON:
|
|
with open(self.fn, "w", newline="") as f:
|
|
json.dump([e.serialize() for e in values], f, indent=4)
|
|
case ExportFormat.pickle:
|
|
raise AttributeError("pickle export not working at the moment!")
|
|
with open(self.fn, "wb") as f:
|
|
pickle.dump(values, f)
|
|
|
|
|
|
class ImportCommand(Command):
|
|
def __init__(
|
|
self, client: Client, what: Type[Serializable], fn: Path, format: ExportFormat
|
|
):
|
|
self.__client = client
|
|
self.what = what
|
|
self.fn = fn
|
|
self.format = format
|
|
|
|
def execute(self) -> None:
|
|
match self.format:
|
|
case ExportFormat.JSON:
|
|
with open(self.fn, "r") as f:
|
|
try:
|
|
values = json.load(f)
|
|
values = [self.what.deserialize(v) for v in values]
|
|
except json.JSONDecodeError as e:
|
|
raise ImportFailedError(e)
|
|
|
|
case ExportFormat.pickle:
|
|
raise AttributeError("pickle import not working at the moment!")
|
|
with open(self.fn, "rb") as f:
|
|
values = pickle.load(f)
|
|
|
|
self.__client.insert(values)
|
|
|
|
|
|
class ImportFailedError(Exception):
|
|
pass
|