Source code for buildingmotif.ingresses.base

import json
from dataclasses import dataclass
from functools import cached_property
from os import PathLike
from pathlib import Path
from typing import List

from rdflib import Graph, Namespace

from buildingmotif import BuildingMOTIF


[docs]@dataclass class Record: """Represents a piece of metadata from some metadata ingress""" # an arbitrary "type hint" rtype: str # possibly-nested dictionary of (semi-)structured data from # the underlying source fields: dict
[docs]class IngressHandler: """Abstract superclass for Record/Graph ingress handlers""" pass
[docs]class RecordIngressHandler(IngressHandler): """Generates Record instances from an underlying metadata source""" def __init__(self, bm: BuildingMOTIF): self.bm = bm @cached_property def records(self) -> List[Record]: """ Generates (then caches) a list of Records from an underlying data source """ raise NotImplementedError("Must be overridden by subclass")
[docs] def dump(self, path: PathLike): """ Takes the contents of the records of this handler and writes them to a JSON file :param path: path to write output file to :type path: PathLike """ output_string = self.dumps() output_file = Path(path) with output_file.open("w", encoding="utf-8") as f: f.write(output_string)
[docs] def dumps(self) -> str: """ Takes the contents of the records of this handler and writes them to a string """ records = [ {"rtype": record.rtype, "fields": record.fields} for record in self.records ] return json.dumps(records)
[docs] @classmethod def load(cls, path: PathLike): """ Takes a file generated by 'dump' and creates a new ingress handler with those records """ return cls.loads(Path(path).read_text())
[docs] @classmethod def loads(cls, s: str): """ Takes the string output by 'dumps' and creates a new ingress handler with those records """ self = cls.__new__(cls) records = [] for record in json.loads(s): records.append(Record(record["rtype"], record["fields"])) self.records = records return self
[docs]class GraphIngressHandler(IngressHandler): """Generates a Graph from an underlying metadata source or RecordIngressHandler""" def __init__(self, bm: BuildingMOTIF): self.bm = bm
[docs] def graph(self, ns: Namespace) -> Graph: """Generates an RDF graph with all entities being placed in the given namespace""" raise NotImplementedError("Must be overridden by subclass")