Skip to content

Instantly share code, notes, and snippets.

@gzigzigzeo
Last active December 24, 2020 20:47
Show Gist options
  • Save gzigzigzeo/47f21565436457bc31f004f32cc038d9 to your computer and use it in GitHub Desktop.
Save gzigzigzeo/47f21565436457bc31f004f32cc038d9 to your computer and use it in GitHub Desktop.
"""Global configuration"""
MODM_PATH = "../.devices/stm32-modm-devices"
"""Extracts memory nodes related to current device"""
def build(descriptor, xml):
nodes = xml.findall("device/driver[@name='core']/memory")
nodes = descriptor.filter_related(nodes)
return [node.attrib for node in nodes]
#!/usr/bin/env python3
import os
import modm
def main():
modm.build_index()
for (name, device) in modm.index.items():
device = device_builder.build(name)
if __name__ == "__main__":
""" This is executed when run from the command line """
main()
import config
import modm_file_descriptor
import typing
import glob
from os import path
from lxml import etree
index = dict()
"""Builds index [partname: str => ModmFileDescriptor]"""
def build_index() -> None:
global index
assert(path.exists(config.MODM_PATH)), "modm devices directory does not exist"
files = glob.glob(path.join(config.MODM_PATH, "*.xml"))
assert(any(files)), "modm devices directory is empty"
for filename in files:
xml = etree.parse(open(filename))
descriptors = modm_file_descriptor.fetch(xml)
for descriptor in descriptors:
index[descriptor.name] = descriptor
def resolve(name: str) -> modm_file_descriptor.ModmFileDescriptor:
return index.get(name)
from funcy import flatten
from dataclasses import dataclass, field
import typing
from lxml import etree
"""Represents MODM device descriptor"""
@dataclass
class ModmFileDescriptor:
name: str
schema: str
props: dict
xml: typing.Any
def find_related(self, path: str) -> [typing.Any]:
nodes = xml.find(path)
return list(filter(self.__filter_related, nodes))
def __filter_related(self, node):
for key, value in self.__props.items():
node_value = node.get(f"device-{key}")
if (node_value == None) or (node_value == ""):
continue
if not (value in node_value.split("|")):
return False
return True
"""Fetches device names from modm-devices file and transforms it to list of ModmFileDescriptor"""
def fetch(xml: typing.Any) -> [ModmFileDescriptor]:
props = xml.find("device").items()
schema = xml.find("device/naming-schema").text
valid = [i.text for i in xml.findall("device/valid-device")]
invalid = [i.text for i in xml.findall("device/invalid-device")]
names = flatten(_expand(dict(), props))
names = filter(lambda name: _validate(
name, schema, valid, invalid), names)
names = [ModmFileDescriptor(_build_name(schema, name), schema, name, xml) for name in names]
return names
"""
Recursively expands | expressions in device signature into list of lists of all possible variants
"""
def _expand(current: dict, props: dict) -> list:
if len(props) == 0:
return [current]
key, value = props[0]
return [_expand({**current, key: version}, props[1:]) for version in value.split("|")]
"""Checks if device name is valid"""
def _validate(name: dict, schema: str, valid: [str], invalid: [str]) -> bool:
name = _build_name(schema, name)
if (len(valid) > 0) and (name in valid):
return True
else:
return False
if (len(invalid) > 0) and (name in invalid):
return False
return True
def _build_name(schema: str, attributes: dict) -> str:
return str.format(schema, **attributes)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment