0321 from macmini

This commit is contained in:
2025-03-21 13:28:36 +08:00
commit cd1fd4bdfa
11397 changed files with 4528845 additions and 0 deletions

View File

@ -0,0 +1,167 @@
import io
import json
import os.path
from jsonschema import validate, ValidationError
from .common import EcadParser, Component, BoundingBox, ExtraFieldData
from ..core.fontparser import FontParser
from ..errors import ParsingException
class GenericJsonParser(EcadParser):
COMPATIBLE_SPEC_VERSIONS = [1]
def extra_data_file_filter(self):
return "Json file ({f})|{f}".format(f=os.path.basename(self.file_name))
def latest_extra_data(self, extra_dirs=None):
return self.file_name
def get_extra_field_data(self, file_name):
if os.path.abspath(file_name) != os.path.abspath(self.file_name):
return None
_, components = self._parse()
field_set = set()
comp_dict = {}
for c in components:
ref_fields = comp_dict.setdefault(c.ref, {})
for k, v in c.extra_fields.items():
field_set.add(k)
ref_fields[k] = v
by_index = {
i: components[i].extra_fields for i in range(len(components))
}
return ExtraFieldData(list(field_set), comp_dict, by_index)
def get_generic_json_pcb(self):
with io.open(self.file_name, 'r', encoding='utf-8') as f:
pcb = json.load(f)
if 'spec_version' not in pcb:
raise ValidationError("'spec_version' is a required property")
if pcb['spec_version'] not in self.COMPATIBLE_SPEC_VERSIONS:
raise ValidationError("Unsupported spec_version ({})"
.format(pcb['spec_version']))
schema_dir = os.path.join(os.path.dirname(__file__), 'schema')
schema_file_name = os.path.join(schema_dir,
'genericjsonpcbdata_v{}.schema'.format(
pcb['spec_version']))
with io.open(schema_file_name, 'r', encoding='utf-8') as f:
schema = json.load(f)
validate(instance=pcb, schema=schema)
return pcb
def _verify(self, pcb):
"""Spot check the pcb object."""
if len(pcb['pcbdata']['footprints']) != len(pcb['components']):
self.logger.error("Length of components list doesn't match"
" length of footprints list.")
return False
return True
@staticmethod
def _texts(pcbdata):
for layer in pcbdata['drawings'].values():
for side in layer.values():
for dwg in side:
if 'text' in dwg:
yield dwg
@staticmethod
def _remove_control_codes(s):
import unicodedata
return ''.join(c for c in s if unicodedata.category(c)[0] != "C")
def _parse_font_data(self, pcbdata):
font_parser = FontParser()
for dwg in self._texts(pcbdata):
if 'svgpath' not in dwg:
dwg['text'] = self._remove_control_codes(dwg['text'])
font_parser.parse_font_for_string(dwg['text'])
if font_parser.get_parsed_font():
pcbdata['font_data'] = font_parser.get_parsed_font()
def _check_font_data(self, pcbdata):
mc = set()
for dwg in self._texts(pcbdata):
dwg['text'] = self._remove_control_codes(dwg['text'])
mc.update({c for c in dwg['text'] if 'svgpath' not in dwg and
c not in pcbdata['font_data']})
if mc:
s = ''.join(mc)
self.logger.error('Provided font_data is missing character(s)'
f' "{s}" that are present in text drawing'
' objects')
return False
else:
return True
def _parse(self):
try:
pcb = self.get_generic_json_pcb()
except ValidationError as e:
self.logger.error('File {f} does not comply with json schema. {m}'
.format(f=self.file_name, m=e.message))
return None, None
if not self._verify(pcb):
self.logger.error('File {} does not appear to be valid generic'
' InteractiveHtmlBom json file.'
.format(self.file_name))
return None, None
pcbdata = pcb['pcbdata']
components = [Component(**c) for c in pcb['components']]
if 'font_data' in pcbdata:
if not self._check_font_data(pcbdata):
raise ParsingException(f'Failed parsing {self.file_name}')
else:
self._parse_font_data(pcbdata)
if 'font_data' in pcbdata:
self.logger.info('No font_data provided in JSON, using '
'newstroke font')
self.logger.info('Successfully parsed {}'.format(self.file_name))
return pcbdata, components
def parse(self):
pcbdata, components = self._parse()
# override board bounding box based on edges
board_outline_bbox = BoundingBox()
for drawing in pcbdata['edges']:
self.add_drawing_bounding_box(drawing, board_outline_bbox)
if board_outline_bbox.initialized():
pcbdata['edges_bbox'] = board_outline_bbox.to_dict()
extra_fields = set(self.config.show_fields)
extra_fields.discard("Footprint")
extra_fields.discard("Value")
if self.config.dnp_field:
extra_fields.add(self.config.dnp_field)
if self.config.board_variant_field:
extra_fields.add(self.config.board_variant_field)
if extra_fields:
for c in components:
c.extra_fields = {
f: c.extra_fields.get(f, "") for f in extra_fields}
self.config.kicad_text_formatting = False
return pcbdata, components