def test_make_length(self):
     """ Lengths are converted correctly. """
     parser = EagleXML()
     self.assertEqual(parser.make_length("0"), 0)
     self.assertEqual(parser.make_length("254"), int(900 * 2.0))
class EagleXMLTests(unittest.TestCase):
    """ The tests of the eagle-xml parser """

    def setUp(self):
        self.parser = EagleXML()


    def test_create_new_eaglexml_parser(self):
        """ Test creating an empty parser. """
        self.assertNotEqual(self.parser, None)


    def test_make_length(self):
        """ Lengths are converted correctly. """
        parser = EagleXML()
        self.assertEqual(parser.make_length("0"), 0)
        self.assertEqual(parser.make_length("254"), int(900 * 2.0))


    @use_file('E1AA60D5.sch')
    def test_library_components(self):
        """ A deviceset should have a matching component. """
        self.assertTrue('atmel:TINY15L:P'
                        in self.design.components.components)


    @use_file('E1AA60D5.sch')
    def test_component_symbols(self):
        """ A component should have 1 symbol. """
        self.assertEqual(
            len(self.get_component('atmel:TINY15L:P').symbols), 1)


    @use_file('D9CD1423.sch')
    def test_component_bodies(self):
        """ A deviceset with 2 gates should have 2 bodies. """
        cpt = self.get_component('Discrete:010-DUAL-N-MOSFET*:_1206-8')
        self.assertEqual(len(cpt.symbols[0].bodies), 2)


    @use_file('E1AA60D5.sch')
    def test_component_body_lines(self):
        """ The right component Lines are created on SBody objects. """
        cpt = self.get_component('atmel:TINY15L:P')
        lines = [s for s in cpt.symbols[0].bodies[0].shapes
                 if s.type == 'line']
        self.assertEqual(len(lines), 4)
        self.assertEqual(lines[0].p1.x / EAGLE_SCALE, self.make_length("12.7"))
        self.assertEqual(lines[0].p1.y / EAGLE_SCALE, self.make_length("-10.16"))
        self.assertEqual(lines[0].p2.x / EAGLE_SCALE, self.make_length("-12.7"))
        self.assertEqual(lines[0].p2.y / EAGLE_SCALE, self.make_length("-10.16"))


    @use_file('E1AA60D5.sch')
    def test_component_body_rectangles(self):
        """ The right component Rectangles are created on SBody objects. """
        cpt = self.get_component('resistor:CPOL-EU:E2.5-6')
        rects = [s for s in cpt.symbols[0].bodies[0].shapes
                 if s.type == 'rectangle']
        self.assertEqual(len(rects), 1)
        self.assertEqual(rects[0].x / EAGLE_SCALE, self.make_length("-1.651"))
        self.assertEqual(rects[0].y / EAGLE_SCALE, self.make_length("-1.651"))
        self.assertEqual(rects[0].width / EAGLE_SCALE,
                         self.make_length("1.651") - self.make_length("-1.651"))
        self.assertEqual(rects[0].height / EAGLE_SCALE,
                         self.make_length("-1.651") - self.make_length("-2.54"))


    @use_file('S12G_Micro_20EVB_RevA.sch')
    def test_component_body_rectangles_rot(self):
        """ The right rotations are applied to Rectangles on SBody objects. """

        cpt = self.get_component('myLibrary:L:0805')
        rect = [s for s in cpt.symbols[0].bodies[0].shapes
                if s.type == 'rectangle'][0]
        self.assertEqual(rect.x / EAGLE_SCALE, self.make_length("-3.556"))
        self.assertEqual(rect.y / EAGLE_SCALE, self.make_length("1.016"))
        self.assertEqual(rect.width / EAGLE_SCALE,
                         self.make_length("3.556") - self.make_length("-3.556"))
        self.assertEqual(rect.height / EAGLE_SCALE,
                         self.make_length("1.016") - self.make_length("-1.016"))


    @use_file('450B679C.sch')
    def test_component_body_polygons(self):
        """ The right component Rectangles are created on SBody objects. """

        cpt = self.get_component('adafruit:LED:5MM')
        polys = [s for s in cpt.symbols[0].bodies[0].shapes
                 if s.type == 'polygon']
        self.assertEqual(len(polys), 2)
        self.assertEqual(len(polys[0].points), 3)
        self.assertEqual(polys[0].points[0].x / EAGLE_SCALE, self.make_length("-3.429"))
        self.assertEqual(polys[0].points[0].y / EAGLE_SCALE, self.make_length("-2.159"))


    @use_file('D9CD1423.sch')
    def test_component_body_circles(self):
        """ The right component Circles are created on SBody objects. """

        cpt = self.get_component('CONNECTER:HEADER_1X10:DD')
        circs = [s for s in cpt.symbols[0].bodies[0].shapes
                 if s.type == 'circle']
        self.assertEqual(len(circs), 9)
        self.assertEqual(circs[0].x, self.make_length("0"))
        self.assertEqual(circs[0].y / EAGLE_SCALE, self.make_length("8.89"))
        self.assertEqual(circs[0].radius / EAGLE_SCALE, self.make_length("1.016"))
        self.assertEqual(circs[0].attributes['eaglexml_width'], "0.254")


    @use_file('E1AA60D5.sch')
    def test_component_body_labels(self):
        """ The right component Labels are created on SBody objects. """
        cpt = self.get_component('con-berg:PN87520:')
        labels = [s for s in cpt.symbols[0].bodies[0].shapes
                  if s.type == 'label']
        self.assertEqual(len(labels), 1)
        self.assertEqual(labels[0].x / EAGLE_SCALE, self.make_length("5.08"))
        self.assertEqual(labels[0].y / EAGLE_SCALE, self.make_length("-2.54"))
        self.assertEqual(labels[0].text, 'USB')
        self.assertEqual(labels[0]._rotation, 1.5)


    @use_file('msp430_f249_ctk.sch')
    def test_component_body_labels_mirrored(self):
        """ The right component Labels are created on SBody objects. """
        cpt = self.get_component('TI_MSP430_v16:F24[X/10]---PM64:')
        labels = [s for s in cpt.symbols[0].bodies[0].shapes
                  if s.type == 'label' and s.text == 'P4.6/TB6']
        self.assertEqual(len(labels), 1)
        self.assertEqual(labels[0].x / EAGLE_SCALE, self.make_length("36.83"))
        self.assertEqual(labels[0].y / EAGLE_SCALE, self.make_length("0.0"))
        self.assertEqual(labels[0]._rotation, 0.0)
        self.assertEqual(labels[0].align, 'right')


    @use_file('E1AA60D5.sch')
    def test_component_body_pins(self):
        """ The right component Pins are created on SBody objects. """
        cpt = self.get_component('atmel:TINY15L:P')
        pins = cpt.symbols[0].bodies[0].pins
        self.assertEqual(len(pins), 8)
        self.assertEqual(pins[0].p1.x / EAGLE_SCALE, 90)
        self.assertEqual(pins[0].p1.y / EAGLE_SCALE, 18)
        self.assertEqual(pins[0].p2.x / EAGLE_SCALE, self.make_length("17.78"))
        self.assertEqual(pins[0].p2.y / EAGLE_SCALE, self.make_length("2.54"))
        self.assertEqual(pins[0].label.text, '(ADC3)PB4')
        self.assertEqual(pins[0].label.x / EAGLE_SCALE, 85.0)
        self.assertEqual(pins[0].label.y / EAGLE_SCALE, 15.0)
        self.assertEqual(pins[0].label._rotation, 0.0)
        self.assertEqual([p.pin_number for p in pins],
                         ['2', '3', '1', '7', '6', '5', '8', '4'])
        self.assertEqual([p.label.text for p in pins],
                         ['(ADC3)PB4', '(ADC2)PB3', '(ADC0)PB5',
                          '(ADC1)PB2', '(OCP)PB1', '(AREF)PB0',
                          'VCC', 'GND'])
        cpt = self.get_component('diode:ZENER-DIODE:DO35Z10')
        pins = cpt.symbols[0].bodies[0].pins
        self.assertEqual(pins[0].label, None)
        self.assertEqual([p.pin_number for p in pins], ['A', 'C'])


    @use_file('Shock Controller.sch')
    def test_component_body_pin_duplicate_names(self):
        """ Duplicate pin names on different gates are de-duplicated
        with pin numbers. """

        cpt = self.get_component('con-molex:22-?-04:27-2041')
        pin_numbers = [p.pin_number for b in cpt.symbols[0].bodies for p in b.pins]
        self.assertEqual(pin_numbers, ['1', '2', '3', '4'])


    @use_file('E1AA60D5.sch')
    def test_component_instances(self):
        """ The right component instances are created. """
        self.assertEqual(
            set(ci.instance_id for ci in self.design.component_instances),
            set(('Q1', 'X2', 'C2', 'IC1', 'X1', 'R4', 'R1', 'R2', 'R3', 'GND3',
                 'GND2', 'GND1', 'GND7', 'GND6', 'GND5', 'GND4','C1', 'P+2',
                 'P+3', 'P+1', 'P+6', 'P+4','P+5', 'D2', 'D1')))


    @use_file('E1AA60D5.sch')
    def test_component_instance_rotation(self):
        """ Component instance rotation is correct. """
        inst = self.get_instance('GND3')
        self.assertEqual(inst.symbol_attributes[0].rotation, 0)
        inst = self.get_instance('R2')
        self.assertEqual(inst.symbol_attributes[0].rotation, 1.5)


    @use_file('E1AA60D5.sch')
    def test_component_instance_refdes(self):
        """ Component instance refdes is correct. """
        inst = self.get_instance('GND3')
        self.assertEqual(inst.get_attribute('refdes'), 'GND3')


    @use_file('E1AA60D5.sch')
    def test_component_instance_position(self):
        """ Component instance position is correct. """
        inst = self.get_instance('GND3')
        self.assertEqual(len(inst.symbol_attributes), 1)
        self.assertEqual(inst.symbol_attributes[0].x / EAGLE_SCALE, self.make_length("116.84"))
        self.assertEqual(inst.symbol_attributes[0].y / EAGLE_SCALE, self.make_length("55.88"))


    @use_file('E1AA60D5.sch')
    def test_component_instance_value(self):
        """ Component instance value is correct. """
        inst = self.get_instance('R2')
        self.assertEqual(inst.attributes['value'], '68')


    @use_file('E1AA60D5.sch')
    def test_component_instance_annotations(self):
        """ Component instance annotations are correct. """
        inst = self.get_instance('R2')
        anns = inst.symbol_attributes[0].annotations
        self.assertEqual(len(anns), 2)
        self.assertEqual(anns[0].value, 'R2')
        self.assertEqual(anns[0].x / EAGLE_SCALE, -27)
        self.assertEqual(anns[0].y / EAGLE_SCALE, 11)
        self.assertEqual(anns[1].value, '68')
        self.assertEqual(anns[1].x / EAGLE_SCALE, -27)
        self.assertEqual(anns[1].y / EAGLE_SCALE, -23)


    @use_file('WiFi.sch')
    def test_component_instance_annotations_case_insensitive(self):
        """ Component instance annotations are correct. """
        inst = self.get_instance('U$1')
        anns = inst.symbol_attributes[0].annotations
        self.assertEqual(len(anns), 1)
        self.assertEqual(anns[0].value, 'U$1')


    @use_file('pcb_switch_switch.sch')
    def test_component_instance_annotations_multi_gates(self):
        """ Component instance annotations with multiple gates are correct. """
        inst = self.get_instance('X1')
        values = []
        for attr in inst.symbol_attributes:
            for ann in attr.annotations:
                values.append(ann.value)
        self.assertEqual(set(values), set(['SW', 'X1-1', 'X1-2']))


    @use_file('E1AA60D5.sch')
    def test_nets(self):
        """ The right nets are created. """
        self.assertEqual(set(n.net_id for n in self.design.nets),
                         set(['VCC', 'GND', 'N$1', 'N$2', 'N$3',
                              'N$4', 'N$5', 'N$6', 'N$7']))


    @use_file('E1AA60D5.sch')
    def test_net_points(self):
        """ The right net points are created. """
        net = [n for n in self.design.nets if n.net_id == 'GND'][0]
        self.assertEqual(len(net.points), 13)
        self.assertTrue(self.make_point_name("40.64", "63.5") in net.points)


    @use_file('E1AA60D5.sch')
    def test_net_points_connected(self):
        """ The right net points are connected. """
        net = [n for n in self.design.nets if n.net_id == 'N$7'][0]
        pt = net.points[self.make_point_name("83.82", "68.58")]
        self.assertEqual(sorted(pt.connected_points),
                         [self.make_point_name("76.2", "68.58"),
                          self.make_point_name("83.82", "48.26")])


    @use_file('S12G_Micro_20EVB_RevA.sch')
    def test_net_points_connected_rot(self):
        """ The right net points are connected for a rotated part. """
        net = [n for n in self.design.nets if n.net_id == 'GND'][0]
        pt = net.points[self.make_point_name("0", "15.24")]
        self.assertEqual(sorted(pt.connected_points),
                         [self.make_point_name("0", "7.62")])


    @use_file('S12G_Micro_20EVB_RevA.sch')
    def test_net_points_connected_flip_rot(self):
        """ The right net points are connected for a flipped and rotated part. """
        net = [n for n in self.design.nets if n.net_id == 'PT1'][0]
        pt = net.points[self.make_point_name("162.56", "33.02")]
        self.assertEqual(sorted(pt.connected_points),
                         [self.make_point_name("162.56", "30.48")])


    @use_file('E1AA60D5.sch')
    def test_net_points_connected_components(self):
        """ The right net points are connected to the right components. """
        net = [n for n in self.design.nets if n.net_id == 'N$7'][0]
        pt = net.points[self.make_point_name("76.2", "68.58")]
        self.assertEqual(len(pt.connected_components), 1)
        self.assertEqual(pt.connected_components[0].instance_id, 'IC1')
        self.assertEqual(pt.connected_components[0].pin_number, '7')


    @use_file('D9CD1423.sch')
    def test_smashed_annotations(self):
        """ The right annotations are created for smashed components. """
        inst = self.get_instance('U1')
        symattr = inst.symbol_attributes[0]
        self.assertEqual(len(symattr.annotations), 2)
        self.assertEqual(symattr.annotations[0].value, 'U1')
        self.assertEqual(symattr.annotations[0].x / EAGLE_SCALE, self.parser.make_length("22.86"))
        self.assertEqual(symattr.annotations[0].y / EAGLE_SCALE, self.parser.make_length("52.07"))
        self.assertEqual(symattr.annotations[0].rotation, 0.0)
        self.assertEqual(symattr.annotations[1].value, 'ATMEGA328AU')
        self.assertEqual(symattr.annotations[1].x / EAGLE_SCALE, self.parser.make_length("22.86"))
        self.assertEqual(symattr.annotations[1].y / EAGLE_SCALE, self.parser.make_length("43.18"))
        self.assertEqual(symattr.annotations[1].rotation, 0.0)


    @use_file('msp430_f249_ctk.sch')
    def test_smashed_annotations_offset(self):
        """ The right annotations are created for smashed components. """
        inst = self.get_instance('SV3')
        symattr = inst.symbol_attributes[0]
        self.assertEqual(len(symattr.annotations), 2)
        self.assertEqual(symattr.annotations[0].value, '14 PIN JTAG')
        self.assertEqual(symattr.annotations[0].x / EAGLE_SCALE,
                         self.parser.make_length("110.49") - self.parser.make_length('118.11'))
        self.assertEqual(symattr.annotations[0].y / EAGLE_SCALE,
                         self.parser.make_length("127") - self.parser.make_length('139.7'))
        self.assertEqual(symattr.annotations[0].rotation, 0.0)
        self.assertEqual(symattr.annotations[1].value, 'SV3')
        self.assertEqual(symattr.annotations[1].x / EAGLE_SCALE,
                         self.parser.make_length("114.3") - self.parser.make_length('118.11'))
        self.assertEqual(symattr.annotations[1].y / EAGLE_SCALE,
                         self.parser.make_length("150.622") - self.parser.make_length('139.7'))
        self.assertEqual(symattr.annotations[1].rotation, 0.0)


    def test_arc_shape(self):
        """ Arc shapes are generated correctly. """
        parser = EagleXML()

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 0.0)
        self.assertEqual(s.end_angle, 1.0)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='-25.4', y1='0', x2='25.4', y2='0', curve='180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 1.0)
        self.assertEqual(s.end_angle, 0.0)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('-25.4'))
        self.assertEqual(s.start_angle, 0.25)
        self.assertEqual(s.end_angle, 0.75)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='-90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('25.4'))
        self.assertEqual(s.start_angle, 1.25)
        self.assertEqual(s.end_angle, 1.75)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='0', y1='25.4', x2='0', y2='-25.4', curve='90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, self.make_length('25.4'))
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 0.75)
        self.assertEqual(s.end_angle, 1.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='0', y1='25.4', x2='0', y2='-25.4', curve='-180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 1.5)
        self.assertEqual(s.end_angle, 0.5)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='270')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('25.4'))
        self.assertEqual(s.start_angle, 1.75)
        self.assertEqual(s.end_angle, 1.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='-270')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('-25.4'))
        self.assertEqual(s.start_angle, 0.75)
        self.assertEqual(s.end_angle, 0.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))


    def get_component(self, library_id):
        """ Return the component given its id. """
        return self.design.components.components[library_id]


    def get_instance(self, instance_id):
        """ Return the instance given its id. """
        return [ci for ci in self.design.component_instances
                if ci.instance_id == instance_id][0]


    def make_length(self, length):
        """ Return a length from the parser. """
        return self.parser.make_length(length)


    def make_point_name(self, x, y):
        """ Return a point name given an eaglexml point. """
        return '%sa%s' % (self.make_length(x), self.make_length(y))
 def setUp(self):
     self.parser = EagleXML()
 def test_create_new_eaglexml_parser(self):
     """ Test creating an empty parser. """
     self.assertNotEqual(EagleXML(), None)
    def test_arc_shape(self):
        """ Arc shapes are generated correctly. """
        parser = EagleXML()

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 0.0)
        self.assertEqual(s.end_angle, 1.0)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='-25.4', y1='0', x2='25.4', y2='0', curve='180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 1.0)
        self.assertEqual(s.end_angle, 0.0)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('-25.4'))
        self.assertEqual(s.start_angle, 0.25)
        self.assertEqual(s.end_angle, 0.75)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='-90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('25.4'))
        self.assertEqual(s.start_angle, 1.25)
        self.assertEqual(s.end_angle, 1.75)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='0', y1='25.4', x2='0', y2='-25.4', curve='90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, self.make_length('25.4'))
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 0.75)
        self.assertEqual(s.end_angle, 1.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='0', y1='25.4', x2='0', y2='-25.4', curve='-180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 1.5)
        self.assertEqual(s.end_angle, 0.5)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='270')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('25.4'))
        self.assertEqual(s.start_angle, 1.75)
        self.assertEqual(s.end_angle, 1.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='-270')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('-25.4'))
        self.assertEqual(s.start_angle, 0.75)
        self.assertEqual(s.end_angle, 0.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))
Пример #6
0
 def test_make_length(self):
     """ Lengths are converted correctly. """
     parser = EagleXML()
     self.assertEqual(parser.make_length("0"), 0)
     self.assertEqual(parser.make_length("254"), int(900 * 2.0))
def get_design(filename):
    if filename not in _cache:
        parser = EagleXML()
        _cache[filename] = parser.parse(join(TEST_DIR, filename))
    return _cache[filename]
Пример #8
0
class EagleXMLTests(unittest.TestCase):
    """ The tests of the eagle-xml parser """
    def setUp(self):
        self.parser = EagleXML()

    def test_create_new_eaglexml_parser(self):
        """ Test creating an empty parser. """
        self.assertNotEqual(self.parser, None)

    def test_make_length(self):
        """ Lengths are converted correctly. """
        parser = EagleXML()
        self.assertEqual(parser.make_length("0"), 0)
        self.assertEqual(parser.make_length("254"), int(900 * 2.0))

    @use_file('E1AA60D5.sch')
    def test_library_components(self):
        """ A deviceset should have a matching component. """
        self.assertTrue('atmel:TINY15L:P' in self.design.components.components)

    @use_file('E1AA60D5.sch')
    def test_component_symbols(self):
        """ A component should have 1 symbol. """
        self.assertEqual(len(self.get_component('atmel:TINY15L:P').symbols), 1)

    @use_file('D9CD1423.sch')
    def test_component_bodies(self):
        """ A deviceset with 2 gates should have 2 bodies. """
        cpt = self.get_component('Discrete:010-DUAL-N-MOSFET*:_1206-8')
        self.assertEqual(len(cpt.symbols[0].bodies), 2)

    @use_file('E1AA60D5.sch')
    def test_component_body_lines(self):
        """ The right component Lines are created on SBody objects. """
        cpt = self.get_component('atmel:TINY15L:P')
        lines = [
            s for s in cpt.symbols[0].bodies[0].shapes if s.type == 'line'
        ]
        self.assertEqual(len(lines), 4)
        self.assertEqual(lines[0].p1.x / EAGLE_SCALE, self.make_length("12.7"))
        self.assertEqual(lines[0].p1.y / EAGLE_SCALE,
                         self.make_length("-10.16"))
        self.assertEqual(lines[0].p2.x / EAGLE_SCALE,
                         self.make_length("-12.7"))
        self.assertEqual(lines[0].p2.y / EAGLE_SCALE,
                         self.make_length("-10.16"))

    @use_file('E1AA60D5.sch')
    def test_component_body_rectangles(self):
        """ The right component Rectangles are created on SBody objects. """
        cpt = self.get_component('resistor:CPOL-EU:E2.5-6')
        rects = [
            s for s in cpt.symbols[0].bodies[0].shapes if s.type == 'rectangle'
        ]
        self.assertEqual(len(rects), 1)
        self.assertEqual(rects[0].x / EAGLE_SCALE, self.make_length("-1.651"))
        self.assertEqual(rects[0].y / EAGLE_SCALE, self.make_length("-1.651"))
        self.assertEqual(
            rects[0].width / EAGLE_SCALE,
            self.make_length("1.651") - self.make_length("-1.651"))
        self.assertEqual(
            rects[0].height / EAGLE_SCALE,
            self.make_length("-1.651") - self.make_length("-2.54"))

    @use_file('S12G_Micro_20EVB_RevA.sch')
    def test_component_body_rectangles_rot(self):
        """ The right rotations are applied to Rectangles on SBody objects. """

        cpt = self.get_component('myLibrary:L:0805')
        rect = [
            s for s in cpt.symbols[0].bodies[0].shapes if s.type == 'rectangle'
        ][0]
        self.assertEqual(rect.x / EAGLE_SCALE, self.make_length("-3.556"))
        self.assertEqual(rect.y / EAGLE_SCALE, self.make_length("1.016"))
        self.assertEqual(
            rect.width / EAGLE_SCALE,
            self.make_length("3.556") - self.make_length("-3.556"))
        self.assertEqual(
            rect.height / EAGLE_SCALE,
            self.make_length("1.016") - self.make_length("-1.016"))

    @use_file('450B679C.sch')
    def test_component_body_polygons(self):
        """ The right component Rectangles are created on SBody objects. """

        cpt = self.get_component('adafruit:LED:5MM')
        polys = [
            s for s in cpt.symbols[0].bodies[0].shapes if s.type == 'polygon'
        ]
        self.assertEqual(len(polys), 2)
        self.assertEqual(len(polys[0].points), 3)
        self.assertEqual(polys[0].points[0].x / EAGLE_SCALE,
                         self.make_length("-3.429"))
        self.assertEqual(polys[0].points[0].y / EAGLE_SCALE,
                         self.make_length("-2.159"))

    @use_file('D9CD1423.sch')
    def test_component_body_circles(self):
        """ The right component Circles are created on SBody objects. """

        cpt = self.get_component('CONNECTER:HEADER_1X10:DD')
        circs = [
            s for s in cpt.symbols[0].bodies[0].shapes if s.type == 'circle'
        ]
        self.assertEqual(len(circs), 9)
        self.assertEqual(circs[0].x, self.make_length("0"))
        self.assertEqual(circs[0].y / EAGLE_SCALE, self.make_length("8.89"))
        self.assertEqual(circs[0].radius / EAGLE_SCALE,
                         self.make_length("1.016"))
        self.assertEqual(circs[0].attributes['eaglexml_width'], "0.254")

    @use_file('E1AA60D5.sch')
    def test_component_body_labels(self):
        """ The right component Labels are created on SBody objects. """
        cpt = self.get_component('con-berg:PN87520:')
        labels = [
            s for s in cpt.symbols[0].bodies[0].shapes if s.type == 'label'
        ]
        self.assertEqual(len(labels), 1)
        self.assertEqual(labels[0].x / EAGLE_SCALE, self.make_length("5.08"))
        self.assertEqual(labels[0].y / EAGLE_SCALE, self.make_length("-2.54"))
        self.assertEqual(labels[0].text, 'USB')
        self.assertEqual(labels[0]._rotation, 1.5)

    @use_file('msp430_f249_ctk.sch')
    def test_component_body_labels_mirrored(self):
        """ The right component Labels are created on SBody objects. """
        cpt = self.get_component('TI_MSP430_v16:F24[X/10]---PM64:')
        labels = [
            s for s in cpt.symbols[0].bodies[0].shapes
            if s.type == 'label' and s.text == 'P4.6/TB6'
        ]
        self.assertEqual(len(labels), 1)
        self.assertEqual(labels[0].x / EAGLE_SCALE, self.make_length("36.83"))
        self.assertEqual(labels[0].y / EAGLE_SCALE, self.make_length("0.0"))
        self.assertEqual(labels[0]._rotation, 0.0)
        self.assertEqual(labels[0].align, 'right')

    @use_file('E1AA60D5.sch')
    def test_component_body_pins(self):
        """ The right component Pins are created on SBody objects. """
        cpt = self.get_component('atmel:TINY15L:P')
        pins = cpt.symbols[0].bodies[0].pins
        self.assertEqual(len(pins), 8)
        self.assertEqual(pins[0].p1.x / EAGLE_SCALE, 90)
        self.assertEqual(pins[0].p1.y / EAGLE_SCALE, 18)
        self.assertEqual(pins[0].p2.x / EAGLE_SCALE, self.make_length("17.78"))
        self.assertEqual(pins[0].p2.y / EAGLE_SCALE, self.make_length("2.54"))
        self.assertEqual(pins[0].label.text, '(ADC3)PB4')
        self.assertEqual(pins[0].label.x / EAGLE_SCALE, 85.0)
        self.assertEqual(pins[0].label.y / EAGLE_SCALE, 15.0)
        self.assertEqual(pins[0].label._rotation, 0.0)
        self.assertEqual([p.pin_number for p in pins],
                         ['2', '3', '1', '7', '6', '5', '8', '4'])
        self.assertEqual([p.label.text for p in pins], [
            '(ADC3)PB4', '(ADC2)PB3', '(ADC0)PB5', '(ADC1)PB2', '(OCP)PB1',
            '(AREF)PB0', 'VCC', 'GND'
        ])
        cpt = self.get_component('diode:ZENER-DIODE:DO35Z10')
        pins = cpt.symbols[0].bodies[0].pins
        self.assertEqual(pins[0].label, None)
        self.assertEqual([p.pin_number for p in pins], ['A', 'C'])

    @use_file('Shock Controller.sch')
    def test_component_body_pin_duplicate_names(self):
        """ Duplicate pin names on different gates are de-duplicated
        with pin numbers. """

        cpt = self.get_component('con-molex:22-?-04:27-2041')
        pin_numbers = [
            p.pin_number for b in cpt.symbols[0].bodies for p in b.pins
        ]
        self.assertEqual(pin_numbers, ['1', '2', '3', '4'])

    @use_file('E1AA60D5.sch')
    def test_component_instances(self):
        """ The right component instances are created. """
        self.assertEqual(
            set(ci.instance_id for ci in self.design.component_instances),
            set(('Q1', 'X2', 'C2', 'IC1', 'X1', 'R4', 'R1', 'R2', 'R3', 'GND3',
                 'GND2', 'GND1', 'GND7', 'GND6', 'GND5', 'GND4', 'C1', 'P+2',
                 'P+3', 'P+1', 'P+6', 'P+4', 'P+5', 'D2', 'D1')))

    @use_file('E1AA60D5.sch')
    def test_component_instance_rotation(self):
        """ Component instance rotation is correct. """
        inst = self.get_instance('GND3')
        self.assertEqual(inst.symbol_attributes[0].rotation, 0)
        inst = self.get_instance('R2')
        self.assertEqual(inst.symbol_attributes[0].rotation, 1.5)

    @use_file('E1AA60D5.sch')
    def test_component_instance_refdes(self):
        """ Component instance refdes is correct. """
        inst = self.get_instance('GND3')
        self.assertEqual(inst.get_attribute('refdes'), 'GND3')

    @use_file('E1AA60D5.sch')
    def test_component_instance_position(self):
        """ Component instance position is correct. """
        inst = self.get_instance('GND3')
        self.assertEqual(len(inst.symbol_attributes), 1)
        self.assertEqual(inst.symbol_attributes[0].x / EAGLE_SCALE,
                         self.make_length("116.84"))
        self.assertEqual(inst.symbol_attributes[0].y / EAGLE_SCALE,
                         self.make_length("55.88"))

    @use_file('E1AA60D5.sch')
    def test_component_instance_value(self):
        """ Component instance value is correct. """
        inst = self.get_instance('R2')
        self.assertEqual(inst.attributes['value'], '68')

    @use_file('E1AA60D5.sch')
    def test_component_instance_annotations(self):
        """ Component instance annotations are correct. """
        inst = self.get_instance('R2')
        anns = inst.symbol_attributes[0].annotations
        self.assertEqual(len(anns), 2)
        self.assertEqual(anns[0].value, 'R2')
        self.assertEqual(anns[0].x / EAGLE_SCALE, -27)
        self.assertEqual(anns[0].y / EAGLE_SCALE, 11)
        self.assertEqual(anns[1].value, '68')
        self.assertEqual(anns[1].x / EAGLE_SCALE, -27)
        self.assertEqual(anns[1].y / EAGLE_SCALE, -23)

    @use_file('WiFi.sch')
    def test_component_instance_annotations_case_insensitive(self):
        """ Component instance annotations are correct. """
        inst = self.get_instance('U$1')
        anns = inst.symbol_attributes[0].annotations
        self.assertEqual(len(anns), 1)
        self.assertEqual(anns[0].value, 'U$1')

    @use_file('pcb_switch_switch.sch')
    def test_component_instance_annotations_multi_gates(self):
        """ Component instance annotations with multiple gates are correct. """
        inst = self.get_instance('X1')
        values = []
        for attr in inst.symbol_attributes:
            for ann in attr.annotations:
                values.append(ann.value)
        self.assertEqual(set(values), set(['SW', 'X1-1', 'X1-2']))

    @use_file('E1AA60D5.sch')
    def test_nets(self):
        """ The right nets are created. """
        self.assertEqual(
            set(n.net_id for n in self.design.nets),
            set([
                'VCC', 'GND', 'N$1', 'N$2', 'N$3', 'N$4', 'N$5', 'N$6', 'N$7'
            ]))

    @use_file('E1AA60D5.sch')
    def test_net_points(self):
        """ The right net points are created. """
        net = [n for n in self.design.nets if n.net_id == 'GND'][0]
        self.assertEqual(len(net.points), 13)
        self.assertTrue(self.make_point_name("40.64", "63.5") in net.points)

    @use_file('E1AA60D5.sch')
    def test_net_points_connected(self):
        """ The right net points are connected. """
        net = [n for n in self.design.nets if n.net_id == 'N$7'][0]
        pt = net.points[self.make_point_name("83.82", "68.58")]
        self.assertEqual(sorted(pt.connected_points), [
            self.make_point_name("76.2", "68.58"),
            self.make_point_name("83.82", "48.26")
        ])

    @use_file('S12G_Micro_20EVB_RevA.sch')
    def test_net_points_connected_rot(self):
        """ The right net points are connected for a rotated part. """
        net = [n for n in self.design.nets if n.net_id == 'GND'][0]
        pt = net.points[self.make_point_name("0", "15.24")]
        self.assertEqual(sorted(pt.connected_points),
                         [self.make_point_name("0", "7.62")])

    @use_file('S12G_Micro_20EVB_RevA.sch')
    def test_net_points_connected_flip_rot(self):
        """ The right net points are connected for a flipped and rotated part. """
        net = [n for n in self.design.nets if n.net_id == 'PT1'][0]
        pt = net.points[self.make_point_name("162.56", "33.02")]
        self.assertEqual(sorted(pt.connected_points),
                         [self.make_point_name("162.56", "30.48")])

    @use_file('E1AA60D5.sch')
    def test_net_points_connected_components(self):
        """ The right net points are connected to the right components. """
        net = [n for n in self.design.nets if n.net_id == 'N$7'][0]
        pt = net.points[self.make_point_name("76.2", "68.58")]
        self.assertEqual(len(pt.connected_components), 1)
        self.assertEqual(pt.connected_components[0].instance_id, 'IC1')
        self.assertEqual(pt.connected_components[0].pin_number, '7')

    @use_file('D9CD1423.sch')
    def test_smashed_annotations(self):
        """ The right annotations are created for smashed components. """
        inst = self.get_instance('U1')
        symattr = inst.symbol_attributes[0]
        self.assertEqual(len(symattr.annotations), 2)
        self.assertEqual(symattr.annotations[0].value, 'U1')
        self.assertEqual(symattr.annotations[0].x / EAGLE_SCALE,
                         self.parser.make_length("22.86"))
        self.assertEqual(symattr.annotations[0].y / EAGLE_SCALE,
                         self.parser.make_length("52.07"))
        self.assertEqual(symattr.annotations[0].rotation, 0.0)
        self.assertEqual(symattr.annotations[1].value, 'ATMEGA328AU')
        self.assertEqual(symattr.annotations[1].x / EAGLE_SCALE,
                         self.parser.make_length("22.86"))
        self.assertEqual(symattr.annotations[1].y / EAGLE_SCALE,
                         self.parser.make_length("43.18"))
        self.assertEqual(symattr.annotations[1].rotation, 0.0)

    @use_file('msp430_f249_ctk.sch')
    def test_smashed_annotations_offset(self):
        """ The right annotations are created for smashed components. """
        inst = self.get_instance('SV3')
        symattr = inst.symbol_attributes[0]
        self.assertEqual(len(symattr.annotations), 2)
        self.assertEqual(symattr.annotations[0].value, '14 PIN JTAG')
        self.assertEqual(
            symattr.annotations[0].x / EAGLE_SCALE,
            self.parser.make_length("110.49") -
            self.parser.make_length('118.11'))
        self.assertEqual(
            symattr.annotations[0].y / EAGLE_SCALE,
            self.parser.make_length("127") - self.parser.make_length('139.7'))
        self.assertEqual(symattr.annotations[0].rotation, 0.0)
        self.assertEqual(symattr.annotations[1].value, 'SV3')
        self.assertEqual(
            symattr.annotations[1].x / EAGLE_SCALE,
            self.parser.make_length("114.3") -
            self.parser.make_length('118.11'))
        self.assertEqual(
            symattr.annotations[1].y / EAGLE_SCALE,
            self.parser.make_length("150.622") -
            self.parser.make_length('139.7'))
        self.assertEqual(symattr.annotations[1].rotation, 0.0)

    def test_arc_shape(self):
        """ Arc shapes are generated correctly. """
        parser = EagleXML()

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 0.0)
        self.assertEqual(s.end_angle, 1.0)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='-25.4', y1='0', x2='25.4', y2='0', curve='180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 1.0)
        self.assertEqual(s.end_angle, 0.0)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('-25.4'))
        self.assertEqual(s.start_angle, 0.25)
        self.assertEqual(s.end_angle, 0.75)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='-90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('25.4'))
        self.assertEqual(s.start_angle, 1.25)
        self.assertEqual(s.end_angle, 1.75)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='0', y1='25.4', x2='0', y2='-25.4', curve='90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, self.make_length('25.4'))
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 0.75)
        self.assertEqual(s.end_angle, 1.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='0', y1='25.4', x2='0', y2='-25.4', curve='-180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 1.5)
        self.assertEqual(s.end_angle, 0.5)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='270')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('25.4'))
        self.assertEqual(s.start_angle, 1.75)
        self.assertEqual(s.end_angle, 1.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='-270')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('-25.4'))
        self.assertEqual(s.start_angle, 0.75)
        self.assertEqual(s.end_angle, 0.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))

    def get_component(self, library_id):
        """ Return the component given its id. """
        return self.design.components.components[library_id]

    def get_instance(self, instance_id):
        """ Return the instance given its id. """
        return [
            ci for ci in self.design.component_instances
            if ci.instance_id == instance_id
        ][0]

    def make_length(self, length):
        """ Return a length from the parser. """
        return self.parser.make_length(length)

    def make_point_name(self, x, y):
        """ Return a point name given an eaglexml point. """
        return '%sa%s' % (self.make_length(x), self.make_length(y))
