def test_pin_bounds(self):
     '''Test bounds() for individual pins'''
     pin = Pin(0, Point(2, 5), Point(4, 3))
     top_left, bottom_right = pin.bounds()
     self.assertEqual(top_left.x, 2)
     self.assertEqual(top_left.y, 3)
     self.assertEqual(bottom_right.x, 4)
     self.assertEqual(bottom_right.y, 5)
 def test_pin_label_bounds(self):
     '''Test bounds() for a pin with a label'''
     lab = Label(0, 0, 'foo', 'left', 0)
     mkbounds(lab, 1, 3, 2, 6)
     pin = Pin(0, Point(2, 2), Point(4, 3), lab)
     top_left, bottom_right = pin.bounds()
     self.assertEqual(top_left.x, 1)
     self.assertEqual(top_left.y, 2)
     self.assertEqual(bottom_right.x, 4)
     self.assertEqual(bottom_right.y, 6)
 def parse_pin(self, args):
     """ Returns a parsed pin. """
     # Pin declaration, seems to only be done once per pin
     pid, xe, ye, xb, yb, rot, side, inv = [int(a) for a in args.split()]
     thispin = Pin(pid, (xb, yb), (xe, ye))
     subdata = defaultdict(list)
     for phrase in self.stream:
         cmd, _sep, args = phrase.partition(' ')
         if cmd not in ('L'):
             self.stream.push(phrase)
             break
         k, v = self.parsenode(cmd)(args)
         subdata[k].append(v)
     if len(subdata['label']) > 0:
         # I suppose if there's more than one label, just go with the first
         thispin.label = subdata['label'][0]
     return ('pin', thispin)
    def parse_library(self, filename, circuit):
        """
        Parse the library file and add the components to the given
        circuit.
        """

        f = open(filename)

        for line in f:
            parts = line.strip().split()
            prefix = parts[0]

            if prefix == 'DEF':
                component = Component(parts[1])
                component.add_attribute('_prefix', parts[2])
                symbol = Symbol()
                component.add_symbol(symbol)
                body = Body()
                symbol.add_body(body)
            elif prefix == 'A':  # Arc
                x, y, radius, start, end = [int(i) for i in parts[1:6]]
                # convert tenths of degrees to pi radians
                start = round(start / 1800.0, 1)
                end = round(end / 1800.0, 1)
                body.add_shape(shape.Arc(x, y, start, end, radius))
            elif prefix == 'C':  # Circle
                x, y, radius = [int(i) for i in parts[1:4]]
                body.add_shape(shape.Circle(x, y, radius))
            elif prefix == 'P':  # Polyline
                num_points = int(parts[1])
                poly = shape.Polygon()
                for i in xrange(num_points):
                    x, y = int(parts[5 + 2 * i]), int(parts[6 + 2 * i])
                    poly.addPoint(x, y)
                body.add_shape(poly)
            elif prefix == 'S':  # Rectangle
                x, y, x2, y2 = [int(i) for i in parts[1:5]]
                rec = shape.Rectangle(x, y, x2 - x, y2 - y)
                body.add_shape(rec)
            elif prefix == 'T':  # Text
                angle, x, y = [int(i) for i in parts[1:4]]
                angle = round(angle / 1800.0, 1)
                text = parts[8].replace('~', ' ')
                body.add_shape(shape.Label(x, y, text, 'left', angle))
            elif prefix == 'X':  # Pin
                num, direction = int(parts[2]), parts[6]
                p2x, p2y, pinlen = int(parts[3]), int(parts[4]), int(parts[5])
                if direction == 'U':  # up
                    p1x = p2x
                    p1y = p2y - pinlen
                elif direction == 'D':  # down
                    p1x = p2x
                    p1y = p2y + pinlen
                elif direction == 'L':  # left
                    p1x = p2x - pinlen
                    p1y = p2y
                elif direction == 'R':  # right
                    p1x = p2x + pinlen
                    p1y = p2y
                else:
                    raise ValueError('unexpected pin direction', direction)
                # TODO: label?
                body.add_pin(Pin(num, (p1x, p1y), (p2x, p2y)))
            elif prefix == 'ENDDEF':
                circuit.add_component(component.name, component)

        f.close()