diff --git a/eris/tools.py b/eris/tools.py index 995e708..577b111 100644 --- a/eris/tools.py +++ b/eris/tools.py @@ -239,7 +239,7 @@ def metadata(path): return (Status.normal, fill3.Text(fill3.join("", text))) -@deps(deps={"pip3/pygments"}, url="python3-pygments") +@deps(deps={"pip/pygments"}, url="python3-pygments") def contents(path): with open(path) as file_: try: @@ -254,35 +254,17 @@ def contents(path): return Status.normal, text_widget -def _is_python_syntax_correct(path, python_version): - if python_version == "python": - stdin, stdout, returncode = _do_command( - ["python", "-c", - f"__import__('compiler').parse(open('{path}').read())"]) - return returncode == 0 - else: # python3 - with open(path) as f: - source = f.read() - try: - ast.parse(source) - except: - return False - return True - - -def _python_version(path): # Need a better hueristic - for version in [PYTHON_EXECUTABLE, "python"]: - if _is_python_syntax_correct(path, version): - return version - return PYTHON_EXECUTABLE - - -@deps(deps={"python"}, - url="https://en.wikipedia.org/wiki/Python_syntax_and_semantics") +@deps(url="https://en.wikipedia.org/wiki/Python_syntax_and_semantics") def python_syntax(path): - status = (Status.ok if _is_python_syntax_correct(path, "python") or - _is_python_syntax_correct(path, "python3") else Status.problem) - return status, fill3.Text("") + with open(path) as f: + source = f.read() + try: + ast.parse(source) + except SyntaxError: + is_correct = False + else: + is_correct = True + return (Status.ok if is_correct else Status.problem), fill3.Text("") def _has_shebang_line(path): @@ -295,12 +277,11 @@ def _is_python_test_file(path): return path.endswith("_test.py") or path.startswith("test_") -@deps(deps={"python", "python3"}, - url="https://docs.python.org/3/library/unittest.html") +@deps(url="https://docs.python.org/3/library/unittest.html") def python_unittests(path): if _is_python_test_file(path): command = ([path] if _has_shebang_line(path) - else [_python_version(path), path]) + else [PYTHON_EXECUTABLE, path]) stdout, stderr, returncode = _do_command(command, timeout=TIMEOUT) status = Status.ok if returncode == 0 else Status.problem return status, fill3.Text(stdout + "\n" + stderr) @@ -308,11 +289,10 @@ def python_unittests(path): return Status.not_applicable, fill3.Text("No tests.") -@deps(deps={"python", "python3"}, - url="https://docs.python.org/3/library/pydoc.html") +@deps(url="https://docs.python.org/3/library/pydoc.html") def pydoc(path): stdout, stderr, returncode = _do_command( - [_python_version(path), "-m", "pydoc", path], timeout=TIMEOUT) + [PYTHON_EXECUTABLE, "-m", "pydoc", path], timeout=TIMEOUT) status = Status.normal if returncode == 0 else Status.not_applicable if not stdout.startswith("Help on module"): status = Status.not_applicable @@ -320,7 +300,7 @@ def pydoc(path): return status, fill3.Text(_fix_input(stdout)) -@deps(deps={"pip3/mypy"}, url="http://mypy-lang.org/", executables={"mypy"}) +@deps(deps={"pip/mypy"}, url="http://mypy-lang.org/", executables={"mypy"}) def mypy(path): stdout, stderr, returncode = _do_command( [PYTHON_EXECUTABLE, "-m", "mypy", path], timeout=TIMEOUT) @@ -335,14 +315,13 @@ def _colorize_coverage_report(text): for line in text.splitlines(keepends=True)]) -@deps(deps={"pip/coverage", "pip3/coverage"}, - url="https://coverage.readthedocs.io/") +@deps(deps={"pip/coverage"}, url="https://coverage.readthedocs.io/") def python_coverage(path): # FIX: Also use test_*.py files. test_path = path[:-(len(".py"))] + "_test.py" if os.path.exists(test_path): with tempfile.TemporaryDirectory() as temp_dir: - coverage_cmd = [_python_version(path), "-m", "coverage"] + coverage_cmd = [PYTHON_EXECUTABLE, "-m", "coverage"] coverage_path = os.path.join(temp_dir, "coverage") env = os.environ.copy() env["COVERAGE_FILE"] = coverage_path @@ -361,28 +340,25 @@ def python_coverage(path): "No corresponding test file: " + os.path.normpath(test_path)) -@deps(deps={"pip/pycodestyle", "pip3/pycodestyle"}, - url="http://pycodestyle.pycqa.org/en/latest/") +@deps(deps={"pip/pycodestyle"}, url="http://pycodestyle.pycqa.org/en/latest/") def pycodestyle(path): - return _run_command([_python_version(path), "-m", "pycodestyle", path]) + return _run_command([PYTHON_EXECUTABLE, "-m", "pycodestyle", path]) -@deps(deps={"pip/pydocstyle", "pip3/pydocstyle"}, - url="http://pycodestyle.pycqa.org/en/latest/") +@deps(deps={"pip/pydocstyle"}, url="http://pycodestyle.pycqa.org/en/latest/") def pydocstyle(path): - return _run_command([_python_version(path), "-m", "pydocstyle", path]) + return _run_command([PYTHON_EXECUTABLE, "-m", "pydocstyle", path]) -@deps(deps={"pip/pyflakes", "pip3/pyflakes"}, - url="https://pypi.org/project/pyflakes/") +@deps(deps={"pip/pyflakes"}, url="https://pypi.org/project/pyflakes/") def pyflakes(path): - return _run_command([_python_version(path), "-m", "pyflakes", path]) + return _run_command([PYTHON_EXECUTABLE, "-m", "pyflakes", path]) -@deps(deps={"pip/pylint", "pip3/pylint"}, url="https://www.pylint.org/") +@deps(deps={"pip/pylint"}, url="https://www.pylint.org/") def pylint(path): - return _run_command([_python_version(path), "-m", "pylint", - "--errors-only", path]) + return _run_command([PYTHON_EXECUTABLE, "-m", "pylint", "--errors-only", + path]) @deps(url="https://github.com/ahamilton/eris/blob/master/gut.py") @@ -393,59 +369,52 @@ def python_gut(path): return Status.normal, source_widget -@deps(deps={"python", "python3"}, - url="https://docs.python.org/3/library/modulefinder.html") +@deps(url="https://docs.python.org/3/library/modulefinder.html") def python_modulefinder(path): - return _run_command([_python_version(path), "-m", "modulefinder", path], + return _run_command([PYTHON_EXECUTABLE, "-m", "modulefinder", path], Status.normal) -@deps(deps={"python", "python3"}, - url="https://docs.python.org/3/library/dis.html") +@deps(url="https://docs.python.org/3/library/dis.html") def dis(path): - return _run_command([_python_version(path), "-m", "dis", path], - Status.normal) + return _run_command([PYTHON_EXECUTABLE, "-m", "dis", path], Status.normal) -def _get_mccabe_line_score(line, python_version): +def _get_mccabe_line_score(line): position, function_name, score = line.split() - return int(score if python_version == PYTHON_EXECUTABLE else score[:-1]) + return int(score) -def _colorize_mccabe(text, python_version): +def _colorize_mccabe(text): return fill3.join("", [ termstr.TermStr(line).fg_color(termstr.Color.yellow) - if _get_mccabe_line_score(line, python_version) > 10 else line + if _get_mccabe_line_score(line) > 10 else line for line in text.splitlines(keepends=True)]) -@deps(deps={"pip/mccabe", "pip3/mccabe"}, - url="https://pypi.org/project/mccabe/") +@deps(deps={"pip/mccabe"}, url="https://pypi.org/project/mccabe/") def python_mccabe(path): - python_version = _python_version(path) - stdout, *rest = _do_command([python_version, "-m", "mccabe", path]) + stdout, *rest = _do_command([PYTHON_EXECUTABLE, "-m", "mccabe", path]) max_score = 0 with contextlib.suppress(ValueError): # When there are no lines - max_score = max(_get_mccabe_line_score(line, python_version) + max_score = max(_get_mccabe_line_score(line) for line in stdout.splitlines()) status = Status.problem if max_score > 10 else Status.ok - return status, fill3.Text(_colorize_mccabe(stdout, python_version)) + return status, fill3.Text(_colorize_mccabe(stdout)) # FIX: Reenable when pydisasm is not causing problems -# @deps(deps={"pip3/xdis"}, executables={"pydisasm"}, +# @deps(deps={"pip/xdis"}, executables={"pydisasm"}, # url="https://pypi.python.org/pypi/xdis") # def pydisasm(path): # return _run_command(["pydisasm", path], Status.normal, # Status.not_applicable) -@deps(deps={"pip/bandit", "pip3/bandit"}, - url="https://pypi.org/project/bandit/") +@deps(deps={"pip/bandit"}, url="https://pypi.org/project/bandit/") def bandit(path): - python_version = _python_version(path) stdout, stderr, returncode = _do_command( - [python_version, "-m", "bandit.cli.main", "-f", "txt", path], + [PYTHON_EXECUTABLE, "-m", "bandit.cli.main", "-f", "txt", path], timeout=TIMEOUT) status = Status.ok if returncode == 0 else Status.problem text_without_timestamp = "".join(stdout.splitlines(keepends=True)[2:]) @@ -534,7 +503,7 @@ def _resize_image(image, new_width): PIL.Image.ANTIALIAS) -@deps(deps={"pip3/pillow"}, url="python3-pil") +@deps(deps={"pip/pillow"}, url="python3-pil") def pil(path): import PIL.Image with open(path, "rb") as image_file: diff --git a/eris/tools.toml b/eris/tools.toml index 0a18e9a..8c6d2d5 100644 --- a/eris/tools.toml +++ b/eris/tools.toml @@ -136,8 +136,8 @@ tools_for_extensions = [ success_status = "normal" [pdf2txt] - dependencies = ["pip/pdfminer"] - url = "https://euske.github.io/pdfminer/" + dependencies = ["pip/pdfminer.six"] + url = "https://github.com/pdfminer/pdfminer.six" command = "pdf2txt.py" success_status = "normal" @@ -216,7 +216,7 @@ tools_for_extensions = [ command = "golint -set_exit_status" [yamllint] - dependencies = ["pip3/yamllint"] + dependencies = ["pip/yamllint"] url = "https://github.com/adrienverge/yamllint" command = "python3.7 -m yamllint" diff --git a/install-tools b/install-tools index 1228af5..8321ff0 100755 --- a/install-tools +++ b/install-tools @@ -8,21 +8,16 @@ import subprocess import eris.tools -pip_deps, pip3_deps, dist_deps = set(), set(), set() +pip_deps, dist_deps = set(), set() for dependency in eris.tools.dependencies(): if "/" in dependency: pip_version, pip_dependency = dependency.split("/") - (pip_deps if pip_version == "pip" else pip3_deps).add(pip_dependency) + pip_deps.add(pip_dependency) else: dist_deps.add(dependency) -if pip_deps: - dist_deps.add("python-pip") if dist_deps: subprocess.run(["sudo", "apt-get", "-y", "install"] + list(dist_deps), check=True) if pip_deps: - subprocess.run(["python", "-m", "pip", "install"] + list(pip_deps), - check=True) -if pip3_deps: subprocess.run(["python" + eris.tools.PYTHON_VERSION, "-m", "pip", - "install"] + list(pip3_deps), check=True) + "install"] + list(pip_deps), check=True) diff --git a/tests/golden-files/input/hi.py b/tests/golden-files/input/hi.py deleted file mode 100644 index f579709..0000000 --- a/tests/golden-files/input/hi.py +++ /dev/null @@ -1,4 +0,0 @@ - - -def hi(): - print "hi" diff --git a/tests/golden-files/results/bandit-hi_py b/tests/golden-files/results/bandit-hi_py deleted file mode 100644 index 70a5fbf..0000000 --- a/tests/golden-files/results/bandit-hi_py +++ /dev/null @@ -1,19 +0,0 @@ -Test results: - No issues identified. - -Code scanned: - Total lines of code: 2 - Total lines skipped (#nosec): 0 - -Run metrics: - Total issues (by severity): - Undefined: 0 - Low: 0 - Medium: 0 - High: 0 - Total issues (by confidence): - Undefined: 0 - Low: 0 - Medium: 0 - High: 0 -Files skipped (0): \ No newline at end of file diff --git a/tests/golden-files/results/mypy-hi_py b/tests/golden-files/results/mypy-hi_py deleted file mode 100644 index cd83200..0000000 --- a/tests/golden-files/results/mypy-hi_py +++ /dev/null @@ -1 +0,0 @@ -input/hi.py:4: error: Missing parentheses in call to 'print'. Did you mean print("hi")? \ No newline at end of file diff --git a/tests/golden-files/results/pycodestyle-hi_py b/tests/golden-files/results/pycodestyle-hi_py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/golden-files/results/pydoc-hi_py b/tests/golden-files/results/pydoc-hi_py deleted file mode 100644 index 304ded2..0000000 --- a/tests/golden-files/results/pydoc-hi_py +++ /dev/null @@ -1,12 +0,0 @@ -Help on module hi: - -NAME - hi - -FILE - input/hi.py - -FUNCTIONS - hi() - - \ No newline at end of file diff --git a/tests/golden-files/results/pyflakes-hi_py b/tests/golden-files/results/pyflakes-hi_py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/golden-files/results/pylint-hi_py b/tests/golden-files/results/pylint-hi_py deleted file mode 100644 index b00b628..0000000 --- a/tests/golden-files/results/pylint-hi_py +++ /dev/null @@ -1 +0,0 @@ -No config file found, using default configuration \ No newline at end of file diff --git a/tests/golden-files/results/python_coverage-hi_py b/tests/golden-files/results/python_coverage-hi_py deleted file mode 100644 index b2d2daf..0000000 --- a/tests/golden-files/results/python_coverage-hi_py +++ /dev/null @@ -1,4 +0,0 @@ - - -(B> def hi():(B -(B> print "hi"(B \ No newline at end of file diff --git a/tests/golden-files/results/python_gut-hi_py b/tests/golden-files/results/python_gut-hi_py deleted file mode 100644 index a2f755f..0000000 --- a/tests/golden-files/results/python_gut-hi_py +++ /dev/null @@ -1 +0,0 @@ -def(B (Bhi(B():(B \ No newline at end of file diff --git a/tests/golden-files/results/python_mccabe-hi_py b/tests/golden-files/results/python_mccabe-hi_py deleted file mode 100644 index b43dc82..0000000 --- a/tests/golden-files/results/python_mccabe-hi_py +++ /dev/null @@ -1 +0,0 @@ -("3:0: 'hi'", 1) \ No newline at end of file diff --git a/tests/golden-files/results/python_modulefinder-hi_py b/tests/golden-files/results/python_modulefinder-hi_py deleted file mode 100644 index bfb7843..0000000 --- a/tests/golden-files/results/python_modulefinder-hi_py +++ /dev/null @@ -1,4 +0,0 @@ - - Name File - ---- ---- -m __main__ ./input/hi.py \ No newline at end of file diff --git a/tests/golden-files/results/python_syntax-hi_py b/tests/golden-files/results/python_syntax-hi_py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/golden-files/results/python_unittests-hi_py b/tests/golden-files/results/python_unittests-hi_py deleted file mode 100644 index 6084130..0000000 --- a/tests/golden-files/results/python_unittests-hi_py +++ /dev/null @@ -1 +0,0 @@ -No tests. \ No newline at end of file diff --git a/tests/tools_test.py b/tests/tools_test.py index 14d186b..bdb6c56 100755 --- a/tests/tools_test.py +++ b/tests/tools_test.py @@ -81,7 +81,7 @@ class ToolsTestCase(unittest.TestCase): def test_contents(self): self._test_tool(tools.contents, [("hi3.py", tools.Status.normal)]) - HI_OK = [("hi3.py", tools.Status.ok), ("hi.py", tools.Status.ok)] + HI_OK = [("hi3.py", tools.Status.ok)] def test_python_syntax(self): self._test_tool(tools.python_syntax, self.HI_OK) @@ -94,8 +94,7 @@ class ToolsTestCase(unittest.TestCase): # ("hi3_test.py", tools.Status.ok), # ("test_foo.py", tools.Status.ok)]) - HI_NORMAL = [("hi3.py", tools.Status.normal), - ("hi.py", tools.Status.normal)] + HI_NORMAL = [("hi3.py", tools.Status.normal)] def test_pydoc(self): # FIX: This is failing inside AppImages. @@ -103,8 +102,7 @@ class ToolsTestCase(unittest.TestCase): self._test_tool(tools.pydoc, self.HI_NORMAL) def test_mypy(self): - self._test_tool(tools.mypy, [("hi3.py", tools.Status.ok), - ("hi.py", tools.Status.problem)]) + self._test_tool(tools.mypy, self.HI_OK) def test_python_coverage(self): self._test_tool(tools.python_coverage, self.HI_NORMAL) @@ -128,8 +126,7 @@ class ToolsTestCase(unittest.TestCase): self._test_tool(tools.python_mccabe, self.HI_OK) def test_bandit(self): - self._test_tool(tools.bandit, [("hi3.py", tools.Status.ok), - ("hi.py", tools.Status.ok)]) + self._test_tool(tools.bandit, self.HI_OK) # FIX: Make the golden-file deterministic # def test_pydisasm(self):