Пример #9
0
 def setUp(self):
     self.parser = EagleXML()
Пример #10
0
    def test_arc_shape(self):
        """ Arc shapes are generated correctly. """
        parser = EagleXML()

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 0.0)
        self.assertEqual(s.end_angle, 1.0)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='-25.4', y1='0', x2='25.4', y2='0', curve='180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 1.0)
        self.assertEqual(s.end_angle, 0.0)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('-25.4'))
        self.assertEqual(s.start_angle, 0.25)
        self.assertEqual(s.end_angle, 0.75)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='-90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('25.4'))
        self.assertEqual(s.start_angle, 1.25)
        self.assertEqual(s.end_angle, 1.75)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='0', y1='25.4', x2='0', y2='-25.4', curve='90')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, self.make_length('25.4'))
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 0.75)
        self.assertEqual(s.end_angle, 1.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='0', y1='25.4', x2='0', y2='-25.4', curve='-180')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, 0)
        self.assertEqual(s.start_angle, 1.5)
        self.assertEqual(s.end_angle, 0.5)
        self.assertEqual(s.radius, parser.make_length('25.4'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='270')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('25.4'))
        self.assertEqual(s.start_angle, 1.75)
        self.assertEqual(s.end_angle, 1.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))

        w = wire(x1='25.4', y1='0', x2='-25.4', y2='0', curve='-270')
        s = parser.make_shape_for_wire(w)
        self.assertEqual(s.x, 0)
        self.assertEqual(s.y, self.make_length('-25.4'))
        self.assertEqual(s.start_angle, 0.75)
        self.assertEqual(s.end_angle, 0.25)
        self.assertEqual(s.radius, parser.make_length('35.915'))
Пример #11
0
class EagleXMLTests(unittest.TestCase):
    """ The tests of the eagle-xml parser """

    def setUp(self):
        self.parser = EagleXML()


    def test_create_new_eaglexml_parser(self):
        """ Test creating an empty parser. """
        self.assertNotEqual(self.parser, None)


    def test_make_length(self):
        """ Lengths are converted correctly. """
        parser = EagleXML()
        self.assertEqual(parser.make_length("0"), 0)
        self.assertEqual(parser.make_length("254"), int(900 * 2.0))


    @use_file('E1AA60D5.sch')
    def test_library_components(self):
        """ A deviceset should have a matching component. """
        self.assertTrue('atmel:TINY15L:logical'
                        in self.design.components.components)


    @use_file('E1AA60D5.sch')
    def test_component_symbols(self):
        """ A logical component should have 1 symbol. """
        self.assertEqual(
            len(self.get_component('atmel:TINY15L:logical').symbols), 1)


    @use_file('D9CD1423.sch')
    def test_component_bodies(self):
        """ A deviceset with 2 gates should have 2 bodies. """
        cpt = self.get_component('Discrete:010-DUAL-N-MOSFET*:logical')
        self.assertEqual(len(cpt.symbols[0].bodies), 2)


    @use_file('E1AA60D5.sch')
    def test_component_body_lines(self):
        """ The right component Lines are created on Body objects. """
        cpt = self.get_component('atmel:TINY15L:logical')
        lines = [s for s in cpt.symbols[0].bodies[0].shapes
                 if s.type == 'line']
        self.assertEqual(len(lines), 4)
        self.assertEqual(lines[0].p1.x, self.make_length("12.7"))
        self.assertEqual(lines[0].p1.y, self.make_length("-10.16"))
        self.assertEqual(lines[0].p2.x, self.make_length("-12.7"))
        self.assertEqual(lines[0].p2.y, self.make_length("-10.16"))


    @use_file('E1AA60D5.sch')
    def test_component_body_rectangles(self):
        """ The right component Rectangles are created on Body objects. """
        cpt = self.get_component('resistor:CPOL-EU:logical')
        rects = [s for s in cpt.symbols[0].bodies[0].shapes
                 if s.type == 'rectangle']
        self.assertEqual(len(rects), 1)
        self.assertEqual(rects[0].x, self.make_length("-1.651"))
        self.assertEqual(rects[0].y, self.make_length("-1.651"))
        self.assertEqual(rects[0].width,
                         self.make_length("1.651") - self.make_length("-1.651"))
        self.assertEqual(rects[0].height,
                         self.make_length("-1.651") - self.make_length("-2.54"))


    @use_file('E1AA60D5.sch')
    def test_component_body_labels(self):
        """ The right component Labels are created on Body objects. """
        cpt = self.get_component('con-berg:PN87520:logical')
        labels = [s for s in cpt.symbols[0].bodies[0].shapes
                  if s.type == 'label']
        self.assertEqual(len(labels), 1)
        self.assertEqual(labels[0].x, self.make_length("5.08"))
        self.assertEqual(labels[0].y, self.make_length("-2.54"))
        self.assertEqual(labels[0].text, 'USB')
        self.assertEqual(labels[0].rotation, 1.5)


    @use_file('E1AA60D5.sch')
    def test_component_body_pins(self):
        """ The right component Pins are created on Body objects. """
        cpt = self.get_component('atmel:TINY15L:logical')
        pins = cpt.symbols[0].bodies[0].pins
        self.assertEqual(len(pins), 8)
        self.assertEqual(pins[0].p1.x, 90)
        self.assertEqual(pins[0].p1.y, 18)
        self.assertEqual(pins[0].p2.x, self.make_length("17.78"))
        self.assertEqual(pins[0].p2.y, self.make_length("2.54"))
        self.assertEqual(pins[0].label.text, '(ADC3)PB4')
        self.assertEqual(pins[0].label.x, 0)
        self.assertEqual(pins[0].label.y, 18)
        self.assertEqual(pins[0].label.rotation, 0.0)

        cpt = self.get_component('diode:ZENER-DIODE:logical')
        pins = cpt.symbols[0].bodies[0].pins
        self.assertEqual(pins[0].label, None)


    @use_file('E1AA60D5.sch')
    def test_component_instances(self):
        """ The right component instances are created. """
        self.assertEqual(
            set(ci.instance_id for ci in self.design.component_instances),
            set(('Q1', 'X2', 'C2', 'IC1', 'X1', 'R4', 'R1', 'R2', 'R3', 'GND3',
                 'GND2', 'GND1', 'GND7', 'GND6', 'GND5', 'GND4','C1', 'P+2',
                 'P+3', 'P+1', 'P+6', 'P+4','P+5', 'D2', 'D1')))


    @use_file('E1AA60D5.sch')
    def test_component_instance_rotation(self):
        """ Component instance rotation is correct. """
        inst = self.get_instance('GND3')
        self.assertEqual(inst.symbol_attributes[0].rotation, 0)
        inst = self.get_instance('R2')
        self.assertEqual(inst.symbol_attributes[0].rotation, 1.5)


    @use_file('E1AA60D5.sch')
    def test_component_instance_position(self):
        """ Component instance position is correct. """
        inst = self.get_instance('GND3')
        self.assertEqual(len(inst.symbol_attributes), 1)
        self.assertEqual(inst.symbol_attributes[0].x, self.make_length("116.84"))
        self.assertEqual(inst.symbol_attributes[0].y, self.make_length("55.88"))


    @use_file('E1AA60D5.sch')
    def test_component_instance_value(self):
        """ Component instance value is correct. """
        inst = self.get_instance('R2')
        self.assertEqual(inst.attributes['value'], '68')


    @use_file('E1AA60D5.sch')
    def test_component_instance_annotations(self):
        """ Component instance annotations are correct. """
        inst = self.get_instance('R2')
        anns = inst.symbol_attributes[0].annotations
        self.assertEqual(len(anns), 2)
        self.assertEqual(anns[0].value, 'R2')
        self.assertEqual(anns[0].x, -27)
        self.assertEqual(anns[0].y, 11)
        self.assertEqual(anns[1].value, '68')
        self.assertEqual(anns[1].x, -27)
        self.assertEqual(anns[1].y, -23)


    @use_file('E1AA60D5.sch')
    def test_nets(self):
        """ The right nets are created. """
        self.assertEqual(set(n.net_id for n in self.design.nets),
                         set(['VCC', 'GND', 'N$1', 'N$2', 'N$3',
                              'N$4', 'N$5', 'N$6', 'N$7']))


    @use_file('E1AA60D5.sch')
    def test_net_points(self):
        """ The right net points are created. """
        net = [n for n in self.design.nets if n.net_id == 'GND'][0]
        self.assertEqual(len(net.points), 13)
        self.assertTrue(self.make_point_name("40.64", "63.5") in net.points)


    @use_file('E1AA60D5.sch')
    def test_net_points_connected(self):
        """ The right net points are connected. """
        net = [n for n in self.design.nets if n.net_id == 'N$7'][0]
        pt = net.points[self.make_point_name("83.82", "68.58")]
        self.assertEqual(sorted(pt.connected_points),
                         [self.make_point_name("76.2", "68.58"),
                          self.make_point_name("83.82", "48.26")])


    @use_file('E1AA60D5.sch')
    def test_net_points_connected_components(self):
        """ The right net points are connected to the right components. """
        net = [n for n in self.design.nets if n.net_id == 'N$7'][0]
        pt = net.points[self.make_point_name("76.2", "68.58")]
        self.assertEqual(len(pt.connected_components), 1)
        self.assertEqual(pt.connected_components[0].instance_id, 'IC1')
        self.assertEqual(pt.connected_components[0].pin_number, '(ADC1)PB2')


    @use_file('D9CD1423.sch')
    def test_smashed_annotations(self):
        """ The right annotations are created for smashed components. """
        inst = self.get_instance('U1')
        symattr = inst.symbol_attributes[0]
        self.assertEqual(len(symattr.annotations), 2)
        self.assertEqual(symattr.annotations[0].value, 'U1')
        self.assertEqual(symattr.annotations[0].x, self.parser.make_length("22.86"))
        self.assertEqual(symattr.annotations[0].y, self.parser.make_length("52.07"))
        self.assertEqual(symattr.annotations[0].rotation, 0.0)
        self.assertEqual(symattr.annotations[1].value, 'ATMEGA328AU')
        self.assertEqual(symattr.annotations[1].x, self.parser.make_length("22.86"))
        self.assertEqual(symattr.annotations[1].y, self.parser.make_length("43.18"))
        self.assertEqual(symattr.annotations[1].rotation, 0.0)


    def get_component(self, library_id):
        """ Return the component given its id. """
        return self.design.components.components[library_id]


    def get_instance(self, instance_id):
        """ Return the instance given its id. """
        return [ci for ci in self.design.component_instances
                if ci.instance_id == instance_id][0]


    def make_length(self, length):
        """ Return a length from the parser. """
        return self.parser.make_length(length)


    def make_point_name(self, x, y):
        """ Return a point name given an eaglexml point. """
        return '%sa%s' % (self.make_length(x), self.make_length(y))
