From 08c4091e57d59b6a08cb0e4f4d684ec7967019fc Mon Sep 17 00:00:00 2001 From: jaseg Date: Mon, 17 Jul 2023 23:23:19 +0200 Subject: kicad: Improve API and fix kicad-nightly compat --- gerbonara/cad/kicad/sexp_mapper.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'gerbonara/cad/kicad/sexp_mapper.py') diff --git a/gerbonara/cad/kicad/sexp_mapper.py b/gerbonara/cad/kicad/sexp_mapper.py index ca000c3..c6e7464 100644 --- a/gerbonara/cad/kicad/sexp_mapper.py +++ b/gerbonara/cad/kicad/sexp_mapper.py @@ -1,7 +1,8 @@ import textwrap -from dataclasses import MISSING +import copy +from dataclasses import MISSING, replace, fields from .sexp import * @@ -121,9 +122,10 @@ class WrapperType: return getattr(self.next_type, '__atoms__', lambda: [])() class Named(WrapperType): - def __init__(self, next_type, name=None): + def __init__(self, next_type, name=None, omit_empty=True): super().__init__(next_type) self.name_atom = Atom(name) if name else None + self.omit_empty = omit_empty def __bind_field__(self, field): if self.next_type is not Atom: @@ -140,8 +142,13 @@ class Named(WrapperType): def __sexp__(self, value): value = sexp(self.next_type, value) - if value is not None: - yield [self.name_atom, *value] + if value is None: + return + + if self.omit_empty and not value: + return + + yield [self.name_atom, *value] class Rename(WrapperType): @@ -389,6 +396,16 @@ class _SexpTemplate: def sexp(self): return next(self.__sexp__(self)) + @staticmethod + def __deepcopy__(self, memo): + return replace(self, **{f.name: copy.deepcopy(getattr(self, f.name), memo) for f in fields(self) if not f.kw_only}) + + @staticmethod + def __copy__(self): + # Even during a shallow copy, we need to deep copy any fields whose types have a __before_sexp__ method to avoid + # those from being called more than once on the same object. + return replace(self, **{f.name: copy.copy(getattr(self, f.name)) for f in fields(self) if not f.kw_only and hasattr(f.type, '__before_sexp__')}) + def sexp_type(name=None): def register(cls): @@ -398,8 +415,10 @@ def sexp_type(name=None): if not hasattr(cls, key): setattr(cls, key, classmethod(getattr(_SexpTemplate, key))) - if not hasattr(cls, 'sexp'): - setattr(cls, 'sexp', getattr(_SexpTemplate, 'sexp')) + for key in 'sexp', '__deepcopy__', '__copy__': + if not hasattr(cls, key): + setattr(cls, key, getattr(_SexpTemplate, key)) + cls.positional = [] cls.keys = {} for f in fields(cls): -- cgit