Make kicad eat schematics written by gerbonara

This commit is contained in:
jaseg 2023-07-18 21:54:26 +02:00
parent 58142cb0c7
commit a1b8cbf861
3 changed files with 32 additions and 16 deletions

View file

@ -34,7 +34,7 @@ class SheetPath:
@sexp_type('junction')
class Junction:
at: AtPos = field(default_factory=AtPos)
at: Rename(XYCoord) = field(default_factory=XYCoord)
diameter: Named(float) = 0
color: Color = field(default_factory=lambda: Color(0, 0, 0, 0))
uuid: UUID = field(default_factory=UUID)
@ -42,7 +42,7 @@ class Junction:
@sexp_type('no_connect')
class NoConnect:
at: AtPos = field(default_factory=AtPos)
at: Rename(XYCoord) = field(default_factory=XYCoord)
uuid: UUID = field(default_factory=UUID)
@ -191,36 +191,41 @@ class SubsheetPin:
uuid: UUID = field(default_factory=UUID)
@sexp_type('fill')
class SubsheetFill:
color: Color = field(default_factory=lambda: Color(0, 0, 0, 0))
@sexp_type('sheet')
class Subsheet:
at: AtPos = field(default_factory=AtPos)
at: Rename(XYCoord) = field(default_factory=XYCoord)
size: Rename(XYCoord) = field(default_factory=lambda: XYCoord(2.54, 2.54))
fields_autoplaced: Wrap(Flag()) = True
stroke: Stroke = field(default_factory=Stroke)
fill: gr.FillMode = field(default_factory=gr.FillMode)
fill: SubsheetFill = field(default_factory=SubsheetFill)
uuid: UUID = field(default_factory=UUID)
_properties: List(DrawnProperty) = field(default_factory=list)
pins: List(SubsheetPin) = field(default_factory=list)
# AFAICT this is completely redundant, just like the one in SymbolInstance
instances: Named(List(SubsheetCrosslinkProject)) = field(default_factory=list)
_: KW_ONLY
_ : SEXP_END = None
sheet_name: object = field(default_factory=lambda: DrawnProperty('Sheetname', ''))
file_name: object = field(default_factory=lambda: DrawnProperty('Sheetfile', ''))
parent: object = None
schematic: object = None
def __after_parse__(self, parent):
self.sheet_name, self.file_name = self._properties
self.parent = parent
self.schematic = parent
def __before_sexp__(self):
self._properties = [self.sheet_name, self.file_name]
def open(self, search_dir=None, safe=True):
if search_dir is None:
if not self.parent.original_filename:
if not self.schematic.original_filename:
raise FileNotFoundError('No search path given and path of parent schematic unknown')
else:
search_dir = Path(self.parent.original_filename).parent
search_dir = Path(self.schematic.original_filename).parent
else:
search_dir = Path(search_dir)
@ -231,15 +236,21 @@ class Subsheet:
return Schematic.open(resolved)
SUPPORTED_FILE_FORMAT_VERSIONS = [20220914]
@sexp_type('lib_symbols')
class LocalLibrary:
symbols: List(Symbol) = field(default_factory=list)
SUPPORTED_FILE_FORMAT_VERSIONS = [20230620]
@sexp_type('kicad_sch')
class Schematic:
_version: Named(int, name='version') = 20211014
_version: Named(int, name='version') = 20230620
generator: Named(Atom) = Atom.gerbonara
uuid: UUID = field(default_factory=UUID)
page_settings: PageSettings = field(default_factory=PageSettings)
path: SheetPath = field(default_factory=SheetPath)
lib_symbols: Named(Array(Symbol)) = field(default_factory=list)
# The doc says this is expected, but eeschema barfs when it's there.
# path: SheetPath = field(default_factory=SheetPath)
lib_symbols: LocalLibrary = field(default_factory=list)
junctions: List(Junction) = field(default_factory=list)
no_connects: List(NoConnect) = field(default_factory=list)
bus_entries: List(BusEntry) = field(default_factory=list)
@ -291,3 +302,5 @@ if __name__ == '__main__':
subsh = subsh.open()
print('Loaded sub-sheet with', len(subsh.wires), 'wires and', len(subsh.symbols), 'symbols.')
sch.write('/tmp/test.kicad_sch')

View file

@ -62,7 +62,7 @@ def sexp(t, v):
t, = t
return [sexp(t, elem) for elem in v]
else:
raise TypeError(f'Python type {t} has no defined s-expression serialization')
raise TypeError(f'Python type {t} of value {v!r} has no defined s-expression serialization')
except MappingError as e:
raise e

View file

@ -247,7 +247,7 @@ class Unit:
if not (m := re.fullmatch(r'(.*)_([0-9]+)_([0-9]+)', self.name)):
raise FormatError(f'Invalid unit name "{self.name}"')
sym_name, unit_index, demorgan_style = m.groups()
if sym_name != self.symbol.name:
if sym_name != self.symbol.raw_name.rpartition(':')[2]:
raise FormatError(f'Unit name "{self.name}" does not match symbol name "{self.symbol.name}"')
self.demorgan_style = int(demorgan_style)
self.unit_index = int(unit_index)
@ -271,7 +271,7 @@ class Unit:
@sexp_type('symbol')
class Symbol:
name: str = None
raw_name: str = None
extends: Named(str) = None
power: Wrap(Flag()) = False
pin_numbers: OmitDefault(PinNumberSpec) = field(default_factory=PinNumberSpec)
@ -284,10 +284,13 @@ class Symbol:
styles: {str: {str: Unit}} = None
global_units: {str: {str: Unit}} = None
library = None
name: str = None
library_name: str = None
def __after_parse__(self, parent):
self.library = parent
self.library_name, _, self.name = self.raw_name.rpartition(':')
self.global_units = {}
self.styles = {}