def _get_config_files(self, paths=[]): """ Get config files. :param list path: ist of paths to add to the scan. :returns: dictionary of config names/filenames. :rtype: dict """ cfg_files = dict() if not paths: return [] for path in paths: for fn in os.listdir(path): bn, fext = os.path.splitext(fn) if fext.lower() in ['.ini', '.cfg']: cfg_file = os.path.join(path, fn) names = bn.split('-') if len(names) < 2: log.warning('improperly named config file: "%s"' % cfg_file) continue style_name, cfg_type = names if style_name not in cfg_files: cfg_files[style_name] = dict(fonts=None, palette=None) log.debug('adding %s config "%s" from "%s".' % (cfg_type, style_name, cfg_file)) cfg_files[style_name][cfg_type] = cfg_file return cfg_files
def remove_edge(self, *args): """ Removes an edge from the graph. :param str UUID: edge UUID :param str conn: connection string (ie "node1.output,node2.input") :returns: edge removal was successful. :rtype: bool """ edges = self.get_edge(*args) if not edges: log.warning('cannot find edge.') return for edge in edges: edge_id = (edge[0], edge[1]) if edge_id in self.network.edges(): log.debug('Removing edge: "%s"' % self.edge_nice_name(*edge_id)) self.network.remove_edge(*edge_id) self.remove_node_edge(*edge_id) # update the scene self.graphUpdated(edge_id) return True return False
def evaluate(self, dagnodes=[], verbose=False): """ Evalute the Graph, updating networkx graph. """ result = True if not dagnodes: dagnodes = self.dagnodes.values() # update network nodes from dag attributes self.updateDagNodes(dagnodes) node_ids = [] invalid_node_ids = [] for node in dagnodes: if self.is_node(node): if node.id not in node_ids: node_ids.append(node.id) if self.network.edges(): for edge in self.network.edges_iter(data=True): src_id, dest_id, edge_attrs = edge source_node = self.dagnodes.get(src_id, None) dest_node = self.dagnodes.get(dest_id, None) if self.network.nodes(): for node in self.network.nodes_iter(data=True): node_id, node_attrs = node if node_id not in node_ids: invalid_node_ids.append(node_id) log.warning('invalid NetworkX node "%s" ( %s )' % (node_attrs.get('name'), node_id)) result = False return result
def _get_qss_files(self, paths=[]): """ Get qss files. :param list path: ist of paths to add to the scan. :returns: dictionary of stylesheet names/filenames. :rtype: dict """ qss_files = dict() if not paths: return [] for path in paths: for fn in os.listdir(path): bn, fext = os.path.splitext(fn) if fext.lower() in ['.qss', '.css']: qss_file = os.path.join(path, fn) if qss_file not in qss_files.values(): style_name = self._parse_stylesheet_name(qss_file) if style_name is None: log.warning('cannot parse style name from "%s".' % qss_file) style_name = 'no-style' log.debug('adding stylesheet "%s" from "%s".' % (style_name, qss_file)) if style_name not in qss_files: qss_files[style_name] = qss_file return qss_files
def snapshot(self): """ Returns a snapshot dictionary for writing scenes and updating undo stack. .. todo:: - try using the nxj.adjacency_data() method. :returns: dictionary of graph data. :rtype: dict """ if not self.evaluate(): log.warning('graph did not evaluate correctly.') attrs = { 'source': 'source', 'target': 'target', 'key': 'key', 'id': 'id', 'src_id': 'src_id', 'dest_id': 'dest_id', 'src_attr': 'src_attr', 'dest_attr': 'dest_attr', 'weight': 'weight', 'style': 'style' } graph_data = nxj.node_link_data(self.network, attrs=attrs) return graph_data
def _get_qss_paths(self, paths=[]): """ Read stylesheets from config paths. :param list paths: list of paths to add to the scan. :returns: array of search paths. :rtype: tuple """ if paths and type(paths) in [str, unicode]: paths = [paths,] qss_paths = () qss_paths = qss_paths + (options.SCENEGRAPH_STYLESHEET_PATH,) # read external paths if 'SCENEGRAPH_STYLESHEET_PATH' in os.environ: qpaths = os.getenv('SCENEGRAPH_STYLESHEET_PATH').split(':') if paths: for p in paths: if p not in qpaths: qpaths.append(p) for path in qpaths: if path not in qss_paths: if not os.path.exists(path): log.warning('stylesheet path "%s" does not exist, skipping.' % path) continue log.debug('reading external stylesheet path: "%s".' % path) qss_paths = qss_paths + (path,) return qss_paths
def _get_config_paths(self, paths=[]): """ Read configs from config paths. :param list paths: list of paths to add to the scan. :returns: array of search paths. :rtype: tuple """ if paths and type(paths) in [str, unicode]: paths = [paths,] cfg_paths = () cfg_paths = cfg_paths + (options.SCENEGRAPH_CONFIG_PATH,) # read external paths if 'SCENEGRAPH_CONFIG_PATH' in os.environ: spaths = os.getenv('SCENEGRAPH_CONFIG_PATH').split(':') if paths: for p in paths: if p not in spaths: spaths.append(p) for path in spaths: if path not in cfg_paths: if not os.path.exists(path): log.warning('config path "%s" does not exist, skipping.' % path) continue log.debug('reading config external path: "%s".' % path) cfg_paths = cfg_paths + (path,) return cfg_paths
def add_edge(self, src, dest, **kwargs): """ Add an edge connecting two nodes. :param src: source node :type src: DagNode :param dest: destination node :type dest: DagNode :returns: edge dictionary :rtype: dict """ src_attr = kwargs.pop('src_attr', 'output') dest_attr = kwargs.pop('dest_attr', 'input') weight = kwargs.pop('weight', 1.0) edge_type = kwargs.pop('edge_type', 'bezier') style = kwargs.pop('style', 'solid') if src is None or dest is None: log.warning('none type passed.') return False if not src or not dest: log.warning('please specify two nodes to connect.') return False # don't connect the same node if src.name == dest.name: log.warning('invalid connection: "%s", "%s"' % (src.name, dest.name)) return conn_str = '%s.%s,%s.%s' % (src.name, src_attr, dest.name, dest_attr) if conn_str in self.connections(): log.warning('connection already exists: %s' % conn_str) return # edge attributes for nx graph edge_attrs = dict(src_id=src.id, dest_id=dest.id, src_attr=src_attr, dest_attr=dest_attr, edge_type=edge_type, style=style) src_conn = src.get_connection(src_attr) dest_conn = dest.get_connection(dest_attr) edge_id_str = '(%s,%s)' % (src.id, dest.id) #if edge_id_str not in src_conn._edges and edge_id_str not in dest_conn._edges: # add the nx edge - weight should go here self.network.add_edge(src.id, dest.id, key='attributes', weight=weight, attr_dict=edge_attrs) log.info('adding edge: "%s"' % self.edge_nice_name(src.id, dest.id)) # new edge = {'attributes': {'dest_attr': 'input', 'src_attr': 'output', 'weight': 1}} new_edge = self.network.edge[src.id][dest.id] #print 'new edge: ', new_edge src_conn._edges.append(edge_id_str) dest_conn._edges.append(edge_id_str) # update the scene self.edgesAdded([new_edge.get('attributes')]) return new_edge
def setScene(self, filename=None): """ Set the current scene value. :param filename: scene file name. :type filename: str :returns: scene file name. :rtype: str """ tmp_dir = os.getenv('TMPDIR') if not tmp_dir: log.warning('environment "TMPDIR" not set, please set and restart.') if tmp_dir not in filename: self.network.graph['scene'] = filename return self.getScene()
def snapshot(self): """ Returns a snapshot dictionary for writing scenes and updating undo stack. .. todo:: - try using the nxj.adjacency_data() method. :returns: dictionary of graph data. :rtype: dict """ if not self.evaluate(): log.warning('graph did not evaluate correctly.') attrs = {'source': 'source', 'target': 'target', 'key': 'key', 'id': 'id', 'src_id': 'src_id', 'dest_id': 'dest_id', 'src_attr': 'src_attr', 'dest_attr': 'dest_attr', 'weight':'weight', 'style':'style'} graph_data = nxj.node_link_data(self.network, attrs=attrs) return graph_data
def setScene(self, filename=None): """ Set the current scene value. :param filename: scene file name. :type filename: str :returns: scene file name. :rtype: str """ tmp_dir = os.getenv('TMPDIR') if not tmp_dir: log.warning( 'environment "TMPDIR" not set, please set and restart.') if tmp_dir not in filename: self.network.graph['scene'] = filename return self.getScene()
def scanNodeTypes(self, path): """ Scan the given directory for node types. :param str path: path to scan. """ nodes = dict() if not os.path.exists(path): log.warning('node path "%s" does not exist.' % path) return nodes for fn in os.listdir(path): if fn not in ['README']: node_name = os.path.splitext(os.path.basename(fn))[0] node_mod = os.path.join(path, '%s.py' % node_name) node_data = os.path.join(path, '%s.mtd' % node_name) if os.path.exists(node_mod) and os.path.exists(node_data): node_attrs = dict() node_attrs['module'] = node_mod node_attrs['metadata'] = node_data nodes[node_name] = node_attrs else: if not os.path.exists(node_mod): log.warning('cannot find "%s" module %s' % (node_name, node_mod)) if not os.path.exists(node_data): log.warning('cannot find "%s" metadata %s' % (node_name, node_data)) return nodes
def scanNodeTypes(self, path): """ Scan the given directory for node types. :param str path: path to scan. """ nodes = dict() if not os.path.exists(path): log.warning('node path "%s" does not exist.' % path) return nodes for fn in os.listdir(path): if fn not in ['README']: node_name = os.path.splitext(os.path.basename(fn))[0] node_mod = os.path.join(path, '%s.py' % node_name) node_data = os.path.join(path, '%s.mtd' % node_name) if os.path.exists(node_mod) and os.path.exists(node_data): node_attrs = dict() node_attrs['module'] = node_mod node_attrs['metadata'] = node_data nodes[node_name]=node_attrs else: if not os.path.exists(node_mod): log.warning('cannot find "%s" module %s' % (node_name, node_mod)) if not os.path.exists(node_data): log.warning('cannot find "%s" metadata %s' % (node_name, node_data)) return nodes
def _get_qss_paths(self, paths=[]): """ Read stylesheets from config paths. :param list paths: list of paths to add to the scan. :returns: array of search paths. :rtype: tuple """ if paths and type(paths) in [str, unicode]: paths = [ paths, ] qss_paths = () qss_paths = qss_paths + (options.SCENEGRAPH_STYLESHEET_PATH, ) # read external paths if 'SCENEGRAPH_STYLESHEET_PATH' in os.environ: qpaths = os.getenv('SCENEGRAPH_STYLESHEET_PATH').split(':') if paths: for p in paths: if p not in qpaths: qpaths.append(p) for path in qpaths: if path not in qss_paths: if not os.path.exists(path): log.warning( 'stylesheet path "%s" does not exist, skipping.' % path) continue log.debug('reading external stylesheet path: "%s".' % path) qss_paths = qss_paths + (path, ) return qss_paths
def _get_config_paths(self, paths=[]): """ Read configs from config paths. :param list paths: list of paths to add to the scan. :returns: array of search paths. :rtype: tuple """ if paths and type(paths) in [str, unicode]: paths = [ paths, ] cfg_paths = () cfg_paths = cfg_paths + (options.SCENEGRAPH_CONFIG_PATH, ) # read external paths if 'SCENEGRAPH_CONFIG_PATH' in os.environ: spaths = os.getenv('SCENEGRAPH_CONFIG_PATH').split(':') if paths: for p in paths: if p not in spaths: spaths.append(p) for path in spaths: if path not in cfg_paths: if not os.path.exists(path): log.warning( 'config path "%s" does not exist, skipping.' % path) continue log.debug('reading config external path: "%s".' % path) cfg_paths = cfg_paths + (path, ) return cfg_paths
def restore(self, data, nodes=True, graph=True): """ Restore current DAG state from data. Also used for restoring graph state for the undo stack. :param dict data: dictionary of scene graph data. :param bool nodes: restore nodes/edges. :param bool graph: restore scene attributes/preferences. """ self.reset() graph_data = data.get('graph', []) node_data = data.get('nodes', []) edge_data = data.get('links', []) self.updateConsole(msg='restoring %d nodes' % len(node_data)) # update graph attributes for gdata in graph_data: if len(gdata): if graph or gdata[0] in ['scene', 'api_version']: if len(gdata) > 1: self.network.graph[gdata[0]] = gdata[1] # build nodes from data if nodes: for node_attrs in node_data: # get the node type node_type = node_attrs.pop('node_type', 'default') # add the dag node/widget dag_node = self.add_node(node_type, **node_attrs) log.debug('building node "%s"' % node_attrs.get('name')) # edge : ['src_attr', 'target', 'weight', 'dest_id', 'source', 'dest_attr', 'key', 'src_id'] for edge in edge_data: src_id = edge.get('src_id') dest_id = edge.get('dest_id') src_attr = edge.get('src_attr') dest_attr = edge.get('dest_attr') weight = edge.get('weight', 1.0) src_dag_nodes = self.get_node(src_id) dest_dag_nodes = self.get_node(dest_id) if not src_dag_nodes or not dest_dag_nodes: log.warning('cannot parse nodes.') return src_dag_node = src_dag_nodes[0] dest_dag_node = dest_dag_nodes[0] src_string = '%s.%s' % (src_dag_node.name, src_attr) dest_string = '%s.%s' % (dest_dag_node.name, dest_attr) # TODO: need to get connection node here log.info('connecting nodes: "%s" "%s"' % (src_string, dest_string)) dag_edge = self.add_edge(src_dag_node, dest_dag_node, src_attr=src_attr, dest_attr=dest_attr, weight=weight) #self.handler.scene.clear() scene_pos = self.network.graph.get('view_center', (0, 0)) view_scale = self.network.graph.get('view_scale', (1.0, 1.0)) # update the UI. if self.mode == 'ui': if graph: self.handler.restoreGeometry(pos=scene_pos, scale=view_scale) self._initialized = 1
def parse(self, filename): """ Parses a single template file. Data is structured into groups of attributes (ie: 'Transform', 'Attributes') :param str filename: file on disk to read. :returns: dictionary of metadata parameters. :rtype: dict """ if self._initialized: self.initialize() log.debug('reading metadata file: "%s"' % filename) data = dict() if filename is not None: if os.path.exists(filename): parent = data attr_name = None for line in open(filename,'r'): #remove newlines line = line.rstrip('\n') rline = line.lstrip(' ') rline = rline.rstrip() if not rline.startswith("#") and not rline.startswith(';') and rline.strip() != "": # parse sections # remove leading spaces # section/attribute header match if re.match(regex.get("section"), rline): section_obj = re.search(regex.get("section_value"), rline) if section_obj: section_type = section_obj.group('attr') section_value = section_obj.group('value') # parse groups if section_type == 'group': if section_value not in parent: parent = data group_data = dict() # set the current parent parent[section_value] = group_data parent = parent[section_value] #print '\nGroup: "%s"' % section_value if section_type == 'attr': attr_data = dict() # connection attributes #attr_data.update(connectable=False) #attr_data.update(connection_type=None) parent[section_value] = attr_data attr_name = section_value #print ' Attribute: "%s"' % attr_name if section_type in ['input', 'output']: conn_data = dict() conn_data.update(connectable=True) conn_data.update(connection_type=section_type) parent[section_value] = conn_data attr_name = section_value #print ' Connection: "%s"' % attr_name else: prop_obj = re.search(regex.get("properties"), rline) if prop_obj: pname = prop_obj.group('name') ptype = prop_obj.group('type') pvalu = prop_obj.group('value') #print 'property: "%s" (%s)' % (pname, rline) value = pvalu if ptype in ['BOOL', 'INPUT', 'OUTPUT']: if ptype == 'BOOL': value = True if pvalu == 'true' else False # return connection types if ptype in ['INPUT', 'OUTPUT']: # data type: pvalu = FILE, DIRECTORY, ETC. value = pvalu.lower() # try and get the actual value else: try: value = eval(pvalu) except: log.warning('cannot parse default value of "%s.%s": "%s" (%s)' % (attr_name, pname, pvalu, filename)) #print ' property: %s (%s)' % (prop_obj.group('name'), attr_name) properties = {pname: {'type':ptype, 'value':value}} parent[attr_name].update(properties) else: if rline: log.debug('skipping: "%s"' % rline) return data
def get_edge(self, *args): """ Return an edge attribute dictionary. Pass connection string ie: ('node1.output, node2.input'), or source dest (ie: 'node1.output', 'node2.input') :returns: list of nx edges (id, id, {attributes}) :rtype: list """ edges=[] cs = lambda x: [y.strip() for y in x.split(',')] # variables to match src_conn = None dest_conn = None src_name = None dest_name = None src_attr = 'output' dest_attr = 'input' edgeid = None # parse connection strings if len(args): if len(args) > 1: if (args[0], args[1]) in self.network.edges(): edgeid = (args[0], args[1]) if type(args[0]) is str and type(args[1]) is str: src_conn = args[0] dest_conn = args[1] else: if type(args[0]) is str: if ',' in args[0]: src_conn, dest_conn = cs(args[0]) if not src_conn or not dest_conn: log.warning('invalid arguments passed.') return if '.' in src_conn: src_name, src_attr = src_conn.split('.') if '.' in dest_conn: dest_name, dest_attr = dest_conn.split('.') # loop through nx edges # edge: (id, id, {'src_id': id, 'dest_attr': 'input', 'src_attr': 'output', 'dest_id': id, 'weight': 1}) for edge in self.network.edges(data=True): srcid, destid, attrs = edge edge_id = (srcid, destid) #match two ids if edge_id == edgeid: edges.append(edge) sn_attr = attrs.get('src_attr', None) dn_attr = attrs.get('dest_attr', None) src_nodes = self.get_node(srcid) dest_nodes = self.get_node(destid) if not src_nodes or not dest_nodes: continue if not sn_attr or not dn_attr: continue src_node = src_nodes[0] dest_node = dest_nodes[0] sn_name = src_node.name dn_name = dest_node.name if src_name == sn_name and dest_name == dn_name: if src_attr == sn_attr and dest_attr == dn_attr: edges.append(edge) return edges
def get_edge(self, *args): """ Return an edge attribute dictionary. Pass connection string ie: ('node1.output, node2.input'), or source dest (ie: 'node1.output', 'node2.input') :returns: list of nx edges (id, id, {attributes}) :rtype: list """ edges = [] cs = lambda x: [y.strip() for y in x.split(',')] # variables to match src_conn = None dest_conn = None src_name = None dest_name = None src_attr = 'output' dest_attr = 'input' edgeid = None # parse connection strings if len(args): if len(args) > 1: if (args[0], args[1]) in self.network.edges(): edgeid = (args[0], args[1]) if type(args[0]) is str and type(args[1]) is str: src_conn = args[0] dest_conn = args[1] else: if type(args[0]) is str: if ',' in args[0]: src_conn, dest_conn = cs(args[0]) if not src_conn or not dest_conn: log.warning('invalid arguments passed.') return if '.' in src_conn: src_name, src_attr = src_conn.split('.') if '.' in dest_conn: dest_name, dest_attr = dest_conn.split('.') # loop through nx edges # edge: (id, id, {'src_id': id, 'dest_attr': 'input', 'src_attr': 'output', 'dest_id': id, 'weight': 1}) for edge in self.network.edges(data=True): srcid, destid, attrs = edge edge_id = (srcid, destid) #match two ids if edge_id == edgeid: edges.append(edge) sn_attr = attrs.get('src_attr', None) dn_attr = attrs.get('dest_attr', None) src_nodes = self.get_node(srcid) dest_nodes = self.get_node(destid) if not src_nodes or not dest_nodes: continue if not sn_attr or not dn_attr: continue src_node = src_nodes[0] dest_node = dest_nodes[0] sn_name = src_node.name dn_name = dest_node.name if src_name == sn_name and dest_name == dn_name: if src_attr == sn_attr and dest_attr == dn_attr: edges.append(edge) return edges
def read_metadata(self, verbose=False): """ Initialize node metadata from metadata files on disk. Metadata is parsed by looking at the __bases__ of each node class (ie: all DagNode subclasses will inherit all of the default DagNode attributes). """ import inspect parser = MetadataParser() node_metadata = dict() if verbose: print '\n# DEBUG: building metadata for: "%s" ' % self.Class() # query the base classes result = [self.__class__,] for pc in self.ParentClasses(): if pc.__name__ != 'Node': result.append(pc) sg_core_path = os.path.join(SCENEGRAPH_CORE, 'nodes.py') for cls in reversed(result): cname = cls.__name__ src_file = inspect.getfile(cls) node_type = None if hasattr(cls, 'node_type'): node_type = cls.node_type py_src = src_file.rstrip('c') if verbose: print ' - base class "%s" source file: "%s"' % (cname, py_src) dirname = os.path.dirname(src_file) basename = os.path.splitext(os.path.basename(src_file))[0] # return the source .py file if it exists if os.path.exists(py_src): src_file = py_src metadata_filename = os.path.join(dirname, '%s.mtd' % basename) # look for code node metadata in ../mtd if py_src == sg_core_path: if node_type: metadata_filename = os.path.join(SCENEGRAPH_METADATA_PATH, '%s.mtd' % node_type) if verbose: print ' - metadata file for "%s": "%s"' % (cname, metadata_filename) if not os.path.exists(metadata_filename): if not verbose: log.warning('plugin description file "%s" does not exist.' % metadata_filename) else: print ' WARNING: metadata file for "%s": "%s" not found' % (cname, metadata_filename) continue log.debug('reading plugin metadata file: "%s".' % metadata_filename) # parse the metadata parsed = parser.parse(metadata_filename) for section in parsed: if section not in node_metadata: node_metadata[section] = dict() attributes = parsed.get(section) # parse out input/output here? for attr in attributes: if attr not in node_metadata[section]: node_metadata.get(section)[attr] = dict() attr_properties = attributes.get(attr) node_metadata.get(section).get(attr).update(attr_properties) return node_metadata
def restore(self, data, nodes=True, graph=True): """ Restore current DAG state from data. Also used for restoring graph state for the undo stack. :param dict data: dictionary of scene graph data. :param bool nodes: restore nodes/edges. :param bool graph: restore scene attributes/preferences. """ self.reset() graph_data = data.get('graph', []) node_data = data.get('nodes', []) edge_data = data.get('links', []) self.updateConsole(msg='restoring %d nodes' % len(node_data)) # update graph attributes for gdata in graph_data: if len(gdata): if graph or gdata[0] in ['scene', 'api_version']: if len(gdata) > 1: self.network.graph[gdata[0]]=gdata[1] # build nodes from data if nodes: for node_attrs in node_data: # get the node type node_type = node_attrs.pop('node_type', 'default') # add the dag node/widget dag_node = self.add_node(node_type, **node_attrs) log.debug('building node "%s"' % node_attrs.get('name')) # edge : ['src_attr', 'target', 'weight', 'dest_id', 'source', 'dest_attr', 'key', 'src_id'] for edge in edge_data: src_id = edge.get('src_id') dest_id = edge.get('dest_id') src_attr = edge.get('src_attr') dest_attr = edge.get('dest_attr') weight = edge.get('weight', 1.0) src_dag_nodes = self.get_node(src_id) dest_dag_nodes = self.get_node(dest_id) if not src_dag_nodes or not dest_dag_nodes: log.warning('cannot parse nodes.') return src_dag_node = src_dag_nodes[0] dest_dag_node = dest_dag_nodes[0] src_string = '%s.%s' % (src_dag_node.name, src_attr) dest_string = '%s.%s' % (dest_dag_node.name, dest_attr) # TODO: need to get connection node here log.info('connecting nodes: "%s" "%s"' % (src_string, dest_string)) dag_edge = self.add_edge(src_dag_node, dest_dag_node, src_attr=src_attr, dest_attr=dest_attr, weight=weight) #self.handler.scene.clear() scene_pos = self.network.graph.get('view_center', (0,0)) view_scale = self.network.graph.get('view_scale', (1.0, 1.0)) # update the UI. if self.mode == 'ui': if graph: self.handler.restoreGeometry(pos=scene_pos, scale=view_scale) self._initialized = 1
def read_metadata(self, verbose=False): """ Initialize node metadata from metadata files on disk. Metadata is parsed by looking at the __bases__ of each node class (ie: all DagNode subclasses will inherit all of the default DagNode attributes). """ import inspect parser = MetadataParser() node_metadata = dict() if verbose: print '\n# DEBUG: building metadata for: "%s" ' % self.Class() # query the base classes result = [ self.__class__, ] for pc in self.ParentClasses(): if pc.__name__ != 'Node': result.append(pc) sg_core_path = os.path.join(SCENEGRAPH_CORE, 'nodes.py') for cls in reversed(result): cname = cls.__name__ src_file = inspect.getfile(cls) node_type = None if hasattr(cls, 'node_type'): node_type = cls.node_type py_src = src_file.rstrip('c') if verbose: print ' - base class "%s" source file: "%s"' % (cname, py_src) dirname = os.path.dirname(src_file) basename = os.path.splitext(os.path.basename(src_file))[0] # return the source .py file if it exists if os.path.exists(py_src): src_file = py_src metadata_filename = os.path.join(dirname, '%s.mtd' % basename) # look for code node metadata in ../mtd if py_src == sg_core_path: if node_type: metadata_filename = os.path.join(SCENEGRAPH_METADATA_PATH, '%s.mtd' % node_type) if verbose: print ' - metadata file for "%s": "%s"' % ( cname, metadata_filename) if not os.path.exists(metadata_filename): if not verbose: log.warning( 'plugin description file "%s" does not exist.' % metadata_filename) else: print ' WARNING: metadata file for "%s": "%s" not found' % ( cname, metadata_filename) continue log.debug('reading plugin metadata file: "%s".' % metadata_filename) # parse the metadata parsed = parser.parse(metadata_filename) for section in parsed: if section not in node_metadata: node_metadata[section] = dict() attributes = parsed.get(section) # parse out input/output here? for attr in attributes: if attr not in node_metadata[section]: node_metadata.get(section)[attr] = dict() attr_properties = attributes.get(attr) node_metadata.get(section).get(attr).update( attr_properties) return node_metadata
def parse(self, filename): """ Parses a single template file. Data is structured into groups of attributes (ie: 'Transform', 'Attributes') :param str filename: file on disk to read. :returns: dictionary of metadata parameters. :rtype: dict """ if self._initialized: self.initialize() log.debug('reading metadata file: "%s"' % filename) data = dict() if filename is not None: if os.path.exists(filename): parent = data attr_name = None for line in open(filename, 'r'): #remove newlines line = line.rstrip('\n') rline = line.lstrip(' ') rline = rline.rstrip() if not rline.startswith("#") and not rline.startswith( ';') and rline.strip() != "": # parse sections # remove leading spaces # section/attribute header match if re.match(regex.get("section"), rline): section_obj = re.search(regex.get("section_value"), rline) if section_obj: section_type = section_obj.group('attr') section_value = section_obj.group('value') # parse groups if section_type == 'group': if section_value not in parent: parent = data group_data = dict() # set the current parent parent[section_value] = group_data parent = parent[section_value] #print '\nGroup: "%s"' % section_value if section_type == 'attr': attr_data = dict() # connection attributes #attr_data.update(connectable=False) #attr_data.update(connection_type=None) parent[section_value] = attr_data attr_name = section_value #print ' Attribute: "%s"' % attr_name if section_type in ['input', 'output']: conn_data = dict() conn_data.update(connectable=True) conn_data.update( connection_type=section_type) parent[section_value] = conn_data attr_name = section_value #print ' Connection: "%s"' % attr_name else: prop_obj = re.search(regex.get("properties"), rline) if prop_obj: pname = prop_obj.group('name') ptype = prop_obj.group('type') pvalu = prop_obj.group('value') #print 'property: "%s" (%s)' % (pname, rline) value = pvalu if ptype in ['BOOL', 'INPUT', 'OUTPUT']: if ptype == 'BOOL': value = True if pvalu == 'true' else False # return connection types if ptype in ['INPUT', 'OUTPUT']: # data type: pvalu = FILE, DIRECTORY, ETC. value = pvalu.lower() # try and get the actual value else: try: value = eval(pvalu) except: log.warning( 'cannot parse default value of "%s.%s": "%s" (%s)' % (attr_name, pname, pvalu, filename)) #print ' property: %s (%s)' % (prop_obj.group('name'), attr_name) properties = { pname: { 'type': ptype, 'value': value } } parent[attr_name].update(properties) else: if rline: log.debug('skipping: "%s"' % rline) return data