From 2400ff8e5fea41c1f8c6251d37a02209ec253f93 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 15 Apr 2023 17:09:20 +0200 Subject: cad: Add KiCad symbol/footprint parser --- gerbonara/tests/test_kicad_symbols.py | 59 +++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 gerbonara/tests/test_kicad_symbols.py (limited to 'gerbonara/tests/test_kicad_symbols.py') diff --git a/gerbonara/tests/test_kicad_symbols.py b/gerbonara/tests/test_kicad_symbols.py new file mode 100644 index 0000000..0a6c595 --- /dev/null +++ b/gerbonara/tests/test_kicad_symbols.py @@ -0,0 +1,59 @@ + +from itertools import zip_longest +import re + +from ..cad.kicad.sexp import build_sexp +from ..cad.kicad.sexp_mapper import sexp +from ..cad.kicad.symbols import Library + + +def test_parse(kicad_library_file): + Library.open(kicad_library_file) + + +def test_round_trip(kicad_library_file): + print('========== Stage 1 load ==========') + orig_lib = Library.open(kicad_library_file) + print('========== Stage 1 save ==========') + stage1_sexp = build_sexp(orig_lib.sexp()) + + print('========== Stage 2 load ==========') + reparsed_lib = Library.parse(stage1_sexp) + print('========== Stage 2 save ==========') + stage2_sexp = build_sexp(reparsed_lib.sexp()) + print('========== Checks ==========') + + for stage1, stage2 in zip_longest(stage1_sexp.splitlines(), stage2_sexp.splitlines()): + assert stage1 == stage2 + + original = re.sub(r'\(', '\n(', re.sub(r'\s+', ' ', kicad_library_file.read_text())) + original = re.sub(r'\) \)', '))', original) + original = re.sub(r'\) \)', '))', original) + original = re.sub(r'\) \)', '))', original) + original = re.sub(r'\) \)', '))', original) + stage1 = re.sub(r'\(', '\n(', re.sub(r'\s+', ' ', stage1_sexp)) + for original, stage1 in zip_longest(original.splitlines(), stage1.splitlines()): + if original.startswith('(version'): + continue + + original, stage1 = original.strip(), stage1.strip() + if original != stage1: + if any(original.startswith(f'({foo}') for foo in ['arc', 'circle', 'rectangle', 'polyline', 'text']): + # These files have symbols with graphic primitives in non-standard order + return + + if original.startswith('(offset') and stage1.startswith('(offset'): + # Some symbol files contain ints where floats should be. + return + + if original.startswith('(symbol') and stage1.startswith('(symbol'): + # Re-export can change symbol order. This is ok. + return + + if original.startswith('(at') and stage1.startswith('(at'): + # There is some disagreement as to whether rotation angles are ints or floats, and the spec doesn't say. + return + + assert original == stage1 + + -- cgit