0321 from macmini
This commit is contained in:
59
3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/__init__.py
vendored
Normal file
59
3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/__init__.py
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
import os
|
||||
import pcbnew
|
||||
|
||||
from .xmlparser import XmlParser
|
||||
from .netlistparser import NetlistParser
|
||||
|
||||
PARSERS = {
|
||||
'.xml': XmlParser,
|
||||
'.net': NetlistParser,
|
||||
}
|
||||
|
||||
|
||||
if hasattr(pcbnew, 'FOOTPRINT'):
|
||||
PARSERS['.kicad_pcb'] = None
|
||||
|
||||
|
||||
def parse_schematic_data(file_name):
|
||||
if not os.path.isfile(file_name):
|
||||
return None
|
||||
extension = os.path.splitext(file_name)[1]
|
||||
if extension not in PARSERS:
|
||||
return None
|
||||
else:
|
||||
parser_cls = PARSERS[extension]
|
||||
if parser_cls is None:
|
||||
return None
|
||||
parser = parser_cls(file_name)
|
||||
return parser.get_extra_field_data()
|
||||
|
||||
|
||||
def find_latest_schematic_data(base_name, directories):
|
||||
"""
|
||||
:param base_name: base name of pcb file
|
||||
:param directories: list of directories to search
|
||||
:return: last modified parsable file path or None if not found
|
||||
"""
|
||||
files = []
|
||||
for d in directories:
|
||||
files.extend(_find_in_dir(d))
|
||||
# sort by decreasing modification time
|
||||
files = sorted(files, reverse=True)
|
||||
if files:
|
||||
# try to find first (last modified) file that has name matching pcb file
|
||||
for _, f in files:
|
||||
if os.path.splitext(os.path.basename(f))[0] == base_name:
|
||||
return f
|
||||
# if no such file is found just return last modified
|
||||
return files[0][1]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _find_in_dir(dir):
|
||||
_, _, files = next(os.walk(dir), (None, None, []))
|
||||
# filter out files that we can not parse
|
||||
files = [f for f in files if os.path.splitext(f)[1] in PARSERS.keys()]
|
||||
files = [os.path.join(dir, f) for f in files]
|
||||
# get their modification time and sort in descending order
|
||||
return [(os.path.getmtime(f), f) for f in files]
|
59
3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/netlistparser.py
vendored
Normal file
59
3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/netlistparser.py
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
import io
|
||||
|
||||
from .parser_base import ParserBase
|
||||
from .sexpressions import parse_sexpression
|
||||
|
||||
|
||||
class NetlistParser(ParserBase):
|
||||
def get_extra_field_data(self):
|
||||
with io.open(self.file_name, 'r', encoding='utf-8') as f:
|
||||
sexpression = parse_sexpression(f.read())
|
||||
components = None
|
||||
for s in sexpression:
|
||||
if s[0] == 'components':
|
||||
components = s[1:]
|
||||
if components is None:
|
||||
return None
|
||||
field_set = set()
|
||||
comp_dict = {}
|
||||
for c in components:
|
||||
ref = None
|
||||
fields = None
|
||||
datasheet = None
|
||||
libsource = None
|
||||
dnp = False
|
||||
for f in c[1:]:
|
||||
if f[0] == 'ref':
|
||||
ref = f[1]
|
||||
if f[0] == 'fields':
|
||||
fields = f[1:]
|
||||
if f[0] == 'datasheet':
|
||||
datasheet = f[1]
|
||||
if f[0] == 'libsource':
|
||||
libsource = f[1:]
|
||||
if f[0] == 'property' and isinstance(f[1], list) and \
|
||||
f[1][0] == 'name' and f[1][1] == 'dnp':
|
||||
dnp = True
|
||||
if ref is None:
|
||||
return None
|
||||
ref_fields = comp_dict.setdefault(ref, {})
|
||||
if datasheet and datasheet != '~':
|
||||
field_set.add('Datasheet')
|
||||
ref_fields['Datasheet'] = datasheet
|
||||
if libsource is not None:
|
||||
for lib_field in libsource:
|
||||
if lib_field[0] == 'description':
|
||||
field_set.add('Description')
|
||||
ref_fields['Description'] = lib_field[1]
|
||||
if dnp:
|
||||
field_set.add('kicad_dnp')
|
||||
ref_fields['kicad_dnp'] = "DNP"
|
||||
if fields is None:
|
||||
continue
|
||||
for f in fields:
|
||||
if len(f) > 1:
|
||||
field_set.add(f[1][1])
|
||||
if len(f) > 2:
|
||||
ref_fields[f[1][1]] = f[2]
|
||||
|
||||
return list(field_set), comp_dict
|
26
3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/parser_base.py
vendored
Normal file
26
3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/parser_base.py
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
class ParserBase:
|
||||
|
||||
def __init__(self, file_name):
|
||||
"""
|
||||
:param file_name: path to file that should be parsed.
|
||||
"""
|
||||
self.file_name = file_name
|
||||
|
||||
def get_extra_field_data(self):
|
||||
# type: () -> tuple
|
||||
"""
|
||||
Parses the file and returns extra field data.
|
||||
:return: tuple of the format
|
||||
(
|
||||
[field_name1, field_name2,... ],
|
||||
{
|
||||
ref1: {
|
||||
field_name1: field_value1,
|
||||
field_name2: field_value2,
|
||||
...
|
||||
],
|
||||
ref2: ...
|
||||
}
|
||||
)
|
||||
"""
|
||||
pass
|
32
3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/sexpressions.py
vendored
Normal file
32
3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/sexpressions.py
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
import re
|
||||
|
||||
term_regex = r'''(?mx)
|
||||
\s*(?:
|
||||
(?P<open>\()|
|
||||
(?P<close>\))|
|
||||
(?P<sq>"(?:\\\\|\\"|[^"])*")|
|
||||
(?P<s>[^(^)\s]+)
|
||||
)'''
|
||||
pattern = re.compile(term_regex)
|
||||
|
||||
|
||||
def parse_sexpression(sexpression):
|
||||
stack = []
|
||||
out = []
|
||||
for terms in pattern.finditer(sexpression):
|
||||
term, value = [(t, v) for t, v in terms.groupdict().items() if v][0]
|
||||
if term == 'open':
|
||||
stack.append(out)
|
||||
out = []
|
||||
elif term == 'close':
|
||||
assert stack, "Trouble with nesting of brackets"
|
||||
tmp, out = out, stack.pop(-1)
|
||||
out.append(tmp)
|
||||
elif term == 'sq':
|
||||
out.append(value[1:-1].replace('\\\\', '\\').replace('\\"', '"'))
|
||||
elif term == 's':
|
||||
out.append(value)
|
||||
else:
|
||||
raise NotImplementedError("Error: %s, %s" % (term, value))
|
||||
assert not stack, "Trouble with nesting of brackets"
|
||||
return out[0]
|
42
3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/xmlparser.py
vendored
Normal file
42
3rdparty/plugins/org_openscopeproject_InteractiveHtmlBom/ecad/kicad_extra/xmlparser.py
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
from xml.dom import minidom
|
||||
|
||||
from .parser_base import ParserBase
|
||||
|
||||
|
||||
class XmlParser(ParserBase):
|
||||
@staticmethod
|
||||
def get_text(nodelist):
|
||||
rc = []
|
||||
for node in nodelist:
|
||||
if node.nodeType == node.TEXT_NODE:
|
||||
rc.append(node.data)
|
||||
return ''.join(rc)
|
||||
|
||||
def get_extra_field_data(self):
|
||||
xml = minidom.parse(self.file_name)
|
||||
components = xml.getElementsByTagName('comp')
|
||||
field_set = set()
|
||||
comp_dict = {}
|
||||
for c in components:
|
||||
ref_fields = comp_dict.setdefault(c.attributes['ref'].value, {})
|
||||
datasheet = c.getElementsByTagName('datasheet')
|
||||
if datasheet:
|
||||
datasheet = self.get_text(datasheet[0].childNodes)
|
||||
if datasheet != '~':
|
||||
field_set.add('Datasheet')
|
||||
ref_fields['Datasheet'] = datasheet
|
||||
libsource = c.getElementsByTagName('libsource')
|
||||
if libsource and libsource[0].hasAttribute('description'):
|
||||
field_set.add('Description')
|
||||
attr = libsource[0].attributes['description']
|
||||
ref_fields['Description'] = attr.value
|
||||
for f in c.getElementsByTagName('field'):
|
||||
name = f.attributes['name'].value
|
||||
field_set.add(name)
|
||||
ref_fields[name] = self.get_text(f.childNodes)
|
||||
for f in c.getElementsByTagName('property'):
|
||||
if f.attributes['name'].value == 'dnp':
|
||||
field_set.add('kicad_dnp')
|
||||
ref_fields['kicad_dnp'] = "DNP"
|
||||
|
||||
return list(field_set), comp_dict
|
Reference in New Issue
Block a user