def currentParameter(self): dbg = "\n ==== currentParameter() ====" dbg += "\n current str to process: |" + self.context.currentStr + "|" resstr = "" if len(self.context.currentStr) in [ 0, 1 ] or self.context.currentArgument.inputType() == Argument.Single: resstr = self.context.currentStr[:self.context.currentStrScope] else: endidx = self.context.currentStrScope dbg += "\n cursor pos in current string " + unistr(endidx) iterator = re.finditer('(?<!\\\)\,', self.context.currentStr) startidx = 0 for match in iterator: pos = match.span() dbg += "\n " + unistr(pos) dbg += "\n " + unistr(endidx) if pos[1] <= endidx: startidx = pos[1] dbg += "\n startidx: " + unistr(startidx) dbg += "\n endidx: " + unistr(endidx) resstr = self.context.currentStr[startidx:endidx] dbg += "\n resulting str: " + resstr self.debug(dbg) return resstr
def configToken(self, token): self.config = self.confmanager.configByName(unistr(token)) if self.config != None: self.disambiguator() argsname = self.config.argumentsName() for argname in argsname: self.remainingArguments.append(argname)
def disambiguator(self): requirednodes = self.config.argumentsByFlags(typeId.Node | Argument.Required) optionalnodes = self.config.argumentsByFlags(typeId.Node | Argument.Optional) requiredpathes = self.config.argumentsByFlags(typeId.Path | Argument.Required) optionalpathes = self.config.argumentsByFlags(typeId.Path | Argument.Optional) rnodes = len(requirednodes) onodes = len(optionalnodes) rpathes = len(requiredpathes) opathes = len(optionalpathes) dbg = "\n ==== Context.disambiguator() ====" if rnodes == 1 and rpathes == 0: self.keylessarg = requirednodes[0] if onodes == 1 and opathes == 0 and rnodes == 0 and rpathes == 0: self.keylessarg = optionalnodes[0] if rpathes == 1 and rnodes == 0: self.keylessarg = requiredpathes[0] if opathes == 1 and onodes == 0 and rnodes == 0 and rpathes == 0: self.keylessarg = optionalpathes[0] if self.keylessarg != None: dbg += "\n keylessarg exists and has been setted to < " + unistr( self.keylessarg.name()) + " >" else: dbg += "\n keylessarg does not exist" self.debug(dbg)
def dump(self): buff = "\n ==== Context.dump() ====" buff += "\n associated config: " if self.config != None: buff += self.config.origin() lparg = len(self.providedArguments) buff += "\n provided arguments: " + unistr(lparg) if lparg != 0: for argname in self.providedArguments.keys(): ret = unistr(self.providedArguments[argname]) buff += "\n " + argname + " --> " + ret lrarg = len(self.remainingArguments) buff += "\n remaining arguments: " + unistr(lrarg) if lrarg != 0: for argname in self.remainingArguments: buff += "\n " + argname buff += "\n threaded: " + unistr(self.threaded) else: buff += " None" buff += "\n currentArgumentScope: " if self.currentArgument != None: buff += unistr(self.currentArgument.name()) else: buff += "None" buff += "\n currentStr: " + unistr(self.currentStr) buff += "\n currentStrScope: " + unistr(self.currentStrScope) return buff
def dispatch(self): matches = "" dbg = "\n ==== dispatch() ====" compfunc = None if self.context.currentArgument != None: parg = self.context.providedArguments[ self.context.currentArgument.name()] dbg += "\n currentArgument exists: " + unistr( self.context.currentArgument.name()) dbg += "\n associated parameter: " + unistr(parg) if parg == None or parg == self.context.currentStr: dbg += "\n completing parameters for argument: " + unistr( self.context.currentArgument.name()) if self.context.currentArgument.type() in [ typeId.Node, typeId.Path ]: compfunc = getattr(self, "completePathes") else: compfunc = getattr(self, "completePredefined") else: dbg += "\n completing argument for currentStr: " + unistr( self.context.currentStr) compfunc = getattr(self, "completeArguments") else: dbg += "\n no current argument to complete" if len(self.context.remainingArguments) > 0: dbg += "\n remaining arguments exist --> total: " + unistr( len(self.context.remainingArguments)) if self.context.keylessarg != None and self.context.keylessarg.name( ) in self.context.remainingArguments: req = 0 dbg += "\n keylessarg != None and has not been provided yet" if not self.context.currentStr.startswith("--"): dbg += "\n keylessarg < " + unistr( self.context.keylessarg.name( )) + " > can be used as default" self.context.currentArgument = self.context.keylessarg if self.context.currentArgument.type() in [ typeId.Node, typeId.Path ]: compfunc = getattr(self, "completePathes") else: compfunc = getattr(self, "completePredefined") else: dbg += "\n keylessarg can not be used as default, complete with remaining arguments" compfunc = getattr(self, "completeArguments") else: dbg += "\n either keylessarg is None or keylessarg already used" compfunc = getattr(self, "completeArguments") else: dbg += "\n nothing to complete" #self.debug(dbg) if compfunc != None: matches = compfunc() dbg += "\n matches:" + unistr(matches) self.debug(dbg) return matches
def setPathContext(self, ctype): rpath = "" supplied = "" children = None sep = os.path.sep path = self.currentParameter() rpath, supplied = splitPath(path, ctype) if ctype == typeId.Node: node = self.vfs.getnode(unistr(rpath)) if node: if node.hasChildren(): children = node.children() elif node.isDir(): children = [] elif os.path.exists(rpath): if os.path.isdir(rpath): try: children = dircache.listdir(unistr(rpath)) except: children = [] return (path, rpath, supplied, children)
def makeCommands(self, line): line = line.rstrip() begidx = len(line) self.makeContexts(line, begidx) commands = [] dbg = "\n ==== LineParser.makeCommands() ====" for context in self.contexts: if context.config != None: try: commands.append( (context.config.origin(), context.makeArguments(), context.threaded, "")) except KeyError, error: commands.append( (context.config.origin(), None, context.threaded, "module < " + context.config.origin() + " >\n" + unistr(error))) except ValueError, error: commands.append( (context.config.origin(), None, context.threaded, "module < " + context.config.origin() + " >\n" + unistr(error)))
def manageShellKeys(self, key, startidx, endidx): dbg = "\n ==== LineParser.manageShellKeys() ====" if key == "&": dbg += "\n & found" dbg += "\n begidx: " + unistr(self.begidx) dbg += "\n endidx: " + unistr(endidx) self.contexts[self.ctxpos].threaded = True dbg += "\n incrementing ctxpos" ctx = Context(self.DEBUG, self.VERBOSITY - 1) self.contexts.append(ctx) self.ctxpos += 1 if self.begidx > endidx: #and endidx != len(self.line): self.scopeCtx = self.ctxpos elif key == "&&": self.contexts.append(Context(self.DEBUG, self.VERBOSITY - 1)) self.ctxpos += 1 if self.begidx == startidx + 1: self.scopeCtx = self.ctxpos self.contexts.append(Context(self.DEBUG, self.VERBOSITY - 1)) self.ctxpos += 1 dbg += "\n key found and begidx in the middle of " + key self.debug(dbg)
def setCurrent(self, token, pos): dbg = "\n ==== Context.setCurrent() ====" dbg += "\n token: " + token dbg += "\n pos: " + unistr(pos) dbg += "\n currentstrscope: " + token[:pos] if len(token.split()) != 0: self.currentStr = token self.currentStrScope = pos else: self.currentStrScope = 0 self.currentStr = "" if self.parsedArgument != None: dbg += "\n parsedArgument != None" if self.providedArguments[self.parsedArgument.name()] in [ token, None ]: dbg += "\n currentArgument = self.parsedArgument --> " + unistr( self.parsedArgument.name()) self.currentArgument = self.parsedArgument else: dbg += "\n currentArgument = None" self.currentArgument = None self.debug(dbg)
def makeArguments(self): command = {} dbg = "\n ==== Context.makeCommand() ====" if len(self.badargs) > 0: raise KeyError("cannot generate config for module < " + self.config.origin() + " > The following arguments do not exist: " + unistr(self.badargs)) for argname in self.providedArguments.keys(): argument = self.config.argumentByName(argname) parameters = self.providedArguments[argname] if argument.inputType() == Argument.List: l = [] iterator = self.paramsplit.finditer(parameters) itcount = 0 previdx = 0 for match in iterator: itcount += 1 pos = match.span() parameter = parameters[previdx:pos[0]] previdx = pos[1] dbg += "\n adding parameter: < " + unistr( parameter) + " > to list" try: realparam = self.__makeParameter(argument, parameter) l.extend(realparam) except: raise if itcount == 0 or previdx != len(parameters): dbg += "\n adding parameter: < " + unistr( parameters[previdx:]) + " > to list" try: parameter = parameters[previdx:] realparam = self.__makeParameter(argument, parameter) l.extend(realparam) except: raise command[argname] = [arg for arg in l] else: ret = unistr(parameters) dbg += "\n adding parameter: < " + unistr(parameters) try: realparam = self.__makeParameter(argument, parameters)[0] command[argname] = realparam except: raise if self.DEBUG and self.VERBOSITY > 0: dbg += "\n resulting command arguments:" for argname in command.keys(): dbg += "\n " + argname + " --> " + unistr( command[argname]) self.debug(dbg) return command
def completePredefined(self): parameter = self.currentParameter() out = { "type": "predefined", "matches": [], "matched": 0, "supplied": parameter, "length": 1 } predefs = self.context.currentArgument.parameters() for predef in predefs: val = unistr(predef.value()) if parameter == "" or val.startswith(parameter): if len(val) > out["length"]: out["length"] = len(val) out["matches"].append(val) out["matched"] += 1 return out
def parameterToken(self, token): dbg = "\n ==== Context.parameterToken() ====" if self.parsedArgument == None: dbg += "\n parsedArgument == None" if self.keylessarg != None and self.keylessarg.name( ) in self.remainingArguments: dbg += "\n keylessarg exists and not setted yet. " + str( self.keylessarg.name()) + " --> " + token self.providedArguments[self.keylessarg.name()] = token self.remainingArguments.remove(self.keylessarg.name()) self.parsedArgument = self.keylessarg elif self.providedArguments[self.parsedArgument.name()] == None: dbg += "\n parsedArgument exists and not setted yet. " + unistr( self.parsedArgument.name()) + " --> " + token self.providedArguments[self.parsedArgument.name()] = token self.remainingArguments.remove(self.parsedArgument.name()) else: dbg += "\n parsedArgument already setted" self.parsedArgument = None self.debug(dbg)
def __argumentToken(self, token): dbg = "\n ==== Context.__argumentToken() ====" argument = self.config.argumentByName(unistr(token[2:])) if argument != None: argname = argument.name() dbg += "\n argument found: " + argname if argname in self.remainingArguments: if argument.inputType() == Argument.Empty: self.providedArguments[argname] = True self.remainingArguments.remove(argname) self.parsedArgument = None else: self.providedArguments[argname] = None self.parsedArgument = argument else: dbg += "\n argument < " + argname + " > already provided" else: self.badargs.append(token) dbg += "\n argument not found" self.parsedArgument = None self.debug(dbg)
def argumentToken(self, token): dbg = "\n ==== Context.argumentToken() ====" if self.parsedArgument != None: if self.parsedArgument.inputType() != Argument.Empty: dbg += "\n token starts with -- and parsedArgument != None and is not a switch" argname = self.parsedArgument.name() if self.providedArguments[argname] == None: if token[2:] not in self.remainingArguments: dbg += "\n currentArgument exists and not setted yet. " + unistr( argname) + " --> " + token self.remainingArguments.remove(argname) self.providedArguments[argname] = token else: self.__argumentToken(token) else: self.__argumentToken(token) else: self.remainingArguments.remove(argname) self.providedArguments[argname] = None self.parsedArgument = None else: self.__argumentToken(token) self.debug(dbg)
def addToken(self, token, curpos=-1): dbg = "\n ==== Context.addToken() ====" dbg += "\n token: " + token dbg += "\n curpos: " + unistr(curpos) self.tokens.append(token) self.debug(dbg) if self.config == None: if curpos != -1: self.setCurrent(token, curpos) self.configToken(token[:curpos]) else: self.configToken(token) else: if token.startswith("--"): if curpos != -1: self.setCurrent(token, curpos) self.argumentToken(token[:curpos]) else: self.argumentToken(token) else: self.parameterToken(token) if curpos != -1: self.setCurrent(token, curpos)
(context.config.origin(), None, context.threaded, "module < " + context.config.origin() + " >\n" + unistr(error))) except ValueError, error: commands.append( (context.config.origin(), None, context.threaded, "module < " + context.config.origin() + " >\n" + unistr(error))) elif len(context.tokens) != 0: commands.append((None, None, None, str("module < " + unistr(context.tokens[0]) + " > does not exist"))) if self.DEBUG and self.VERBOSITY: dbg += "\n stacked commands:" for command in commands: dbg += "\n command name: " + unistr( command[0]) if command[0] else "" dbg += "\n arguments: " + unistr( command[1]) if command[1] else "" dbg += "\n to thread: " + unistr( command[2]) if command[2] else "" + "\n" self.debug(dbg) return commands def makeContexts(self, line, begidx=-1): self.begidx = begidx self.contexts = [] self.scopeCtx = -1 self.line = line self.ctxpos = 0 startidx = 0 i = 0
def __makeParameter(self, argument, parameter): lret = [] ctype = argument.type() if ctype == typeId.Node: path, supplied = splitPath(parameter, ctype) if isGlobed(supplied): root = self.vfs.getnode(unistr(path)) if root: children = root.children() else: raise ValueError("Base node for globing " + unistr(parameter) + " provided to argument < " + unistr(argument.name()) + " > does not exist") for child in children: if fnmatch.fnmatch(addEscape(child.name()), supplied): lret.append(child) if len(lret) == 0: raise ValueError("Globing nodes with " + unistr(parameter) + " provided to argument < " + unistr(argument.name()) + " > gives no results") else: parameter = unistr(removeEscape(parameter)) n = self.vfs.getnode(parameter) if n: lret.append(n) else: raise ValueError("Node " + parameter + " provided to argument < " + unistr(argument.name()) + " > does not exist") elif ctype == typeId.Path: rpath, supplied = splitPath(parameter, ctype) if os.name == "nt": if rpath.startswith("/"): rpath = os.path.join("C:", rpath) rpath = os.path.normpath(rpath) if isGlobed(supplied): try: children = dircache.listdir(rpath) except: raise ValueError("Base path for globing " + unistr(parameter) + " provided to argument < " + unistr(argument.name()) + " > does not exist") for child in children: if fnmatch.fnmatch(addEscape(child), supplied): lret.append(unistr(os.path.join(rpath, child))) if len(lret) == 0: raise ValueError("Globing paths with " + unistr(parameter) + " provided to argument < " + unistr(argument.name()) + " > gives no results") else: abspath = os.path.join(rpath, removeEscape(supplied)) if os.path.exists(abspath): lret.append(unistr(abspath)) else: raise ValueError("Path " + unistr(parameter) + " provided to argument < " + unistr(argument.name()) + " > does not exist") elif ctype == typeId.String: lret.append(unistr(removeEscape(parameter))) else: lret.append(parameter) return lret
class LineParser(): def __init__(self, DEBUG=False, VERBOSITY=0): self.DEBUG = DEBUG self.VERBOSITY = VERBOSITY self.ctxs = [] self.shellKeys = [";", "&"] def debug(self, msg): if self.DEBUG and self.VERBOSITY: print " ", msg def currentContext(self): if self.scopeCtx >= 0: return self.contexts[self.scopeCtx] return None def manageShellKeys(self, key, startidx, endidx): dbg = "\n ==== LineParser.manageShellKeys() ====" if key == "&": dbg += "\n & found" dbg += "\n begidx: " + unistr(self.begidx) dbg += "\n endidx: " + unistr(endidx) self.contexts[self.ctxpos].threaded = True dbg += "\n incrementing ctxpos" ctx = Context(self.DEBUG, self.VERBOSITY - 1) self.contexts.append(ctx) self.ctxpos += 1 if self.begidx > endidx: #and endidx != len(self.line): self.scopeCtx = self.ctxpos elif key == "&&": self.contexts.append(Context(self.DEBUG, self.VERBOSITY - 1)) self.ctxpos += 1 if self.begidx == startidx + 1: self.scopeCtx = self.ctxpos self.contexts.append(Context(self.DEBUG, self.VERBOSITY - 1)) self.ctxpos += 1 dbg += "\n key found and begidx in the middle of " + key self.debug(dbg) def makeCommands(self, line): line = line.rstrip() begidx = len(line) self.makeContexts(line, begidx) commands = [] dbg = "\n ==== LineParser.makeCommands() ====" for context in self.contexts: if context.config != None: try: commands.append( (context.config.origin(), context.makeArguments(), context.threaded, "")) except KeyError, error: commands.append( (context.config.origin(), None, context.threaded, "module < " + context.config.origin() + " >\n" + unistr(error))) except ValueError, error: commands.append( (context.config.origin(), None, context.threaded, "module < " + context.config.origin() + " >\n" + unistr(error))) elif len(context.tokens) != 0: commands.append((None, None, None, str("module < " + unistr(context.tokens[0]) + " > does not exist")))
def completePathes(self): out = { "type": "path", "matches": [], "length": 1, "supplied": "", "matched": 0 } ctype = self.context.currentArgument.type() itype = self.context.currentArgument.inputType() path, rpath, supplied, children = self.setPathContext(ctype) out["supplied"] = supplied sep = "/" dbg = "\n ==== completePathes() ====" if children == None: dbg += "\n cannot complete with provided path" self.debug(dbg) return "" dbg += "\n path: " + path dbg += "\n relative path: " + rpath dbg += "\n supplied str: " + supplied if ctype == typeId.Node: dbg += "\n children: " + unistr( [child.name() for child in children]) else: dbg += "\n children: " + unistr(children) if len(children) == 0: if rpath[-1] != sep: out["matches"].append(sep) else: out["matches"].append("") out["matched"] += 1 else: glob = isGlobed(supplied) match = False for child in children: name = unicodeChild(child, ctype) if glob: if fnmatch.fnmatch(addEscape(name), supplied): match = True elif len(supplied) == 0: match = True elif len(supplied) == 1 and supplied[0] == "\\": if name[0] in SPECIAL_CHARS: match = True elif name.startswith(removeEscape(supplied)): match = True if match: match = False if (ctype == typeId.Node and child.hasChildren()) or ( ctype == typeId.Path and os.path.isdir(os.path.join(rpath, name))): if len(name + sep) > out["length"]: out["length"] = len(name + sep) out["matches"].append(name + sep) else: if len(name) > out["length"]: out["length"] = len(name) out["matches"].append(name) out["matched"] += 1 self.debug(dbg) return out
def makeContexts(self, line, begidx=-1): self.begidx = begidx self.contexts = [] self.scopeCtx = -1 self.line = line self.ctxpos = 0 startidx = 0 i = 0 token = "" dbg = "\n ==== LineParser.makeContext() ====" dbg += "\n line: |" + line + "|" dbg += "\n begidx: " + unistr(begidx) if len(line) != 0: ctx = Context(self.DEBUG, self.VERBOSITY - 1) self.contexts.append(ctx) while i < len(line): if line[i] == " " and (line[i - 1] != "\\") and len( token.split()) != 0: if self.begidx >= startidx and self.begidx <= i: self.scopeCtx = self.ctxpos self.contexts[self.ctxpos].addToken( token, self.begidx - startidx) else: self.contexts[self.ctxpos].addToken(token) token = "" startidx = i elif line[i] in self.shellKeys and (line[i - 1] != "\\"): if len(token.split()) != 0: if self.begidx >= startidx and self.begidx <= i: self.contexts[self.ctxpos].addToken( token, self.begidx - startidx) self.scopeCtx = self.ctxpos else: self.contexts[self.ctxpos].addToken(token) token = "" startidx = i key = "" while i < len(line) and line[i] in self.shellKeys: key += line[i] i += 1 self.manageShellKeys(key, startidx, i) startidx = i if i < len(line): token = line[i] else: token = "" startidx = i elif len(token.split()) == 0: startidx = i token = line[i] else: token = token + line[i] i += 1 if len(token.split()) != 0: if self.begidx >= startidx and self.begidx <= i: self.contexts[self.ctxpos].addToken( token, self.begidx - startidx) self.scopeCtx = self.ctxpos else: self.contexts[self.ctxpos].addToken(token) elif self.begidx == len(line): self.contexts[self.ctxpos].addToken(token, self.begidx - startidx) self.scopeCtx = self.ctxpos if self.DEBUG and self.VERBOSITY > 0: dbg += "\n current context: " if self.contexts[self.scopeCtx].config: dbg += unistr(self.contexts[self.scopeCtx].config.origin()) else: dbg += "None" dbg += "\n scopeCtx: " + unistr(self.scopeCtx) dbg += "\n ctxpox: " + unistr(self.ctxpos) print dbg for ctx in self.contexts: print ctx.dump() print