modm_data.html.stmicro.document
1# Copyright 2022, Niklas Hauser 2# SPDX-License-Identifier: MPL-2.0 3 4import json 5from collections import defaultdict 6from ...html import Document 7from ...utils import cache_path, ext_path 8from .datasheet import DatasheetMicro, DatasheetSensor 9from .reference import ReferenceManual 10from ...owl import DeviceIdentifier 11from ...owl.stmicro import did_from_string 12 13 14MAP_DEVICE_DOC_FILE = cache_path("stmicro-did-doc.json") 15DOCUMENT_CACHE = None 16 17 18def load_documents() -> list: 19 documents = defaultdict(dict) 20 for path in sorted(ext_path("stmicro/html").glob("*-v*")): 21 # This doc is parsed wrongly since it has a DRAFT background 22 if "DS12960-v5" in path.stem: continue 23 # This doc has a preliminary ordering information STM32WBA52CGU6TR 24 if "DS14127" in path.stem: continue 25 doc = Document(path) 26 if "DS" in doc.name and (chap := doc.chapters("chapter 0")): 27 # FIXME: Better detection that DS13252 is a STM32WB55 module, not a chip! 28 if any("STM32" in h.html for h in chap[0].headings()) and \ 29 "DS13252" not in doc.name and "DS14096" not in doc.name: 30 documents[doc.name][doc.version] = DatasheetMicro(path) 31 else: 32 documents[doc.name][doc.version] = DatasheetSensor(path) 33 elif "RM" in doc.name: 34 documents[doc.name][doc.version] = ReferenceManual(path) 35 return documents 36 37 38def load_document_devices(use_cached=True) -> tuple[dict[DeviceIdentifier, DatasheetMicro], 39 dict[DeviceIdentifier, ReferenceManual]]: 40 global DOCUMENT_CACHE 41 if DOCUMENT_CACHE is not None: 42 return DOCUMENT_CACHE 43 44 global MAP_DEVICE_DOC_FILE 45 if MAP_DEVICE_DOC_FILE.exists() and use_cached: 46 with MAP_DEVICE_DOC_FILE.open('r', encoding='utf-8') as fh: 47 json_data = json.load(fh) 48 49 docs = {} 50 for path in set(json_data["ds"].values()): 51 docs[path] = DatasheetMicro(path) 52 for path in set(json_data["rm"].values()): 53 docs[path] = ReferenceManual(path) 54 datasheets = {did_from_string(did): docs[path] 55 for did, path in json_data["ds"].items()} 56 reference_manuals = {did_from_string(did): docs[path] 57 for did, path in json_data["rm"].items()} 58 else: 59 dss = defaultdict(set) 60 rms = defaultdict(set) 61 for name, versions in load_documents().items(): 62 # Always choose the latest version 63 doc = list(versions.values())[-1] 64 # print(doc.path_pdf.relative_to(Path().cwd()), doc.path.relative_to(Path().cwd())) 65 # print(doc.devices) 66 if isinstance(doc, DatasheetMicro): 67 if not doc.devices: 68 raise ValueError(f"{doc} has no associated devices!") 69 for dev in doc.devices: 70 dss[dev].add(doc) 71 elif isinstance(doc, ReferenceManual): 72 if not doc.devices: 73 raise ValueError(f"{doc} has no associated devices!") 74 for dev in doc.devices: 75 rms[dev].add(doc) 76 77 for dev, docs in dss.items(): 78 if len(docs) != 1: 79 raise ValueError(f"One device points to multiple datasheets! {dev} -> {docs}") 80 datasheets = {did:list(ds)[0] for did, ds in dss.items()} 81 # print(len(datasheets.keys()), sorted(list(d.string for d in datasheets.keys()))) 82 83 manuals = defaultdict(set) 84 for dev, docs in rms.items(): 85 if len(docs) != 1: 86 raise ValueError(f"One device points to multiple reference manuals! {dev} -> {docs}") 87 for dev in list(docs)[0].filter_devices(datasheets.keys()): 88 manuals[dev].add(list(docs)[0]) 89 90 for dev, docs in manuals.items(): 91 if len(docs) != 1: 92 raise ValueError(f"One device points to multiple reference manuals! {dev} -> {docs}") 93 94 reference_manuals = {did:list(rm)[0] for did, rm in manuals.items()} 95 96 # Cache the results for the next call 97 json_data = { 98 "ds": {did.string: str(doc.path) for did, doc in datasheets.items()}, 99 "rm": {did.string: str(doc.path) for did, doc in reference_manuals.items()} 100 } 101 MAP_DEVICE_DOC_FILE.parent.mkdir(parents=True, exist_ok=True) 102 with MAP_DEVICE_DOC_FILE.open('w', encoding='utf-8') as fh: 103 json.dump(json_data, fh, indent=4) 104 105 DOCUMENT_CACHE = (datasheets, reference_manuals) 106 return datasheets, reference_manuals 107 108 109def _document_for_device(did: DeviceIdentifier, documents): 110 if did in documents: 111 return documents[did] 112 113 # Find the first device without temperature key that matches 114 did = did.copy() 115 for temp in ["7", "6", "3"]: 116 did.set("temperature", temp) 117 if did in documents: 118 return documents[did] 119 120 return None 121 122 123def datasheet_for_device(did: DeviceIdentifier) -> DatasheetMicro: 124 datasheets, _ = load_document_devices() 125 return _document_for_device(did, datasheets) 126 127 128def reference_manual_for_device(did: DeviceIdentifier) -> ReferenceManual: 129 _, reference_manual = load_document_devices() 130 return _document_for_device(did, reference_manual)
MAP_DEVICE_DOC_FILE =
PosixPath('/opt/hostedtoolcache/Python/3.12.2/x64/lib/python3.12/site-packages/ext/cache/stmicro-did-doc.json')
DOCUMENT_CACHE =
None
def
load_documents() -> list:
19def load_documents() -> list: 20 documents = defaultdict(dict) 21 for path in sorted(ext_path("stmicro/html").glob("*-v*")): 22 # This doc is parsed wrongly since it has a DRAFT background 23 if "DS12960-v5" in path.stem: continue 24 # This doc has a preliminary ordering information STM32WBA52CGU6TR 25 if "DS14127" in path.stem: continue 26 doc = Document(path) 27 if "DS" in doc.name and (chap := doc.chapters("chapter 0")): 28 # FIXME: Better detection that DS13252 is a STM32WB55 module, not a chip! 29 if any("STM32" in h.html for h in chap[0].headings()) and \ 30 "DS13252" not in doc.name and "DS14096" not in doc.name: 31 documents[doc.name][doc.version] = DatasheetMicro(path) 32 else: 33 documents[doc.name][doc.version] = DatasheetSensor(path) 34 elif "RM" in doc.name: 35 documents[doc.name][doc.version] = ReferenceManual(path) 36 return documents
def
load_document_devices( use_cached=True) -> tuple[dict[modm_data.owl.identifier.DeviceIdentifier, modm_data.html.stmicro.datasheet.DatasheetMicro], dict[modm_data.owl.identifier.DeviceIdentifier, modm_data.html.stmicro.reference.ReferenceManual]]:
39def load_document_devices(use_cached=True) -> tuple[dict[DeviceIdentifier, DatasheetMicro], 40 dict[DeviceIdentifier, ReferenceManual]]: 41 global DOCUMENT_CACHE 42 if DOCUMENT_CACHE is not None: 43 return DOCUMENT_CACHE 44 45 global MAP_DEVICE_DOC_FILE 46 if MAP_DEVICE_DOC_FILE.exists() and use_cached: 47 with MAP_DEVICE_DOC_FILE.open('r', encoding='utf-8') as fh: 48 json_data = json.load(fh) 49 50 docs = {} 51 for path in set(json_data["ds"].values()): 52 docs[path] = DatasheetMicro(path) 53 for path in set(json_data["rm"].values()): 54 docs[path] = ReferenceManual(path) 55 datasheets = {did_from_string(did): docs[path] 56 for did, path in json_data["ds"].items()} 57 reference_manuals = {did_from_string(did): docs[path] 58 for did, path in json_data["rm"].items()} 59 else: 60 dss = defaultdict(set) 61 rms = defaultdict(set) 62 for name, versions in load_documents().items(): 63 # Always choose the latest version 64 doc = list(versions.values())[-1] 65 # print(doc.path_pdf.relative_to(Path().cwd()), doc.path.relative_to(Path().cwd())) 66 # print(doc.devices) 67 if isinstance(doc, DatasheetMicro): 68 if not doc.devices: 69 raise ValueError(f"{doc} has no associated devices!") 70 for dev in doc.devices: 71 dss[dev].add(doc) 72 elif isinstance(doc, ReferenceManual): 73 if not doc.devices: 74 raise ValueError(f"{doc} has no associated devices!") 75 for dev in doc.devices: 76 rms[dev].add(doc) 77 78 for dev, docs in dss.items(): 79 if len(docs) != 1: 80 raise ValueError(f"One device points to multiple datasheets! {dev} -> {docs}") 81 datasheets = {did:list(ds)[0] for did, ds in dss.items()} 82 # print(len(datasheets.keys()), sorted(list(d.string for d in datasheets.keys()))) 83 84 manuals = defaultdict(set) 85 for dev, docs in rms.items(): 86 if len(docs) != 1: 87 raise ValueError(f"One device points to multiple reference manuals! {dev} -> {docs}") 88 for dev in list(docs)[0].filter_devices(datasheets.keys()): 89 manuals[dev].add(list(docs)[0]) 90 91 for dev, docs in manuals.items(): 92 if len(docs) != 1: 93 raise ValueError(f"One device points to multiple reference manuals! {dev} -> {docs}") 94 95 reference_manuals = {did:list(rm)[0] for did, rm in manuals.items()} 96 97 # Cache the results for the next call 98 json_data = { 99 "ds": {did.string: str(doc.path) for did, doc in datasheets.items()}, 100 "rm": {did.string: str(doc.path) for did, doc in reference_manuals.items()} 101 } 102 MAP_DEVICE_DOC_FILE.parent.mkdir(parents=True, exist_ok=True) 103 with MAP_DEVICE_DOC_FILE.open('w', encoding='utf-8') as fh: 104 json.dump(json_data, fh, indent=4) 105 106 DOCUMENT_CACHE = (datasheets, reference_manuals) 107 return datasheets, reference_manuals
def
datasheet_for_device( did: modm_data.owl.identifier.DeviceIdentifier) -> modm_data.html.stmicro.datasheet.DatasheetMicro:
def
reference_manual_for_device( did: modm_data.owl.identifier.DeviceIdentifier) -> modm_data.html.stmicro.reference.ReferenceManual: