Source code for bw_interface_schemas.lci

import json
import re
from pathlib import Path
from typing import Optional, Union

from pydantic import BaseModel, ConfigDict, JsonValue, Field
from datetime import datetime


[docs] class Parsimonius(BaseModel): """Change defaule `model_dump` behaviour to not export unset values by default"""
[docs] model_config = ConfigDict( extra="allow", )
[docs] def model_dump(self, exclude_unset=True, *args, **kwargs): return super().model_dump(*args, exclude_unset=exclude_unset, **kwargs)
[docs] class DataSource(Parsimonius): """A data source, such as a publication or field measurement. Very preliminary."""
[docs] authors: list[str]
[docs] year: int
[docs] title: str
[docs] doi: Optional[str] = None
[docs] class UncertaintyDistribution(Parsimonius): """Separate out the fields used in uncertainty distributions"""
[docs] amount: float
[docs] uncertainty_type: Optional[int] = None
[docs] loc: Optional[float] = None
[docs] scale: Optional[float] = None
[docs] shape: Optional[float] = None
[docs] minimum: Optional[float] = None
[docs] maximum: Optional[float] = None
[docs] negative: Optional[bool] = None
[docs] class Edge(UncertaintyDistribution): """An quantitative edge linking two nodes in the graph."""
[docs] edge_type: str = Field(alias="type")
[docs] source: 'Node'
[docs] target: 'Node'
# The people want freedom
[docs] properties: dict[str, Union[float, int]]
[docs] tags: Optional[dict[str, JsonValue]] = None
[docs] class Node(Parsimonius): # Combination of database and code uniquely identifies a node
[docs] code: str
[docs] database: str
# Recommended labels for these attributes
[docs] created: Optional[datetime] = None
[docs] modified: Optional[datetime] = None
[docs] name: Optional[str] = None
[docs] unit: Optional[str] = None
[docs] location: Optional[str] = None
[docs] node_type: Optional[str] = Field(alias="type", default=None)
# Comment can be a single string or something more structured.
[docs] comment: Union[str, dict[str, str], None] = None
[docs] filename: Optional[str] = None
[docs] references: Optional[list[DataSource]] = None
# Was previously classifications - we want something more generic # Tags are chosen from defined set of possibilities
[docs] tags: Optional[dict[str, JsonValue]] = None
[docs] exchanges: list[Edge] = []
[docs] class Process(Node): """A generic process, possibly multi-functional. Does not have a reference product. Only difference from `Node` is that some more fields are required."""
[docs] name: str
[docs] unit: str
[docs] location: str
# TBD: Time range?
[docs] class ProcessWithReferenceProduct(Process): """Chimaera which serves as both a product and a process in the graph.""" # Use `ProcessWithReferenceProduct.model_dump(by_alias=True)` # to get a dictionary using the alias field
[docs] reference_product: str = Field(alias="reference product")
# Optional name for the amount of reference product produced. # Duplicates information in the exchanges. # Should be net amount.
[docs] production_amount: Optional[float] = None
# Properties for reference product
[docs] properties: Optional[dict[str, Union[float, int]]] = None
[docs] model_config = ConfigDict( populate_by_name=False, )
[docs] class Product(Node):
[docs] name: str
[docs] unit: str
# Some products are the same globally, other have specific local properties
[docs] location: Optional[str] = None
# Properties are quantitative; use tags to choose from a set of possible values
[docs] properties: dict[str, Union[float, int]]
[docs] class ElementaryFlow(Node): # Previously called categories in Brightway
[docs] context: list[str]
[docs] name: str
[docs] unit: str
if __name__ == "__main__":
[docs] hiss = lambda name: re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
dirpath = Path(__file__).parent / "json_schema" for cls in (ElementaryFlow, Product, ProcessWithReferenceProduct, Process, Node, Edge): with open(dirpath / (hiss(cls.__name__) + ".json"), "w") as f: json.dump(cls.model_json_schema(), f, indent=2, ensure_ascii=False)