diff options
Diffstat (limited to 'gerbonara/cad/kicad/sexp_mapper.py')
-rw-r--r-- | gerbonara/cad/kicad/sexp_mapper.py | 79 |
1 files changed, 49 insertions, 30 deletions
diff --git a/gerbonara/cad/kicad/sexp_mapper.py b/gerbonara/cad/kicad/sexp_mapper.py index 0f52340..ca000c3 100644 --- a/gerbonara/cad/kicad/sexp_mapper.py +++ b/gerbonara/cad/kicad/sexp_mapper.py @@ -1,4 +1,6 @@ +import textwrap + from dataclasses import MISSING from .sexp import * @@ -48,39 +50,58 @@ class Flag: def sexp(t, v): - if v is None: - return [] - elif t in (int, float, str, Atom): - return [t(v)] - elif hasattr(t, '__sexp__'): - return list(t.__sexp__(v)) - elif isinstance(t, list): - t, = t - return [sexp(t, elem) for elem in v] - else: - raise TypeError(f'Python type {t} has no defined s-expression serialization') + try: + if v is None: + return [] + elif t in (int, float, str, Atom): + return [t(v)] + elif hasattr(t, '__sexp__'): + return list(t.__sexp__(v)) + elif isinstance(t, list): + t, = t + return [sexp(t, elem) for elem in v] + else: + raise TypeError(f'Python type {t} has no defined s-expression serialization') + + except MappingError as e: + raise e + + except Exception as e: + raise MappingError(f'Error trying to serialize {textwrap.shorten(str(v), width=120)} into type {t}', t, v) from e + +class MappingError(TypeError): + def __init__(self, msg, t, sexp): + super().__init__(msg) + self.t, self.sexp = t, sexp def map_sexp(t, v, parent=None): - if t is not Atom and hasattr(t, '__map__'): - return t.__map__(v, parent=parent) - - elif t in (int, float, str, Atom): - v, = v - if not isinstance(v, t): - types = set({type(v), t}) - if types == {int, float} or types == {str, Atom}: - v = t(v) - else: - raise TypeError(f'Cannot map s-expression value {v} of type {type(v)} to Python type {t}') - return v + try: + if t is not Atom and hasattr(t, '__map__'): + return t.__map__(v, parent=parent) + + elif t in (int, float, str, Atom): + v, = v + if not isinstance(v, t): + types = set({type(v), t}) + if types == {int, float} or types == {str, Atom}: + v = t(v) + else: + raise TypeError(f'Cannot map s-expression value {v} of type {type(v)} to Python type {t}') + return v + + elif isinstance(t, list): + t, = t + return [map_sexp(t, elem, parent=parent) for elem in v] + + else: + raise TypeError(f'Python type {t} has no defined s-expression deserialization') - elif isinstance(t, list): - t, = t - return [map_sexp(t, elem, parent=parent) for elem in v] + except MappingError as e: + raise e - else: - raise TypeError(f'Python type {t} has no defined s-expression deserialization') + except Exception as e: + raise MappingError(f'Error trying to map {textwrap.shorten(str(v), width=120)} into type {t}', t, v) from e class WrapperType: @@ -301,8 +322,6 @@ def sexp_type(name=None): return register - - class List(WrapperType): def __bind_field__(self, field): self.attr = field.name |