From b0c55082b001a1232fb20bae25390a1514c9e8a9 Mon Sep 17 00:00:00 2001 From: Hamilton Kibbe Date: Mon, 9 Feb 2015 13:57:15 -0500 Subject: Add aperture macro statement tests --- gerber/am_statements.py | 218 +++++++++++++++++++------------ gerber/tests/test_am_statements.py | 261 ++++++++++++++++++++++++++++++++++++- gerber/tests/tests.py | 2 +- 3 files changed, 393 insertions(+), 88 deletions(-) diff --git a/gerber/am_statements.py b/gerber/am_statements.py index 9559424..0e27623 100644 --- a/gerber/am_statements.py +++ b/gerber/am_statements.py @@ -21,6 +21,18 @@ from .utils import validate_coordinates # TODO: Add support for aperture macro variables +__all__ = ['AMPrimitive', 'AMCommentPrimitive', 'AMCirclePrimitive', + 'AMVectorLinePrimitive', 'AMOutlinePrimitive', 'AMPolygonPrimitive', + 'AMMoirePrimitive', 'AMThermalPrimitive', 'AMCenterLinePrimitive', + 'AMLowerLeftLinePrimitive', 'AMUnsupportPrimitive'] + +def metric(value): + return value * 25.4 + +def inch(value): + return value / 25.4 + + class AMPrimitive(object): """ Aperture Macro Primitive Base Class @@ -57,10 +69,10 @@ class AMPrimitive(object): self.exposure = exposure.lower() if exposure is not None else None def to_inch(self): - pass + raise NotImplementedError('Subclass must implement `to-inch`') def to_metric(self): - pass + raise NotImplementedError('Subclass must implement `to-metric`') class AMCommentPrimitive(AMPrimitive): @@ -103,6 +115,12 @@ class AMCommentPrimitive(AMPrimitive): super(AMCommentPrimitive, self).__init__(code) self.comment = comment.strip(' *') + def to_inch(self): + pass + + def to_metric(self): + pass + def to_gerber(self, settings=None): return '0 %s *' % self.comment @@ -154,11 +172,19 @@ class AMCirclePrimitive(AMPrimitive): def __init__(self, code, exposure, diameter, position): validate_coordinates(position) if code != 1: - raise ValueError('Not a valid Aperture Macro Circle statement') + raise ValueError('CirclePrimitive code is 1') super(AMCirclePrimitive, self).__init__(code, exposure) self.diameter = diameter self.position = position + def to_inch(self): + self.diameter = inch(self.diameter) + self.position = tuple([inch(x) for x in self.position]) + + def to_metric(self): + self.diameter = metric(self.diameter) + self.position = tuple([metric(x) for x in self.position]) + def to_gerber(self, settings=None): data = dict(code = self.code, exposure = '1' if self.exposure == 'on' else 0, @@ -222,17 +248,29 @@ class AMVectorLinePrimitive(AMPrimitive): validate_coordinates(start) validate_coordinates(end) if code not in (2, 20): - raise ValueError('Valid VectorLinePrimitive codes are 2 or 20') + raise ValueError('VectorLinePrimitive codes are 2 or 20') super(AMVectorLinePrimitive, self).__init__(code, exposure) self.width = width self.start = start self.end = end self.rotation = rotation + def to_inch(self): + self.width = inch(self.width) + self.start = tuple([inch(x) for x in self.start]) + self.end = tuple([inch(x) for x in self.end]) + + def to_metric(self): + self.width = metric(self.width) + self.start = tuple([metric(x) for x in self.start]) + self.end = tuple([metric(x) for x in self.end]) + + def to_gerber(self, settings=None): - fmtstr = '{code},{exp},{width},{startx},{starty},{endx},{endy},{rot}*' + fmtstr = '{code},{exp},{width},{startx},{starty},{endx},{endy},{rotation}*' data = dict(code = self.code, exp = 1 if self.exposure == 'on' else 0, + width = self.width, startx = self.start[0], starty = self.start[1], endx = self.end[0], @@ -240,9 +278,9 @@ class AMVectorLinePrimitive(AMPrimitive): rotation = self.rotation) return fmtstr.format(**data) -# Code 4 + class AMOutlinePrimitive(AMPrimitive): - """ Aperture Macro Outline primitive. Code 6. + """ Aperture Macro Outline primitive. Code 4. An outline primitive is an area enclosed by an n-point polygon defined by its start point and n subsequent points. The outline must be closed, i.e. @@ -256,7 +294,7 @@ class AMOutlinePrimitive(AMPrimitive): Parameters ---------- code : int - OutlinePrimitive code. Must be 4. + OutlinePrimitive code. Must be 6. exposure : string 'on' or 'off' @@ -299,31 +337,35 @@ class AMOutlinePrimitive(AMPrimitive): validate_coordinates(start_point) for point in points: validate_coordinates(point) + if code != 4: + raise ValueError('OutlinePrimitive code is 4') super(AMOutlinePrimitive, self).__init__(code, exposure) self.start_point = start_point + if points[-1] != start_point: + raise ValueError('OutlinePrimitive must be closed') self.points = points self.rotation = rotation def to_inch(self): - self.start_point = tuple([x / 25.4 for x in self.start_point]) - self.points = tuple([(x / 25.4, y / 25.4) for x, y in self.points]) + self.start_point = tuple([inch(x) for x in self.start_point]) + self.points = tuple([(inch(x), inch(y)) for x, y in self.points]) def to_metric(self): - self.start_point = tuple([x * 25.4 for x in self.start_point]) - self.points = tuple([(x * 25.4, y * 25.4) for x, y in self.points]) + self.start_point = tuple([metric(x) for x in self.start_point]) + self.points = tuple([(metric(x), metric(y)) for x, y in self.points]) def to_gerber(self, settings=None): data = dict( code=self.code, exposure="1" if self.exposure == "on" else "0", n_points=len(self.points), - start_point="%.4f,%.4f" % self.start_point, - points=",".join(["%.4f,%.4f" % point for point in self.points]), + start_point="%.4g,%.4g" % self.start_point, + points=",".join(["%.4g,%.4g" % point for point in self.points]), rotation=str(self.rotation) ) return "{code},{exposure},{n_points},{start_point},{points},{rotation}*".format(**data) -# Code 5 + class AMPolygonPrimitive(AMPrimitive): """ Aperture Macro Polygon primitive. Code 5. @@ -378,6 +420,8 @@ class AMPolygonPrimitive(AMPrimitive): def __init__(self, code, exposure, vertices, position, diameter, rotation): """ Initialize AMPolygonPrimitive """ + if code != 5: + raise ValueError('PolygonPrimitive code is 5') super(AMPolygonPrimitive, self).__init__(code, exposure) if vertices < 3 or vertices > 12: raise ValueError('Number of vertices must be between 3 and 12') @@ -388,27 +432,26 @@ class AMPolygonPrimitive(AMPrimitive): self.rotation = rotation def to_inch(self): - self.position = tuple([x / 25.4 for x in self.position]) - self.diameter = self.diameter / 25.4 + self.position = tuple([inch(x) for x in self.position]) + self.diameter = inch(self.diameter) def to_metric(self): - self.position = tuple([x * 25.4 for x in self.position]) - self.diameter = self.diameter * 25.4 + self.position = tuple([metric(x) for x in self.position]) + self.diameter = metric(self.diameter) def to_gerber(self, settings=None): data = dict( code=self.code, exposure="1" if self.exposure == "on" else "0", vertices=self.vertices, - position="%.4f,%.4f" % self.position, - diameter = '%.4f' % self.diameter, + position="%.4g,%.4g" % self.position, + diameter = '%.4g' % self.diameter, rotation=str(self.rotation) ) fmt = "{code},{exposure},{vertices},{position},{diameter},{rotation}*" return fmt.format(**data) -# Code 6 class AMMoirePrimitive(AMPrimitive): """ Aperture Macro Moire primitive. Code 6. @@ -474,6 +517,8 @@ class AMMoirePrimitive(AMPrimitive): def __init__(self, code, position, diameter, ring_thickness, gap, max_rings, crosshair_thickness, crosshair_length, rotation): """ Initialize AMoirePrimitive """ + if code != 6: + raise ValueError('MoirePrimitive code is 6') super(AMMoirePrimitive, self).__init__(code, 'on') validate_coordinates(position) self.position = position @@ -486,38 +531,38 @@ class AMMoirePrimitive(AMPrimitive): self.rotation = rotation def to_inch(self): - self.position = tuple([x / 25.4 for x in self.position]) - self.diameter = self.diameter / 25.4 - self.ring_thickness = self.ring_thickness / 25.4 - self.gap = self.gap / 25.4 - self.crosshair_thickness = self.crosshair_thickness / 25.4 - self.crosshair_length = self.crosshair_length / 25.4 + self.position = tuple([inch(x) for x in self.position]) + self.diameter = inch(self.diameter) + self.ring_thickness = inch(self.ring_thickness) + self.gap = inch(self.gap) + self.crosshair_thickness = inch(self.crosshair_thickness) + self.crosshair_length = inch(self.crosshair_length) def to_metric(self): - self.position = tuple([x * 25.4 for x in self.position]) - self.diameter = self.diameter * 25.4 - self.ring_thickness = self.ring_thickness * 25.4 - self.gap = self.gap / 25.4 - self.crosshair_thickness = self.crosshair_thickness * 25.4 - self.crosshair_length = self.crosshair_length * 25.4 + self.position = tuple([metric(x) for x in self.position]) + self.diameter = metric(self.diameter) + self.ring_thickness = metric(self.ring_thickness) + self.gap = metric(self.gap) + self.crosshair_thickness = metric(self.crosshair_thickness) + self.crosshair_length = metric(self.crosshair_length) def to_gerber(self, settings=None): data = dict( code=self.code, - position="%.4f,%.4f" % self.position, - diameter = '%.4f' % self.diameter, - ring_thickness = '%.4f' % self.ring_thickness, - gap = '%.4f' % self.gap, - max_rings = str(self.max_rings), - crosshair_thickness = '%.4f' % self.crosshair_thickness, - crosshair_length = '%.4f' % self.crosshair_length, - rotation=str(self.rotation) + position="%.4g,%.4g" % self.position, + diameter = self.diameter, + ring_thickness = self.ring_thickness, + gap = self.gap, + max_rings = self.max_rings, + crosshair_thickness = self.crosshair_thickness, + crosshair_length = self.crosshair_length, + rotation=self.rotation ) fmt = "{code},{position},{diameter},{ring_thickness},{gap},{max_rings},{crosshair_thickness},{crosshair_length},{rotation}*" return fmt.format(**data) -# Code 7 + class AMThermalPrimitive(AMPrimitive): """ Aperture Macro Thermal primitive. Code 7. @@ -565,45 +610,43 @@ class AMThermalPrimitive(AMPrimitive): outer_diameter = float(modifiers[3]) inner_diameter= float(modifiers[4]) gap = float(modifiers[5]) - rotation = float(modifiers[6]) - return cls(code, position, outer_diameter, inner_diameter, gap, rotation) + return cls(code, position, outer_diameter, inner_diameter, gap) - def __init__(self, code, position, outer_diameter, inner_diameter, gap, rotation): - super(AMThermalPrimitive, self).__init(code, 'on') + def __init__(self, code, position, outer_diameter, inner_diameter, gap): + if code != 7: + raise ValueError('ThermalPrimitive code is 7') + super(AMThermalPrimitive, self).__init__(code, 'on') validate_coordinates(position) self.position = position self.outer_diameter = outer_diameter self.inner_diameter = inner_diameter self.gap = gap - self.rotation = rotation def to_inch(self): - self.position = tuple([x / 25.4 for x in self.position]) - self.outer_diameter = self.outer_diameter / 25.4 - self.inner_diameter = self.inner_diameter / 25.4 - self.gap = self.gap / 25.4 + self.position = tuple([inch(x) for x in self.position]) + self.outer_diameter = inch(self.outer_diameter) + self.inner_diameter = inch(self.inner_diameter) + self.gap = inch(self.gap) def to_metric(self): - self.position = tuple([x * 25.4 for x in self.position]) - self.outer_diameter = self.outer_diameter * 25.4 - self.inner_diameter = self.inner_diameter * 25.4 - self.gap = self.gap * 25.4 + self.position = tuple([metric(x) for x in self.position]) + self.outer_diameter = metric(self.outer_diameter) + self.inner_diameter = metric(self.inner_diameter) + self.gap = metric(self.gap) def to_gerber(self, settings=None): data = dict( code=self.code, - position="%.4f,%.4f" % self.position, - outer_diameter = '%.4f' % self.outer_diameter, - inner_diameter = '%.4f' % self.inner_diameter, - gap = '%.4f' % self.gap, - rotation=str(self.rotation) + position="%.4g,%.4g" % self.position, + outer_diameter = self.outer_diameter, + inner_diameter = self.inner_diameter, + gap = self.gap, ) - fmt = "{code},{position},{outer_diameter},{inner_diameter},{gap},{rotation}*" + fmt = "{code},{position},{outer_diameter},{inner_diameter},{gap}*" return fmt.format(**data) -# Code 21 class AMCenterLinePrimitive(AMPrimitive): """ Aperture Macro Center Line primitive. Code 21. @@ -655,6 +698,8 @@ class AMCenterLinePrimitive(AMPrimitive): return cls(code, exposure, width, height, center, rotation) def __init__(self, code, exposure, width, height, center, rotation): + if code != 21: + raise ValueError('CenterLinePrimitive code is 21') super (AMCenterLinePrimitive, self).__init__(code, exposure) self.width = width self.height = height @@ -663,29 +708,28 @@ class AMCenterLinePrimitive(AMPrimitive): self.rotation = rotation def to_inch(self): - self.center = tuple([x / 25.4 for x in self.center]) - self.width = self.width / 25.4 - self.heignt = self.height / 25.4 + self.center = tuple([inch(x) for x in self.center]) + self.width = inch(self.width) + self.height = inch(self.height) def to_metric(self): - self.center = tuple([x * 25.4 for x in self.center]) - self.width = self.width * 25.4 - self.heignt = self.height * 25.4 + self.center = tuple([metric(x) for x in self.center]) + self.width = metric(self.width) + self.height = metric(self.height) def to_gerber(self, settings=None): data = dict( code=self.code, exposure = '1' if self.exposure == 'on' else '0', - width = '%.4f' % self.width, - height = '%.4f' % self.height, - center="%.4f,%.4f" % self.center, - rotation=str(self.rotation) + width = self.width, + height = self.height, + center="%.4g,%.4g" % self.center, + rotation=self.rotation ) fmt = "{code},{exposure},{width},{height},{center},{rotation}*" return fmt.format(**data) -# Code 22 class AMLowerLeftLinePrimitive(AMPrimitive): """ Aperture Macro Lower Left Line primitive. Code 22. @@ -698,7 +742,7 @@ class AMLowerLeftLinePrimitive(AMPrimitive): Parameters ---------- code : int - Center Line Primitive code. Must be 21. + Center Line Primitive code. Must be 22. exposure : str 'on' or 'off' @@ -736,7 +780,9 @@ class AMLowerLeftLinePrimitive(AMPrimitive): return cls(code, exposure, width, height, lower_left, rotation) def __init__(self, code, exposure, width, height, lower_left, rotation): - super (AMCenterLinePrimitive, self).__init__(code, exposure) + if code != 22: + raise ValueError('LowerLeftLinePrimitive code is 22') + super (AMLowerLeftLinePrimitive, self).__init__(code, exposure) self.width = width self.height = height validate_coordinates(lower_left) @@ -744,23 +790,23 @@ class AMLowerLeftLinePrimitive(AMPrimitive): self.rotation = rotation def to_inch(self): - self.lower_left = tuple([x / 25.4 for x in self.lower_left]) - self.width = self.width / 25.4 - self.heignt = self.height / 25.4 + self.lower_left = tuple([inch(x) for x in self.lower_left]) + self.width = inch(self.width) + self.height = inch(self.height) def to_metric(self): - self.lower_left = tuple([x * 25.4 for x in self.lower_left]) - self.width = self.width * 25.4 - self.heignt = self.height * 25.4 + self.lower_left = tuple([metric(x) for x in self.lower_left]) + self.width = metric(self.width) + self.height = metric(self.height) def to_gerber(self, settings=None): data = dict( code=self.code, exposure = '1' if self.exposure == 'on' else '0', - width = '%.4f' % self.width, - height = '%.4f' % self.height, - lower_left="%.4f,%.4f" % self.lower_left, - rotation=str(self.rotation) + width = self.width, + height = self.height, + lower_left="%.4g,%.4g" % self.lower_left, + rotation=self.rotation ) fmt = "{code},{exposure},{width},{height},{lower_left},{rotation}*" return fmt.format(**data) diff --git a/gerber/tests/test_am_statements.py b/gerber/tests/test_am_statements.py index 2ba7733..696d951 100644 --- a/gerber/tests/test_am_statements.py +++ b/gerber/tests/test_am_statements.py @@ -5,6 +5,7 @@ from .tests import * from ..am_statements import * +from ..am_statements import inch, metric def test_AMPrimitive_ctor(): for exposure in ('on', 'off', 'ON', 'OFF'): @@ -19,6 +20,12 @@ def test_AMPrimitive_validation(): assert_raises(ValueError, AMPrimitive, 0, 'exposed') assert_raises(ValueError, AMPrimitive, 3, 'off') +def test_AMPrimitive_conversion(): + p = AMPrimitive(4, 'on') + assert_raises(NotImplementedError, p.to_inch) + assert_raises(NotImplementedError, p.to_metric) + + def test_AMCommentPrimitive_ctor(): c = AMCommentPrimitive(0, ' This is a comment *') @@ -40,6 +47,19 @@ def test_AMCommentPrimitive_dump(): c = AMCommentPrimitive(0, 'Rectangle with rounded corners.') assert_equal(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_equal(c, ci) + assert_equal(c, cm) + +def test_AMCommentPrimitive_string(): + c = AMCommentPrimitive(0, 'Test Comment') + assert_equal(str(c), '') + def test_AMCirclePrimitive_ctor(): test_cases = ((1, 'on', 0, (0, 0)), @@ -72,6 +92,245 @@ def test_AMCirclePrimitive_dump(): c = AMCirclePrimitive(1, 'on', 5, (0, 0)) assert_equal(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_equal(c.diameter, 1) + assert_equal(c.position, (1, 0)) + + c = AMCirclePrimitive(1, 'off', 1, (1, 0)) + c.to_metric() + assert_equal(c.diameter, 25.4) + assert_equal(c.position, (25.4, 0)) + +def test_AMVectorLinePrimitive_validation(): + assert_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_equal(l.code, 20) + assert_equal(l.exposure, 'on') + assert_equal(l.width, 0.9) + assert_equal(l.start, (0, 0.45)) + assert_equal(l.end, (12, 0.45)) + assert_equal(l.rotation, 0) + +def test_AMVectorLinePrimitive_dump(): + l = AMVectorLinePrimitive.from_gerber('20,1,0.9,0,0.45,12,0.45,0*') + assert_equal(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_equal(l.width, 1) + assert_equal(l.start, (0, 0)) + assert_equal(l.end, (1, 1)) + + l = AMVectorLinePrimitive(20, 'on', 1, (0,0), (1, 1), 0) + l.to_metric() + assert_equal(l.width, 25.4) + assert_equal(l.start, (0, 0)) + assert_equal(l.end, (25.4, 25.4)) + +def test_AMOutlinePrimitive_validation(): + assert_raises(ValueError, AMOutlinePrimitive, 7, 'on', (0,0), [(3.3, 5.4), (4.0, 5.4), (0, 0)], 0) + assert_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_equal(o.code, 4) + assert_equal(o.exposure, 'on') + assert_equal(o.start_point, (0, 0)) + assert_equal(o.points, [(3, 3), (3, 0), (0, 0)]) + assert_equal(o.rotation, 0) + +def test_AMOUtlinePrimitive_dump(): + o = AMOutlinePrimitive(4, 'on', (0, 0), [(3, 3), (3, 0), (0, 0)], 0) + assert_equal(o.to_gerber(), '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_equal(o.start_point, (0, 0)) + assert_equal(o.points, ((1., 1.), (1., 0.), (0., 0.))) + + o = AMOutlinePrimitive(4, 'on', (0, 0), [(1, 1), (1, 0), (0, 0)], 0) + o.to_metric() + assert_equal(o.start_point, (0, 0)) + assert_equal(o.points, ((25.4, 25.4), (25.4, 0), (0, 0))) + + +def test_AMPolygonPrimitive_validation(): + assert_raises(ValueError, AMPolygonPrimitive, 6, 'on', 3, (3.3, 5.4), 3, 0) + assert_raises(ValueError, AMPolygonPrimitive, 5, 'on', 2, (3.3, 5.4), 3, 0) + assert_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_equal(p.code, 5) + assert_equal(p.exposure, 'on') + assert_equal(p.vertices, 3) + assert_equal(p.position, (3.3, 5.4)) + assert_equal(p.diameter, 3) + assert_equal(p.rotation, 0) + +def test_AMPolygonPrimitive_dump(): + p = AMPolygonPrimitive(5, 'on', 3, (3.3, 5.4), 3, 0) + assert_equal(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_equal(p.diameter, 1) + assert_equal(p.position, (1, 0)) + + p = AMPolygonPrimitive(5, 'off', 3, (1, 0), 1, 0) + p.to_metric() + assert_equal(p.diameter, 25.4) + assert_equal(p.position, (25.4, 0)) + + +def test_AMMoirePrimitive_validation(): + assert_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_equal(m.code, 6) + assert_equal(m.position, (0, 0)) + assert_equal(m.diameter, 5) + assert_equal(m.ring_thickness, 0.5) + assert_equal(m.gap, 0.5) + assert_equal(m.max_rings, 2) + assert_equal(m.crosshair_thickness, 0.1) + assert_equal(m.crosshair_length, 6) + assert_equal(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_equal(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_equal(m.position, (1., 1.)) + assert_equal(m.diameter, 1.) + assert_equal(m.ring_thickness, 1.) + assert_equal(m.gap, 1.) + assert_equal(m.crosshair_thickness, 1.) + assert_equal(m.crosshair_length, 1.) + + m = AMMoirePrimitive(6, (1, 1), 1, 1, 1, 6, 1, 1, 0) + m.to_metric() + assert_equal(m.position, (25.4, 25.4)) + assert_equal(m.diameter, 25.4) + assert_equal(m.ring_thickness, 25.4) + assert_equal(m.gap, 25.4) + assert_equal(m.crosshair_thickness, 25.4) + assert_equal(m.crosshair_length, 25.4) + +def test_AMThermalPrimitive_validation(): + assert_raises(ValueError, AMThermalPrimitive, 8, (0.0, 0.0), 7, 5, 0.2) + assert_raises(TypeError, AMThermalPrimitive, 7, (0.0, '0'), 7, 5, 0.2) + +def test_AMThermalPrimitive_factory(): + t = AMThermalPrimitive.from_gerber('7,0,0,7,6,0.2*') + assert_equal(t.code, 7) + assert_equal(t.position, (0, 0)) + assert_equal(t.outer_diameter, 7) + assert_equal(t.inner_diameter, 6) + assert_equal(t.gap, 0.2) + +def test_AMThermalPrimitive_dump(): + t = AMThermalPrimitive.from_gerber('7,0,0,7,6,0.2*') + assert_equal(t.to_gerber(), '7,0,0,7.0,6.0,0.2*') + +def test_AMThermalPrimitive_conversion(): + t = AMThermalPrimitive(7, (25.4, 25.4), 25.4, 25.4, 25.4) + t.to_inch() + assert_equal(t.position, (1., 1.)) + assert_equal(t.outer_diameter, 1.) + assert_equal(t.inner_diameter, 1.) + assert_equal(t.gap, 1.) + + t = AMThermalPrimitive(7, (1, 1), 1, 1, 1) + t.to_metric() + assert_equal(t.position, (25.4, 25.4)) + assert_equal(t.outer_diameter, 25.4) + assert_equal(t.inner_diameter, 25.4) + assert_equal(t.gap, 25.4) + + +def test_AMCenterLinePrimitive_validation(): + assert_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_equal(l.code, 21) + assert_equal(l.exposure, 'on') + assert_equal(l.width, 6.8) + assert_equal(l.height, 1.2) + assert_equal(l.center, (3.4, 0.6)) + assert_equal(l.rotation, 0) + +def test_AMCenterLinePrimitive_dump(): + l = AMCenterLinePrimitive.from_gerber('21,1,6.8,1.2,3.4,0.6,0*') + assert_equal(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_equal(l.width, 1.) + assert_equal(l.height, 1.) + assert_equal(l.center, (1., 1.)) + + l = AMCenterLinePrimitive(21, 'on', 1, 1, (1, 1), 0) + l.to_metric() + assert_equal(l.width, 25.4) + assert_equal(l.height, 25.4) + assert_equal(l.center, (25.4, 25.4)) + +def test_AMLowerLeftLinePrimitive_validation(): + assert_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_equal(l.code, 22) + assert_equal(l.exposure, 'on') + assert_equal(l.width, 6.8) + assert_equal(l.height, 1.2) + assert_equal(l.lower_left, (3.4, 0.6)) + assert_equal(l.rotation, 0) + +def test_AMLowerLeftLinePrimitive_dump(): + l = AMLowerLeftLinePrimitive.from_gerber('22,1,6.8,1.2,3.4,0.6,0*') + assert_equal(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_equal(l.width, 1.) + assert_equal(l.height, 1.) + assert_equal(l.lower_left, (1., 1.)) + + l = AMLowerLeftLinePrimitive(22, 'on', 1, 1, (1, 1), 0) + l.to_metric() + assert_equal(l.width, 25.4) + assert_equal(l.height, 25.4) + assert_equal(l.lower_left, (25.4, 25.4)) + +def test_AMUnsupportPrimitive(): + u = AMUnsupportPrimitive.from_gerber('Test') + assert_equal(u.primitive, 'Test') + u = AMUnsupportPrimitive('Test') + assert_equal(u.to_gerber(), 'Test') + + + +def test_inch(): + assert_equal(inch(25.4), 1) + +def test_metric(): + assert_equal(metric(1), 25.4) + - \ No newline at end of file diff --git a/gerber/tests/tests.py b/gerber/tests/tests.py index e7029e4..db02949 100644 --- a/gerber/tests/tests.py +++ b/gerber/tests/tests.py @@ -21,4 +21,4 @@ __all__ = ['assert_in', 'assert_not_in', 'assert_equal', 'assert_not_equal', def assert_array_almost_equal(arr1, arr2, decimal=6): assert_equal(len(arr1), len(arr2)) for i in xrange(len(arr1)): - assert_almost_equal(arr1[i], arr2[i], decimal) \ No newline at end of file + assert_almost_equal(arr1[i], arr2[i], decimal) -- cgit