def __init__(self, symbol_dirs=None): """ Constuct a gEDA parser object. Specifying a list of symbol directories in *symbol_dir* will provide a symbol file lookup in the specified directories. The lookup will be generated instantly examining each directory (if it exists). Kwargs: symbol_dirs (list): List of directories containing .sym files """ self.offset = shape.Point(40000, 40000) ## Initialise frame size with largest possible size self.frame_width = 0 self.frame_height = 0 # initialise PIN counter self.pin_counter = itertools.count(0) # initialise PATH counter self.path_counter = itertools.count(0) ## add flag to allow for auto inclusion if symbol_dirs is None: symbol_dirs = [] symbol_dirs = symbol_dirs + \ [os.path.join(os.path.dirname(__file__), '..', 'library', 'geda')] self.known_symbols = find_symbols(symbol_dirs) self.design = None self.segments = None self.net_points = None self.net_names = None self.geda_zip = None
def test_write_component_to_file(self): """ Tests writing a component to a symbol file. """ sym_dir = '/tmp/sym' if os.path.exists(sym_dir): shutil.rmtree(sym_dir) os.mkdir(sym_dir) self.geda_writer.set_offset(shape.Point(-500, -500)) self.geda_writer.component_library = dict() self.geda_writer.project_dirs['symbol'] = sym_dir simple_design = self.oj_parser.parse('test/openjson/simple.upv') library_id = '0000000000000001' component = simple_design.components.components[library_id] self.geda_writer.write_component_to_file(library_id, component) component_library = self.geda_writer.component_library self.assertEquals(len(component_library), 4) self.assertEquals( component_library, { (library_id, 0): 'Flag_1-0.sym', (library_id, 1): 'Flag_2-1.sym', (library_id, 2): 'GND-2.sym', (library_id, 3): 'VCC-3.sym' }) self.assertEquals( sorted(os.listdir(sym_dir)), ['Flag_1-0.sym', 'Flag_2-1.sym', 'GND-2.sym', 'VCC-3.sym'])
def parse_component_data(self, stream, params): """ Creates a component from the component *params* and the following commands in the stream. If the component data is embedded in the schematic file, all coordinates will be translated into the origin first. Only a single symbol/body is created for each component since gEDA symbols contain exactly one description. Returns the newly created Component object. """ # pylint: disable=R0912 basename = os.path.splitext(params['basename'])[0] saved_offset = self.offset self.offset = shape.Point(0, 0) ## retrieve if component is mirrored around Y-axis mirror = self._is_mirrored_command(params) if mirror: basename += '_MIRRORED' move_to = None if basename.startswith('EMBEDDED'): move_to = (params['x'], params['y']) ## grab next line (should be '[' typ, params = self._parse_command(stream, move_to) if typ == '[': typ, params = self._parse_command(stream, move_to) component = components.Component(basename) symbol = components.Symbol() component.add_symbol(symbol) body = components.Body() symbol.add_body(body) ##NOTE: adding this attribute to make parsing UPV data easier ## when using re-exported UPV. component.add_attribute('_geda_imported', 'true') self.pin_counter = itertools.count(0) while typ is not None: params['mirror'] = mirror objects = getattr(self, "_parse_%s" % typ)(stream, params) attributes = self._parse_environment(stream) component.attributes.update(attributes or {}) self.add_objects_to_component(component, objects) typ, params = self._parse_command(stream, move_to) self.offset = saved_offset return component
def test_write_schematic_file(self): """ Reads the gEDA *simple_example* file into a design using the gEDA parser, writes the result to a gEDA file and reads it into a new design. Both designs are then compared regarding their respective components, instances and nets. """ # pylint: disable=R0914 # pylint: disable=R0915 sym_dir = '/tmp/sym' if os.path.exists('/tmp/converted.sch'): os.remove('/tmp/converted.sch') if os.path.exists(sym_dir): shutil.rmtree(sym_dir) geda_parser = upconvert.parser.geda.GEDA( symbol_dirs=['test/geda/simple_example/symbols']) geda_parser.set_offset(shape.Point(0, 0)) simple_design = geda_parser.parse( 'test/geda/simple_example/simple_example.sch') geda_writer = GEDA() geda_writer.write(simple_design, '/tmp/converted.sch') converted_design = geda_parser.parse('/tmp/converted.sch') ## parse design again to make sure it is a clean slate geda_parser = upconvert.parser.geda.GEDA( symbol_dirs=['test/geda/simple_example/symbols']) geda_parser.set_offset(shape.Point(0, 0)) simple_design = geda_parser.parse( 'test/geda/simple_example/simple_example.sch') ##compare nets self.assertEquals( sorted([(net.net_id, len(net.points)) for net in simple_design.nets]), sorted([(net.net_id, len(net.points)) for net in converted_design.nets])) snets = dict([(net.net_id, net) for net in simple_design.nets]) cnets = dict([(net.net_id, net) for net in converted_design.nets]) for snet_id, snet in snets.items(): cnet = cnets[snet_id] spoints = dict([(pt.point_id, pt) for pt in snet.points.values()]) cpoints = dict([(pt.point_id, pt) for pt in cnet.points.values()]) self.assertEqual(sorted(spoints.keys()), sorted(cpoints.keys())) for spoint_id, spoint in spoints.items(): cpoint = cpoints[spoint_id] self.assertEquals(spoint.x, cpoint.x) self.assertEquals(spoint.y, cpoint.y) ## compare component library self.assertEqual(sorted(simple_design.components.components.keys()), sorted(converted_design.components.components.keys())) for lib_id in simple_design.components.components: scomponent = simple_design.components.components[lib_id] ccomponent = converted_design.components.components[lib_id] self.assertEquals(scomponent.name, ccomponent.name) self.assertEquals(scomponent.attributes, ccomponent.attributes) self.assertEquals(len(scomponent.symbols), 1) self.assertEquals(len(scomponent.symbols), len(ccomponent.symbols)) self.assertEquals(len(scomponent.symbols[0].bodies), 1) self.assertEquals(len(scomponent.symbols[0].bodies), len(ccomponent.symbols[0].bodies)) sbody = scomponent.symbols[0].bodies[0] cbody = ccomponent.symbols[0].bodies[0] ## skip the unassigned shapes component as it adds an additional ## text from the basename when importing GEDA if scomponent.name != 'UNASSIGNED_SHAPES': self.assertEquals(len(sbody.shapes), len(cbody.shapes)) self.assertEquals(len(sbody.pins), len(cbody.pins)) for spin, cpin in zip(sbody.pins, cbody.pins): self.assertEquals(spin.p1.x, cpin.p1.x) self.assertEquals(spin.p1.x, cpin.p1.x) self.assertEquals(spin.p2.y, cpin.p2.y) self.assertEquals(spin.p2.y, cpin.p2.y) if spin.label is None: self.assertEquals(cpin.label, None) else: self.assertEquals(spin.label.text, cpin.label.text) for sshape, cshape in zip(sbody.shapes, cbody.shapes): self.assertEquals(sshape.type, cshape.type) ## compare component instances scomp_instances = dict([(comp.instance_id, comp) for comp in simple_design.component_instances]) ccomp_instances = dict([ (comp.instance_id, comp) for comp in converted_design.component_instances ]) for instance_id in scomp_instances: sinst = scomp_instances[instance_id] cinst = ccomp_instances[instance_id] self.assertEquals(sinst.instance_id, cinst.instance_id) self.assertEquals(sinst.library_id, cinst.library_id) self.assertEquals(sinst.symbol_index, cinst.symbol_index) self.assertEquals(sinst.symbol_attributes[0].x, cinst.symbol_attributes[0].x) self.assertEquals(sinst.symbol_attributes[0].y, cinst.symbol_attributes[0].y) self.assertEquals(sinst.symbol_attributes[0].rotation, cinst.symbol_attributes[0].rotation)
def write_component_to_file(self, library_id, component): """ Writes a *component* to a local symbol file and adds it to the symbol lookup used for instantiating components. A component might have a special attribute 'geda_imported' assigned when converted with the upconverter parser. This allows for retrieving that a local symbol file can be referenced. If this attribute is not present, a new symbol file will be generated in the project directory's symbols directory. """ # pylint: disable=R0914 ##NOTE: extract and remove gEDA internal attribute geda_imported = component.attributes.get('_geda_imported', 'false') geda_imported = (geda_imported == "true") component.attributes['_refdes'] = '%s?%s' % (component.attributes.get( '_prefix', ''), component.attributes.get('_suffix', '')) symbol_filename = None ##NOTE: this attributed is used in the parser to mark at component ## as being imported using the upconverter. If this marker is found ## local .sym files will be referenced if available. if geda_imported: ##remove mirrored tag from name if '_MIRRORED' in component.name: component.name = component.name.replace('_MIRRORED', '') ##check if component is known sym file in OS dirs symbol_filename = "%s.sym" % component.name.replace('EMBEDDED', '') self.component_library[(library_id.replace('_MIRRORED', ''), 0)] = symbol_filename if component.name.replace('EMBEDDED', '') in self.known_symbols: return ## symbol files should not use offset saved_offset = self.offset self.offset = shape.Point(0, 0) ## write symbol file for each symbol in component for sym_idx, symbol in enumerate(component.symbols): symbol_attr = "_symbol_%d_0" % sym_idx if symbol_attr in component.attributes: prefix = component.attributes[symbol_attr] del component.attributes[symbol_attr] else: prefix = component.name if not geda_imported: prefix = prefix.replace(' ', '_') symbol_filename = "%s-%d.sym" % (prefix, sym_idx) commands = [] for body in symbol.bodies: commands += self.generate_body_commands(body) attr_y = 0 for key, value in component.attributes.items(): if not key.startswith('_symbol') \ and key not in self.ignored_attributes: commands += self._create_attribute( key, value, 0, attr_y, ) attr_y = attr_y + 10 ## write commands to file path = os.path.join(self.project_dirs['symbol'], symbol_filename) with codecs.open(path, encoding='utf-8', mode='w') as fout: fout.write(self.commands_to_string(commands)) ## required for instantiating components later self.component_library[(library_id, sym_idx)] = symbol_filename ## restore offset self.offset = saved_offset