Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added src/assembly/__init__.py
Empty file.
79 changes: 79 additions & 0 deletions src/assembly/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from dataclasses import Field, dataclass, field
from datetime import date

from dataclass_utils.Mixins import DataclassFromDictMixin


@dataclass
class AssemblyDtoBase(DataclassFromDictMixin):
id: str
name: str


@dataclass
class Assembly(AssemblyDtoBase):
lifetime: float
unit: str
conversion_factor: float
description: str
layers: list["Layer"] = field(default_factory=list)

@classmethod
def _coerce_value(cls, field: Field, value: any):
if field.name == "layers":
return [Layer.from_dict(layer) for layer in value]
return super()._coerce_value(field, value)


@dataclass
class Layer(AssemblyDtoBase):
description: str
reference_service_life: int
transport_distance: float
transport_conversion_factor: float
# TODO: Check if this is correct. Its used to calculate amount of product used
conversion_factor: float = 0
epd: "Epd" = None

@classmethod
def _coerce_value(cls, field: Field, value: any):
if field.name == "epd":
return Epd.from_dict(value)
return super()._coerce_value(field, value)


@dataclass
class Epd(AssemblyDtoBase):
declared_unit: str
version: str
valid_until: date
published_date: date
source: str
location: str
subtype: str
reference_service_life: int
gwp: "Gwp"
comment: str = ""
conversions: list["Conversion"] = field(default_factory=list)

@classmethod
def _coerce_value(cls, field: Field, value: any):
if field.name == "conversions":
return [Conversion.from_dict(c) for c in value]
if field.name == "gwp":
return Gwp.from_dict(value)
return super()._coerce_value(field, value)


@dataclass
class Conversion(DataclassFromDictMixin):
to: str
value: float


@dataclass
class Gwp(DataclassFromDictMixin):
a1a3: float
c3: float
c4: float
d: float
27 changes: 27 additions & 0 deletions src/dataclass_utils/Mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from dataclasses import MISSING, Field, fields


class DataclassFromDictMixin:
@classmethod
def _get_field_value(cls, context: dict, field: Field[any]):
if field.name in context:
return context[field.name]
# default and default_factory will have the same value (MISSING) if not set.
if field.default == field.default_factory:
raise ValueError(f"Cannot find value for field {field.name} when creating {cls.__name__}")

return field.default if field.default != MISSING else field.default_factory()

@classmethod
def _coerce_value(cls, field: Field[any], value: any):
return value

@classmethod
def from_dict(cls, dict: dict):
kwargs = {}
for f in fields(cls):
value = cls._get_field_value(dict, f)
value = cls._coerce_value(f, value)
kwargs[f.name] = value

return cls(**kwargs)
Empty file added src/dataclass_utils/__init__.py
Empty file.
134 changes: 0 additions & 134 deletions src/logic/export/lcabyg/edges.py

This file was deleted.

140 changes: 140 additions & 0 deletions src/logic/export/lcabyg/graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import uuid
from dataclasses import dataclass, field

from logic.export.lcabyg.utilities import Stages, Units


def _generate_id():
return str(uuid.uuid4())


def _get_name_dict(name: str):
return {
"Danish": name,
"English": name,
"German": name,
}


@dataclass
class LcaBygGraphEntity:
def as_dict(self) -> dict:
return {}


@dataclass
class Edge(LcaBygGraphEntity):
id: str = field(init=False, default_factory=_generate_id)
type: str
parent: str
child: str
metadata: dict = None

def as_dict(self):
return {"Edge": [{self.type: {"id": self.id, **(self.metadata or {})}}, self.parent, self.child]}


@dataclass
class CategoryToStageEdge(LcaBygGraphEntity):
id: str = field(init=False, default_factory=_generate_id)
parent: str
child: str

def as_dict(self):
return {"Edge": [{"CategoryToStage": self.id}, self.parent, self.child]}


@dataclass
class Node:
id: str
name: str
comment: str
locked: bool = field(init=False, default=True)
source: str = field(init=False, default="User")

def _add_to_dict(self, dict: dict):
dict["id"] = self.id
dict["name"] = _get_name_dict(self.name)
dict["comment"] = self.comment
dict["locked"] = self.locked
dict["source"] = self.source

def as_dict(self):
dict = {}
self._add_to_dict(dict)
return {
"Node": {
self.__class__.__name__: dict,
}
}


@dataclass
class Element(Node):
enabled: bool = field(init=False, default=True)

def _add_to_dict(self, dict: dict):
super()._add_to_dict(dict)
dict["enabled"] = self.enabled


@dataclass
class Construction(Node):
unit: str

def _add_to_dict(self, dict: dict):
super()._add_to_dict(dict)
dict["unit"] = Units(self.unit)


@dataclass
class Product(Node):
uncertainty_factor: float = field(init=False, default=1.0)
uncertainty_factor_dgnb: float = field(init=False, default=1.3)

def _add_to_dict(self, dict: dict):
super()._add_to_dict(dict)
dict["uncertainty_factor"] = self.uncertainty_factor
dict["uncertainty_factor_dgnb"] = self.uncertainty_factor_dgnb


@dataclass
class Stage(Node):
stage: Stages
data_type: str
unit: str
valid_to: str
mass_factor: float
gwp: int = 0

def _add_to_dict(self, dict: dict):
super()._add_to_dict(dict)
dict.update(
**{
"valid_to": self.valid_to,
"stage": self.stage,
"stage_unit": Units(self.unit),
"indicator_unit": Units(self.unit),
"stage_factor": 1.0,
"mass_factor": self.mass_factor,
"indicator_factor": 1.0,
"external_source": self.source,
"external_id": "",
"external_url": "",
"external_version": "",
"data_type": self.data_type,
"indicators": {
"GWP": self.gwp,
"ODP": 0,
"POCP": 0,
"AP": 0,
"EP": 0,
"ADPE": 0,
"ADPF": 0,
"PENR": 0,
"PER": 0,
"SENR": 0,
"SER": 0,
},
}
)
Loading