modm_data.dl.stmicro.document

  1# Copyright 2022, Niklas Hauser
  2# SPDX-License-Identifier: MPL-2.0
  3
  4import json
  5import logging
  6from pathlib import Path
  7from functools import cached_property
  8from ..store import download_file, download_data
  9from ...utils import ext_path
 10
 11LOGGER = logging.getLogger(__name__)
 12
 13
 14class Document:
 15    """
 16    Smaller helper class to store all relevant information about a remote
 17    STMicro PDF document and how to download it.
 18    """
 19
 20    def __init__(self, data):
 21        # Primary information from JSON data
 22        self._title = data["title"]
 23        self._description = data["localizedDescriptions"]["en"]
 24        self._url = data["localizedLinks"]["en"]
 25        self._version = data["version"]
 26        self._update = data["latestUpdate"]
 27        self._type = data.get("resourceType", "Unknown")
 28
 29        # Derived information
 30        self._short_type = self._title[:2]
 31        clean_version = self._version.replace(".0", "").replace(".", "_")
 32        self.name = self._title + "-v" + clean_version
 33        """The full name of the document including version."""
 34        self.filename = self.name + ".pdf"
 35        """The leaf filename of the document."""
 36        self.url = "https://www.st.com" + self._url
 37        """The full URL that the file was downloaded from."""
 38
 39    @property
 40    def data(self) -> dict:
 41        """
 42        A dictionary uniquely identifying this document version in a similar
 43        format to the one used by the STMicro homepage. This can be used to
 44        keep track of which documents have already been downloaded and which
 45        have been updated upstream.
 46        """
 47        return {
 48            "title": self._title,
 49            "localizedDescriptions": {"en": self._description},
 50            "localizedLinks": {"en": self._url},
 51            "version": self._version,
 52            "latestUpdate": self._update,
 53            "resourceType": self._type,
 54        }
 55
 56    def store_pdf(self, path: str, overwrite: bool = False) -> bool:
 57        """Download the PDF file to the path, optionally overwriting it."""
 58        return download_file(self.url, path, overwrite=overwrite)
 59
 60    def __repr__(self) -> str:
 61        return f"Doc({self._title} v{self._version.replace('.0', '')})"
 62
 63    def __eq__(self, other) -> bool:
 64        if not isinstance(other, type(self)):
 65            return False
 66        return self.filename == other.filename
 67
 68    def __hash__(self) -> int:
 69        return hash(self.filename)
 70
 71
 72_json_short_urls = {
 73    # Technical docs for STM32 microcontrollers
 74    "stm32": [
 75        "CL1734",
 76        "SC2154",
 77        "SC2155",
 78        "SC2157",
 79        "SC2156",
 80    ],
 81    # Technical docs for STM32 development boards
 82    "boards": [
 83        "LN1847",
 84        "LN1848",
 85        "LN1199",
 86    ],
 87    # Technical docs for STMicro sensors
 88    "sensors": [
 89        "SC444",
 90        #SC1946",
 91        "SC1449",
 92        "SC1288",
 93        #SC1718",
 94        "SC1448",
 95        "SC1922",
 96        "SC1316",
 97        "SC294",
 98    ],
 99    # Technical docs for STMicro data converters
100    "converters": [
101        "SC47",
102        "SC2514",
103        "SC397",
104    ],
105    # Technical docs for STMicro hardware debug tools
106    "debug": [
107        "SC2330"
108    ]
109}
110_json_url_prefix = "https://www.st.com/bin/st/selectors/cxst/en.cxst-rs-grid.html/"
111_json_url_suffix = ".technical_literature.json"
112
113_json_urls = {key: [_json_url_prefix + url + _json_url_suffix for url in urls]
114              for key, urls in _json_short_urls.items()}
115_remote_info = "remote.json"
116_local_info = "local.json"
117
118
119def load_remote_info(base_dir: Path, use_cached: bool = False) -> list[dict]:
120    info = base_dir / _remote_info
121    if use_cached and info.exists():
122        LOGGER.debug(f"Loading remote info from cache")
123        docs = json.loads(info.read_text())
124    else:
125        LOGGER.info(f"Downloading remote info")
126        docs = []
127        for urls in _json_urls.values():
128            for url in urls:
129                docs.extend(json.loads(download_data(url))["rows"])
130    return docs
131
132
133def store_remote_info(base_dir: Path, docs: list[dict]):
134    info = base_dir / _remote_info
135    info.parent.mkdir(parents=True, exist_ok=True)
136    info.write_text(json.dumps(sorted(docs,
137        key=lambda d: (d["title"], d["version"])), indent=4, sort_keys=True))
138
139
140def load_local_info(base_dir: Path) -> list[dict]:
141    info = base_dir / _local_info
142    if info.exists():
143        LOGGER.debug(f"Loading local info from cache")
144        return json.loads(info.read_text())
145    return []
146
147
148def store_local_info(base_dir: Path, docs: list[dict]):
149    info = base_dir / _local_info
150    info.parent.mkdir(parents=True, exist_ok=True)
151    info.write_text(json.dumps(sorted(docs,
152        key=lambda d: (d["title"], d["version"])), indent=4, sort_keys=True))
153
154
155def sync_info(base_dir: Path, use_cached: bool = False) -> set[Document]:
156    remote_docs = set(map(Document, load_remote_info(base_dir, use_cached)))
157    local_docs = set(map(Document, load_local_info(base_dir)))
158    return remote_docs - local_docs
LOGGER = <Logger modm_data.dl.stmicro.document (WARNING)>
class Document:
15class Document:
16    """
17    Smaller helper class to store all relevant information about a remote
18    STMicro PDF document and how to download it.
19    """
20
21    def __init__(self, data):
22        # Primary information from JSON data
23        self._title = data["title"]
24        self._description = data["localizedDescriptions"]["en"]
25        self._url = data["localizedLinks"]["en"]
26        self._version = data["version"]
27        self._update = data["latestUpdate"]
28        self._type = data.get("resourceType", "Unknown")
29
30        # Derived information
31        self._short_type = self._title[:2]
32        clean_version = self._version.replace(".0", "").replace(".", "_")
33        self.name = self._title + "-v" + clean_version
34        """The full name of the document including version."""
35        self.filename = self.name + ".pdf"
36        """The leaf filename of the document."""
37        self.url = "https://www.st.com" + self._url
38        """The full URL that the file was downloaded from."""
39
40    @property
41    def data(self) -> dict:
42        """
43        A dictionary uniquely identifying this document version in a similar
44        format to the one used by the STMicro homepage. This can be used to
45        keep track of which documents have already been downloaded and which
46        have been updated upstream.
47        """
48        return {
49            "title": self._title,
50            "localizedDescriptions": {"en": self._description},
51            "localizedLinks": {"en": self._url},
52            "version": self._version,
53            "latestUpdate": self._update,
54            "resourceType": self._type,
55        }
56
57    def store_pdf(self, path: str, overwrite: bool = False) -> bool:
58        """Download the PDF file to the path, optionally overwriting it."""
59        return download_file(self.url, path, overwrite=overwrite)
60
61    def __repr__(self) -> str:
62        return f"Doc({self._title} v{self._version.replace('.0', '')})"
63
64    def __eq__(self, other) -> bool:
65        if not isinstance(other, type(self)):
66            return False
67        return self.filename == other.filename
68
69    def __hash__(self) -> int:
70        return hash(self.filename)

