def lint_with_text(self, request, text): cwd = request.cwd prefset = getProxiedEffectivePrefs(request) # Remove a possible "-d" in the shebang line, this will tell Perl to # launch the debugger which, if the PDK is installed, is the PDK # debugger. Be careful to handle single-line files correctly. splitText = text.split("\n", 1) firstLine = RemoveDashDFromShebangLine(splitText[0]) if len(splitText) > 1: text = "\n".join([firstLine, splitText[1]]) else: text = firstLine if prefset.getBooleanPref("perl_lintOption_disableBeginBlocks"): text = _begin_to_init_re.sub("INIT", text) # Save perl buffer to a temporary file. tmpFileName = self._writeTempFile(cwd, text) try: perlExe = self._selectPerlExe(prefset) lintOptions = prefset.getStringPref("perl_lintOption") option = '-' + lintOptions perlExtraPaths = prefset.getStringPref("perlExtraPaths") if perlExtraPaths: if sys.platform.startswith("win"): perlExtraPaths = perlExtraPaths.replace('\\', '/') perlExtraPaths = [ x for x in perlExtraPaths.split(os.pathsep) if x.strip() ] argv = [perlExe] for incpath in perlExtraPaths: argv += ['-I', incpath] if prefset.getBooleanPref( "perl_lintOption_includeCurrentDirForLinter"): argv += ['-I', '.'] # bug 27963: Fix instances of <<use PerlTray>> from code # to make them innocuous for the syntax checker. # 'use PerlTray' in comments or strings will trigger a false positive if sys.platform.startswith( "win") and self._use_perltray_module.search(text): argv += ['-I', self._perlTrayDir] argv.append(option) argv.append(tmpFileName) cwd = cwd or None # convert '' to None (cwd=='' for new files) env = koprocessutils.getUserEnv() # We only need stderr output. p = process.ProcessOpen(argv, cwd=cwd, env=env, stdin=None) _, stderr = p.communicate() lintResults = PerlWarnsToLintResults(stderr.splitlines(1), tmpFileName, request.koDoc.displayPath, text) finally: os.unlink(tmpFileName) return lintResults
def lint_with_text(self, request, text): if not text: return None prefset = getProxiedEffectivePrefs(request) if not prefset.getBooleanPref("lint_python_with_pyflakes"): return pythonExe = self._pythonInfo.getExecutableFromDocument(request.koDoc) if not pythonExe: return tmpfilename = tempfile.mktemp() + '.py' fout = open(tmpfilename, 'wb') fout.write(text) fout.close() textlines = text.splitlines() cwd = request.cwd env = self._get_fixed_env(prefset) try: checkerExe = which.which("pyflakes", path=_getUserPath()) except which.WhichError: log.warn("pyflakes not found") return if not checkerExe: log.warn("pyflakes not found") return cmd = [pythonExe, checkerExe, tmpfilename] # stdout for pyflakes.checker.Checker # stderr for __builtin__.compile() try: p = process.ProcessOpen(cmd, cwd=cwd, env=env, stdin=None) stdout, stderr = p.communicate() errorLines = stderr.splitlines(0) # Don't need the newlines. warnLines = stdout.splitlines() finally: os.unlink(tmpfilename) results = koLintResults() # "createAddResult" will change lineno in some situation, so we use our version self._createAddResult(results, textlines, errorLines, koLintResult.SEV_ERROR) self._createAddResult(results, textlines, warnLines, koLintResult.SEV_WARNING) return results
def run(self): """Process lint requests serially until told to stop. Before the requested linter is run on a document it is first checked for encoding problems (i.e. encoding is not sufficient for current content). """ TIME_LINTS = False log.info("manager thread: start") while 1: try: # wait for next request request = self.requests.get() # quit if request is the quit sentinel if request is None: log.info("manager thread: quit sentinel") break # process the request if TIME_LINTS: startlint = time.clock() log.info("manager thread: process request: %r", request) try: # Look for encoding errors first. results = self._getEncodingLintResults(request.content, request.encoding) if TIME_LINTS: endencodinglint = time.clock() # If there were no encoding errors, try the # requested linter. if not results.getNumResults() and request.linter: #XXX This is where context-sensitive linting args should # be passed in, but linters don't support this yet. log.debug("manager thread: call linter.lint(request)") try: if self._passesGenericCheck(request): results = request.linter.lint(request) #results = UnwrapObject(request.linter).lint(request) # This makes a red statusbar icon go green, but it # might not be what we always want. # Needs more investigation. #if results is None: # results = koLintResults() except: log.exception("Unexpected error while linting") # This makes a red statusbar icon go green, but it # might not be what we always want. # Needs more investigation. #if results is None: # results = koLintResults() log.debug("manager thread: linter.lint(request) returned") if TIME_LINTS: endlintlint = time.clock() prefset = getProxiedEffectivePrefs(request) if prefset.getBooleanPref("lintEOLs"): # Also look for mixed-line endings warnings. self._addMixedEOLWarnings(results, request.content, request.koDoc.new_line_endings) if TIME_LINTS: endeollint = time.clock() print "lint of '%s': encoding=%.3fs lint=%.3fs eol=%.3fs"\ % (request.koDoc.baseName, endencodinglint-startlint, endlintlint-endencodinglint, endeollint-endlintlint) request.results = results except (ServerException, COMException), ex: request.errorString = str(ex) except: # Any exceptions that are not ServerException or # COMException are unexpected internal errors. try: err = "unexpected internal error checking '%s' with '%s' linter"\ % (request.koDoc.baseName, request.linterType) log.exception(err) request.errorString = err except: err = "Unexpected error in koLintService.run" log.error(err) request.errorString = err else: log.info("manager thread: lint results for uid %s: %r", request.uid, results) # Notify of request completion # Note: this is not guaranteed to properly guard the proxy # call because a context switch could happen in between the # condition check and body. That is ok though. At worst it # will raise an exception that will be trapped just below. # The point is to catch the common case. I am pretty sure # that there is no way to do this properly without going # to great lengths. if not self._shuttingDown: try: # Proxy this so the worker thread can report results on this iface. lintBufferProxy = getProxyForObject(1, components.interfaces.koILintBuffer, request.lintBuffer, PROXY_ALWAYS | PROXY_SYNC) lintBufferProxy.reportResults(request) except COMException, ex: # Ignore this error, which will happen if results # are reported after the buffer has gone away (i.e. # the file owning that buffer was closed): # Traceback (most recent call last): # File "...\koLintService.py", line 370, in run # request.lintBuffer.reportResults(request) # File "<XPCOMObject method 'reportResults'>", line 3, in reportResults # Exception: 0x80570021 () errno = ex.args[0] if errno == 0x80570021: pass else: raise
def __init__(self, request, scope): if haveKO8: self.prefset = request.prefset else: self.prefset = getProxiedEffectivePrefs(request) self.scope = scope
def lint_with_text(self, request, text): if not text.strip(): return None prefset = getProxiedEffectivePrefs(request) cwd = request.cwd env = koprocessutils.getUserEnv() settingsDir = env.get("DJANGO_SETTINGS_MODULE", None) if not settingsDir: settingsDir = self._getSettingsDir(cwd) if settingsDir: # Save the current buffer to a temporary file. tmpFileName = tempfile.mktemp() fout = open(tmpFileName, 'wb') try: fout.write(text) fout.close() #XXX: How to tell whether we're using Python or Python3? prefName = "pythonExtraPaths" pythonPath = prefset.hasPref( prefName) and prefset.getStringPref(prefName) or None pythonPathEnv = env.get("PYTHONPATH", "") if pythonPathEnv: if pythonPath: pythonPath += os.pathsep + pythonPathEnv else: pythonPath = pythonPathEnv if pythonPath: if sys.platform.startswith("win"): pythonPath = pythonPath.replace('\\', '/') env["PYTHONPATH"] = pythonPath elif env.has_key("PYTHONPATH"): del env["PYTHONPATH"] results = koLintResults() pythonExe = self._pythonInfo.getExecutableFromDocument( request.koDoc) argv = [ pythonExe, self._djangoLinterPath, tmpFileName, settingsDir ] p = process.ProcessOpen(argv, cwd=cwd, env=env, stdin=None) output, error = p.communicate() #log.debug("Django output: output:[%s], error:[%s]", output, error) retval = p.returncode finally: os.unlink(tmpFileName) if retval == 1: if error: results.addResult(self._buildResult(text, error)) else: results.addResult( self._buildResult(text, "Unexpected error")) else: result = KoLintResult() result.lineStart = 1 result.lineEnd = 1 result.columnStart = 1 result.columnEnd = 1 + len(text.splitlines(1)[0]) result.description = "Can't find settings.py for this Django file" result.encodedDescription = result.description result.severity = result.SEV_ERROR results = koLintResults() results.addResult(result) return results
def lint_with_text(self, request, text): """Lint the given Tcl content. Raise an exception if there is a problem. """ prefset = getProxiedEffectivePrefs(request) argv = self._getLinterArgv(prefset) env = koprocessutils.getUserEnv() # if there is no setting for the dev kit environment, use # the shared directory for it. This enables site wide # use of *.pdx and *.pcx files for debugging if "TCLDEVKIT_LOCAL" not in env: koDirs = components.classes["@activestate.com/koDirs;1"].\ getService(components.interfaces.koIDirs) sharedDir = os.path.join(koDirs.commonDataDir, "tcl") env["TCLDEVKIT_LOCAL"] = sharedDir if prefset.hasPref("tclExtraPaths"): tclExtraPaths = prefset.getStringPref("tclExtraPaths") # If TCLLIBPATH is set, then it must contain a valid Tcl # list giving directories to search during auto-load # operations. Directories must be specified in Tcl format, # using "/" as the path separator, regardless of platform. # This variable is only used when initializing the # auto_path variable. Also escape spaces in paths. tclExtraPaths = tclExtraPaths.replace('\\', '/') tclExtraPaths = tclExtraPaths.replace(' ', '\ ') TCLLIBPATH = ' '.join(tclExtraPaths.split(os.pathsep)) env["TCLLIBPATH"] = TCLLIBPATH cwd = request.cwd or None print 'argv: %r' % (argv, ) p = process.ProcessOpen(argv, cwd=cwd, env=env) lOutput, lErrOut = p.communicate(text) lOutput = lOutput.splitlines(1) #print '======' #print lOutput #print '======' #print lErrOut #print '<<<<<<' if not lOutput and lErrOut: raise ServerException(nsError.NS_ERROR_UNEXPECTED, lErrOut) if not lOutput: # this should never happen unless the tcl linter is broken, or # not executable on linux. raise ServerException(nsError.NS_ERROR_UNEXPECTED, "No output from Tcl linter available") if lOutput[0].startswith("TclPro") or \ lOutput[0].startswith("scanning"): # The open source TclPro has the header stripped, # so we need to check for both "TclPro" and "scanning" lInput = text.split('\n') return self._TclPro_lint(lInput, lOutput) else: errmsg = "unrecognized lint output format:\n%s" % lOutput[0] raise ServerException(nsError.NS_ERROR_UNEXPECTED, errmsg)
def lint_with_text(self, request, text): encoding_name = request.encoding.python_encoding_name cwd = request.cwd prefset = getProxiedEffectivePrefs(request) prefName = "lint_%s_with_standard_python" % self.language_name_lc if not prefset.getBooleanPref(prefName): return try: # Get the Python interpreter (prefs or first valid one on the path). interpreter_pref_name = "%sDefaultInterpreter" % (self.language_name_lc, ) python = prefset.getString(interpreter_pref_name) if not python: python = self._pythonInfo.executablePath if not python: return if not self._pythonInfo.isSupportedBinary(python): raise ServerException(nsError.NS_ERROR_FAILURE, "Invalid %r executable: %r" % (self.language_name, python)) # Determine the pycompile settings. if self.language_name == "Python3": compilePy = os.path.join(self._koDirSvc.supportDir, "python", "py3compile.py") if encoding_name not in self._simple_python3_string_encodings: # First, make sure the text is Unicode if type(text) == self._stringType: text = text.decode(encoding_name) # Now save it as utf-8 -- python3 knows how to read utf-8 text = text.encode("utf-8") else: compilePy = os.path.join(self._koDirSvc.supportDir, "python", "pycompile.py") if request.koDoc.displayPath.startswith("macro2://"): text = projectUtils.wrapPythonMacro(text) leadingWS = _leading_ws_re.match(text.splitlines()[1]).group(1) else: leadingWS = None # Save the current buffer to a temporary file. tmpFileName = tempfile.mktemp() fout = open(tmpFileName, 'wb') fout.write(text) fout.close() results = koLintResults() try: argv = [python, '-u', compilePy, tmpFileName] #print "---- check syntax of the following with %r" % argv #sys.stdout.write(text) #print "-"*70 cwd = cwd or None env = self._get_fixed_env(prefset) if sys.platform.startswith("win") and cwd is not None\ and cwd.startswith("\\\\"): # Don't try to switch to a UNC path because pycompile.py # ends up spitting out: # CMD.EXE was started with '\\netshare\apps\Komodo\stuff' as the current directory # path. UNC paths are not supported. Defaulting to Windows directory. # XXX Could perhaps try to ensure that command is not # run via "cmd.exe /c", but don't know if that would # help either. cwd = None p = process.ProcessOpen(argv, cwd=cwd, env=env, stdin=None) output, error = p.communicate() retval = p.returncode #print "-"*60, "env" #pprint(env) #print "-"*60, "output" #print output #print "-"*60, "error" #print error #print "-"*70 if retval: errmsg = "Error checking syntax: retval=%s, stderr=%s"\ % (retval, error) log.exception(errmsg) raise ServerException(nsError.NS_ERROR_UNEXPECTED, errmsg) else: # Parse syntax errors in the output. dicts = eval(output) for d in dicts: results.addResult( self._buildResult(d, leadingWS) ) # Parse warnings in the error. results.addResults(self._parseWarnings(error, text, leadingWS)) finally: os.unlink(tmpFileName) except ServerException: log.exception("ServerException") raise except: # non-ServerException's are unexpected internal errors log.exception("unexpected internal error") raise return results
def lint_with_text(self, request, text): if not text: return None prefset = getProxiedEffectivePrefs(request) if not prefset.getBooleanPref("lint_python_with_pychecker"): return pychecker = prefset.getStringPref("pychecker_wrapper_location") if not pychecker: return if sys.platform.startswith("win") and not os.path.exists(pychecker): if os.path.exists(pychecker + ".bat"): pychecker = pychecker + ".bat" elif os.path.exists(pychecker + ".exe"): pychecker = pychecker + ".exe" if not os.path.exists(pychecker): return tmpfilename = tempfile.mktemp() + '.py' fout = open(tmpfilename, 'wb') fout.write(text) fout.close() textlines = text.splitlines() cwd = request.cwd env = self._get_fixed_env(prefset) rcfilePath = prefset.getStringPref("pychecker_checking_rcfile") if rcfilePath and os.path.exists(rcfilePath): if self.nonIdentChar_RE.search(rcfilePath): rcfilePath = '"' + rcfilePath + '"' extraArgs = [ "--config=" + rcfilePath ] else: extraArgs = [] cmd = [pychecker, "--keepgoing", "--only"] + extraArgs + [tmpfilename] cwd = request.cwd or None # We only need the stdout result. try: p = process.ProcessOpen(cmd, cwd=cwd, env=env, stdin=None) stdout, stderr = p.communicate() warnLines = stdout.splitlines(0) # Don't need the newlines. errorLines = stderr.splitlines(0) finally: os.unlink(tmpfilename) # Check raw output for an exception results = koLintResults() re_escaped_filename = re.escape(tmpfilename) exception_ptn = re.compile('''Caught exception importing module.+?File "%s", line (\d+), in <module>.+?\s*(\w+(?:Error|Exception):\s+.*)''' % re_escaped_filename, re.DOTALL) m = exception_ptn.search(stderr) if m: lineNo = int(m.group(1)) desc = m.group(2) koLintResult.createAddResult(results, textlines, koLintResult.SEV_ERROR, lineNo, desc) warn_ptn = re.compile(r'^%s:(\d+):\s+(.+)' % re_escaped_filename) error_ptn = re.compile(r'(.*[Ee]rror:.*?)\s*\(%s,\s+line\s+(\d+)\)' % re_escaped_filename) for line in warnLines: m = warn_ptn.match(line) if m: lineNo = int(m.group(1)) desc = m.group(2) koLintResult.createAddResult(results, textlines, koLintResult.SEV_WARNING, lineNo, "pychecker: " + desc) for line in errorLines: m = error_ptn.match(line) if m: lineNo = int(m.group(2)) desc = m.group(1) koLintResult.createAddResult(results, textlines, koLintResult.SEV_ERROR, lineNo, "pychecker: " + desc) return results
def lint_with_text(self, request, text): if not text: return None prefset = getProxiedEffectivePrefs(request) if not prefset.getBooleanPref("lint_python_with_pylint"): return # if not prefset.getBooleanPref("lintWithPylint"): return pythonExe = self._pythonInfo.getExecutableFromDocument(request.koDoc) if not pythonExe: return tmpfilename = tempfile.mktemp() + '.py' fout = open(tmpfilename, 'wb') fout.write(text) fout.close() textlines = text.splitlines() cwd = request.cwd env = self._get_fixed_env(prefset) rcfilePath = prefset.getStringPref("pylint_checking_rcfile") if rcfilePath and os.path.exists(rcfilePath): if self.nonIdentChar_RE.search(rcfilePath): rcfilePath = '"' + rcfilePath + '"' extraArgs = [ "--rcfile=" + rcfilePath ] else: # Hardwire in these three messages: extraArgs = []# [ "-d", "C0103", "-d" , "C0111", "-d", "F0401"] preferredLineWidth = prefset.getLongPref("editAutoWrapColumn") if preferredLineWidth > 0: extraArgs.append("--max-line-length=%d" % preferredLineWidth) baseArgs = [pythonExe, '-c', 'import sys; from pylint.lint import Run; Run(sys.argv[1:])'] cmd = baseArgs + ["-f", "text", "-r", "n", "-i", "y"] + extraArgs # Put config file entry here: .rcfile=<file> cmd.append(tmpfilename) cwd = request.cwd or None # We only need the stdout result. try: p = process.ProcessOpen(cmd, cwd=cwd, env=env, stdin=None) stdout, _ = p.communicate() warnLines = stdout.splitlines(0) # Don't need the newlines. except: log.exception("Failed to run %s", cmd) stdout = "" warnLines = [] finally: os.unlink(tmpfilename) ptn = re.compile(r'^([A-Z])(\d+):\s*(\d+)(?:,\d+)?:\s*(.*)') results = koLintResults() for line in warnLines: m = ptn.match(line) if m: status = m.group(1) statusCode = m.group(2) lineNo = int(m.group(3)) desc = "pylint: %s%s %s" % (status, statusCode, m.group(4)) if status in ("E", "F"): severity = koLintResult.SEV_ERROR elif status in ("C", "R", "W"): severity = koLintResult.SEV_WARNING else: #log.debug("Skip %s", line) continue koLintResult.createAddResult(results, textlines, severity, lineNo, desc) return results
def lint_with_text(self, request, text): """Lint the given Tcl content. Raise an exception if there is a problem. """ if gHaveGetProxiedEffectivePrefs: prefset = getProxiedEffectivePrefs(request) else: # Komodo 8 sets the prefet on the request. prefset = request.prefset argv = self._getLinterArgv(prefset) env = koprocessutils.getUserEnv() # if there is no setting for the dev kit environment, use # the shared directory for it. This enables site wide # use of *.pdx and *.pcx files for debugging if "TCLDEVKIT_LOCAL" not in env: koDirs = components.classes["@activestate.com/koDirs;1"].\ getService(components.interfaces.koIDirs) sharedDir = os.path.join(koDirs.commonDataDir, "tcl") env["TCLDEVKIT_LOCAL"] = sharedDir if prefset.hasPref("tclExtraPaths"): tclExtraPaths = prefset.getStringPref("tclExtraPaths") # If TCLLIBPATH is set, then it must contain a valid Tcl # list giving directories to search during auto-load # operations. Directories must be specified in Tcl format, # using "/" as the path separator, regardless of platform. # This variable is only used when initializing the # auto_path variable. Also escape spaces in paths. tclExtraPaths = tclExtraPaths.replace('\\', '/') tclExtraPaths = tclExtraPaths.replace(' ', '\ ') TCLLIBPATH = ' '.join(tclExtraPaths.split(os.pathsep)) env["TCLLIBPATH"] = TCLLIBPATH cwd = request.cwd or None print 'argv: %r' % (argv, ) p = process.ProcessOpen(argv, cwd=cwd, env=env) lOutput, lErrOut = p.communicate(text) lOutput = lOutput.splitlines(1) #print '======' #print lOutput #print '======' #print lErrOut #print '<<<<<<' if not lOutput and lErrOut: raise ServerException(nsError.NS_ERROR_UNEXPECTED, lErrOut) if not lOutput: # this should never happen unless the tcl linter is broken, or # not executable on linux. raise ServerException(nsError.NS_ERROR_UNEXPECTED, "No output from Tcl linter available") if lOutput[0].startswith("TclPro") or \ lOutput[0].startswith("scanning"): # The open source TclPro has the header stripped, # so we need to check for both "TclPro" and "scanning" lInput = text.split('\n') return self._TclPro_lint(lInput, lOutput) else: errmsg = "unrecognized lint output format:\n%s" % lOutput[0] raise ServerException(nsError.NS_ERROR_UNEXPECTED, errmsg)
def lint_with_text(self, request, text): prefset = getProxiedEffectivePrefs(request) criticLevel = prefset.getStringPref('perl_lintOption_perlCriticLevel') if criticLevel == 'off': return if not self._appInfoEx.isPerlCriticInstalled(False): # This check is necessary in case Perl::Critic and/or criticism were uninstalled # between Komodo sessions. appInfoEx.isPerlCriticInstalled caches the state # until the pref is changed. return # Bug 82713: Since linting isn't done on the actual file, but a copy, # Perl-Critic will complain about legitimate package declarations. # Find them, and append an annotation to turn the Perl-Critic feature off. # This will also tag comments, strings, and POD, but that won't affect # lint results. # This is no longer needed with Perl-Critic 1.5, which # goes by the filename given in any #line directives perlCriticVersion = self._appInfoEx.getPerlCriticVersion() currFile = request.koDoc.file baseFileName = None if currFile: baseFileName = currFile.baseName[0:-len(currFile.ext)] if perlCriticVersion < 1.500: munger = re.compile( r'''^\s*(?P<package1>package \s+ (?:[\w\d_]+::)*) (?P<baseFileName>%s) (?P<space1>\s*;) (?P<space2>\s*) (?P<rest>(?:\#.*)?)$''' % (baseFileName, ), re.MULTILINE | re.VERBOSE) text = munger.sub(self._insertPerlCriticFilenameMatchInhibitor, text) elif perlCriticVersion >= 1.500 and currFile: text = "#line 1 " + currFile.baseName + "\n" + text cwd = request.cwd or None # convert '' to None (cwd=='' for new files) tmpFileName = self._writeTempFile(cwd, text) try: perlExe = self._selectPerlExe(prefset) lintOptions = prefset.getStringPref("perl_lintOption") option = '-' + lintOptions if perlCriticVersion <= 1.100 or not baseFileName: pcOption = '-Mcriticism=' + criticLevel else: pcOption = '''-Mcriticism (-severity => '%s', 'as-filename' => '%s')''' % ( criticLevel, baseFileName) perlExtraPaths = prefset.getStringPref("perlExtraPaths") if perlExtraPaths: if sys.platform.startswith("win"): perlExtraPaths = perlExtraPaths.replace('\\', '/') perlExtraPaths = [ x for x in perlExtraPaths.split(os.pathsep) if x.strip() ] argv = [perlExe] for incpath in perlExtraPaths: argv += ['-I', incpath] if 'T' in lintOptions and prefset.getBooleanPref( "perl_lintOption_includeCurrentDirForLinter"): argv += ['-I', '.'] # bug 27963: Fix instances of <<use PerlTray>> from code # to make them innocuous for the syntax checker. # 'use PerlTray' in comments or strings will trigger a false positive if sys.platform.startswith( "win") and self._use_perltray_module.search(text): argv += ['-I', self._perlTrayDir] argv.append(option) argv.append(pcOption) argv.append(tmpFileName) env = koprocessutils.getUserEnv() # We only need stderr output. p = process.ProcessOpen(argv, cwd=cwd, env=env, stdin=None) _, stderr = p.communicate() lintResults = PerlWarnsToLintResults(stderr.splitlines(1), tmpFileName, request.koDoc.displayPath, text) finally: os.unlink(tmpFileName) return lintResults
def __init__(self, request, scope): self.prefset = getProxiedEffectivePrefs(request) self.scope = scope