From 125eb821b9f5d4c58b17d43e318e9a6829120d03 Mon Sep 17 00:00:00 2001 From: jaseg Date: Mon, 8 Nov 2021 13:06:23 +0100 Subject: Parser half-refactored --- .../gerber/tests/panelize/data/ref_gerber_inch.gtl | 1 - .../tests/panelize/data/ref_gerber_metric.gtl | 1 - .../panelize/data/ref_gerber_single_quadrant.gtl | 40 --- .../tests/panelize/expects/RS2724x_offset.gtl | 1 - .../tests/panelize/expects/RS2724x_rotate.gtl | 1 - .../gerber/tests/panelize/expects/RS2724x_save.gtl | 1 - .../panelize/expects/RS2724x_single_quadrant.gtl | 35 -- .../tests/panelize/expects/RS2724x_to_inch.gtl | 1 - .../tests/panelize/expects/RS2724x_to_metric.gtl | 1 - .../gerber/tests/panelize/test_am_expression.py | 13 - gerbonara/gerber/tests/panelize/test_rs274x.py | 5 - gerbonara/gerber/tests/test_am_statements.py | 395 --------------------- gerbonara/gerber/tests/test_cairo_backend.py | 382 -------------------- gerbonara/gerber/tests/test_gerber_statements.py | 64 +--- 14 files changed, 4 insertions(+), 937 deletions(-) delete mode 100644 gerbonara/gerber/tests/panelize/data/ref_gerber_single_quadrant.gtl delete mode 100644 gerbonara/gerber/tests/panelize/expects/RS2724x_single_quadrant.gtl delete mode 100644 gerbonara/gerber/tests/test_am_statements.py delete mode 100644 gerbonara/gerber/tests/test_cairo_backend.py (limited to 'gerbonara/gerber/tests') diff --git a/gerbonara/gerber/tests/panelize/data/ref_gerber_inch.gtl b/gerbonara/gerber/tests/panelize/data/ref_gerber_inch.gtl index 3ec60d8..f71c948 100644 --- a/gerbonara/gerber/tests/panelize/data/ref_gerber_inch.gtl +++ b/gerbonara/gerber/tests/panelize/data/ref_gerber_inch.gtl @@ -8,7 +8,6 @@ 1,1,0.015748,-0.0472441,0,$1* 4,1,4,0.0472441,0,0.0551181,-0.00787402,0.0472441,-0.015748,0.0393701,-0.00787402,0.0472441,0,$1* 5,1,6,0.0472441,0.00787402,0.015748,$1* -6,-0.0275591,0,0.019685,0.0019685,0.00590551,2,0.0019685,0.023622,$1* 7,0.0275591,0,0.023622,0.019685,0.00590551,$1*% %ADD10C,0.0003937*% %ADD11C,0.03937X0.01575*% diff --git a/gerbonara/gerber/tests/panelize/data/ref_gerber_metric.gtl b/gerbonara/gerber/tests/panelize/data/ref_gerber_metric.gtl index 8dfbdd4..98833de 100644 --- a/gerbonara/gerber/tests/panelize/data/ref_gerber_metric.gtl +++ b/gerbonara/gerber/tests/panelize/data/ref_gerber_metric.gtl @@ -8,7 +8,6 @@ 1,1,0.4,-1.2,0,$1* 4,1,4,1.2,0,1.4,-0.2,1.2,-0.4,1,-0.2,1.2,0,$1* 5,1,6,1.2,0.2,0.4,$1* -6,-0.7,0,0.5,0.05,0.15,2,0.05,0.6,$1* 7,0.7,0,0.6,0.5,0.15,$1*% %ADD10C,0.01*% %ADD11C,1X0.4*% diff --git a/gerbonara/gerber/tests/panelize/data/ref_gerber_single_quadrant.gtl b/gerbonara/gerber/tests/panelize/data/ref_gerber_single_quadrant.gtl deleted file mode 100644 index f31f1e7..0000000 --- a/gerbonara/gerber/tests/panelize/data/ref_gerber_single_quadrant.gtl +++ /dev/null @@ -1,40 +0,0 @@ -%MOMM*% -%FSLAX34Y34*% -%IPPOS*% -%ADD10C,0.1*% -G74* -%LPD*% - -D10* - -G36* -G01* -X0Y10000D02* -Y90000D01* -G02* -X10000Y100000I10000* -X20000Y90000J10000* -G01* -Y20000* -X40000* -G02* -X50000Y10000J10000* -X40000Y0I10000* -G01* -X10000* -G02* -X0Y10000J10000* -G37* - -G03* -X70000Y50000D02* -X60000Y60000I10000D01* -X50000Y50000J10000* -X60000Y40000I10000* -X70000Y50000J10000* - -G02* -X60000Y90000D02* -X60000Y90000I10000D01* - -M02* diff --git a/gerbonara/gerber/tests/panelize/expects/RS2724x_offset.gtl b/gerbonara/gerber/tests/panelize/expects/RS2724x_offset.gtl index 3dc3e6a..0bebd07 100644 --- a/gerbonara/gerber/tests/panelize/expects/RS2724x_offset.gtl +++ b/gerbonara/gerber/tests/panelize/expects/RS2724x_offset.gtl @@ -7,7 +7,6 @@ 1,1,0.4,-1.2,0,$1* 4,1,4,1.2,0,1.4,-0.2,1.2,-0.4,1,-0.2,1.2,0,$1* 5,1,6,1.2,0.2,0.4,$1* -6,-0.7,0,0.5,0.05,0.15,2,0.05,0.6,$1* 7,0.7,0,0.6,0.5,0.15,$1*% %ADD10C,0.01*% %ADD11C,1X0.4*% diff --git a/gerbonara/gerber/tests/panelize/expects/RS2724x_rotate.gtl b/gerbonara/gerber/tests/panelize/expects/RS2724x_rotate.gtl index f7c82cd..00335b8 100644 --- a/gerbonara/gerber/tests/panelize/expects/RS2724x_rotate.gtl +++ b/gerbonara/gerber/tests/panelize/expects/RS2724x_rotate.gtl @@ -7,7 +7,6 @@ 1,1,0.4,-1.2,0,($1)+(20)* 4,1,4,1.2,0,1.4,-0.2,1.2,-0.4,1,-0.2,1.2,0,($1)+(20)* 5,1,6,1.2,0.2,0.4,($1)+(20)* -6,-0.7,0,0.5,0.05,0.15,2,0.05,0.6,($1)+(20)* 7,0.7,0,0.6,0.5,0.15,($1)+(20)*% %AMMACR* 21,1,$1,$2,0,0,20* diff --git a/gerbonara/gerber/tests/panelize/expects/RS2724x_save.gtl b/gerbonara/gerber/tests/panelize/expects/RS2724x_save.gtl index 5053d99..b4fe9e1 100644 --- a/gerbonara/gerber/tests/panelize/expects/RS2724x_save.gtl +++ b/gerbonara/gerber/tests/panelize/expects/RS2724x_save.gtl @@ -7,7 +7,6 @@ 1,1,0.4,-1.2,0,$1* 4,1,4,1.2,0,1.4,-0.2,1.2,-0.4,1,-0.2,1.2,0,$1* 5,1,6,1.2,0.2,0.4,$1* -6,-0.7,0,0.5,0.05,0.15,2,0.05,0.6,$1* 7,0.7,0,0.6,0.5,0.15,$1*% %ADD10C,0.01*% %ADD11C,1X0.4*% diff --git a/gerbonara/gerber/tests/panelize/expects/RS2724x_single_quadrant.gtl b/gerbonara/gerber/tests/panelize/expects/RS2724x_single_quadrant.gtl deleted file mode 100644 index dbec705..0000000 --- a/gerbonara/gerber/tests/panelize/expects/RS2724x_single_quadrant.gtl +++ /dev/null @@ -1,35 +0,0 @@ -%MOMM*% -%FSLAX34Y34*% -%IPPOS*% -%ADD10C,0.1*% -G75* -%LPD*% -D10* -G36* -G01* -X0Y10000D02* -X0Y90000D01* -G02* -X10000Y100000I10000J0D01* -X20000Y90000I0J-10000D01* -G01* -X20000Y20000D01* -X40000Y20000D01* -G02* -X50000Y10000I0J-10000D01* -X40000Y0I-10000J0D01* -G01* -X10000Y0D01* -G02* -X0Y10000I0J10000D01* -G37* -G03* -X70000Y50000D02* -X60000Y60000I-10000J0D01* -X50000Y50000I0J-10000D01* -X60000Y40000I10000J0D01* -X70000Y50000I0J10000D01* -G02* -X60000Y90000D02* -X60000Y90000I0J0D01* -M02* diff --git a/gerbonara/gerber/tests/panelize/expects/RS2724x_to_inch.gtl b/gerbonara/gerber/tests/panelize/expects/RS2724x_to_inch.gtl index cb9234e..ed23a58 100644 --- a/gerbonara/gerber/tests/panelize/expects/RS2724x_to_inch.gtl +++ b/gerbonara/gerber/tests/panelize/expects/RS2724x_to_inch.gtl @@ -7,7 +7,6 @@ 1,1,0.015748,-0.0472441,0,$1* 4,1,4,0.0472441,0,0.0551181,-0.00787402,0.0472441,-0.015748,0.0393701,-0.00787402,0.0472441,0,$1* 5,1,6,0.0472441,0.00787402,0.015748,$1* -6,-0.0275591,0,0.019685,0.0019685,0.00590551,2,0.0019685,0.023622,$1* 7,0.0275591,0,0.023622,0.019685,0.00590551,$1*% %ADD10C,0.0003937*% %ADD11C,0.03937X0.01575*% diff --git a/gerbonara/gerber/tests/panelize/expects/RS2724x_to_metric.gtl b/gerbonara/gerber/tests/panelize/expects/RS2724x_to_metric.gtl index a8efda8..2a4df41 100644 --- a/gerbonara/gerber/tests/panelize/expects/RS2724x_to_metric.gtl +++ b/gerbonara/gerber/tests/panelize/expects/RS2724x_to_metric.gtl @@ -7,7 +7,6 @@ 1,1,0.399999,-1.2,0,$1* 4,1,4,1.2,0,1.4,-0.2,1.2,-0.399999,1,-0.2,1.2,0,$1* 5,1,6,1.2,0.2,0.399999,$1* -6,-0.700001,0,0.499999,0.0499999,0.15,2,0.0499999,0.599999,$1* 7,0.700001,0,0.599999,0.499999,0.15,$1*% %ADD10C,0.01*% %ADD11C,1X0.4*% diff --git a/gerbonara/gerber/tests/panelize/test_am_expression.py b/gerbonara/gerber/tests/panelize/test_am_expression.py index 45758b7..576be88 100644 --- a/gerbonara/gerber/tests/panelize/test_am_expression.py +++ b/gerbonara/gerber/tests/panelize/test_am_expression.py @@ -30,10 +30,6 @@ class TestAMConstantExpression(unittest.TestCase): self.assertEqual(self.const_int.to_gerber(), '7') self.assertEqual(self.const_float.to_gerber(), '1.2345') - def test_to_instructions(self): - self.const_int.to_instructions() - self.const_float.to_instructions() - class TestAMVariableExpression(unittest.TestCase): def setUp(self): self.var1_num = 1 @@ -57,10 +53,6 @@ class TestAMVariableExpression(unittest.TestCase): self.assertEqual(self.var1.to_gerber(), '$1') self.assertEqual(self.var2.to_gerber(), '$512') - def test_to_instructions(self): - self.var1.to_instructions() - self.var2.to_instructions() - class TestAMOperatorExpression(unittest.TestCase): def setUp(self): self.c1 = 10 @@ -132,11 +124,6 @@ class TestAMOperatorExpression(unittest.TestCase): self.c1, self.c2, self.c1, self.c2 )) - def test_to_instructions(self): - for of, expression in self.vc_exps + self.cv_exps + self.cc_exps: - expression.to_instructions() - self.composition.to_instructions() - class TestAMExpression(unittest.TestCase): def setUp(self): self.c1 = 10 diff --git a/gerbonara/gerber/tests/panelize/test_rs274x.py b/gerbonara/gerber/tests/panelize/test_rs274x.py index 067717d..73f3172 100644 --- a/gerbonara/gerber/tests/panelize/test_rs274x.py +++ b/gerbonara/gerber/tests/panelize/test_rs274x.py @@ -68,8 +68,3 @@ class TestRs274x(unittest.TestCase): gerber.rotate(20, (10,10)) gerber.write(outfile) - def test_single_quadrant(self): - with self._check_result('RS2724x_single_quadrant.gtl') as outfile: - gerber = read(self.SQ_FILE) - gerber.write(outfile) - diff --git a/gerbonara/gerber/tests/test_am_statements.py b/gerbonara/gerber/tests/test_am_statements.py deleted file mode 100644 index 0d100b5..0000000 --- a/gerbonara/gerber/tests/test_am_statements.py +++ /dev/null @@ -1,395 +0,0 @@ -#! /usr/bin/env python -# -*- coding: utf-8 -*- - -# Author: Hamilton Kibbe - -import pytest - -from ..am_statements import * -from ..am_statements import inch, metric - - -def test_AMPrimitive_ctor(): - for exposure in ("on", "off", "ON", "OFF"): - for code in (0, 1, 2, 4, 5, 6, 7, 20, 21, 22): - p = AMPrimitive(code, exposure) - assert p.code == code - assert p.exposure == exposure.lower() - - -def test_AMPrimitive_validation(): - pytest.raises(TypeError, AMPrimitive, "1", "off") - pytest.raises(ValueError, AMPrimitive, 0, "exposed") - pytest.raises(ValueError, AMPrimitive, 3, "off") - - -def test_AMPrimitive_conversion(): - p = AMPrimitive(4, "on") - pytest.raises(NotImplementedError, p.to_inch) - pytest.raises(NotImplementedError, p.to_metric) - - -def test_AMCommentPrimitive_ctor(): - c = AMCommentPrimitive(0, " This is a comment *") - assert c.code == 0 - assert c.comment == "This is a comment" - - -def test_AMCommentPrimitive_validation(): - pytest.raises(ValueError, AMCommentPrimitive, 1, "This is a comment") - - -def test_AMCommentPrimitive_factory(): - c = AMCommentPrimitive.from_gerber("0 Rectangle with rounded corners. *") - assert c.code == 0 - assert c.comment == "Rectangle with rounded corners." - - -def test_AMCommentPrimitive_dump(): - c = AMCommentPrimitive(0, "Rectangle with rounded corners.") - assert c.to_gerber() == "0 Rectangle with rounded corners. *" - - -def test_AMCommentPrimitive_conversion(): - c = AMCommentPrimitive(0, "Rectangle with rounded corners.") - ci = c - cm = c - ci.to_inch() - cm.to_metric() - assert c == ci - assert c == cm - - -def test_AMCommentPrimitive_string(): - c = AMCommentPrimitive(0, "Test Comment") - assert str(c) == "" - - -def test_AMCirclePrimitive_ctor(): - test_cases = ( - (1, "on", 0, (0, 0)), - (1, "off", 1, (0, 1)), - (1, "on", 2.5, (0, 2)), - (1, "off", 5.0, (3, 3)), - ) - for code, exposure, diameter, position in test_cases: - c = AMCirclePrimitive(code, exposure, diameter, position) - assert c.code == code - assert c.exposure == exposure - assert c.diameter == diameter - assert c.position == position - - -def test_AMCirclePrimitive_validation(): - pytest.raises(ValueError, AMCirclePrimitive, 2, "on", 0, (0, 0)) - - -def test_AMCirclePrimitive_factory(): - c = AMCirclePrimitive.from_gerber("1,0,5,0,0*") - assert c.code == 1 - assert c.exposure == "off" - assert c.diameter == 5 - assert c.position == (0, 0) - - -def test_AMCirclePrimitive_dump(): - c = AMCirclePrimitive(1, "off", 5, (0, 0)) - assert c.to_gerber() == "1,0,5,0,0*" - c = AMCirclePrimitive(1, "on", 5, (0, 0)) - assert c.to_gerber() == "1,1,5,0,0*" - - -def test_AMCirclePrimitive_conversion(): - c = AMCirclePrimitive(1, "off", 25.4, (25.4, 0)) - c.to_inch() - assert c.diameter == 1 - assert c.position == (1, 0) - - c = AMCirclePrimitive(1, "off", 1, (1, 0)) - c.to_metric() - assert c.diameter == 25.4 - assert c.position == (25.4, 0) - - -def test_AMVectorLinePrimitive_validation(): - pytest.raises( - ValueError, AMVectorLinePrimitive, 3, "on", 0.1, (0, 0), (3.3, 5.4), 0 - ) - - -def test_AMVectorLinePrimitive_factory(): - l = AMVectorLinePrimitive.from_gerber("20,1,0.9,0,0.45,12,0.45,0*") - assert l.code == 20 - assert l.exposure == "on" - assert l.width == 0.9 - assert l.start == (0, 0.45) - assert l.end == (12, 0.45) - assert l.rotation == 0 - - -def test_AMVectorLinePrimitive_dump(): - l = AMVectorLinePrimitive.from_gerber("20,1,0.9,0,0.45,12,0.45,0*") - assert l.to_gerber() == "20,1,0.9,0.0,0.45,12.0,0.45,0.0*" - - -def test_AMVectorLinePrimtive_conversion(): - l = AMVectorLinePrimitive(20, "on", 25.4, (0, 0), (25.4, 25.4), 0) - l.to_inch() - assert l.width == 1 - assert l.start == (0, 0) - assert l.end == (1, 1) - - l = AMVectorLinePrimitive(20, "on", 1, (0, 0), (1, 1), 0) - l.to_metric() - assert l.width == 25.4 - assert l.start == (0, 0) - assert l.end == (25.4, 25.4) - - -def test_AMOutlinePrimitive_validation(): - pytest.raises( - ValueError, - AMOutlinePrimitive, - 7, - "on", - (0, 0), - [(3.3, 5.4), (4.0, 5.4), (0, 0)], - 0, - ) - pytest.raises( - ValueError, - AMOutlinePrimitive, - 4, - "on", - (0, 0), - [(3.3, 5.4), (4.0, 5.4), (0, 1)], - 0, - ) - - -def test_AMOutlinePrimitive_factory(): - o = AMOutlinePrimitive.from_gerber("4,1,3,0,0,3,3,3,0,0,0,0*") - assert o.code == 4 - assert o.exposure == "on" - assert o.start_point == (0, 0) - assert o.points == [(3, 3), (3, 0), (0, 0)] - assert o.rotation == 0 - - -def test_AMOUtlinePrimitive_dump(): - o = AMOutlinePrimitive(4, "on", (0, 0), [(3, 3), (3, 0), (0, 0)], 0) - # New lines don't matter for Gerber, but we insert them to make it easier to remove - # For test purposes we can ignore them - assert o.to_gerber().replace("\n", "") == "4,1,3,0,0,3,3,3,0,0,0,0*" - - -def test_AMOutlinePrimitive_conversion(): - o = AMOutlinePrimitive(4, "on", (0, 0), [(25.4, 25.4), (25.4, 0), (0, 0)], 0) - o.to_inch() - assert o.start_point == (0, 0) - assert o.points == ((1.0, 1.0), (1.0, 0.0), (0.0, 0.0)) - - o = AMOutlinePrimitive(4, "on", (0, 0), [(1, 1), (1, 0), (0, 0)], 0) - o.to_metric() - assert o.start_point == (0, 0) - assert o.points == ((25.4, 25.4), (25.4, 0), (0, 0)) - - -def test_AMPolygonPrimitive_validation(): - pytest.raises(ValueError, AMPolygonPrimitive, 6, "on", 3, (3.3, 5.4), 3, 0) - pytest.raises(ValueError, AMPolygonPrimitive, 5, "on", 2, (3.3, 5.4), 3, 0) - pytest.raises(ValueError, AMPolygonPrimitive, 5, "on", 13, (3.3, 5.4), 3, 0) - - -def test_AMPolygonPrimitive_factory(): - p = AMPolygonPrimitive.from_gerber("5,1,3,3.3,5.4,3,0") - assert p.code == 5 - assert p.exposure == "on" - assert p.vertices == 3 - assert p.position == (3.3, 5.4) - assert p.diameter == 3 - assert p.rotation == 0 - - -def test_AMPolygonPrimitive_dump(): - p = AMPolygonPrimitive(5, "on", 3, (3.3, 5.4), 3, 0) - assert p.to_gerber() == "5,1,3,3.3,5.4,3,0*" - - -def test_AMPolygonPrimitive_conversion(): - p = AMPolygonPrimitive(5, "off", 3, (25.4, 0), 25.4, 0) - p.to_inch() - assert p.diameter == 1 - assert p.position == (1, 0) - - p = AMPolygonPrimitive(5, "off", 3, (1, 0), 1, 0) - p.to_metric() - assert p.diameter == 25.4 - assert p.position == (25.4, 0) - - -def test_AMMoirePrimitive_validation(): - pytest.raises( - ValueError, AMMoirePrimitive, 7, (0, 0), 5.1, 0.2, 0.4, 6, 0.1, 6.1, 0 - ) - - -def test_AMMoirePrimitive_factory(): - m = AMMoirePrimitive.from_gerber("6,0,0,5,0.5,0.5,2,0.1,6,0*") - assert m.code == 6 - assert m.position == (0, 0) - assert m.diameter == 5 - assert m.ring_thickness == 0.5 - assert m.gap == 0.5 - assert m.max_rings == 2 - assert m.crosshair_thickness == 0.1 - assert m.crosshair_length == 6 - assert m.rotation == 0 - - -def test_AMMoirePrimitive_dump(): - m = AMMoirePrimitive.from_gerber("6,0,0,5,0.5,0.5,2,0.1,6,0*") - assert m.to_gerber() == "6,0,0,5.0,0.5,0.5,2,0.1,6.0,0.0*" - - -def test_AMMoirePrimitive_conversion(): - m = AMMoirePrimitive(6, (25.4, 25.4), 25.4, 25.4, 25.4, 6, 25.4, 25.4, 0) - m.to_inch() - assert m.position == (1.0, 1.0) - assert m.diameter == 1.0 - assert m.ring_thickness == 1.0 - assert m.gap == 1.0 - assert m.crosshair_thickness == 1.0 - assert m.crosshair_length == 1.0 - - m = AMMoirePrimitive(6, (1, 1), 1, 1, 1, 6, 1, 1, 0) - m.to_metric() - assert m.position == (25.4, 25.4) - assert m.diameter == 25.4 - assert m.ring_thickness == 25.4 - assert m.gap == 25.4 - assert m.crosshair_thickness == 25.4 - assert m.crosshair_length == 25.4 - - -def test_AMThermalPrimitive_validation(): - pytest.raises(ValueError, AMThermalPrimitive, 8, (0.0, 0.0), 7, 5, 0.2, 0.0) - pytest.raises(TypeError, AMThermalPrimitive, 7, (0.0, "0"), 7, 5, 0.2, 0.0) - - -def test_AMThermalPrimitive_factory(): - t = AMThermalPrimitive.from_gerber("7,0,0,7,6,0.2,45*") - assert t.code == 7 - assert t.position == (0, 0) - assert t.outer_diameter == 7 - assert t.inner_diameter == 6 - assert t.gap == 0.2 - assert t.rotation == 45 - - -def test_AMThermalPrimitive_dump(): - t = AMThermalPrimitive.from_gerber("7,0,0,7,6,0.2,30*") - assert t.to_gerber() == "7,0,0,7.0,6.0,0.2,30.0*" - - -def test_AMThermalPrimitive_conversion(): - t = AMThermalPrimitive(7, (25.4, 25.4), 25.4, 25.4, 25.4, 0.0) - t.to_inch() - assert t.position == (1.0, 1.0) - assert t.outer_diameter == 1.0 - assert t.inner_diameter == 1.0 - assert t.gap == 1.0 - - t = AMThermalPrimitive(7, (1, 1), 1, 1, 1, 0) - t.to_metric() - assert t.position == (25.4, 25.4) - assert t.outer_diameter == 25.4 - assert t.inner_diameter == 25.4 - assert t.gap == 25.4 - - -def test_AMCenterLinePrimitive_validation(): - pytest.raises(ValueError, AMCenterLinePrimitive, 22, 1, 0.2, 0.5, (0, 0), 0) - - -def test_AMCenterLinePrimtive_factory(): - l = AMCenterLinePrimitive.from_gerber("21,1,6.8,1.2,3.4,0.6,0*") - assert l.code == 21 - assert l.exposure == "on" - assert l.width == 6.8 - assert l.height == 1.2 - assert l.center == (3.4, 0.6) - assert l.rotation == 0 - - -def test_AMCenterLinePrimitive_dump(): - l = AMCenterLinePrimitive.from_gerber("21,1,6.8,1.2,3.4,0.6,0*") - assert l.to_gerber() == "21,1,6.8,1.2,3.4,0.6,0.0*" - - -def test_AMCenterLinePrimitive_conversion(): - l = AMCenterLinePrimitive(21, "on", 25.4, 25.4, (25.4, 25.4), 0) - l.to_inch() - assert l.width == 1.0 - assert l.height == 1.0 - assert l.center == (1.0, 1.0) - - l = AMCenterLinePrimitive(21, "on", 1, 1, (1, 1), 0) - l.to_metric() - assert l.width == 25.4 - assert l.height == 25.4 - assert l.center == (25.4, 25.4) - - -def test_AMLowerLeftLinePrimitive_validation(): - pytest.raises(ValueError, AMLowerLeftLinePrimitive, 23, 1, 0.2, 0.5, (0, 0), 0) - - -def test_AMLowerLeftLinePrimtive_factory(): - l = AMLowerLeftLinePrimitive.from_gerber("22,1,6.8,1.2,3.4,0.6,0*") - assert l.code == 22 - assert l.exposure == "on" - assert l.width == 6.8 - assert l.height == 1.2 - assert l.lower_left == (3.4, 0.6) - assert l.rotation == 0 - - -def test_AMLowerLeftLinePrimitive_dump(): - l = AMLowerLeftLinePrimitive.from_gerber("22,1,6.8,1.2,3.4,0.6,0*") - assert l.to_gerber() == "22,1,6.8,1.2,3.4,0.6,0.0*" - - -def test_AMLowerLeftLinePrimitive_conversion(): - l = AMLowerLeftLinePrimitive(22, "on", 25.4, 25.4, (25.4, 25.4), 0) - l.to_inch() - assert l.width == 1.0 - assert l.height == 1.0 - assert l.lower_left == (1.0, 1.0) - - l = AMLowerLeftLinePrimitive(22, "on", 1, 1, (1, 1), 0) - l.to_metric() - assert l.width == 25.4 - assert l.height == 25.4 - assert l.lower_left == (25.4, 25.4) - - -def test_AMUnsupportPrimitive(): - u = AMUnsupportPrimitive.from_gerber("Test") - assert u.primitive == "Test" - u = AMUnsupportPrimitive("Test") - assert u.to_gerber() == "Test" - - -def test_AMUnsupportPrimitive_smoketest(): - u = AMUnsupportPrimitive.from_gerber("Test") - u.to_inch() - u.to_metric() - - -def test_inch(): - assert inch(25.4) == 1 - - -def test_metric(): - assert metric(1) == 25.4 diff --git a/gerbonara/gerber/tests/test_cairo_backend.py b/gerbonara/gerber/tests/test_cairo_backend.py deleted file mode 100644 index b8c9676..0000000 --- a/gerbonara/gerber/tests/test_cairo_backend.py +++ /dev/null @@ -1,382 +0,0 @@ -#! /usr/bin/env python -# -*- coding: utf-8 -*- - -# Author: Garret Fick -import os -import shutil -import io -import tempfile -import uuid -import cv2 -from pathlib import Path - -import pytest -from PIL import Image -import numpy as np - -from ..render.cairo_backend import GerberCairoContext -from ..rs274x import read - -class Tempdir: - def __init__(self): - self.path = tempfile.mkdtemp(prefix='gerbonara-test-') - self.delete = True - - def cleanup(self): - if self.delete: - shutil.rmtree(self.path) - - def create(self, prefix='fail-', suffix=''): - return Path(self.path) / f'{prefix}{uuid.uuid4()}{suffix}' - - def keep(self): - self.delete = False - -output_dir = Tempdir() -@pytest.fixture(scope='session', autouse=True) -def cleanup(request): - global output_dir - request.addfinalizer(output_dir.cleanup) - -def test_render_two_boxes(): - """Umaco exapmle of two boxes""" - _test_render("resources/example_two_square_boxes.gbr", "golden/example_two_square_boxes.png") - - -def test_render_simple_contour(): - """Umaco exapmle of a simple arrow-shaped contour""" - gerber = _test_render("resources/example_simple_contour.gbr", "golden/example_simple_contour.png") - - # Check the resulting dimensions - assert ((2.0, 11.0), (1.0, 9.0)) == gerber.bounding_box - - -def test_render_single_contour_1(): - """Umaco example of a single contour - - The resulting image for this test is used by other tests because they must generate the same output.""" - _test_render( - "resources/example_single_contour_1.gbr", "golden/example_single_contour.png", - 0.001 # TODO: It looks like we have some aliasing artifacts here. Make sure this is not caused by an actual error. - ) - - -def test_render_single_contour_2(): - """Umaco exapmle of a single contour, alternate contour end order - - The resulting image for this test is used by other tests because they must generate the same output.""" - _test_render( - "resources/example_single_contour_2.gbr", "golden/example_single_contour.png", - 0.001 # TODO: It looks like we have some aliasing artifacts here. Make sure this is not caused by an actual error. - ) - - -def test_render_single_contour_3(): - """Umaco exapmle of a single contour with extra line""" - _test_render( - "resources/example_single_contour_3.gbr", "golden/example_single_contour_3.png", - 0.001 # TODO: It looks like we have some aliasing artifacts here. Make sure this is not caused by an actual error. - ) - - -def test_render_not_overlapping_contour(): - """Umaco example of D02 staring a second contour""" - _test_render( - "resources/example_not_overlapping_contour.gbr", - "golden/example_not_overlapping_contour.png", - ) - - -def test_render_not_overlapping_touching(): - """Umaco example of D02 staring a second contour""" - _test_render( - "resources/example_not_overlapping_touching.gbr", - "golden/example_not_overlapping_touching.png", - ) - - -def test_render_overlapping_touching(): - """Umaco example of D02 staring a second contour""" - _test_render( - "resources/example_overlapping_touching.gbr", - "golden/example_overlapping_touching.png", - ) - - -def test_render_overlapping_contour(): - """Umaco example of D02 staring a second contour""" - _test_render("resources/example_overlapping_contour.gbr", "golden/example_overlapping_contour.png") - - -def test_render_level_holes(): - """Umaco example of using multiple levels to create multiple holes""" - _test_render("resources/example_level_holes.gbr", "golden/example_level_holes.png", - autocrop_golden=True, auto_contrast=True, scale=50, max_delta=0.005) - - -def test_render_cutin(): - """Umaco example of using a cutin""" - _test_render("resources/example_cutin.gbr", "golden/example_cutin.png", - autocrop_golden=True, auto_contrast=True, max_delta=0.005) - - -def test_render_fully_coincident(): - """Umaco example of coincident lines rendering two contours""" - - _test_render( - "resources/example_fully_coincident.gbr", "golden/example_fully_coincident.png" - ) - - -def test_render_coincident_hole(): - """Umaco example of coincident lines rendering a hole in the contour""" - - _test_render( - "resources/example_coincident_hole.gbr", "golden/example_coincident_hole.png" - ) - - -def test_render_cutin_multiple(): - """Umaco example of a region with multiple cutins""" - - _test_render( - "resources/example_cutin_multiple.gbr", "golden/example_cutin_multiple.png" - ) - - -def test_flash_circle(): - """Umaco example a simple circular flash with and without a hole""" - - _test_render( - "resources/example_flash_circle.gbr", - "golden/example_flash_circle.png", - ) - - -def test_flash_rectangle(): - """Umaco example a simple rectangular flash with and without a hole""" - - _test_render( - "resources/example_flash_rectangle.gbr", "golden/example_flash_rectangle.png" - ) - - -def test_flash_obround(): - """Umaco example a simple obround flash with and without a hole""" - - _test_render( - "resources/example_flash_obround.gbr", "golden/example_flash_obround.png" - ) - - -def test_flash_polygon(): - """Umaco example a simple polygon flash with and without a hole""" - - _test_render( - "resources/example_flash_polygon.gbr", "golden/example_flash_polygon.png" - ) - - -def test_holes_dont_clear(): - """Umaco example that an aperture with a hole does not clear the area""" - - _test_render( - "resources/example_holes_dont_clear.gbr", "golden/example_holes_dont_clear.png" - ) - - -def test_render_am_exposure_modifier(): - """Umaco example that an aperture macro with a hole does not clear the area""" - - _test_render( - "resources/example_am_exposure_modifier.gbr", - "golden/example_am_exposure_modifier.png", - scale = 50, - autocrop_golden = True, - auto_contrast = True, - max_delta = 0.005 # Take artifacts due to differences in anti-aliasing and thresholding into account - ) - - -def test_render_svg_simple_contour(): - """Example of rendering to an SVG file""" - _test_simple_render_svg("resources/example_simple_contour.gbr") - - -def test_fine_lines_x(): - """ Regression test for pcb-tools upstream PR #199 """ - for fn, axis in [ - ('resources/test_fine_lines_x.gbr', 1), - ('resources/test_fine_lines_y.gbr', 0) ]: - gerber_path = _resolve_path(fn) - - gerber = read(gerber_path) - - # Create PNG image to the memory stream - ctx = GerberCairoContext(scale=51) - gerber.render(ctx) - - global output_dir - with output_dir.create(suffix='.png') as outfile: - actual_bytes = ctx.dump(outfile) - - out = Image.open(outfile) - out = np.array(out) - out = out.astype(float).mean(axis=2) / 255 - - means = out[10:-10,10:-10].mean(axis=axis) - - print(means.mean(), means.max(), means.min(), means.std()) - #print(means_y.mean(), means_y.max(), means_y.min(), means_y.std()) - # means_x broken: 0.3240598567858516 0.3443678513071895 0.2778033088235294 0.017457710324088545 - # means_x fixed: 0.33338519639882097 0.3443678513071895 0.3183159722222221 0.006792500045785638 - # means_y broken: 0.3240598567858518 0.3247468922209409 0.1660387030629246 0.009953477851147686 - # means_y fixed: 0.33338519639882114 0.3340766371908242 0.17388184031782652 0.010043400730860096 - - assert means.std() < 0.01 - -# TODO add scale tests: Export with different scale=... params and compare against bitmap-scaled reference image - -def _resolve_path(path): - return os.path.join(os.path.dirname(__file__), path) - -def images_match(reference, output, max_delta, autocrop_golden=False, auto_contrast=False): - global output_dir - - ref, out = Image.open(reference), Image.open(output) - if ref.mode == 'P': # palette mode - ref = ref.convert('RGB') - - ref, out = np.array(ref), np.array(out) - # convert to grayscale - ref, out = ref.astype(float).mean(axis=2), out.astype(float).mean(axis=2) - - if autocrop_golden: - rows = ref.sum(axis=1) - cols = ref.sum(axis=0) - - x0 = np.argmax(cols > 0) - y0 = np.argmax(rows > 0) - x1 = len(cols) - np.argmax(cols[::-1] > 0) - y1 = len(rows) - np.argmax(rows[::-1] > 0) - print(f'{x0=} {y0=} {x1=} {y1=}') - - ref = ref[y0:y1, x0:x1] - ref = cv2.resize(ref, dsize=out.shape[::-1], interpolation=cv2.INTER_LINEAR) - - def print_stats(name, ref): - print(name, 'stats:', ref.min(), ref.mean(), ref.max(), 'std:', ref.std()) - - if auto_contrast: - print_stats('ref pre proc', ref) - print_stats('out pre proc', out) - - ref -= ref.min() - ref /= ref.max() + 1e-9 - ref *= 255 - - out -= out.min() - out /= out.max() + 1e-9 - out *= 255 - - def write_refout(): - nonlocal autocrop_golden, ref - if autocrop_golden: - global output_dir - with output_dir.create(suffix='.png') as ref_out: - cv2.imwrite(str(ref_out), ref) - print('Processed reference image:', ref_out) - - if ref.shape != out.shape: - print(f'Rendering image size mismatch: {ref.shape} != {out.shape}') - print(f'Reference image: {Path(reference).absolute()}') - print(f'Actual output: {output}') - - write_refout() - output_dir.keep() - - return False - - delta = np.abs(out - ref).astype(float) / 255 - - if delta.mean() > max_delta: - print(f'Renderings mismatch: {delta.mean()=}, {max_delta=}') - print(f'Reference image: {Path(reference).absolute()}') - print(f'Actual output: {output}') - with output_dir.create(suffix='.png') as proc_out: - cv2.imwrite(str(proc_out), out) - print('Processed output image:', proc_out) - print_stats('reference', ref) - print_stats('actual', out) - - write_refout() - output_dir.keep() - - return False - - return True - - -def _test_render(gerber_path, png_expected_path, max_delta=1e-6, scale=300, autocrop_golden=False, auto_contrast=False): - """Render the gerber file and compare to the expected PNG output. - - Parameters - ---------- - gerber_path : string - Path to Gerber file to open - png_expected_path : string - Path to the PNG file to compare to - create_output : string|None - If not None, write the generated PNG to the specified path. - This is primarily to help with - """ - - gerber_path = _resolve_path(gerber_path) - png_expected_path = _resolve_path(png_expected_path) - - gerber = read(gerber_path) - - # Create PNG image to the memory stream - ctx = GerberCairoContext(scale=scale) - gerber.render(ctx) - - global output_dir - with output_dir.create(suffix='.png') as outfile: - actual_bytes = ctx.dump(outfile) - - assert images_match(png_expected_path, outfile, max_delta, autocrop_golden, auto_contrast) - - return gerber - - -def _test_simple_render_svg(gerber_path): - """Render the gerber file as SVG - - Note: verifies only the header, not the full content. - - Parameters - ---------- - gerber_path : string - Path to Gerber file to open - """ - - gerber_path = _resolve_path(gerber_path) - gerber = read(gerber_path) - - # Create SVG image to the memory stream - ctx = GerberCairoContext() - gerber.render(ctx) - - temp_dir = tempfile.mkdtemp() - svg_temp_path = os.path.join(temp_dir, "output.svg") - - assert not os.path.exists(svg_temp_path) - ctx.dump(svg_temp_path) - assert os.path.exists(svg_temp_path) - - with open(svg_temp_path, "r") as expected_file: - expected_bytes = expected_file.read() - assert expected_bytes[:38] == '' - - shutil.rmtree(temp_dir) - diff --git a/gerbonara/gerber/tests/test_gerber_statements.py b/gerbonara/gerber/tests/test_gerber_statements.py index 140cbd1..17e2591 100644 --- a/gerbonara/gerber/tests/test_gerber_statements.py +++ b/gerbonara/gerber/tests/test_gerber_statements.py @@ -413,84 +413,29 @@ def test_AMParamStmt_factory(): 1,1,1.5,0,0* 20,1,0.9,0,0.45,12,0.45,0* 21,1,6.8,1.2,3.4,0.6,0* -22,1,6.8,1.2,0,0,0* 4,1,4,0.1,0.1,0.5,0.1,0.5,0.5,0.1,0.5,0.1,0.1,0* 5,1,8,0,0,8,0* -6,0,0,5,0.5,0.5,2,0.1,6,0* 7,0,0,7,6,0.2,0* -8,THIS IS AN UNSUPPORTED PRIMITIVE* """ - s = AMParamStmt.from_dict({"param": "AM", "name": name, "macro": macro}) - s.build() + s = AMParamStmt.from_dict({"param": "AM", "name": name, "macro": macro}, units='mm') assert len(s.primitives) == 10 assert isinstance(s.primitives[0], AMCommentPrimitive) assert isinstance(s.primitives[1], AMCirclePrimitive) assert isinstance(s.primitives[2], AMVectorLinePrimitive) assert isinstance(s.primitives[3], AMCenterLinePrimitive) - assert isinstance(s.primitives[4], AMLowerLeftLinePrimitive) assert isinstance(s.primitives[5], AMOutlinePrimitive) assert isinstance(s.primitives[6], AMPolygonPrimitive) - assert isinstance(s.primitives[7], AMMoirePrimitive) assert isinstance(s.primitives[8], AMThermalPrimitive) - assert isinstance(s.primitives[9], AMUnsupportPrimitive) - - -def testAMParamStmt_conversion(): - name = "POLYGON" - macro = "5,1,8,25.4,25.4,25.4,0*" - s = AMParamStmt.from_dict({"param": "AM", "name": name, "macro": macro}) - - s.build() - s.units = "metric" - - # No effect - s.to_metric() - assert s.primitives[0].position == (25.4, 25.4) - assert s.primitives[0].diameter == 25.4 - - s.to_inch() - assert s.units == "inch" - assert s.primitives[0].position == (1.0, 1.0) - assert s.primitives[0].diameter == 1.0 - - # No effect - s.to_inch() - assert s.primitives[0].position == (1.0, 1.0) - assert s.primitives[0].diameter == 1.0 - - macro = "5,1,8,1,1,1,0*" - s = AMParamStmt.from_dict({"param": "AM", "name": name, "macro": macro}) - s.build() - s.units = "inch" - - # No effect - s.to_inch() - assert s.primitives[0].position == (1.0, 1.0) - assert s.primitives[0].diameter == 1.0 - - s.to_metric() - assert s.units == "metric" - assert s.primitives[0].position == (25.4, 25.4) - assert s.primitives[0].diameter == 25.4 - - # No effect - s.to_metric() - assert s.primitives[0].position == (25.4, 25.4) - assert s.primitives[0].diameter == 25.4 def test_AMParamStmt_dump(): name = "POLYGON" macro = "5,1,8,25.4,25.4,25.4,0.0" - s = AMParamStmt.from_dict({"param": "AM", "name": name, "macro": macro}) - s.build() + s = AMParamStmt.from_dict({"param": "AM", "name": name, "macro": macro}, units='mm') assert s.to_gerber() == "%AMPOLYGON*5,1,8,25.4,25.4,25.4,0.0*%" # TODO - Store Equations and update on unit change... - s = AMParamStmt.from_dict( - {"param": "AM", "name": "OC8", "macro": "5,1,8,0,0,1.08239X$1,22.5"} - ) - s.build() + s = AMParamStmt.from_dict({"param": "AM", "name": "OC8", "macro": "5,1,8,0,0,1.08239X$1,22.5"}, units='mm') # assert_equal(s.to_gerber(), '%AMOC8*5,1,8,0,0,1.08239X$1,22.5*%') assert s.to_gerber() == "%AMOC8*5,1,8,0,0,0,22.5*%" @@ -498,8 +443,7 @@ def test_AMParamStmt_dump(): def test_AMParamStmt_string(): name = "POLYGON" macro = "5,1,8,25.4,25.4,25.4,0*" - s = AMParamStmt.from_dict({"param": "AM", "name": name, "macro": macro}) - s.build() + s = AMParamStmt.from_dict({"param": "AM", "name": name, "macro": macro}, units='mm') assert str(s) == "" -- cgit