From 97c8bb9db96e27051f8746865f657408263db0b8 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Tue, 26 Feb 2019 23:08:19 +0100 Subject: o Creating a PartDb that manages a file system directory with one xml file per part. o Switching xml-based code to use PartDb. --- src/ee/part/__init__.py | 103 ++++++++++++++++++++++++++ src/ee/part/create_distributor_search_list.py | 33 +++++++++ 2 files changed, 136 insertions(+) create mode 100644 src/ee/part/__init__.py create mode 100644 src/ee/part/create_distributor_search_list.py (limited to 'src/ee/part') diff --git a/src/ee/part/__init__.py b/src/ee/part/__init__.py new file mode 100644 index 0000000..84a6174 --- /dev/null +++ b/src/ee/part/__init__.py @@ -0,0 +1,103 @@ +from pathlib import Path +from typing import List, MutableMapping, Optional, Iterator + +from ee import EeException +from ee.xml import bomFile, indexFile +from ee.xml.bom_file_utils import find_pn, find_dpn, find_root_tag + +__all__ = [ + "PartDb", + "load_db", + "save_db", +] + + +class Entry(object): + def __init__(self, new: bool, part: bomFile.Part): + self.new = new + self.part = part + + self.pn = find_pn(part) + + def dpn(self, uri: str): + return find_dpn(self.part, uri) + + +class PartDb(object): + def __init__(self): + self.parts = [] # type: List[Entry] + self.pn_index = {} # type: MutableMapping[str, Entry] + self.dpn_indexes = {} # type: MutableMapping[str, MutableMapping[str, Entry]] + self.new_entries = 0 + + def add_entry(self, part: bomFile.Part, new: bool): + e = Entry(new, part) + self.parts.append(e) + + if e.pn: + self.pn_index[e.pn] = e + + if e.new: + self.new_entries = self.new_entries + 1 + + def iterparts(self) -> Iterator[bomFile.Part]: + return [e.part for e in self.parts] + + def size(self) -> int: + return len(self.parts) + + def find_by_pn(self, pn: str) -> Optional[bomFile.Part]: + entry = self.pn_index.get(pn, None) + return entry.part if entry else None + + def find_by_dpn(self, distributor: str, pn: str) -> bomFile.Part: + idx = self.dpn_indexes.get(distributor) + + if idx is None: + tmp = [(find_dpn(entry.part, distributor), entry) for entry in self.parts] + idx = {dpn: entry for dpn, entry in tmp if dpn is not None} + self.dpn_indexes[distributor] = idx + + return idx[pn].part + + +def load_db(dir_path: Path) -> PartDb: + db = PartDb() + + for file in dir_path.iterdir(): + if not file.is_file() or not file.name.endswith(".xml") or file.name == "index.xml": + continue + + part = bomFile.parse(str(file), silence=True) # type: bomFile.Part + db.add_entry(part, False) + + return db + + +def save_db(dir_path: Path, db: PartDb): + if dir_path.exists(): + if not dir_path.is_dir(): + raise EeException("The given db path is not a directory") + + idx_path = dir_path / "index.xml" + if not idx_path.is_file(): + raise EeException("The given db directory exists, but does not look like a part db dir") + + dir_path.rmdir() + + dir_path.mkdir(parents=True, exist_ok=True) + + idx = indexFile.IndexFile() + idx.filesProp = indexFile.FileList() + files = idx.filesProp.fileProp + + for part in db.iterparts(): + id_ = part.id + path = dir_path / "{}.xml".format(id_) + with path.open("w") as f: + part.export(outfile=f, level=0, name_=find_root_tag(part)) + + files.append(indexFile.File(path=str(path))) + + with (dir_path / "index.xml").open("w") as f: + idx.export(f, level=0, name_=find_root_tag(idx)) diff --git a/src/ee/part/create_distributor_search_list.py b/src/ee/part/create_distributor_search_list.py new file mode 100644 index 0000000..ef91e1f --- /dev/null +++ b/src/ee/part/create_distributor_search_list.py @@ -0,0 +1,33 @@ +from pathlib import Path + +from ee.part import PartDb, load_db, save_db +from ee.xml.bom_file_utils import * + +__all__ = ["create_distributor_search_list"] + + +def create_distributor_search_list(in_dir: Path, out_dir: Path): + print("in: {}, out: {}".format(in_dir, out_dir)) + + in_parts = load_db(in_dir) + out_parts = PartDb() + + print("loaded {} existing parts".format(in_parts.size())) + + for part in in_parts.iterparts(): + pn_value = find_pn(part) + + if pn_value is None: + print("Skipping part with no part number: id={}".format(part.idProp)) + continue + + entry = out_parts.find_by_pn(pn_value) + + if entry is not None: + continue + + part.id = pn_value + out_parts.add_entry(part, True) + + print("Saving {} work parts".format(out_parts.size())) + save_db(out_dir, out_parts) -- cgit v1.2.3