class EagleXMLTests(unittest.TestCase):
    """ The tests of the eagle-xml parser """

    def setUp(self):
        self.parser = EagleXML()


    def test_create_new_eaglexml_parser(self):
        """ Test creating an empty parser. """
        self.assertNotEqual(self.parser, None)


    def test_make_length(self):
        """ Lengths are converted correctly. """
        parser = EagleXML()
        self.assertEqual(parser.make_length("0"), 0)
        self.assertEqual(parser.make_length("254"), int(900 * 2.0))


    @use_file('E1AA60D5.sch')
    def test_library_components(self):
        """ A deviceset should have a matching component. """
        self.assertTrue('atmel:TINY15L:logical'
                        in self.design.components.components)


    @use_file('E1AA60D5.sch')
    def test_component_symbols(self):
        """ A logical component should have 1 symbol. """
        self.assertEqual(
            len(self.get_component('atmel:TINY15L:logical').symbols), 1)


    @use_file('D9CD1423.sch')
    def test_component_bodies(self):
        """ A deviceset with 2 gates should have 2 bodies. """
        cpt = self.get_component('Discrete:010-DUAL-N-MOSFET*:logical')
        self.assertEqual(len(cpt.symbols[0].bodies), 2)


    @use_file('E1AA60D5.sch')
    def test_component_body_lines(self):
        """ The right component Lines are created on Body objects. """
        cpt = self.get_component('atmel:TINY15L:logical')
        lines = [s for s in cpt.symbols[0].bodies[0].shapes
                 if s.type == 'line']
        self.assertEqual(len(lines), 4)
        self.assertEqual(lines[0].p1.x, self.make_length("12.7"))
        self.assertEqual(lines[0].p1.y, self.make_length("-10.16"))
        self.assertEqual(lines[0].p2.x, self.make_length("-12.7"))
        self.assertEqual(lines[0].p2.y, self.make_length("-10.16"))


    @use_file('E1AA60D5.sch')
    def test_component_body_rectangles(self):
        """ The right component Rectangles are created on Body objects. """
        cpt = self.get_component('resistor:CPOL-EU:logical')
        rects = [s for s in cpt.symbols[0].bodies[0].shapes
                 if s.type == 'rectangle']
        self.assertEqual(len(rects), 1)
        self.assertEqual(rects[0].x, self.make_length("-1.651"))
        self.assertEqual(rects[0].y, self.make_length("-1.651"))
        self.assertEqual(rects[0].width,
                         self.make_length("1.651") - self.make_length("-1.651"))
        self.assertEqual(rects[0].height,
                         self.make_length("-1.651") - self.make_length("-2.54"))


    @use_file('450B679C.sch')
    def test_component_body_polygons(self):
        """ The right component Rectangles are created on Body objects. """

        cpt = self.get_component('adafruit:LED:logical')
        polys = [s for s in cpt.symbols[0].bodies[0].shapes
                 if s.type == 'polygon']
        self.assertEqual(len(polys), 2)
        self.assertEqual(len(polys[0].points), 3)
        self.assertEqual(polys[0].points[0].x, self.make_length("-3.429"))
        self.assertEqual(polys[0].points[0].y, self.make_length("-2.159"))


    @use_file('D9CD1423.sch')
    def test_component_body_circles(self):
        """ The right component Circles are created on Body objects. """

        cpt = self.get_component('CONNECTER:HEADER_1X10:logical')
        circs = [s for s in cpt.symbols[0].bodies[0].shapes
                 if s.type == 'circle']
        self.assertEqual(len(circs), 9)
        self.assertEqual(circs[0].x, self.make_length("0"))
        self.assertEqual(circs[0].y, self.make_length("8.89"))
        self.assertEqual(circs[0].radius, self.make_length("1.016"))
        self.assertEqual(circs[0].attributes['eaglexml_width'], "0.254")


    @use_file('E1AA60D5.sch')
    def test_component_body_labels(self):
        """ The right component Labels are created on Body objects. """
        cpt = self.get_component('con-berg:PN87520:logical')
        labels = [s for s in cpt.symbols[0].bodies[0].shapes
                  if s.type == 'label']
        self.assertEqual(len(labels), 1)
        self.assertEqual(labels[0].x, self.make_length("5.08"))
        self.assertEqual(labels[0].y, self.make_length("-2.54"))
        self.assertEqual(labels[0].text, 'USB')
        self.assertEqual(labels[0].rotation, 1.5)


    @use_file('E1AA60D5.sch')
    def test_component_body_pins(self):
        """ The right component Pins are created on Body objects. """
        cpt = self.get_component('atmel:TINY15L:logical')
        pins = cpt.symbols[0].bodies[0].pins
        self.assertEqual(len(pins), 8)
        self.assertEqual(pins[0].p1.x, 90)
        self.assertEqual(pins[0].p1.y, 18)
        self.assertEqual(pins[0].p2.x, self.make_length("17.78"))
        self.assertEqual(pins[0].p2.y, self.make_length("2.54"))
        self.assertEqual(pins[0].label.text, '(ADC3)PB4')
        self.assertEqual(pins[0].label.x, 0)
        self.assertEqual(pins[0].label.y, 18)
        self.assertEqual(pins[0].label.rotation, 0.0)

        cpt = self.get_component('diode:ZENER-DIODE:logical')
        pins = cpt.symbols[0].bodies[0].pins
        self.assertEqual(pins[0].label, None)


    @use_file('E1AA60D5.sch')
    def test_component_instances(self):
        """ The right component instances are created. """
        self.assertEqual(
            set(ci.instance_id for ci in self.design.component_instances),
            set(('Q1', 'X2', 'C2', 'IC1', 'X1', 'R4', 'R1', 'R2', 'R3', 'GND3',
                 'GND2', 'GND1', 'GND7', 'GND6', 'GND5', 'GND4','C1', 'P+2',
                 'P+3', 'P+1', 'P+6', 'P+4','P+5', 'D2', 'D1')))


    @use_file('E1AA60D5.sch')
    def test_component_instance_rotation(self):
        """ Component instance rotation is correct. """
        inst = self.get_instance('GND3')
        self.assertEqual(inst.symbol_attributes[0].rotation, 0)
        inst = self.get_instance('R2')
        self.assertEqual(inst.symbol_attributes[0].rotation, 1.5)


    @use_file('E1AA60D5.sch')
    def test_component_instance_position(self):
        """ Component instance position is correct. """
        inst = self.get_instance('GND3')
        self.assertEqual(len(inst.symbol_attributes), 1)
        self.assertEqual(inst.symbol_attributes[0].x, self.make_length("116.84"))
        self.assertEqual(inst.symbol_attributes[0].y, self.make_length("55.88"))


    @use_file('E1AA60D5.sch')
    def test_component_instance_value(self):
        """ Component instance value is correct. """
        inst = self.get_instance('R2')
        self.assertEqual(inst.attributes['value'], '68')


    @use_file('E1AA60D5.sch')
    def test_component_instance_annotations(self):
        """ Component instance annotations are correct. """
        inst = self.get_instance('R2')
        anns = inst.symbol_attributes[0].annotations
        self.assertEqual(len(anns), 2)
        self.assertEqual(anns[0].value, 'R2')
        self.assertEqual(anns[0].x, -27)
        self.assertEqual(anns[0].y, 11)
        self.assertEqual(anns[1].value, '68')
        self.assertEqual(anns[1].x, -27)
        self.assertEqual(anns[1].y, -23)


    @use_file('E1AA60D5.sch')
    def test_nets(self):
        """ The right nets are created. """
        self.assertEqual(set(n.net_id for n in self.design.nets),
                         set(['VCC', 'GND', 'N$1', 'N$2', 'N$3',
                              'N$4', 'N$5', 'N$6', 'N$7']))


    @use_file('E1AA60D5.sch')
    def test_net_points(self):
        """ The right net points are created. """
        net = [n for n in self.design.nets if n.net_id == 'GND'][0]
        self.assertEqual(len(net.points), 13)
        self.assertTrue(self.make_point_name("40.64", "63.5") in net.points)


    @use_file('E1AA60D5.sch')
    def test_net_points_connected(self):
        """ The right net points are connected. """
        net = [n for n in self.design.nets if n.net_id == 'N$7'][0]
        pt = net.points[self.make_point_name("83.82", "68.58")]
        self.assertEqual(sorted(pt.connected_points),
                         [self.make_point_name("76.2", "68.58"),
                          self.make_point_name("83.82", "48.26")])


    @use_file('E1AA60D5.sch')
    def test_net_points_connected_components(self):
        """ The right net points are connected to the right components. """
        net = [n for n in self.design.nets if n.net_id == 'N$7'][0]
        pt = net.points[self.make_point_name("76.2", "68.58")]
        self.assertEqual(len(pt.connected_components), 1)
        self.assertEqual(pt.connected_components[0].instance_id, 'IC1')
        self.assertEqual(pt.connected_components[0].pin_number, '(ADC1)PB2')


    @use_file('D9CD1423.sch')
    def test_smashed_annotations(self):
        """ The right annotations are created for smashed components. """
        inst = self.get_instance('U1')
        symattr = inst.symbol_attributes[0]
        self.assertEqual(len(symattr.annotations), 2)
        self.assertEqual(symattr.annotations[0].value, 'U1')
        self.assertEqual(symattr.annotations[0].x, self.parser.make_length("22.86"))
        self.assertEqual(symattr.annotations[0].y, self.parser.make_length("52.07"))
        self.assertEqual(symattr.annotations[0].rotation, 0.0)
        self.assertEqual(symattr.annotations[1].value, 'ATMEGA328AU')
        self.assertEqual(symattr.annotations[1].x, self.parser.make_length("22.86"))
        self.assertEqual(symattr.annotations[1].y, self.parser.make_length("43.18"))
        self.assertEqual(symattr.annotations[1].rotation, 0.0)


    def get_component(self, library_id):
        """ Return the component given its id. """
        return self.design.components.components[library_id]


    def get_instance(self, instance_id):
        """ Return the instance given its id. """
        return [ci for ci in self.design.component_instances
                if ci.instance_id == instance_id][0]


    def make_length(self, length):
        """ Return a length from the parser. """
        return self.parser.make_length(length)


    def make_point_name(self, x, y):
        """ Return a point name given an eaglexml point. """
        return '%sa%s' % (self.make_length(x), self.make_length(y))
