def test_bounds_all_elts(self): '''bounds() with all the elements competing''' net = Net('foo') mkbounds(net, 3, 3, -1, -2) self.des.add_net(net) annot = Annotation('foo', 3, 3, 0, True) mkbounds(annot, 3, 3, 3, 5) self.des.design_attributes.add_annotation(annot) libcomp = Component('bar') libcomp.add_symbol(Symbol()) libcomp.symbols[0].add_body(Body()) mkbounds(libcomp.symbols[0].bodies[0], 0, 0, 3, 3) self.des.add_component('foo', libcomp) compinst = ComponentInstance('bar', 'foo', 0) compinst.add_symbol_attribute(SymbolAttribute(3, 0, 0, False)) self.des.add_component_instance(compinst) top_left, btm_right = self.des.bounds() self.assertEqual(top_left.x, -1) self.assertEqual(top_left.y, -2) self.assertEqual(btm_right.x, 6) self.assertEqual(btm_right.y, 5)
def parse_component_instance(self, f): """ Parse a component instance from a $Comp block """ # pylint: disable=R0914 # name & reference prefix, name, reference = f.readline().split() assert prefix == 'L' ref_count_idx = 1 while reference in self.instance_names: ref_count_idx += 1 reference = reference + '-' + str(ref_count_idx) self.instance_names.append(reference) comp = None if self.library is not None: library_part = self.library.lookup_part(name) if library_part is not None: name = library_part.name # unit & convert prefix, unit, convert, ar_path = f.readline().split(None, 3) unit, convert = int(unit), int(convert) assert prefix == 'U' # position prefix, compx, compy = f.readline().split() assert prefix == 'P' compx, compy = int(compx), int(compy) line = f.readline() rotation = 0 flip = False annotations = [] while line.strip() not in ("$EndComp", ''): if line.startswith('F '): annotations.append(self.parse_field(compx, compy, line)) elif line.startswith('\t'): parts = line.strip().split() if len(parts) == 4: rotation, flip = MATRIX2ROTATIONFLIP.get( tuple(int(i) for i in parts), (0, False)) elif line.startswith('AR Path'): if '?' in reference: path_line = line.strip().split() ar_path_check = path_line[1].strip('"')[7:] #removes Path="/ if ar_path.strip() == ar_path_check: reference = path_line[2].strip('"')[5:] #removes Ref=" line = f.readline() inst = ComponentInstance(reference, library_part, name.upper(), convert - 1) symbattr = SymbolAttribute(compx, -compy, rotation, flip) for ann in annotations: symbattr.add_annotation(ann) inst.add_symbol_attribute(symbattr) return inst, comp
def test_write_instance(self): """ Convert component instance """ inst = ComponentInstance('id', 'libid', 1) inst.add_symbol_attribute(SymbolAttribute(3, 4, 0.5, False)) writer = Specctra() obj = writer._convert_component_instance(inst) self.assertEqual( to_string(writer, obj), '(component libid-1 (place id 31.250000 41.666667 front 270) )')
def ensure_component_instance(self, parts, instance): """ Ensure there is a component instance for an eagle instance. """ part = parts[instance.part] if part.name in self.part2inst: return self.part2inst[part.name] library_id = part.library + ':' + part.deviceset + ':' + part.device cpt = self.design.components.components[library_id] self.part2inst[part.name] = ComponentInstance(instance.part, part, library_id, 0) self.part2inst[part.name].add_attribute('refdes', part.name) # pre-create symbol attributes, to be filled in during # instance processing for _ in cpt.symbols[0].bodies: self.part2inst[part.name].add_symbol_attribute( SymbolAttribute(0, 0, 0.0, False)) if part.value: self.part2inst[part.name].add_attribute('value', part.value) self.design.add_component_instance(self.part2inst[part.name]) self.part2inst[part.name].add_attribute('eaglexml_device', part.device) return self.part2inst[part.name]
def parse_component_instance(self, f): """ Parse a component instance from a $Comp block """ # pylint: disable=R0914 # name & reference prefix, name, reference = f.readline().split() assert prefix == 'L' # unit & convert prefix, unit, convert, _ = f.readline().split(None, 3) unit, convert = int(unit), int(convert) assert prefix == 'U' # position prefix, compx, compy = f.readline().split() assert prefix == 'P' compx, compy = int(compx), int(compy) line = f.readline() rotation = 0 annotations = [] while line.strip() not in ("$EndComp", ''): if line.startswith('F '): parts = line.split('"', 2) value = parts[1].decode('utf-8', 'replace') parts = parts[2].strip().split() annotations.append( Annotation(value, make_length(int(parts[1]) - compx), -make_length(int(parts[2]) - compy), 0 if parts[0] == 'H' else 1, 'true')) elif line.startswith('\t'): parts = line.strip().split() if len(parts) == 4: rotation = MATRIX2ROTATION.get( tuple(int(i) for i in parts), 0) line = f.readline() inst = ComponentInstance(reference, name, convert - 1) symbattr = SymbolAttribute(make_length(compx), -make_length(compy), rotation) for ann in annotations: symbattr.add_annotation(ann) inst.add_symbol_attribute(symbattr) return inst
def test_bounds_parts(self): '''test bounds() with just components in the design''' libcomp = Component('bar') libcomp.add_symbol(Symbol()) libcomp.symbols[0].add_body(Body()) mkbounds(libcomp.symbols[0].bodies[0], 0, 0, 10, 10) self.des.add_component('foo', libcomp) for (x, y) in ((1, 3), (3, 2), (5, 3), (3, 7)): compinst = ComponentInstance(str((x, y)), 'foo', 0) compinst.add_symbol_attribute(SymbolAttribute(x, y, 0, False)) self.des.add_component_instance(compinst) top_left, btm_right = self.des.bounds() self.assertEqual(top_left.x, 1) self.assertEqual(top_left.y, 2) self.assertEqual(btm_right.x, 15) self.assertEqual(btm_right.y, 17)
def test_create_new_instance(self): """ Test the creation of a new empty instance. """ inst = ComponentInstance('001', None, '002', '003') assert inst.instance_id == '001' assert inst.library_id == '002' assert inst.symbol_index == '003' assert len(inst.symbol_attributes) == 0 assert len(inst.attributes) == 0
def parse_inst(self, args): """ Returns a parsed component instance. """ inst, libname, libnum, x, y, rot, _scale, _b = args.split() # scale is a floating point scaling constant. Also, evil. thisinst = ComponentInstance(inst, self.lookup(libname, libnum), 0) if int(rot) > 3: # part is flipped around y-axis. When applying transforms, flip it # first, then rotate it. rot = str(int(rot) - 4) # flip = True thisinst.add_symbol_attribute(SymbolAttribute(int(x), int(y), float(rot) / 2)) subdata = defaultdict(list) for phrase in self.stream: cmd, _sep, args = phrase.partition(' ') if cmd not in ('|R', 'A', 'C'): self.stream.push(phrase) break k, v = self.parsenode(cmd)(args) subdata[k].append(v) for annot in subdata['annot']: thisinst.symbol_attributes[0].add_annotation(annot) if '=' in annot.value: thisinst.add_attribute(*(annot.value.split('=', 1))) # Turns out C can reference a net before it's been created via # the N command. Really don't like passing stuff inband like this. Ugh. thisinst.conns = subdata['conn'] return ('inst', thisinst)
def parse_component_instance(self, f): """ Parse a component instance from a $Comp block """ # pylint: disable=R0914 # name & reference prefix, name, reference = f.readline().split() assert prefix == 'L' if self.library is not None: library_part = self.library.lookup_part(name) if library_part is not None: name = library_part.name # unit & convert prefix, unit, convert, _ = f.readline().split(None, 3) unit, convert = int(unit), int(convert) assert prefix == 'U' # position prefix, compx, compy = f.readline().split() assert prefix == 'P' compx, compy = int(compx), int(compy) line = f.readline() rotation = 0 annotations = [] while line.strip() not in ("$EndComp", ''): if line.startswith('F '): annotations.append(self.parse_field(compx, compy, line)) elif line.startswith('\t'): parts = line.strip().split() if len(parts) == 4: rotation = MATRIX2ROTATION.get( tuple(int(i) for i in parts), 0) line = f.readline() inst = ComponentInstance(reference, name.upper(), convert - 1) symbattr = SymbolAttribute(make_length(compx), -make_length(compy), rotation, False) for ann in annotations: symbattr.add_annotation(ann) inst.add_symbol_attribute(symbattr) return inst
def _convert_components(self, struct): for component in struct.placement.component: library_id = component.image_id for place in component.place: # Outside PCB boundary if not place.vertex: continue mirror = {90:270, 270:90} if place.side == 'back': rotation = place.rotation else: rotation = mirror.get(int(place.rotation), place.rotation) inst = ComponentInstance(place.component_id, library_id, 0) v = self.to_pixels(place.vertex) symbattr = SymbolAttribute(v[0], v[1], to_piradians(rotation), False) inst.add_symbol_attribute(symbattr) self.design.add_component_instance(inst)
def _convert_components(self, struct): """ Convert component """ for component in struct.placement.component: library_id = component.image_id for place in component.place: # Outside PCB boundary if not place.vertex: continue mirror = {90:270, 270:90} if place.side == 'back': rotation = place.rotation else: rotation = mirror.get(int(place.rotation), place.rotation) inst = ComponentInstance(place.component_id, component, library_id, 0) v = self.to_pixels(place.vertex) symbattr = FootprintAttribute(v[0], v[1], to_piradians(rotation), False) inst.add_symbol_attribute(symbattr) self.design.add_component_instance(inst)
def make_component_instance(self, parts, instance): """ Construct an openjson component instance for an eagle instance. """ part = parts[instance.part] library_id = part.library + ':' + part.deviceset # TODO pick correct symbol index inst = ComponentInstance(instance.part, library_id, 0) # TODO handle mirror # TODO handle smashed? attr = SymbolAttribute(self.make_length(instance.x), self.make_length(instance.y), self.make_angle(instance.rot or '0')) inst.add_symbol_attribute(attr) return inst
def test_write_instance(self): """ The write_instance method serializes a component instance correctly. """ inst = ComponentInstance('id', 'libid', 1) inst.add_symbol_attribute(SymbolAttribute(3, 4, 0.5)) writer = KiCAD() buf = StringIO() writer.write_instance(buf, inst) self.assertEqual(buf.getvalue(), '''\ $Comp L libid id U 1 1 00000000 P 33 -44 \t1 33 -44 \t0 1 1 0 $EndComp ''')
def test_write_instance(self): """ The write_instance method serializes a component instance correctly. """ inst = ComponentInstance('id', 'libid', 1) inst.add_symbol_attribute(SymbolAttribute(3, 4, 0.5, False)) writer = KiCAD() buf = StringIO() writer.write_instance(buf, inst) self.assertEqual( buf.getvalue(), '''\ $Comp L libid id U 1 1 00000000 P 33 -44 \t1 33 -44 \t0 1 1 0 $EndComp ''')
def parse_component_instance(self, f): """ Parse a component instance from a $Comp block """ # pylint: disable=R0914 # name & reference prefix, name, reference = f.readline().split() assert prefix == 'L' # unit & convert prefix, unit, convert, _ = f.readline().split(None, 3) unit, convert = int(unit), int(convert) assert prefix == 'U' # position prefix, compx, compy = f.readline().split() assert prefix == 'P' compx, compy = int(compx), int(compy) line = f.readline() rotation = 0 annotations = [] while line.strip() not in ("$EndComp", ''): if line.startswith('F '): annotations.append(self.parse_field(compx, compy, line)) elif line.startswith('\t'): parts = line.strip().split() if len(parts) == 4: rotation = MATRIX2ROTATION.get( tuple(int(i) for i in parts), 0) line = f.readline() inst = ComponentInstance(reference, name, convert - 1) symbattr = SymbolAttribute(make_length(compx), -make_length(compy), rotation) for ann in annotations: symbattr.add_annotation(ann) inst.add_symbol_attribute(symbattr) return inst
def parse_inst(self, args): """ Returns a parsed component instance. """ inst, libname, libnum, x, y, rot, _scale, _unknown = args.split() # scale is a floating point scaling constant. Also, evil. thisinst = ComponentInstance(inst, self.lookup(libname, libnum), 0) flip = False if int(rot) > 3: # part is flipped around y-axis. When applying transforms, flip it # first, then rotate it. rot = str(int(rot) - 4) flip = True thisinst.add_symbol_attribute(SymbolAttribute(int(x), int(y), (2 - float(rot) / 2) % 2, flip)) subdata = self.sub_nodes('|R A C'.split()) for annot in subdata['annot']: thisinst.symbol_attributes[0].add_annotation(annot) if '=' in annot.value: thisinst.add_attribute(*(annot.value.split('=', 1))) # Turns out C can reference a net before it's been created via # the N command. Really don't like passing stuff inband like this. Ugh. thisinst.conns = subdata['conn'] return ('inst', thisinst)
def parse_component_instance(self, inst): """ Parse a Fritzing non-wire instance into a ComponentInstance """ view = inst.find('views/schematicView') if view is None: return if view.get('layer') == 'breadboardbreadboard': return cpt = self.ensure_component(inst) if cpt is None: return index = inst.get('modelIndex') idref = inst.get('moduleIdRef') title = inst.find('title').text geom = view.find('geometry') xform = geom.find('transform') x, y = float(geom.get('x', 0)), float(geom.get('y', 0)) if xform is None: rotation = 0.0 else: matrix = tuple( int(float(xform.get(key, 0))) for key in ('m11', 'm12', 'm21', 'm22')) x, y = rotate_component(cpt, matrix, x, y) rotation = MATRIX2ROTATION.get(matrix, 0.0) compinst = ComponentInstance(title, cpt, idref, 0) compinst.add_symbol_attribute( SymbolAttribute(make_x(x), make_y(y), rotation, False)) self.component_instances[index] = compinst
def parse_component_instance(self, inst): """ Parse a Fritzing non-wire instance into a ComponentInstance """ view = inst.find('views/schematicView') if view is None: return if view.get('layer') == 'breadboardbreadboard': return cpt = self.ensure_component(inst) if cpt is None: return index = inst.get('modelIndex') idref = inst.get('moduleIdRef') title = inst.find('title').text geom = view.find('geometry') xform = geom.find('transform') x, y = float(geom.get('x', 0)), float(geom.get('y', 0)) if xform is None: rotation = 0.0 else: matrix = tuple(int(float(xform.get(key, 0))) for key in ('m11', 'm12', 'm21', 'm22')) x, y = rotate_component(cpt, matrix, x, y) rotation = MATRIX2ROTATION.get(matrix, 0.0) compinst = ComponentInstance(title, cpt, idref, 0) compinst.add_symbol_attribute( SymbolAttribute(make_x(x), make_y(y), rotation, False)) self.component_instances[index] = compinst
def parse_inst(self, args): """ Returns a parsed component instance. """ inst, libname, libnum, x, y, rot, scale, _unknown = args.split() # scale is a floating point scaling constant. Also, evil. if scale != '1': libkey = self.scaled_component(libname, libnum, scale) else: libkey = self.lookup(libname, libnum) thisinst = ComponentInstance(inst, self.lib.components[libkey], libkey, 0) rot, flip = self.rot_and_flip(rot) thisinst.add_symbol_attribute( SymbolAttribute(int(x), int(y), rot, flip)) subdata = self.sub_nodes('|R A C'.split()) for annot in subdata['annot']: thisinst.symbol_attributes[0].add_annotation(annot) if '=' in annot.value: thisinst.add_attribute(*(annot.value.split('=', 1))) # Turns out C can reference a net before it's been created via # the N command. Really don't like passing stuff inband like this. Ugh. thisinst.conns = subdata['conn'] return ('inst', thisinst)
def parse_inst(self, args): """ Returns a parsed component instance. """ inst, libname, libnum, x, y, rot, _scale, _unknown = args.split() # scale is a floating point scaling constant. Also, evil. thisinst = ComponentInstance(inst, self.lookup(libname, libnum), 0) flip = False if int(rot) > 3: # part is flipped around y-axis. When applying transforms, flip it # first, then rotate it. rot = str(int(rot) - 4) flip = True thisinst.add_symbol_attribute( SymbolAttribute(int(x), int(y), (2 - float(rot) / 2) % 2, flip)) subdata = self.sub_nodes('|R A C'.split()) for annot in subdata['annot']: thisinst.symbol_attributes[0].add_annotation(annot) if '=' in annot.value: thisinst.add_attribute(*(annot.value.split('=', 1))) # Turns out C can reference a net before it's been created via # the N command. Really don't like passing stuff inband like this. Ugh. thisinst.conns = subdata['conn'] return ('inst', thisinst)
def parse_component_instances(self, component_instances): """ Extract the component instances. """ for instance in component_instances: # Get instance_id, library_id and symbol_index instance_id = instance.get('instance_id') library_id = instance.get('library_id') symbol_index = int(instance.get('symbol_index')) # Make the ComponentInstance() inst = ComponentInstance(instance_id, library_id, symbol_index) # Get the SymbolAttributes for symbol_attribute in instance.get('symbol_attributes'): attr = self.parse_symbol_attribute(symbol_attribute) inst.add_symbol_attribute(attr) # Get the Attributes for key, value in instance.get('attributes').items(): inst.add_attribute(key, value) # Add the ComponentInstance self.design.add_component_instance(inst)
def parse_inst(self, args): """ Returns a parsed component instance. """ inst, libname, libnum, x, y, rot, scale, _unknown = args.split() # scale is a floating point scaling constant. Also, evil. if scale != '1': libkey = self.scaled_component(libname, libnum, scale) else: libkey = self.lookup(libname, libnum) thisinst = ComponentInstance(inst, libkey, 0) rot, flip = self.rot_and_flip(rot) thisinst.add_symbol_attribute(SymbolAttribute(int(x), int(y), rot, flip)) subdata = self.sub_nodes('|R A C'.split()) for annot in subdata['annot']: thisinst.symbol_attributes[0].add_annotation(annot) if '=' in annot.value: thisinst.add_attribute(*(annot.value.split('=', 1))) # Turns out C can reference a net before it's been created via # the N command. Really don't like passing stuff inband like this. Ugh. thisinst.conns = subdata['conn'] return ('inst', thisinst)
def _parse_component(self, stream, params): """ Creates a component instance according to the component *params*. If the component is not known in the library, a the component will be created according to its description in the embedded environment ``[]`` or a symbol file. The component is added to the library automatically if necessary. An instance of this component will be created and added to the design. A GEDAError is raised when either the component file is invalid or the referenced symbol file cannot be found in the known directories. Returns a tuple of Component and ComponentInstance objects. """ basename, _ = os.path.splitext(params['basename']) component_name = basename if params.get('mirror'): component_name += '_MIRRORED' if component_name in self.design.components.components: component = self.design.components.components[component_name] ## skipping embedded data might be required self.skip_embedded_section(stream) else: ##check if sym file is embedded or referenced if basename.startswith('EMBEDDED'): ## embedded only has to be processed when NOT in symbol lookup if basename not in self.known_symbols: component = self.parse_component_data(stream, params) else: if basename not in self.known_symbols: log.warn("referenced symbol file '%s' unknown" % basename) ## create a unknown symbol reference component = self.parse_component_data( StringIO(UNKNOWN_COMPONENT % basename), params ) ## parse optional attached environment before continuing self._parse_environment(stream) return None, None ## requires parsing of referenced symbol file with open(self.known_symbols[basename], "rU") as f_in: self._check_version(f_in) component = self.parse_component_data(f_in, params) self.design.add_component(component_name, component) ## get all attributes assigned to component instance attributes = self._parse_environment(stream) ## refdes attribute is name of component (mandatory as of gEDA doc) ## examples if gaf repo have components without refdes, use part of ## basename if attributes is not None: instance = ComponentInstance( attributes.get('_refdes', component.name), component.name, 0 ) for key, value in attributes.items(): instance.add_attribute(key, value) else: instance = ComponentInstance( component.name, component.name, 0 ) ## generate a component instance using attributes self.design.add_component_instance(instance) symbol = SymbolAttribute( self.x_to_px(params['x']), self.y_to_px(params['y']), self.conv_angle(params['angle'], False) ) instance.add_symbol_attribute(symbol) ## add annotation for special attributes for idx, attribute_key in enumerate(['_refdes', 'device']): if attribute_key in component.attributes \ or attribute_key in instance.attributes: symbol.add_annotation( Annotation( '{{%s}}' % attribute_key, 0, 0+idx*10, 0.0, 'true' ) ) return component, instance
def parse_component_instance(self, f): """ Parse a component instance from a $Comp block """ # pylint: disable=R0914 # name & reference prefix, name, reference = f.readline().split() assert prefix == 'L' ref_count_idx = 1 while reference in self.instance_names: ref_count_idx += 1 reference = reference + '-' + str(ref_count_idx) self.instance_names.append(reference) comp = None if self.library is not None: library_part = self.library.lookup_part(name) if library_part is not None: name = library_part.name # unit & convert prefix, unit, convert, ar_path = f.readline().split(None, 3) unit, convert = int(unit), int(convert) assert prefix == 'U' # position prefix, compx, compy = f.readline().split() assert prefix == 'P' compx, compy = int(compx), int(compy) line = f.readline() rotation = 0 flip = False annotations = [] while line.strip() not in ("$EndComp", ''): if line.startswith('F '): annotations.append(self.parse_field(compx, compy, line)) elif line.startswith('\t'): parts = line.strip().split() if len(parts) == 4: rotation, flip = MATRIX2ROTATIONFLIP.get( tuple(int(i) for i in parts), (0, False)) elif line.startswith('AR Path'): if '?' in reference: path_line = line.strip().split() ar_path_check = path_line[1].strip('"')[ 7:] #removes Path="/ if ar_path.strip() == ar_path_check: reference = path_line[2].strip('"')[5:] #removes Ref=" line = f.readline() inst = ComponentInstance(reference, library_part, name.upper(), convert - 1) symbattr = SymbolAttribute(compx, -compy, rotation, flip) for ann in annotations: symbattr.add_annotation(ann) inst.add_symbol_attribute(symbattr) return inst, comp
def _parse_component(self, stream, params): """ Creates a component instance according to the component *params*. If the component is not known in the library, a the component will be created according to its description in the embedded environment ``[]`` or a symbol file. The component is added to the library automatically if necessary. An instance of this component will be created and added to the design. A GEDAError is raised when either the component file is invalid or the referenced symbol file cannot be found in the known directories. Returns a tuple of Component and ComponentInstance objects. """ basename, _ = os.path.splitext(params['basename']) component_name = basename if params.get('mirror'): component_name += '_MIRRORED' if component_name in self.design.components.components: component = self.design.components.components[component_name] ## skipping embedded data might be required self.skip_embedded_section(stream) else: ##check if sym file is embedded or referenced if basename.startswith('EMBEDDED'): ## embedded only has to be processed when NOT in symbol lookup if basename not in self.known_symbols: component = self.parse_component_data(stream, params) else: if basename not in self.known_symbols: log.warn("referenced symbol file '%s' unknown" % basename) ## create a unknown symbol reference component = self.parse_component_data( StringIO(UNKNOWN_COMPONENT % basename), params) ## parse optional attached environment before continuing self._parse_environment(stream) return None, None ## requires parsing of referenced symbol file with open(self.known_symbols[basename], "rU") as f_in: self._check_version(f_in) component = self.parse_component_data(f_in, params) self.design.add_component(component_name, component) ## get all attributes assigned to component instance attributes = self._parse_environment(stream) ## refdes attribute is name of component (mandatory as of gEDA doc) ## examples if gaf repo have components without refdes, use part of ## basename if attributes is not None: instance = ComponentInstance( attributes.get('_refdes', component.name), component.name, 0) for key, value in attributes.items(): instance.add_attribute(key, value) else: instance = ComponentInstance(component.name, component.name, 0) ## generate a component instance using attributes self.design.add_component_instance(instance) symbol = SymbolAttribute(self.x_to_px(params['x']), self.y_to_px(params['y']), self.conv_angle(params['angle'], False)) instance.add_symbol_attribute(symbol) ## add annotation for special attributes for idx, attribute_key in enumerate(['_refdes', 'device']): if attribute_key in component.attributes \ or attribute_key in instance.attributes: symbol.add_annotation( Annotation('{{%s}}' % attribute_key, 0, 0 + idx * 10, 0.0, 'true')) return component, instance
def parse_component_instances(self, component_instances): """ Extract the component instances. """ if component_instances is None: return None for instance in component_instances: # Get instance_id, library_id and symbol_index instance_id = instance.get('instance_id') library_id = instance.get('library_id') symbol_index = int(instance.get('symbol_index')) footprint_index = int(instance.get('footprint_index')) # Make the ComponentInstance() inst = ComponentInstance(instance_id, self.design.components.components[library_id], library_id, symbol_index, footprint_index) # Get the SymbolAttributes for symbol_attribute in instance.get('symbol_attributes', []): attr = self.parse_symbol_attribute(symbol_attribute) inst.add_symbol_attribute(attr) # TODO(shamer) footprint_pos, fleb and genobj positions are relative to the footprint_pos for footprint_attribute in instance.get('footprint_attributes', []): attr = self.parse_footprint_attribute(footprint_attribute) inst.add_footprint_attribute(attr) for gen_obj_attribute in instance.get('gen_obj_attributes', []): attr = self.parse_gen_obj_attribute(gen_obj_attribute) inst.add_gen_obj_attribute(attr) footprint_json = instance.get('footprint_pos') if footprint_json: footprint_pos = self.parse_footprint_pos(footprint_json) else: footprint_pos = None inst.set_footprint_pos(footprint_pos) # Get the Attributes for key, value in instance.get('attributes').items(): inst.add_attribute(key, value) # Add the ComponentInstance self.design.add_component_instance(inst)
def parse(self, inputfile): """ Parse a gEDA file into a design. Returns the design corresponding to the gEDA file. """ inputfiles = [] ## check if inputfile is in ZIP format if zipfile.is_zipfile(inputfile): self.geda_zip = zipfile.ZipFile(inputfile) for filename in self.geda_zip.namelist(): if filename.endswith('.sch'): inputfiles.append(filename) else: inputfiles = [inputfile] self.design = Design() self.unassigned_body = components.Body() ## parse frame data of first schematic to extract ## page size (assumes same frame for all files) with self._open_file_or_zip(inputfiles[0]) as stream: self._check_version(stream) for line in stream.readlines(): if 'title' in line and line.startswith('C'): obj_type, params = self._parse_command(StringIO(line)) assert(obj_type == 'C') params['basename'], _ = os.path.splitext( params['basename'], ) log.debug("using title file: %s", params['basename']) self._parse_title_frame(params) for filename in inputfiles: f_in = self._open_file_or_zip(filename) self._check_version(f_in) self.parse_schematic(f_in) basename, _ = os.path.splitext(os.path.basename(filename)) self.design.design_attributes.metadata.set_name(basename) ## modify offset for next page to be shifted to the right self.offset.x = self.offset.x - self.frame_width f_in.close() ## if unassigned shapes have been found during parsing add a new ## component to the design if len(self.unassigned_body.shapes + self.unassigned_body.pins) > 0: component = components.Component("UNASSIGNED_SHAPES") symbol = components.Symbol() component.add_symbol(symbol) symbol.add_body(self.unassigned_body) instance = ComponentInstance(component.name, component.name, 0) symbol = SymbolAttribute(0, 0, 0) instance.add_symbol_attribute(symbol) self.design.add_component(component.name, component) self.design.add_component_instance(instance) return self.design
def parse_component_instances(self, component_instances): """ Extract the component instances. """ if component_instances is None: return None for instance in component_instances: # Get instance_id, library_id and symbol_index instance_id = instance.get('instance_id') library_id = instance.get('library_id') symbol_index = int(instance.get('symbol_index')) footprint_index = int(instance.get('footprint_index')) # Make the ComponentInstance() inst = ComponentInstance( instance_id, self.design.components.components[library_id], library_id, symbol_index, footprint_index) # Get the SymbolAttributes for symbol_attribute in instance.get('symbol_attributes', []): attr = self.parse_symbol_attribute(symbol_attribute) inst.add_symbol_attribute(attr) # TODO(shamer) footprint_pos, fleb and genobj positions are relative to the footprint_pos for footprint_attribute in instance.get('footprint_attributes', []): attr = self.parse_footprint_attribute(footprint_attribute) inst.add_footprint_attribute(attr) for gen_obj_attribute in instance.get('gen_obj_attributes', []): attr = self.parse_gen_obj_attribute(gen_obj_attribute) inst.add_gen_obj_attribute(attr) footprint_json = instance.get('footprint_pos') if footprint_json: footprint_pos = self.parse_footprint_pos(footprint_json) else: footprint_pos = None inst.set_footprint_pos(footprint_pos) # Get the Attributes for key, value in instance.get('attributes').items(): inst.add_attribute(key, value) # Add the ComponentInstance self.design.add_component_instance(inst)