2020-08-21 22:42:15 +00:00
|
|
|
"""transfer common classes"""
|
|
|
|
from dataclasses import asdict, dataclass, field, is_dataclass
|
|
|
|
from json.encoder import JSONEncoder
|
|
|
|
from typing import Any, Dict, List
|
|
|
|
from uuid import UUID
|
|
|
|
|
|
|
|
from passbook.lib.models import SerializerModel
|
|
|
|
from passbook.lib.sentry import SentryIgnoredException
|
|
|
|
|
|
|
|
|
|
|
|
def get_attrs(obj: SerializerModel) -> Dict[str, Any]:
|
|
|
|
"""Get object's attributes via their serializer, and covert it to a normal dict"""
|
|
|
|
data = dict(obj.serializer(obj).data)
|
2020-09-05 23:07:06 +00:00
|
|
|
to_remove = ("policies", "stages", "pk")
|
|
|
|
for to_remove_name in to_remove:
|
|
|
|
if to_remove_name in data:
|
|
|
|
data.pop(to_remove_name)
|
2020-08-21 22:42:15 +00:00
|
|
|
return data
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class FlowBundleEntry:
|
|
|
|
"""Single entry of a bundle"""
|
|
|
|
|
2020-09-05 23:07:06 +00:00
|
|
|
identifiers: Dict[str, Any]
|
2020-08-21 22:42:15 +00:00
|
|
|
model: str
|
|
|
|
attrs: Dict[str, Any]
|
|
|
|
|
|
|
|
@staticmethod
|
2020-09-05 23:07:06 +00:00
|
|
|
def from_model(
|
|
|
|
model: SerializerModel, *extra_identifier_names: str
|
|
|
|
) -> "FlowBundleEntry":
|
2020-08-21 22:42:15 +00:00
|
|
|
"""Convert a SerializerModel instance to a Bundle Entry"""
|
2020-09-05 23:07:06 +00:00
|
|
|
identifiers = {
|
|
|
|
"pk": model.pk,
|
|
|
|
}
|
|
|
|
all_attrs = get_attrs(model)
|
|
|
|
|
|
|
|
for extra_identifier_name in extra_identifier_names:
|
|
|
|
identifiers[extra_identifier_name] = all_attrs.pop(extra_identifier_name)
|
2020-08-21 22:42:15 +00:00
|
|
|
return FlowBundleEntry(
|
2020-09-05 23:07:06 +00:00
|
|
|
identifiers=identifiers,
|
2020-08-21 22:42:15 +00:00
|
|
|
model=f"{model._meta.app_label}.{model._meta.model_name}",
|
2020-09-05 23:07:06 +00:00
|
|
|
attrs=all_attrs,
|
2020-08-21 22:42:15 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class FlowBundle:
|
|
|
|
"""Dataclass used for a full export"""
|
|
|
|
|
|
|
|
version: int = field(default=1)
|
|
|
|
entries: List[FlowBundleEntry] = field(default_factory=list)
|
|
|
|
|
|
|
|
|
|
|
|
class DataclassEncoder(JSONEncoder):
|
|
|
|
"""Convert FlowBundleEntry to json"""
|
|
|
|
|
|
|
|
def default(self, o):
|
|
|
|
if is_dataclass(o):
|
|
|
|
return asdict(o)
|
|
|
|
if isinstance(o, UUID):
|
|
|
|
return str(o)
|
|
|
|
return super().default(o)
|
|
|
|
|
|
|
|
|
|
|
|
class EntryInvalidError(SentryIgnoredException):
|
|
|
|
"""Error raised when an entry is invalid"""
|