Smaller helper class to store all relevant information about a remote STMicro PDF document and how to download it.

Document(data)
21    def __init__(self, data):
22        # Primary information from JSON data
23        self._title = data["title"]
24        self._description = data["localizedDescriptions"]["en"]
25        self._url = data["localizedLinks"]["en"]
26        self._version = data["version"]
27        self._update = data["latestUpdate"]
28        self._type = data.get("resourceType", "Unknown")
29
30        # Derived information
31        self._short_type = self._title[:2]
32        clean_version = self._version.replace(".0", "").replace(".", "_")
33        self.name = self._title + "-v" + clean_version
34        """The full name of the document including version."""
35        self.filename = self.name + ".pdf"
36        """The leaf filename of the document."""
37        self.url = "https://www.st.com" + self._url
38        """The full URL that the file was downloaded from."""
name

The full name of the document including version.

filename

The leaf filename of the document.

url

The full URL that the file was downloaded from.

data: dict
40    @property
41    def data(self) -> dict:
42        """
43        A dictionary uniquely identifying this document version in a similar
44        format to the one used by the STMicro homepage. This can be used to
45        keep track of which documents have already been downloaded and which
46        have been updated upstream.
47        """
48        return {
49            "title": self._title,
50            "localizedDescriptions": {"en": self._description},
51            "localizedLinks": {"en": self._url},
52            "version": self._version,
53            "latestUpdate": self._update,
54            "resourceType": self._type,
55        }

A dictionary uniquely identifying this document version in a similar format to the one used by the STMicro homepage. This can be used to keep track of which documents have already been downloaded and which have been updated upstream.

def store_pdf(self, path: str, overwrite: bool = False) -> bool:
57    def store_pdf(self, path: str, overwrite: bool = False) -> bool:
58        """Download the PDF file to the path, optionally overwriting it."""
59        return download_file(self.url, path, overwrite=overwrite)

Download the PDF file to the path, optionally overwriting it.

def load_remote_info(base_dir: pathlib.Path, use_cached: bool = False) -> list[dict]:
120def load_remote_info(base_dir: Path, use_cached: bool = False) -> list[dict]:
121    info = base_dir / _remote_info
122    if use_cached and info.exists():
123        LOGGER.debug(f"Loading remote info from cache")
124        docs = json.loads(info.read_text())
125    else:
126        LOGGER.info(f"Downloading remote info")
127        docs = []
128        for urls in _json_urls.values():
129            for url in urls:
130                docs.extend(json.loads(download_data(url))["rows"])
131    return docs
def store_remote_info(base_dir: pathlib.Path, docs: list[dict]):
134def store_remote_info(base_dir: Path, docs: list[dict]):
135    info = base_dir / _remote_info
136    info.parent.mkdir(parents=True, exist_ok=True)
137    info.write_text(json.dumps(sorted(docs,
138        key=lambda d: (d["title"], d["version"])), indent=4, sort_keys=True))
def load_local_info(base_dir: pathlib.Path) -> list[dict]:
141def load_local_info(base_dir: Path) -> list[dict]:
142    info = base_dir / _local_info
143    if info.exists():
144        LOGGER.debug(f"Loading local info from cache")
145        return json.loads(info.read_text())
146    return []
def store_local_info(base_dir: pathlib.Path, docs: list[dict]):
149def store_local_info(base_dir: Path, docs: list[dict]):
150    info = base_dir / _local_info
151    info.parent.mkdir(parents=True, exist_ok=True)
152    info.write_text(json.dumps(sorted(docs,
153        key=lambda d: (d["title"], d["version"])), indent=4, sort_keys=True))
def sync_info( base_dir: pathlib.Path, use_cached: bool = False) -> set[Document]:
156def sync_info(base_dir: Path, use_cached: bool = False) -> set[Document]:
157    remote_docs = set(map(Document, load_remote_info(base_dir, use_cached)))
158    local_docs = set(map(Document, load_local_info(base_dir)))
159    return remote_docs - local_docs