def change(self): """change component SIDL_SYMBOL options """ project,graph = Globals().getProjectAndGraph(self.projectName) # delete uses or provides port if self.options.deletePortName: allmyports = [x.getName() for x in self._b_provides + self._b_uses] for p in self.options.deletePortName: if p not in allmyports: err('There is not port named ' + p + ' in this component.') for pname in self.options.deletePortName: for theport in self._b_uses + self._b_provides: if pname == theport.getName(): # TODO: Make sure this port is not in the implements or provides list under more than one name # before deleting the type ptype = theport.getType() if [x.getType()==ptype for x in self._b_uses + self._b_provides].count(True) + self._b_implements.keys().count(ptype) <= 0: # remove edge self.removeInEdge(ptype, kind = 'port', graph=graph) if location == '%external%': # Remove external file name in project defaults file if not self._findExternal(ptype): project.removeDefaultValue(ptype,'External') print >>DEBUGSTREAM, 'Removed external port or interface: ' + ptype if ptype in self._b_externalSidlFiles.keys(): del self._b_externalSidlFiles[ptype] try: if theport in self._b_uses: self._b_uses.remove(theport) elif theport in self._b_provides: self._b_provides.remove(theport) except: err('Could not remove port %s, port not used or provided in component %s' % (pname, self.symbol)) # Let class handle everything it can (it also calls the builder update method) Sidlclass.change(self) return 0
def parseFile(self, filename, stripBocca=False): ''' Parse the file and return an AST object ''' if not os.path.exists(filename): err('[SIDL parser] file not found: ' + filename) self.filename = filename f = file(filename) s = f.read() f.close() # Strip bocca splice delimiters and protected blocks from old text if (stripBocca): lineList = s.split('\n') noBoccaList = [ l for l in lineList if l.find('DO-NOT-DELETE bocca.splicer.') == -1] inProtected=False noBlockList=[] for l in noBoccaList: if inProtected: if l.find("DO-NOT-DELETE bocca.protected.end") != -1: inProtected = False continue else: if l.find("DO-NOT-DELETE bocca.protected.begin") != -1: inProtected = True continue noBlockList.append(l) if inProtected: err('[SIDL parser] unterminated bocca.protected block in input.') s = '\n'.join(noBlockList) return self.parse(s)
def loadFile(self, input, key, preserveProtected=False): """Load a file as a set of blocks chunked up by key. returns (0, "ok") or (1, "errmsg"). If you don't have a file but have a list of lines, use loadList instead. """ self.fin = input self.nsplices = 0 try: f = fileManager.open(input, 'r') lines = f.readlines() f.close() except IOError, e: err('Error loading file ' + str(input) + '(' + str(e) +')' )
def writeString(self, outFileName, verbose=False, rejectSave=True, rejectFileName="", rejectLines =[]): """return string representation of file for other's to output. outFileName is used to write rejects if specified or to issue error messages. @return (status, resultString) where if status is True, string will be valid and if false, the input source was apparently empty.""" fname = outFileName writeRejects = (rejectSave and rejectLines != None) if writeRejects: rname = fname + ".rej" if len(rejectFileName) > 0: rname = rejectFileName if self.nsplices < 1: if verbose: print "Nothing new to write to ", fname if self.num < 1: print "Nothing old to copy to ", fname print "Reading ", self.fin, " failed?" return (False, "") if verbose: if writeRejects: print "Writing rejects to ", rname print "Writing to string for ", fname if True: outlist = [] if writeRejects: try: rejfile = fileManager.open(rname,"w") except: err('splicer could not open rejects file for writing: ' + rname) for i in self.sections: isProtected = False for s in self.protectedSymbols: if i == self.getProtectedBlock(s): isProtected = True break if isProtected: continue lines = i.getLines() for p in lines: outlist.append( p.strip("\n") ) stringified = "\n".join(outlist) if writeRejects: date = Line.stringdate() print >> rejfile, "#FROM %s on %s" % (fname, date) for p in rejectLines: print >> rejfile , p.strip("\n") if verbose: if writeRejects: print " Finished ", rname print " Finished ", fname return (True, stringified) else: print "Error writing for "+ fname return (False, "")
def __init__(self, modulePath, project): '''Constructor Must be called from every derived plugin before rest of plugin's init. @param modulePath the directory containing the implementation of the BuilderInterface ''' if str(project.__class__) != 'project.Project': err("Builder plugin: invoking update on a vertex that is not a Project: " + str(project.__class__)) self.project = project # Load the local LocationManagerInterface implementation try: (file,filename,description) = imp.find_module('locations',[modulePath]) locations = imp.load_module('locations', file, filename, description) except ImportError,e: err('Builder: Could not import locations module from ' + modulePath + ': ' + str(e))
def writeRejects(self, rejectFileName, rejectLines='', originalFile='', verbose=False, dryrun=False): if len(rejectLines) == 0: print "No rejection information to put into " + rejectFileName return False if dryrun: print "Dry run: Not writing to " + rejectFileName # For a dry run, don't do anything return True if verbose: print "Writing rejects to: " + rejectFileName outfile = None try: outfile = fileManager.open(rejectFileName,'w') except IOError, e: err('splicer could not open reject file %s for writing: %s' % (rejectFileName, str(e)))
def write(self, outFileName, verbose=False, dryrun=False, rejectSave=True, rejectFileName="", rejectLines =[]): """return true if succeeds writing to output file named.""" fname = outFileName writeRejects = (rejectSave and rejectLines != None and len(rejectLines) > 0) if writeRejects: rname = fname + ".rej" if len(rejectFileName) > 0: rname = rejectFileName if self.nsplices < 1: if verbose: print "Nothing new to write to ", fname if self.num < 1: print "Nothing old to copy to ", fname print "Reading ", self.fin, " failed?" return False if dryrun: return True if True: outfile = None try: outfile = fileManager.open(fname,"w") except IOError,e: err('splicer could not open file for writing: ' + fname + '; ' + str(e)) for i in self.sections: # Kludge to get around printing protected symbols in the merged file. isProtected = False for s in self.protectedSymbols: if i == self.getProtectedBlock(s): isProtected=True break if isProtected: continue lines = i.getLines() # print "writing section ", i.key(), " len = ", len(lines) for p in lines: print >> outfile, "%s" % p.strip("\n") if writeRejects: if not self.writeRejects(rname, rejectLines, originalFile=outFileName, verbose=verbose, dryrun=dryrun): return False if verbose: if writeRejects: print " Finished ", rname print " Finished ", fname outfile.close() return True
def visitEnumeration(self, node): if self.parentVertex.kind in ['package','project','enum']: parentid = node.getParent().getFullIdentifier() id = node.getFullIdentifier() if self.matchPartialSymbols(id, self.symbols) or self.doAll: shortId = node.getIdentifier() if parentid in self.packages.keys(): pVertex = self.packages[parentid] else: if self.parentVertex.kind not in ['package', 'project', 'enum']: err('Enums can only be imported into Bocca packages') pVertex = self.parentVertex newId = pVertex.symbol + '.' + shortId if self.parentVertex.kind == 'project': newId = id slist = self.graph.findSymbol(newId, kind='any') if len(slist) == 1 and slist[0].kind == 'enum': enum = slist[0] enum.setASTNode(node) elif not slist: if self.parentVertex.kind != 'enum': enum = cct.enum.Enum(action='create', args=[newId], version=pVertex.version, project=self.project, modulePath=self.project.modulePath, graph=self.graph) else: enum = self.parentVertex enum.setASTNode(node) if len(node.getContents()): enum.genDummy = False if self.parentVertex.kind != 'enum': enum.create() comment = node.getStartComment() if comment: enum.setComment(comment) else: self._symbolConflictError(slist) edge = BEdge(pVertex, enum, self.graph, action='contains') self.enums[id] = enum self.visitVertex(node) pass
def portArgsToDict(self, arg): """ Return dictionary of port arguments, where Dictionary keys = Port Names Dictionary entries = Port Types """ # Make sure we have a unified list of portType:portName pairs, possible # derived from multiple sub-lists on the command line # TODO: Check whether this way of specifying oprt arguments is too flexible. argList = ','.join(arg).split(',') d = {} for p in argList: l = p.split(':') if (len(l)!= 2): err("Invalid port specification : " + p +"\nPort specification of the form portType:portnAME", 2) if l[1] in d.keys(): err("Duplicate specification of port name \"", p[1], "\"", 2) print >> DEBUGSTREAM, "port name = ", l[1] print >> DEBUGSTREAM, "port type = ", l[0] d[l[1]] = l[0] return d
def defineArgs(self, action): '''Defines command line options and defaults for this command. This is invoked in the constructor of the parent class Subcommand. ''' if (action == 'create'): self.defineArgsCreate() elif action == 'copy': Sidlclass.defineArgsCopy(self) elif action == 'rename': pass elif action == 'display': Sidlclass.defineArgs(self, action) elif action == 'change': self.defineArgsChange() elif action == 'edit' or action == 'whereis': Sidlclass.defineArgs(self, action) elif action == 'remove': Sidlclass.defineArgsRemove(self) else: err('Component verb "' + action + '" NOT implemented yet.', 3) return
def visitInterface(self,node): if self.parentVertex.kind in ['package','project']: parentid = node.getParent().getFullIdentifier() id = node.getFullIdentifier() if self.matchPartialSymbols(id, self.symbols) or self.doAll: shortId = node.getIdentifier() if parentid in self.packages.keys(): pVertex = self.packages[parentid] else: if self.parentVertex.kind not in ['project','package']: err('Interfaces can only be imported into Bocca packages') pVertex = self.parentVertex newId = pVertex.symbol + '.' + shortId if self.parentVertex.kind == 'project': newId = id slist = self.graph.findSymbol(newId,kind='any') if len(slist) == 1 and slist[0].kind in ['interface','port']: interface = slist[0] interface.setASTNode(node) elif not slist: if 'gov.cca.Port' in node.getParentIds(): interface = cct.port.Port(action='create', args=[newId], version=pVertex.version, project=self.project, modulePath=self.project.modulePath, graph=self.graph) else: interface = cct.interface.Interface(action='create', args=[newId], version=pVertex.version, project=self.project, modulePath=self.project.modulePath, graph=self.graph) interface.setASTNode(node) interface.create() comment = node.getStartComment() if comment: interface.setComment(comment) self.methods[newId]=[] else: self._symbolConflictError(slist) edge = BEdge(pVertex, interface, self.graph, action='contains') self.interfaces[id] = interface self.visitVertex(node) pass
def visitClass(self,node): if self.parentVertex.kind in ['package','project']: parentid = node.getParent().getFullIdentifier() id = node.getFullIdentifier() if self.matchPartialSymbols(id, self.symbols) or self.doAll: shortId = node.getIdentifier() if parentid in self.packages.keys(): pVertex = self.packages[parentid] else: if self.parentVertex.kind not in ['project','package']: err('Classes can only be imported into Bocca packages') pVertex = self.parentVertex newId = pVertex.symbol + '.' + shortId if self.parentVertex.kind == 'project': newId = id slist = self.graph.findSymbol(newId,kind='any') if len(slist) == 1 and slist[0].kind in ['class','component']: klass = slist[0] klass.setASTNode(node) elif not slist: if 'gov.cca.Component' in [p.getIdentifier() for p in node.getInterfacesAll()]: klass = cct.component.Component(action='create', args=[newId], version=pVertex.version, project=self.project, modulePath=self.project.modulePath, graph=self.graph) else: klass = cct.sidlclass.Sidlclass(action='create', args=[newId], version=pVertex.version, project=self.project, modulePath=self.project.modulePath, graph=self.graph) klass.setASTNode(node) klass.create() comment = node.getStartComment() if comment: klass.setComment(comment) self.methods[newId]=[] else: self._symbolConflictError(slist) edge = BEdge(pVertex, klass, self.graph, action='contains') self.classes[id] = klass self.visitVertex(node) pass
def visitMethod(self,node): parent = node.getParent() if parent is None: print 'parent is None' if parent: parentid = parent.getFullIdentifier() if self.matchPartialSymbols(parentid, self.symbols) or self.doAll: if self.parentVertex.kind in ['package','project'] and self.matchPartialSymbols(parentid, self.interfaces.keys()): symbol = self.interfaces[parentid].symbol elif self.parentVertex.kind in ['package','project'] and self.matchPartialSymbols(parentid, self.classes.keys()): symbol = self.classes[parentid].symbol elif self.parentVertex.kind in ['interface', 'port', 'class', 'component']: symbol = self.parentVertex.symbol else: err('cannot import methods into a ' + self.parentVertex.kind + ' (only into project, package, interface, port, class, or component)') if not self.methods.has_key(symbol): self.methods[symbol]=[] if node not in self.methods[symbol]: print >>DEBUGSTREAM,'adding method ' + node.getIdentifier() + ' to ' + symbol self.methods[symbol].append(node) self.visitVertex(node) pass
def processArgs(self, action): """ Dispatch argument processing based in required action """ print >> DEBUGSTREAM, "Component called with options ", \ str(self.options) , " leaving args " , str(self.args) if (action == 'create'): self.processCreateArgs() elif (action == 'change'): self.processChangeArgs() elif (action == 'display'): Sidlclass.processDisplayArgs(self) elif (action == 'rename'): self.processRenameArgs() elif (action == 'edit' or action == 'whereis'): Sidlclass.processArgs(self, action) elif (action == 'remove'): Sidlclass.processRemoveArgs(self) elif (action == 'copy'): Sidlclass.processCopyArgs(self) else: err("Action "+ action + " NOT implemented yet", 3) return
def go_option_callback(option, opt, value, parser): """ handler for --go[=portname]. There is an auxiliary value GoPortStatus which is 0 if the user did not apply --go during the current invocation. This needs to get stored in the permanent data structure eventually. This allows us to differentiate a user specified go port (-p) and a generated goport prototype --go. The expected values of GoPortStatus are: 0: --go never appeared. If goport is found, came from -p. 1: --go appeared and a default go impl should be generated. 2: [future] --go-done. We used --go before, but future updates if uses list changes should be suppressed. 3: [future] --go-delegate=portname[:delegateclass] delegated goport instead of inherited. """ if opt == "--go" or opt == "-g": porttype="gov.cca.ports.GoPort" if value == None or len(value) < 1 : portname="GO" else: portname=value if parser.values.providesPort == None: parser.values.providesPort=[] if portname[0] == '-': err("--go needs an argument. Got another switch.", 2) parser.values.providesPort.append(porttype+"@"+portname) parser.values.GoPortStatus=1
def processCommonCreateAndChangeArgs(self): print >>DEBUGSTREAM, "component: processCommonCreateAndChangeArgs" options, args = self.options, self.args # print "UH_component:processCommonCreateAndChangeArgs" # dpathdata = self._processDpathOptions() # self._updateDpaths(dpathdata) # relocatd base call from end of method. Sidlclass.processCommonCreateAndChangeArgs(self) if options.usesPort: self.newUses = self._processSymbolAssociationOptions(options.usesPort, '--uses/-u') if options.providesPort: self.newProvides = self._processSymbolAssociationOptions(options.providesPort, '--provides/-p') print >>DEBUGSTREAM, "\nComponent: newProvides = ", self.newProvides, \ "\nComponent: newUses = ", self.newUses for newp in self.newUses + self.newProvides: for p in [x.getName() for x in self._b_uses + self._b_provides]: if p == newp.getName(): err('This component already uses or provides a port of this name: ' + str(p) + ' (port names must be unique within a component),') for newp in self.newProvides: for i in [x.getType() for x in self._b_provides] + self._b_implements.keys(): if i == newp.getType(): err('This component already implements this interface or provides a port of this type: ' + str(i)) if [x.getType() for x in self.newProvides].count(newp) > 1: err('A port cannot be provided more than once: ' + str(newp)) # relocating base call to beginning of method return
def t_error(self,t): col = self.find_column(t.lexer.lexdata,t) err("[SIDL parse] illegal character '%s' at line %s, column %s (%s)" % (t.value[0], t.lexer.lineno, col, str(t))) t.lexer.skip(1)
def _symbolConflictError(self, symlist): buf = '' for sym in symlist: buf += str(sym) + ', ' buf.rstrip(',') err('cannot import package into ' + self.parentVertex.symbol + ' due to a symbol conflict:\n' + buf)
def getBabelCommandString(self, vertex, checkSIDLOnly=False): '''Returns the string containing the complete babel invocation for generating client or server code for the specified vertex. @param vertex: the vertex correponding to the SIDL symbol for which code will be generated by the constructed Babel command @param checkSIDLOnly: if True, do not generate code, just check the syntax of the SIDL definition corresponding to vertex. @return the Babel command string. ''' if self.__class__ is BuilderDefault: raise NotImplementedError if vertex.kind not in ['interface', 'port', 'class', 'component', 'enum']: return '' if vertex.getAttr('removed'): return '' babelcmd = '' extra_babel_options = '' project, pgraph = Globals().getProjectAndGraph() ccaVars = Globals().getCCAVars() if len(ccaVars) == 0: err('[sidlclass] could not load CCA settings from defaults file') sidlIncludes = Set() if vertex.kind in ['port', 'component']: sidlIncludes.add(Globals().getCCAVars(projectName=project.symbol)['CCA_sidl']) if vertex._b_xmlRepos: otherRepos = ' -R'.join([' '] + vertex._b_xmlRepos) else: otherRepos = '' # Keep a list of unique paths in inclpaths and check each new path against it before # adding an -I option for it (since Babel 1.0.8 crashes for duplicate paths), bocca issue 217 inclpaths = [] if vertex._b_externalSidlFiles: extFiles = [] for sym in vertex._b_externalSidlFiles.keys(): files = vertex._getExternalSIDLPath(sym).split(',') if files: for f in files: fname = f.strip() if fname and not fname in inclpaths: extFiles.append(fname) inclpaths.append(fname) for f in extFiles: sidlIncludes.add(f) extFiles = [] for v in vertex.dependencies(): if v.kind not in ['port', 'interface', 'component','class', 'enum']: continue if v.getAttr('removed'): continue thepath = '' if v.symbol.startswith('gov.cca'): sidlIncludes.add(Globals().getCCAVars(projectName=project.getName())['CCA_sidl']) continue if v._b_sidlFile: if not v._b_sidlFile.startswith(os.sep): thepath = os.path.join(project.getDir(), v._b_sidlFile) else: thepath = v._b_sidlFile if not thepath.strip() in inclpaths: if thepath.strip(): sidlIncludes.add(thepath) inclpaths.append(thepath) # Check for external SIDL files in if v._b_externalSidlFiles: extFiles = [] for sym in v._b_externalSidlFiles.keys(): files = v._getExternalSIDLPath(sym).split(',') if files: for f in files: if not f in inclpaths: extFiles.append(f) inclpaths.append(f) for f in extFiles: sidlIncludes.add(f) if len(sidlIncludes) > 0: sidlIncludesString = ' -I'.join(sidlIncludes) sidlIncludesString = ' -I'+sidlIncludesString else: sidlIncludesString = '' print >>DEBUGSTREAM, 'SIDL files this class depends on:\n\t' \ + sidlIncludesString \ + '\n\texternal: ' + str(extFiles) if not ccaVars["CCASPEC_BABEL_BRANCH"].startswith('1.0'): extra_babel_options = ' --cca-mode --rename-splicers ' if checkSIDLOnly and self.autochecksidl == 'enabled': babelcmd = '%s -p %s %s %s %s' % (ccaVars['CCASPEC_BABEL_BABEL'], \ sidlIncludesString, otherRepos, extra_babel_options, os.path.join(project.getDir(), vertex._b_sidlFile)) if vertex.kind in ['class','component']: if vertex.project: theproject = vertex.project else: theproject = project # Generate Impl files outdir = os.path.join(project.getDir(), 'components', vertex.symbol) babelOptions = '-s %s -u -m .%s. -o %s' % \ (vertex._b_language, vertex.symbol, outdir) print >> DEBUGSTREAM, 'Builder execute prep babelOptions: ' + babelOptions print >> DEBUGSTREAM, 'Builder execute prep sidlIncludesString: ' + sidlIncludesString babelcmd = '%s %s %s %s %s %s' % (ccaVars['CCASPEC_BABEL_BABEL'], babelOptions, sidlIncludesString, otherRepos, extra_babel_options, os.path.join(theproject.getDir(), vertex._b_sidlFile)) return babelcmd
def p_error(t): line,col = find_column(t.lexer.lexdata,t) pos = (col-1)*' ' err("[SIDL parsing] unexpected symbol '%s' at line %s, column %s:\n\t%s\n\t%s^" % (t.value, t.lexer.lineno, col, line, pos))
def getWriter (self, language, dialect, babelVersion='', kind = 'component'): ccaVars = Globals().getCCAVars() if len(ccaVars) == 0: err('[BoccaWriterFactory] could not load CCA settings from defaults file') if babelVersion is '': # The CCASPEC_BABEL_VERSION has a timestamp instead of a version for nightly # tarballs, so call babel to determine version cmd = ccaVars['CCASPEC_BABEL_BABEL'] + ' --version' try: f = os.popen(cmd) lines = f.readlines() for l in lines: cl = l.strip() if cl.startswith('Babel version'): babelVersion = l.split()[-1] except: err('[BoccaWriterFactory] Could not determine Babel version') print >> DEBUGSTREAM, '[BoccaWriterFactory] Babel version is ' + str(babelVersion) # Handle nightly Babel tarballs, which don't have a regular version number if babelVersion.count('.') == 0: if 'CCASPEC_BABEL_SNAPSHOT' in ccaVars.keys(): if ccaVars['CCASPEC_BABEL_SNAPSHOT'] == '1': babelVersion = ccaVars['CCASPEC_BABEL_BRANCH'] if babelVersion.count('.') == 0: # Sometimes the version number is in that variable, whether it's a snapshot or not if 'CCASPEC_BABEL_BRANCH' in ccaVars.keys(): babelVersion = ccaVars['CCASPEC_BABEL_BRANCH'] if babelVersion.count('.') == 0: err('[BoccaWriterFactory] Invalid Babel version encountered') for key in self.writers.keys(): (lang, versionList, dial) = key.split(':') versionList = versionList.split('|') if (lang != language): continue if (dial != dialect): continue (major, minor, patch) = babelVersion.upper().split('.') matchingVer = '' for v in versionList: v_elements = v.upper().split('.') v_major = v_elements[0] v_minor='X' v_patch='X' if (len(v_elements) > 3): err('Invalid supported Babel version number ' + v + ' in class ' + str(self.writers[key][0]), 2) if(len(v_elements) == 2): v_minor = v_elements[1] elif (len(v_elements) == 3): v_minor = v_elements[1] v_patch = v_elements[2] match = False if (v_major == 'X'): match = True matchingVer = v break if (v_major != major): continue if (v_minor == 'X'): match = True matchingVer = v break if (v_minor != minor): continue if (v_patch == 'X'): match = True matchingVer = v break if (v_patch != patch): continue if (not match): print >> DEBUGSTREAM, 'Babel version', babelVersion , 'NOT matched by writer versions', versionList continue print >> DEBUGSTREAM, 'Babel version', babelVersion , 'is matched by writer version', matchingVer (classRef, classInstance) = self.writers[key] if (classInstance == None): classInstance = classRef(kind) self.writers[key] = (classRef, classInstance) classInstance.setBabelVersion(babelVersion) return classInstance err('No writer supports ' + language + ' for Babel version ' + babelVersion + ' and dialect ' + dialect, 1)