Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse cube-finder-db.db and include MPNs in output #6

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.swp
__pycache__
.mypy_cache/
tmp/
90 changes: 87 additions & 3 deletions extract.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,86 @@
import argparse
import json
import sqlite3
import zipfile
from os import makedirs, path
from typing import Any, Dict
from typing import Any, Dict, List, Optional
import xml.etree.ElementTree as ET


class CubeFinderDbPart:
"""
Class representing a part from the Cube Finder Database
"""
def __init__(self, mpn: str, t_min: Optional[float], t_max: Optional[float],
packing_type: Optional[str], status: Optional[str]):
self.mpn = mpn
self.t_min = t_min
self.t_max = t_max
self.packing_type = packing_type
self.status = status

def to_json(self) -> dict:
"""
Generate the JSON data to be included in generated files
"""
return dict(
mpn=self.mpn,
temperature_min=self.t_min,
temperature_max=self.t_max,
packing_type=self.packing_type,
status=self.status,
)


class CubeFinderDb:
"""
Helper class to extract information from ST's Cube Finder Database
"""
def __init__(self, db_file: str):
self._db = sqlite3.connect(db_file)
self._cur = self._db.cursor()

def get_parts_for_ref(self, ref: str) -> List[str]:
"""
Get a list of all parts for a given MCU ref
"""
res = self._cur.execute(
"SELECT id, cpn FROM cpn WHERE refname = :refname",
dict(refname=ref),
)
return [
CubeFinderDbPart(
mpn=row[1],
t_min=self._get_attribute(row[0], 'temperatureMin', is_num=True),
t_max=self._get_attribute(row[0], 'temperatureMax', is_num=True),
packing_type=self._get_attribute(row[0], 'packing_type'),
status=self._get_attribute(row[0], 'marketingStatus'),
)
for row in res.fetchall()
]

def _get_attribute(self, cpn_id: int, attribute_name: str,
is_num: bool = False) -> str:
"""
Extract a specific attribute of a given cpn_id
"""
res = self._cur.execute(
"SELECT strValue, numValue FROM cpn_has_attribute "
"LEFT JOIN attribute "
"ON attribute.id = cpn_has_attribute.attribute_id "
"WHERE cpn_id = :cpn_id "
"AND attribute.name = :attribute_name",
dict(
cpn_id=cpn_id,
attribute_name=attribute_name,
),
).fetchone()
Comment on lines +67 to +77
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be a multi-line string for easier readability:

        res = self._cur.execute("""
            SELECT strValue, numValue FROM cpn_has_attribute
            LEFT JOIN attribute
            ON attribute.id = cpn_has_attribute.attribute_id
            WHERE cpn_id = :cpn_id
            AND attribute.name = :attribute_name
            """,
            dict(
                cpn_id=cpn_id,
                attribute_name=attribute_name,
            ),
        ).fetchone()

if res is not None:
return res[1 if is_num else 0]
else:
return None


def _makedir(dirpath: str) -> None:
"""
Helper function to ensure that a directory exists.
Expand All @@ -15,6 +91,13 @@ def _makedir(dirpath: str) -> None:

def main(args):
_makedir('data')
_makedir('tmp')

# Extract MCU Finder SQLite database into the local directory and load it.
cube_finder_zip = path.join(args.db, 'plugins', 'mcufinder', 'mcu', 'cube-finder-db.zip')
with zipfile.ZipFile(cube_finder_zip, 'r') as f:
f.extract('cube-finder-db.db', 'tmp')
db = CubeFinderDb('tmp/cube-finder-db.db')

with open(path.join(args.db, 'mcu', 'families.xml'), 'r') as f:
tree = ET.parse(f)
Expand All @@ -26,10 +109,10 @@ def main(args):
print(' Processing subfamily {}'.format(subfamily.get('Name')))
for mcu in subfamily:
print(' Processing MCU {}'.format(mcu.get('Name')))
process_mcu(args, mcu.get('Name'), mcu.get('RefName'), mcu.get('RPN'))
process_mcu(args, db, mcu.get('Name'), mcu.get('RefName'), mcu.get('RPN'))


def process_mcu(args, name: str, ref: str, rpn: str):
def process_mcu(args, db: CubeFinderDb, name: str, ref: str, rpn: str):
"""
Fetch pinout information for this MCU and write it to the data dir.
"""
Expand All @@ -52,6 +135,7 @@ def process_mcu(args, name: str, ref: str, rpn: str):
'ram': int(mcu.find('{*}Ram').text), # type: ignore
'io': int(mcu.find('{*}IONb').text), # type: ignore
},
'parts': [part.to_json() for part in db.get_parts_for_ref(ref)],
} # type: Dict[str, Any]
if mcu.find('{*}Core') is not None:
data['silicon']['core'] = mcu.find('{*}Core').text # type: ignore
Expand Down