Пример #13
0
def get_design(filename):
    if filename not in _cache:
        parser = EagleXML()
        _cache[filename] = parser.parse(join(TEST_DIR, filename))
    return _cache[filename]
Пример #14
0
class EagleXMLTests(unittest.TestCase):
    """ The tests of the eagle-xml parser """

    def setUp(self):
        self.parser = EagleXML()

    def test_create_new_eaglexml_parser(self):
        """ Test creating an empty parser. """
        self.assertNotEqual(self.parser, None)

    def test_make_length(self):
        """ Lengths are converted correctly. """
        parser = EagleXML()
        self.assertEqual(parser.make_length("0"), 0)
        self.assertEqual(parser.make_length("254"), int(900 * 2.0))

    @use_file("E1AA60D5.sch")
    def test_library_components(self):
        """ A deviceset should have a matching component. """
        self.assertTrue("atmel:TINY15L:logical" in self.design.components.components)

    @use_file("E1AA60D5.sch")
    def test_component_symbols(self):
        """ A logical component should have 1 symbol. """
        self.assertEqual(len(self.get_component("atmel:TINY15L:logical").symbols), 1)

    @use_file("D9CD1423.sch")
    def test_component_bodies(self):
        """ A deviceset with 2 gates should have 2 bodies. """
        cpt = self.get_component("Discrete:010-DUAL-N-MOSFET*:logical")
        self.assertEqual(len(cpt.symbols[0].bodies), 2)

    @use_file("E1AA60D5.sch")
    def test_component_body_lines(self):
        """ The right component Lines are created on Body objects. """
        cpt = self.get_component("atmel:TINY15L:logical")
        lines = [s for s in cpt.symbols[0].bodies[0].shapes if s.type == "line"]
        self.assertEqual(len(lines), 4)
        self.assertEqual(lines[0].p1.x, self.make_length("12.7"))
        self.assertEqual(lines[0].p1.y, self.make_length("-10.16"))
        self.assertEqual(lines[0].p2.x, self.make_length("-12.7"))
        self.assertEqual(lines[0].p2.y, self.make_length("-10.16"))

    @use_file("E1AA60D5.sch")
    def test_component_body_rectangles(self):
        """ The right component Rectangles are created on Body objects. """
        cpt = self.get_component("resistor:CPOL-EU:logical")
        rects = [s for s in cpt.symbols[0].bodies[0].shapes if s.type == "rectangle"]
        self.assertEqual(len(rects), 1)
        self.assertEqual(rects[0].x, self.make_length("-1.651"))
        self.assertEqual(rects[0].y, self.make_length("-1.651"))
        self.assertEqual(rects[0].width, self.make_length("1.651") - self.make_length("-1.651"))
        self.assertEqual(rects[0].height, self.make_length("-1.651") - self.make_length("-2.54"))

    @use_file("E1AA60D5.sch")
    def test_component_body_labels(self):
        """ The right component Labels are created on Body objects. """
        cpt = self.get_component("con-berg:PN87520:logical")
        labels = [s for s in cpt.symbols[0].bodies[0].shapes if s.type == "label"]
        self.assertEqual(len(labels), 1)
        self.assertEqual(labels[0].x, self.make_length("5.08"))
        self.assertEqual(labels[0].y, self.make_length("-2.54"))
        self.assertEqual(labels[0].text, "USB")
        self.assertEqual(labels[0].rotation, 1.5)

    @use_file("E1AA60D5.sch")
    def test_component_body_pins(self):
        """ The right component Pins are created on Body objects. """
        cpt = self.get_component("atmel:TINY15L:logical")
        pins = cpt.symbols[0].bodies[0].pins
        self.assertEqual(len(pins), 8)
        self.assertEqual(pins[0].p1.x, 90)
        self.assertEqual(pins[0].p1.y, 18)
        self.assertEqual(pins[0].p2.x, self.make_length("17.78"))
        self.assertEqual(pins[0].p2.y, self.make_length("2.54"))
        self.assertEqual(pins[0].label.text, "(ADC3)PB4")
        self.assertEqual(pins[0].label.x, 0)
        self.assertEqual(pins[0].label.y, 18)
        self.assertEqual(pins[0].label.rotation, 0.0)

        cpt = self.get_component("diode:ZENER-DIODE:logical")
        pins = cpt.symbols[0].bodies[0].pins
        self.assertEqual(pins[0].label, None)

    @use_file("E1AA60D5.sch")
    def test_component_instances(self):
        """ The right component instances are created. """
        self.assertEqual(
            set(ci.instance_id for ci in self.design.component_instances),
            set(
                (
                    "Q1",
                    "X2",
                    "C2",
                    "IC1",
                    "X1",
                    "R4",
                    "R1",
                    "R2",
                    "R3",
                    "GND3",
                    "GND2",
                    "GND1",
                    "GND7",
                    "GND6",
                    "GND5",
                    "GND4",
                    "C1",
                    "P+2",
                    "P+3",
                    "P+1",
                    "P+6",
                    "P+4",
                    "P+5",
                    "D2",
                    "D1",
                )
            ),
        )

    @use_file("E1AA60D5.sch")
    def test_component_instance_rotation(self):
        """ Component instance rotation is correct. """
        inst = self.get_instance("GND3")
        self.assertEqual(inst.symbol_attributes[0].rotation, 0)
        inst = self.get_instance("R2")
        self.assertEqual(inst.symbol_attributes[0].rotation, 1.5)

    @use_file("E1AA60D5.sch")
    def test_component_instance_position(self):
        """ Component instance position is correct. """
        inst = self.get_instance("GND3")
        self.assertEqual(len(inst.symbol_attributes), 1)
        self.assertEqual(inst.symbol_attributes[0].x, self.make_length("116.84"))
        self.assertEqual(inst.symbol_attributes[0].y, self.make_length("55.88"))

    @use_file("E1AA60D5.sch")
    def test_component_instance_value(self):
        """ Component instance value is correct. """
        inst = self.get_instance("R2")
        self.assertEqual(inst.attributes["value"], "68")

    @use_file("E1AA60D5.sch")
    def test_component_instance_annotations(self):
        """ Component instance annotations are correct. """
        inst = self.get_instance("R2")
        anns = inst.symbol_attributes[0].annotations
        self.assertEqual(len(anns), 2)
        self.assertEqual(anns[0].value, "R2")
        self.assertEqual(anns[0].x, -27)
        self.assertEqual(anns[0].y, 11)
        self.assertEqual(anns[1].value, "68")
        self.assertEqual(anns[1].x, -27)
        self.assertEqual(anns[1].y, -23)

    @use_file("E1AA60D5.sch")
    def test_nets(self):
        """ The right nets are created. """
        self.assertEqual(
            set(n.net_id for n in self.design.nets),
            set(["VCC", "GND", "N$1", "N$2", "N$3", "N$4", "N$5", "N$6", "N$7"]),
        )

    @use_file("E1AA60D5.sch")
    def test_net_points(self):
        """ The right net points are created. """
        net = [n for n in self.design.nets if n.net_id == "GND"][0]
        self.assertEqual(len(net.points), 13)
        self.assertTrue(self.make_point_name("40.64", "63.5") in net.points)

    @use_file("E1AA60D5.sch")
    def test_net_points_connected(self):
        """ The right net points are connected. """
        net = [n for n in self.design.nets if n.net_id == "N$7"][0]
        pt = net.points[self.make_point_name("83.82", "68.58")]
        self.assertEqual(
            sorted(pt.connected_points), [self.make_point_name("76.2", "68.58"), self.make_point_name("83.82", "48.26")]
        )

    @use_file("E1AA60D5.sch")
    def test_net_points_connected_components(self):
        """ The right net points are connected to the right components. """
        net = [n for n in self.design.nets if n.net_id == "N$7"][0]
        pt = net.points[self.make_point_name("76.2", "68.58")]
        self.assertEqual(len(pt.connected_components), 1)
        self.assertEqual(pt.connected_components[0].instance_id, "IC1")
        self.assertEqual(pt.connected_components[0].pin_number, "(ADC1)PB2")

    @use_file("D9CD1423.sch")
    def test_smashed_annotations(self):
        """ The right annotations are created for smashed components. """
        inst = self.get_instance("U1")
        symattr = inst.symbol_attributes[0]
        self.assertEqual(len(symattr.annotations), 2)
        self.assertEqual(symattr.annotations[0].value, "U1")
        self.assertEqual(symattr.annotations[0].x, self.parser.make_length("22.86"))
        self.assertEqual(symattr.annotations[0].y, self.parser.make_length("52.07"))
        self.assertEqual(symattr.annotations[0].rotation, 0.0)
        self.assertEqual(symattr.annotations[1].value, "ATMEGA328AU")
        self.assertEqual(symattr.annotations[1].x, self.parser.make_length("22.86"))
        self.assertEqual(symattr.annotations[1].y, self.parser.make_length("43.18"))
        self.assertEqual(symattr.annotations[1].rotation, 0.0)

    def get_component(self, library_id):
        """ Return the component given its id. """
        return self.design.components.components[library_id]

    def get_instance(self, instance_id):
        """ Return the instance given its id. """
        return [ci for ci in self.design.component_instances if ci.instance_id == instance_id][0]

    def make_length(self, length):
        """ Return a length from the parser. """
        return self.parser.make_length(length)

    def make_point_name(self, x, y):
        """ Return a point name given an eaglexml point. """
        return "%sa%s" % (self.make_length(x), self.make_length(y))