Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

7.7.0: pytest is failing in tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist unit #358

Open
kloczek opened this issue Aug 21, 2023 · 33 comments

Comments

@kloczek
Copy link

kloczek commented Aug 21, 2023

I'm packaging your module as an rpm package so I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

  • python3 -sBm build -w --no-isolation
  • because I'm calling build with --no-isolation I'm using during all processes only locally installed modules
  • install .whl file in </install/prefix> using 'installer` module
  • run pytest with $PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>
  • build is performed in env which is cut off from access to the public network (pytest is executed with -m "not network")

pytest is failing with message that that flake8 is not installed despite fact that it is installed.
First thing is why test suite is checking is that module installed? 🤔
Here is pytest output:

+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-7.7.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-7.7.0-2.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra -m 'not network'
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.8.17, pytest-7.4.0, pluggy-1.2.0
rootdir: /home/tkloczko/rpmbuild/BUILD/diff_cover-7.7.0
configfile: pyproject.toml
plugins: datadir-1.4.1, flake8-1.1.1, mock-3.11.1
collected 288 items

tests/test_clover_violations_reporter.py .                                                                                                                                            [  0%]
tests/test_config_parser.py ...............                                                                                                                                           [  5%]
tests/test_diff_cover_main.py ..                                                                                                                                                      [  6%]
tests/test_diff_cover_tool.py .......                                                                                                                                                 [  8%]
tests/test_diff_quality_main.py ............                                                                                                                                          [ 12%]
tests/test_diff_reporter.py .......................................                                                                                                                   [ 26%]
tests/test_git_diff.py ..........                                                                                                                                                     [ 29%]
tests/test_git_path.py .....                                                                                                                                                          [ 31%]
tests/test_integration.py ................................................                                                                                                            [ 48%]
tests/test_java_violations_reporter.py ..............                                                                                                                                 [ 53%]
tests/test_report_generator.py ..............................                                                                                                                         [ 63%]
tests/test_snippets.py ...................                                                                                                                                            [ 70%]
tests/test_util.py .                                                                                                                                                                  [ 70%]
tests/test_violations_reporter.py ...........................................F.........................................                                                               [100%]

========================================================================================= FAILURES ==========================================================================================
__________________________________________________________________ TestFlake8QualityReporterTest.test_file_does_not_exist ___________________________________________________________________

self = <tests.test_violations_reporter.TestFlake8QualityReporterTest object at 0x7fef6adb8310>

    @pytest.mark.disable_all_files_exist
    def test_file_does_not_exist(self):
        quality = QualityReporter(flake8_driver)
        file_paths = ["ajshdjlasdhajksdh.py"]
        # Expect that we get no results because that file does not exist
        for path in file_paths:
>           result = quality.violations(path)

tests/test_violations_reporter.py:1120:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <diff_cover.violationsreporters.base.QualityReporter object at 0x7fef6964cdc0>, src_path = 'ajshdjlasdhajksdh.py'

    def violations(self, src_path):
        """
        Return a list of Violations recorded in `src_path`.
        """
        if not any(src_path.endswith(ext) for ext in self.driver.supported_extensions):
            return []
        if src_path not in self.violations_dict:
            if self.reports:
                self.violations_dict = self.driver.parse_reports(self.reports)
            else:
                if self.driver_tool_installed is None:
                    self.driver_tool_installed = self.driver.installed()
                if not self.driver_tool_installed:
>                   raise OSError(f"{self.driver.name} is not installed")
E                   OSError: flake8 is not installed

diff_cover/violationsreporters/base.py:160: OSError
================================================================================== short test summary info ==================================================================================
FAILED tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist - OSError: flake8 is not installed
============================================================================== 1 failed, 287 passed in 10.18s ===============================================================================

Here is list of installed modules in build env

Package           Version
----------------- -------
astroid           2.15.6
build             0.10.0
chardet           5.2.0
dill              0.3.7
distro            1.8.0
exceptiongroup    1.1.1
flake8            6.1.0
gpg               1.20.0
iniconfig         2.0.0
installer         0.7.0
isort             5.12.0
Jinja2            3.1.2
lazy-object-proxy 1.9.0
libcomps          0.1.19
MarkupSafe        2.1.3
mccabe            0.7.0
mock              5.1.0
packaging         23.1
platformdirs      3.10.0
pluggy            1.2.0
poetry-core       1.7.0
pycodestyle       2.11.0
pyflakes          3.1.0
Pygments          2.16.0
pylint            2.17.5
pyproject_hooks   1.0.0
pytest            7.4.0
pytest-datadir    1.4.1
pytest-flake8     1.1.1
pytest-mock       3.11.1
python-dateutil   2.8.2
six               1.16.0
tomli             2.0.1
tomlkit           0.12.1
typing_extensions 4.7.1
wheel             0.41.1
wrapt             1.14.1
@Bachmann1234
Copy link
Owner

So the most likely reason the suite is failing is that the command is not available on your path. Diff quality runs its commands via subprocess (since it does not assume the command are installed in the same python environment or are even python tools).

This error actually comes up on the command that checks for the tools existence.

@kloczek
Copy link
Author

kloczek commented Mar 21, 2024

So the most likely reason the suite is failing is that the command is not available on your path. Diff quality runs its commands via subprocess (since it does not assume the command are installed in the same python environment or are even python tools).

This error actually comes up on the command that checks for the tools existence.

OK but which one command? 🤔

In mean time I've moved to python 3.9 and pytest 8.1.1 and now pytest fails in new units

Here is pytest output:
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-8.0.3-2.fc36.x86_64/usr/lib64/python3.9/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-8.0.3-2.fc36.x86_64/usr/lib/python3.9/site-packages
+ /usr/bin/pytest -ra -m 'not network'
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.9.18, pytest-8.1.1, pluggy-1.4.0
rootdir: /home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3
configfile: pyproject.toml
plugins: flake8-1.1.1, mock-3.12.0, datadir-1.5.0
collected 288 items

tests/test_clover_violations_reporter.py .                                                                                                                                            [  0%]
tests/test_config_parser.py ...............                                                                                                                                           [  5%]
tests/test_diff_cover_main.py ..                                                                                                                                                      [  6%]
tests/test_diff_cover_tool.py .......                                                                                                                                                 [  8%]
tests/test_diff_quality_main.py ............                                                                                                                                          [ 12%]
tests/test_diff_reporter.py .......................................                                                                                                                   [ 26%]
tests/test_git_diff.py ..........                                                                                                                                                     [ 29%]
tests/test_git_path.py .....                                                                                                                                                          [ 31%]
tests/test_integration.py .............................FFF.......F.......F                                                                                                            [ 48%]
tests/test_java_violations_reporter.py ..............                                                                                                                                 [ 53%]
tests/test_report_generator.py ..............................                                                                                                                         [ 63%]
tests/test_snippets.py ...................                                                                                                                                            [ 70%]
tests/test_util.py .                                                                                                                                                                  [ 70%]
tests/test_violations_reporter.py ...........................................F.........................................                                                               [100%]

========================================================================================= FAILURES ==========================================================================================
__________________________________________________________________ TestDiffQualityIntegration.test_added_file_pylint_html ___________________________________________________________________

self = <tests.test_integration.TestDiffQualityIntegration object at 0x7f03f73be3d0>

    def test_added_file_pylint_html(self):
>       self._check_html_report(
            "git_diff_violations.txt",
            "pylint_violations_report.html",
            ["diff-quality", "--violations=pylint"],
        )

/home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3/tests/test_integration.py:446:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <tests.test_integration.TestDiffQualityIntegration object at 0x7f03f73be3d0>, git_diff_path = 'git_diff_violations.txt', expected_html_path = 'pylint_violations_report.html'
tool_args = ['diff-quality', '--violations=pylint'], expected_status = 0, css_file = None

    def _check_html_report(
        self,
        git_diff_path,
        expected_html_path,
        tool_args,
        expected_status=0,
        css_file=None,
    ):
        """
        Verify that the tool produces the expected HTML report.

        `git_diff_path` is a path to a fixture containing the (patched) output of
        the call to `git diff`.

        `expected_console_path` is a path to the fixture containing
        the expected HTML output of the tool.

        `tool_args` is a list of command line arguments to pass
        to the tool.  You should include the name of the tool
        as the first argument.
        """

        # Patch the output of `git diff`
        with open(git_diff_path, encoding="utf-8") as git_diff_file:
            self._set_git_diff_output(git_diff_file.read(), "")

        # Create a temporary directory to hold the output HTML report
        # Add a cleanup to ensure the directory gets deleted
        temp_dir = self.tmp_path / "dummy"
        temp_dir.mkdir()

        html_report_path = os.path.join(temp_dir, "diff_coverage.html")

        args = tool_args + ["--html-report", html_report_path]

        if css_file:
            css_file = os.path.join(temp_dir, css_file)
            args += ["--external-css-file", css_file]

        # Execute the tool
        if "diff-cover" in args[0]:
            code = diff_cover_tool.main(args)
        else:
            code = diff_quality_tool.main(args)

>       assert code == expected_status
E       assert 1 == 0

/home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3/tests/test_integration.py:111: AssertionError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
ERROR    diff_cover.diff_quality_tool:diff_quality_tool.py:379 Failure: 'pylint is not installed'
______________________________________________________________________ TestDiffQualityIntegration.test_fail_under_html ______________________________________________________________________

self = <tests.test_integration.TestDiffQualityIntegration object at 0x7f03f73be250>

    def test_fail_under_html(self):
>       self._check_html_report(
            "git_diff_violations.txt",
            "pylint_violations_report.html",
            ["diff-quality", "--violations=pylint", "--fail-under=80"],
            expected_status=1,
        )

/home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3/tests/test_integration.py:453:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3/tests/test_integration.py:119: in _check_html_report
    html = self._clear_css(html)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <tests.test_integration.TestDiffQualityIntegration object at 0x7f03f73be250>, content = ''

    def _clear_css(self, content):
        """
        The CSS is provided by pygments and changes fairly often.
        Im ok with simply saying "There was css"

        Perhaps I will eat these words
        """
        clean_content = re.sub("r'<style>.*</style>", content, "", re.DOTALL)
>       assert len(content) > len(clean_content)
E       AssertionError: assert 0 > 0
E        +  where 0 = len('')
E        +  and   0 = len('')

/home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3/tests/test_integration.py:63: AssertionError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
ERROR    diff_cover.diff_quality_tool:diff_quality_tool.py:379 Failure: 'pylint is not installed'
___________________________________________________________________ TestDiffQualityIntegration.test_fail_under_pass_html ____________________________________________________________________

self = <tests.test_integration.TestDiffQualityIntegration object at 0x7f03f73be730>

    def test_fail_under_pass_html(self):
>       self._check_html_report(
            "git_diff_violations.txt",
            "pylint_violations_report.html",
            ["diff-quality", "--violations=pylint", "--fail-under=40"],
            expected_status=0,
        )

/home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3/tests/test_integration.py:461:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <tests.test_integration.TestDiffQualityIntegration object at 0x7f03f73be730>, git_diff_path = 'git_diff_violations.txt', expected_html_path = 'pylint_violations_report.html'
tool_args = ['diff-quality', '--violations=pylint', '--fail-under=40'], expected_status = 0, css_file = None

    def _check_html_report(
        self,
        git_diff_path,
        expected_html_path,
        tool_args,
        expected_status=0,
        css_file=None,
    ):
        """
        Verify that the tool produces the expected HTML report.

        `git_diff_path` is a path to a fixture containing the (patched) output of
        the call to `git diff`.

        `expected_console_path` is a path to the fixture containing
        the expected HTML output of the tool.

        `tool_args` is a list of command line arguments to pass
        to the tool.  You should include the name of the tool
        as the first argument.
        """

        # Patch the output of `git diff`
        with open(git_diff_path, encoding="utf-8") as git_diff_file:
            self._set_git_diff_output(git_diff_file.read(), "")

        # Create a temporary directory to hold the output HTML report
        # Add a cleanup to ensure the directory gets deleted
        temp_dir = self.tmp_path / "dummy"
        temp_dir.mkdir()

        html_report_path = os.path.join(temp_dir, "diff_coverage.html")

        args = tool_args + ["--html-report", html_report_path]

        if css_file:
            css_file = os.path.join(temp_dir, css_file)
            args += ["--external-css-file", css_file]

        # Execute the tool
        if "diff-cover" in args[0]:
            code = diff_cover_tool.main(args)
        else:
            code = diff_quality_tool.main(args)

>       assert code == expected_status
E       assert 1 == 0

/home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3/tests/test_integration.py:111: AssertionError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
ERROR    diff_cover.diff_quality_tool:diff_quality_tool.py:379 Failure: 'pylint is not installed'
_________________________________________________________________ TestDiffQualityIntegration.test_added_file_pylint_console _________________________________________________________________

self = <tests.test_integration.TestDiffQualityIntegration object at 0x7f03f73c1c40>

    def test_added_file_pylint_console(self):
        console_report = "pylint_violations_console_report.txt"
>       self._check_console_report(
            "git_diff_violations.txt",
            console_report,
            ["diff-quality", "--violations=pylint"],
        )

/home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3/tests/test_integration.py:527:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <tests.test_integration.TestDiffQualityIntegration object at 0x7f03f73c1c40>, git_diff_path = 'git_diff_violations.txt'
expected_console_path = 'pylint_violations_console_report.txt', tool_args = ['diff-quality', '--violations=pylint'], expected_status = 0

    def _check_console_report(
        self, git_diff_path, expected_console_path, tool_args, expected_status=0
    ):
        """
        Verify that the tool produces the expected console report.

        `git_diff_path` is a path to a fixture containing the (patched) output of
        the call to `git diff`.

        `expected_console_path` is a path to the fixture containing
        the expected console output of the tool.

        `tool_args` is a list of command line arguments to pass
        to the tool.  You should include the name of the tool
        as the first argument.
        """

        # Patch the output of `git diff`
        with open(git_diff_path, encoding="utf-8") as git_diff_file:
            self._set_git_diff_output(git_diff_file.read(), "")

        # Capture stdout to a string buffer
        string_buffer = BytesIO()
        self._capture_stdout(string_buffer)

        # Execute the tool
        if "diff-cover" in tool_args[0]:
            code = diff_cover_tool.main(tool_args)
        else:
            code = diff_quality_tool.main(tool_args)

>       assert code == expected_status
E       assert 1 == 0

/home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3/tests/test_integration.py:156: AssertionError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
ERROR    diff_cover.diff_quality_tool:diff_quality_tool.py:379 Failure: 'pylint is not installed'
________________________________________________________________________ TestDiffQualityIntegration.test_quiet_mode _________________________________________________________________________

self = <tests.test_integration.TestDiffQualityIntegration object at 0x7f03f61829a0>

    def test_quiet_mode(self):
>       self._check_console_report(
            "git_diff_violations.txt",
            "empty.txt",
            ["diff-quality", "--violations=pylint", "-q"],
        )

/home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3/tests/test_integration.py:618:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <tests.test_integration.TestDiffQualityIntegration object at 0x7f03f61829a0>, git_diff_path = 'git_diff_violations.txt', expected_console_path = 'empty.txt'
tool_args = ['diff-quality', '--violations=pylint', '-q'], expected_status = 0

    def _check_console_report(
        self, git_diff_path, expected_console_path, tool_args, expected_status=0
    ):
        """
        Verify that the tool produces the expected console report.

        `git_diff_path` is a path to a fixture containing the (patched) output of
        the call to `git diff`.

        `expected_console_path` is a path to the fixture containing
        the expected console output of the tool.

        `tool_args` is a list of command line arguments to pass
        to the tool.  You should include the name of the tool
        as the first argument.
        """

        # Patch the output of `git diff`
        with open(git_diff_path, encoding="utf-8") as git_diff_file:
            self._set_git_diff_output(git_diff_file.read(), "")

        # Capture stdout to a string buffer
        string_buffer = BytesIO()
        self._capture_stdout(string_buffer)

        # Execute the tool
        if "diff-cover" in tool_args[0]:
            code = diff_cover_tool.main(tool_args)
        else:
            code = diff_quality_tool.main(tool_args)

>       assert code == expected_status
E       assert 1 == 0

/home/tkloczko/rpmbuild/BUILD/diff_cover-8.0.3/tests/test_integration.py:156: AssertionError
------------------------------------------------------------------------------------- Captured log call -------------------------------------------------------------------------------------
ERROR    diff_cover.diff_quality_tool:diff_quality_tool.py:379 Failure: 'pylint is not installed'
__________________________________________________________________ TestFlake8QualityReporterTest.test_file_does_not_exist ___________________________________________________________________

self = <tests.test_violations_reporter.TestFlake8QualityReporterTest object at 0x7f03f61c4730>

    @pytest.mark.disable_all_files_exist
    def test_file_does_not_exist(self):
        quality = QualityReporter(flake8_driver)
        file_paths = ["ajshdjlasdhajksdh.py"]
        # Expect that we get no results because that file does not exist
        for path in file_paths:
>           result = quality.violations(path)

tests/test_violations_reporter.py:1109:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <diff_cover.violationsreporters.base.QualityReporter object at 0x7f03f4993970>, src_path = 'ajshdjlasdhajksdh.py'

    def violations(self, src_path):
        """
        Return a list of Violations recorded in `src_path`.
        """
        if not any(src_path.endswith(ext) for ext in self.driver.supported_extensions):
            return []
        if src_path not in self.violations_dict:
            if self.reports:
                self.violations_dict = self.driver.parse_reports(self.reports)
            else:
                if self.driver_tool_installed is None:
                    self.driver_tool_installed = self.driver.installed()
                if not self.driver_tool_installed:
>                   raise OSError(f"{self.driver.name} is not installed")
E                   OSError: flake8 is not installed

diff_cover/violationsreporters/base.py:160: OSError
================================================================================== short test summary info ==================================================================================
FAILED tests/test_integration.py::TestDiffQualityIntegration::test_added_file_pylint_html - assert 1 == 0
FAILED tests/test_integration.py::TestDiffQualityIntegration::test_fail_under_html - AssertionError: assert 0 > 0
FAILED tests/test_integration.py::TestDiffQualityIntegration::test_fail_under_pass_html - assert 1 == 0
FAILED tests/test_integration.py::TestDiffQualityIntegration::test_added_file_pylint_console - assert 1 == 0
FAILED tests/test_integration.py::TestDiffQualityIntegration::test_quiet_mode - assert 1 == 0
FAILED tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist - OSError: flake8 is not installed
=============================================================================== 6 failed, 282 passed in 4.94s ===============================================================================

@Bachmann1234
Copy link
Owner

@kloczek for pylint the command is pylint --version

Defined here

self.command_to_check_install = ["pylint", "--version"]

Based on the output that command is failing (returning a non zero code)

@Bachmann1234
Copy link
Owner

To elaborate further. It really looks like whatever environment this is running in does not have pylint in its path

@kloczek
Copy link
Author

kloczek commented Apr 15, 2024

Just tested new 9.0.0 with installed pylint and after that step indeed some units stopped failing however still have one failing unit

Here is pytest output:
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/lib64/python3.10/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/lib/python3.10/site-packages
+ /usr/bin/pytest -ra -m 'not network'
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0
rootdir: /home/tkloczko/rpmbuild/BUILD/diff_cover-9.0.0
configfile: pyproject.toml
plugins: datadir-1.5.0, flake8-1.1.1, mock-3.14.0
collected 288 items

tests/test_clover_violations_reporter.py .                                                                                                                                            [  0%]
tests/test_config_parser.py ...............                                                                                                                                           [  5%]
tests/test_diff_cover_main.py ..                                                                                                                                                      [  6%]
tests/test_diff_cover_tool.py .......                                                                                                                                                 [  8%]
tests/test_diff_quality_main.py ............                                                                                                                                          [ 12%]
tests/test_diff_reporter.py .......................................                                                                                                                   [ 26%]
tests/test_git_diff.py ..........                                                                                                                                                     [ 29%]
tests/test_git_path.py .....                                                                                                                                                          [ 31%]
tests/test_integration.py ................................................                                                                                                            [ 48%]
tests/test_java_violations_reporter.py ..............                                                                                                                                 [ 53%]
tests/test_report_generator.py ..............................                                                                                                                         [ 63%]
tests/test_snippets.py ...................                                                                                                                                            [ 70%]
tests/test_util.py .                                                                                                                                                                  [ 70%]
tests/test_violations_reporter.py ...........................................F.........................................                                                               [100%]

========================================================================================= FAILURES ==========================================================================================
__________________________________________________________________ TestFlake8QualityReporterTest.test_file_does_not_exist ___________________________________________________________________

self = <tests.test_violations_reporter.TestFlake8QualityReporterTest object at 0x7fb179f18c70>

    @pytest.mark.disable_all_files_exist
    def test_file_does_not_exist(self):
        quality = QualityReporter(flake8_driver)
        file_paths = ["ajshdjlasdhajksdh.py"]
        # Expect that we get no results because that file does not exist
        for path in file_paths:
>           result = quality.violations(path)

tests/test_violations_reporter.py:1109:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <diff_cover.violationsreporters.base.QualityReporter object at 0x7fb1786b6860>, src_path = 'ajshdjlasdhajksdh.py'

    def violations(self, src_path):
        """
        Return a list of Violations recorded in `src_path`.
        """
        if not any(src_path.endswith(ext) for ext in self.driver.supported_extensions):
            return []
        if src_path not in self.violations_dict:
            if self.reports:
                self.violations_dict = self.driver.parse_reports(self.reports)
            else:
                if self.driver_tool_installed is None:
                    self.driver_tool_installed = self.driver.installed()
                if not self.driver_tool_installed:
>                   raise OSError(f"{self.driver.name} is not installed")
E                   OSError: flake8 is not installed

diff_cover/violationsreporters/base.py:160: OSError
================================================================================== short test summary info ==================================================================================
FAILED tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist - OSError: flake8 is not installed
=============================================================================== 1 failed, 287 passed in 8.59s ===============================================================================

Error message does no match to actual situation because in build env is installed flake8

[tkloczko@pers-jacek SPECS]$ pip show flake8
Name: flake8
Version: 6.1.0
Summary: the modular source code checker: pep8 pyflakes and co
Home-page: https://github.com/pycqa/flake8
Author: Tarek Ziade
Author-email: tarek@ziade.org
License: MIT
Location: /usr/lib/python3.10/site-packages
Requires: mccabe, pycodestyle, pyflakes
Required-by: pytest-flake8

@Bachmann1234
Copy link
Owner

Just tested new 9.0.0 with installed pylint and after that step indeed some units stopped failing however still have one failing unit

Here is pytest output:
Error message does no match to actual situation because in build env is installed flake8

[tkloczko@pers-jacek SPECS]$ pip show flake8
Name: flake8
Version: 6.1.0
Summary: the modular source code checker: pep8 pyflakes and co
Home-page: https://github.com/pycqa/flake8
Author: Tarek Ziade
Author-email: tarek@ziade.org
License: MIT
Location: /usr/lib/python3.10/site-packages
Requires: mccabe, pycodestyle, pyflakes
Required-by: pytest-flake8

I dont really know what to tell you. That test failing implies the command flake8 --version is returning a non zero exit code. The most common reason for this is the command is not actually in the path. SO the library being installed is part of it but ultimately in whatever python running the test is having trouble running that check.

@kloczek
Copy link
Author

kloczek commented Apr 15, 2024

I dont really know what to tell you. That test failing implies the command flake8 --version is returning a non zero exit code. The most common reason for this is the command is not actually in the path. SO the library being installed is part of it but ultimately in whatever python running the test is having trouble running that check.

[tkloczko@pers-jacek build]$ flake8 --version
6.1.0 (mccabe: 0.7.0, pycodestyle: 2.11.0, pyflakes: 3.1.0) CPython 3.10.14 on Linux
[tkloczko@pers-jacek build]$ echo $?
0

Problems happens .. you don't need ot say anything 😄

Do you have any propositions about what I can try to do to diagnose this effect? 🤔
FYI: temporary I've added to --deselect list this unit assuming that more likely with testing procedure than tested code.

@Bachmann1234
Copy link
Owner

I'll take another stab at reproducing this sometime this week. But at this point I think the only path would be putting a line in to log the exception and see how the command is failing

@Bachmann1234
Copy link
Owner

@kloczek what does which flake8 show? IS that path accessible in whatever you are doing to run the tests?

Because im not convinced python3 -sBm build -w --no-isolation is installing dev dependencies.

I created a virtual env
installed build and poetry
then ran python3 -sBm build -w --no-isolation

❯ flake8
zsh: command not found: flake8

This is the output of pip --freeze

build==1.2.1
CacheControl==0.14.0
certifi==2024.2.2
cffi==1.16.0
charset-normalizer==3.3.2
cleo==2.1.0
crashtest==0.4.1
distlib==0.3.8
dulwich==0.21.7
fastjsonschema==2.19.1
filelock==3.13.4
idna==3.7
installer==0.7.0
jaraco.classes==3.4.0
keyring==24.3.1
more-itertools==10.2.0
msgpack==1.0.8
packaging==24.0
pexpect==4.9.0
pkginfo==1.10.0
platformdirs==4.2.0
poetry==1.8.2
poetry-core==1.9.0
poetry-plugin-export==1.7.1
ptyprocess==0.7.0
pycparser==2.22
pyproject_hooks==1.0.0
rapidfuzz==3.8.1
requests==2.31.0
requests-toolbelt==1.0.0
shellingham==1.5.4
tomlkit==0.12.4
trove-classifiers==2024.4.10
urllib3==2.2.1
virtualenv==20.25.2
xattr==1.1.0

@kloczek
Copy link
Author

kloczek commented Apr 17, 2024

@kloczek what does which flake8 show? IS that path accessible in whatever you are doing to run the tests?

I've already provided that details opening ticket

flake8            6.1.0

Because im not convinced python3 -sBm build -w --no-isolation is installing dev dependencies.

Of course it is not installing anything because that command is responsible for only build .whl archive.
Nevertheless in this case it is issue not with building but with testing.

@Bachmann1234
Copy link
Owner

@kloczek I don't see anything about the output of which flake8

I see that the library seems to be installed (and I admit last night I neglected to expand the details)

But it still may be interesting to know where in the build system that command is.

What procedure was used to install the quality tools? Simple pip install? Or something else?

@kloczek
Copy link
Author

kloczek commented Apr 17, 2024

But it still may be interesting to know where in the build system that command is.

Hmm .. what you mean "where"? 🤔

What procedure was used to install the quality tools? Simple pip install? Or something else?

Full build, install and testing procedure is described on top of this ticket 🙄 😋
I'm installing all modules from rpm packages
I'm not interested to test anything what is provided as .whl archives on pypi but only distribution resources on which I'm working.
This is why build is performed with --no-isolation.

@Bachmann1234
Copy link
Owner

But it still may be interesting to know where in the build system that command is.

Hmm .. what you mean "where"? 🤔

What procedure was used to install the quality tools? Simple pip install? Or something else?

Full build, install and testing procedure is described on top of this ticket 🙄 😋
I'm installing all modules from rpm packages
I'm not interested to test anything what is provided as .whl archives on pypi but only distribution resources on which I'm working.
This is why build is performed with --no-isolation.

The path! Running which will confirm the path of the command! So many times in Python builds executables end up in weird places

@kloczek
Copy link
Author

kloczek commented Apr 17, 2024

The path! Running which will confirm the path of the command! So many times in Python builds executables end up in weird places

I'm building all packages in dedicated build envs created to build only one package.
Inside build are installed only build dependencies.
In distribution is only one python package which provides /usr/bin/python3 and it is ATM python 3.11.14.
After finis build procedure build env is deleted.
In other words .. in such env thee is no possibility to have multiple python binaries/versions.

@Bachmann1234
Copy link
Owner

Clearly I don't know a lot about Linux packaging beyond basic user commands

But the test that's failing is running a command, not running a function that's imported from a lib. Your single package might be combining all the dependencies but it probably is not installing all the commands for the quality tools into some path that can be executed. But again, I know you are able to run it yourself.

So if your package does not have access to run the command then it will fail that test. This is why I keep asking you to run which to try and confirm where that command is. Because you have demonstrated that you can run it. So it's clearly in your users $PATH

But if that command exists in a place where in the context of the test it does not have access then it won't find the executable.

So that's why I keep asking. What does which pylint tell you. Because if pylint is somewhere the command does not see then it might as well not exist at all.

But honestly, I don't think it's likely that seeing where that command is will make it obvious what's going on. I suspect I'm gonna have to expose the underlying error so you can see specifically what's failing. May not be able to do that for a couple weeks though.

I just think the most likely cause is some kind of path error. In the context of the test, it can't find the pylint executable. I think when I expose the error it's going to be something boring like "command not found" and the question will become "but why?!"

@kloczek
Copy link
Author

kloczek commented Apr 17, 2024

Clearly I don't know a lot about Linux packaging beyond basic user commands

reported issue has nothing to do with packaging so you don't need to know anything about that.

So that's why I keep asking. What does which pylint tell you. Because if pylint is somewhere the command does not see then it might as well not exist at all.

Please have look on provided output .. first time ever and/or one more time.
Error message has nothing to do with pylint.

Why at all test using unis custom code checking "is module XXX installed" if for that can be used OOTB pytest calls? 🤔

Again flake8 is installed in build env and it works in casesof other modules build procedures

[tkloczko@pers-jacek SPECS]$ grep "BuildRequires:.*python3dist(flake8)" *
crypto-policies.spec:BuildRequires:     python3dist(flake8)
python-diff-cover.spec:BuildRequires:   python3dist(flake8)
python-flake8-bugbear.spec:BuildRequires:       python3dist(flake8)     >= 3.0.0
python-flake8-dunder-all.spec:BuildRequires:    python3dist(flake8)
python-flake8-pyi.spec:BuildRequires:   python3dist(flake8)     >= 3.2.1
python-mypy.spec:BuildRequires: python3dist(flake8)
python-pytest-flake8.spec:BuildRequires:        python3dist(flake8)     >= 3.5

As you see in above is literally flake8 is listed in case of this module. With installed that module in build it is not possible to start build. pip show that flake8 is installed but code of that unit for some reason is not able to find it.

@Bachmann1234
Copy link
Owner

I swear im not trying to be difficult here. I know my mixing up of the specific quality tool is not helping. Ive been responding in the morning and at night while juggling other things and thats my bad. But the theory is the same.

Here is a screenshot from your output

Screenshot 2024-04-17 at 12 57 22 PM

The test is an integration test, it executes flake8 --version as a subprocess command and if that command fails it catches the failure and returns that output 'flake8 is not installed.

Now I know you can run this command yourself, you demonstrated it. And I know flake8 is technically installed. But the point is the subprocess is failing to run it one way or another.

I suspect thats because the library is being installed but the executable for said library is not accessable when running the test and I dont know why.

So you have two options to figure this out.

  1. Put some print statement around here to spit out the actual output of the subprocess command (basically capture the stdout, stdin that is currently ignored and print it) [The docs for communicate] (https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate)
    I would replace this with
stdin, stdout = process.communicate()
print(stdin)
print(stdout)

that should tell you exactly why the subprocess command is failing. Though again, I suspect its gonna be a path failure of some kind. Where it says the command does not exist despite being installed.

  1. wait for me to find time to think of a way to expose it and release a version with that. Probably do something similar what the main execute function is doing. Though that will be a bit as I am not in a position to do work on diff cover right now.

@kloczek
Copy link
Author

kloczek commented Apr 17, 2024

I've modified my spec file %check to:

%check
echo; pip show flake8; echo
%pytest tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist
%pytest %{!?with_failing_tests: \
        --deselect tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist \
}

and added pip to build dependencies (normally it is not needed) I've send that spec as test build request (each build is performed in build env created from scratch and after build such build env is deleted).

Here is result literally taken from build log of the rpm %check (test suite execution):

Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.dxRdmQ
+ umask 022
+ cd /home/tkloczko/rpmbuild/BUILD
+ '[' /home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64 '!=' / ']'
+ rm -rf /home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64
+ cd diff_cover-9.0.0
+ /usr/bin/python3 -sBm installer dist/diff_cover-9.0.0-py3-none-any.whl --destdir /home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64
+ /usr/bin/rm -rfv /home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/bin/__pycache__
+ for distinfo in /home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/lib/python3.10/site-packages/*.dist-info /home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/lib64/python3.10/site-packages/*.dist-info
+ '[' -f /home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/lib/python3.10/site-packages/diff_cover-9.0.0.dist-info/direct_url.json ']'
+ for distinfo in /home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/lib/python3.10/site-packages/*.dist-info /home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/lib64/python3.10/site-packages/*.dist-info
+ '[' -f '/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/lib64/python3.10/site-packages/*.dist-info/direct_url.json' ']'
+ /usr/bin/find-debuginfo -j48 --strict-build-id -m -i --build-id-seed 9.0.0-2.fc37 --unique-debug-suffix -9.0.0-2.fc37.x86_64 --unique-debug-src-base python-diff-cover-9.0.0-2.fc37.x86_64 --run-dwz --dwz-low-mem-die-limit none --dwz-max-die-limit 110000000 -S debugsourcefiles.list /home/tkloczko/rpmbuild/BUILD/diff_cover-9.0.0
find-debuginfo: starting
Extracting debug info from 0 files
Creating .debug symlinks for symlinks to ELF files
find: ‘debug’: No such file or directory
find-debuginfo: done
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/redhat/brp-ldconfig
+ /usr/lib/rpm/brp-compress
+ /usr/lib/rpm/brp-strip-static-archive /usr/bin/strip
+ /usr/lib/rpm/check-rpaths
+ /usr/lib/rpm/redhat/brp-mangle-shebangs
Executing(%check): /bin/sh -e /var/tmp/rpm-tmp.KOoawZ
+ umask 022
+ cd /home/tkloczko/rpmbuild/BUILD
+ cd diff_cover-9.0.0
+ echo

+ pip show flake8
Name: flake8
Version: 6.1.0
Summary: the modular source code checker: pep8 pyflakes and co
Home-page: https://github.com/pycqa/flake8
Author: Tarek Ziade
Author-email: tarek@ziade.org
License: MIT
Location: /usr/lib/python3.10/site-packages
Requires: mccabe, pycodestyle, pyflakes
Required-by: pytest-flake8
+ echo

+ ASMFLAGS='-m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O2 -g -grecord-gcc-switches -pipe -mtls-dialect=gnu2 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fdata-sections -ffunction-sections -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -flto=auto -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -Wall -Werror=format-security'
+ CFLAGS='-m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O2 -g -grecord-gcc-switches -pipe -mtls-dialect=gnu2 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fdata-sections -ffunction-sections -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -flto=auto -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -Wall -Werror=format-security'
+ CXXFLAGS='-m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O2 -g -grecord-gcc-switches -pipe -mtls-dialect=gnu2 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fdata-sections -ffunction-sections -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -flto=auto -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -Wall -Werror=format-security'
+ FFLAGS='-m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O2 -g -grecord-gcc-switches -pipe -mtls-dialect=gnu2 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fdata-sections -ffunction-sections -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -flto=auto -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -Wall -Werror=format-security -I/usr/lib64/gfortran/modules'
+ FCFLAGS='-m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O2 -g -grecord-gcc-switches -pipe -mtls-dialect=gnu2 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fdata-sections -ffunction-sections -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -flto=auto -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -Wall -Werror=format-security -I/usr/lib64/gfortran/modules'
+ LDFLAGS='-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--gc-sections -Wl,--as-needed -Wl,--build-id=sha1 -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-z,pack-relative-relocs -flto=auto -fuse-linker-plugin'
+ RUSTFLAGS='-C codegen-units=1 -C debuginfo=2 -C opt-level=2 -C link-arg=-Wl,--as-needed -C link-arg=-Wl,--build-id=sha1 -C link-arg=-Wl,-z,now -C link-arg=-specs=/usr/lib/rpm/redhat/redhat-hardened-ld -C link-arg=-Wl,-z,pack-relative-relocs -C link-arg=-Wl,-z,relro -C link-arg=-flto=auto --cap-lints=warn'
+ VALAFLAGS=-g
+ CC=/usr/bin/gcc
+ CXX=/usr/bin/g++
+ FC=/usr/bin/gfortran
+ AR=/usr/bin/gcc-ar
+ NM=/usr/bin/gcc-nm
+ RANLIB=/usr/bin/gcc-ranlib
+ export ASMFLAGS CFLAGS CXXFLAGS FFLAGS FCFLAGS LDFLAGS VALAFLAGS CC CXX FC AR NM RANLIB RUSTFLAGS VALAFLAGS
+ PATH=/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/bin:/usr/bin:/usr/sbin:/usr/local/sbin
+ LD_LIBRARY_PATH=/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/lib64
+ PYTHONDONTWRITEBYTECODE=1
+ PDM_BUILD_SCM_VERSION=9.0.0
+ PBR_VERSION=9.0.0
+ SETUPTOOLS_SCM_PRETEND_VERSION=9.0.0
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/lib64/python3.10/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/lib/python3.10/site-packages
+ /usr/bin/pytest -ra -m 'not network' tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist
============================= test session starts ==============================
platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0
benchmark: 4.0.0 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /home/tkloczko/rpmbuild/BUILD/diff_cover-9.0.0
configfile: pyproject.toml
plugins: forked-1.6.0, hypothesis-6.100.0, mock-3.14.0, benchmark-4.0.0, timeout-2.3.1, flaky-3.8.1, subprocess-1.5.0, flake8-1.1.1, datadir-1.5.0
collected 1 item

tests/test_violations_reporter.py F                                      [100%]

=================================== FAILURES ===================================
____________ TestFlake8QualityReporterTest.test_file_does_not_exist ____________

self = <tests.test_violations_reporter.TestFlake8QualityReporterTest object at 0x7f0e718e4550>

    @pytest.mark.disable_all_files_exist
    def test_file_does_not_exist(self):
        quality = QualityReporter(flake8_driver)
        file_paths = ["ajshdjlasdhajksdh.py"]
        # Expect that we get no results because that file does not exist
        for path in file_paths:
>           result = quality.violations(path)

tests/test_violations_reporter.py:1109:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <diff_cover.violationsreporters.base.QualityReporter object at 0x7f0e718e4520>
src_path = 'ajshdjlasdhajksdh.py'

    def violations(self, src_path):
        """
        Return a list of Violations recorded in `src_path`.
        """
        if not any(src_path.endswith(ext) for ext in self.driver.supported_extensions):
            return []
        if src_path not in self.violations_dict:
            if self.reports:
                self.violations_dict = self.driver.parse_reports(self.reports)
            else:
                if self.driver_tool_installed is None:
                    self.driver_tool_installed = self.driver.installed()
                if not self.driver_tool_installed:
>                   raise OSError(f"{self.driver.name} is not installed")
E                   OSError: flake8 is not installed

diff_cover/violationsreporters/base.py:160: OSError
=========================== short test summary info ============================
FAILED tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist
============================== 1 failed in 1.10s ===============================

As you see pip shows tat flake8 is present and your cede that it is not. Can you explain that? 🤔

Just humble question one more time: why at all this module test procedure needs to check is flake8 installed? 🤔

flake8 as many other modules never should be executed as module over python -m foo because when pyton is executed with -m it adds current directory to sys.path which messes with many such modules.
This is why flake, pytest and many more provides wrapper script like

[tkloczko@pers-jacek SPECS]$ cat /usr/bin/flake8
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from flake8.main.cli import main
if __name__ == "__main__":
    sys.argv[0] = re.sub(r"(-script\.pyw|\.exe)?$", "", sys.argv[0])
    sys.exit(main())

In other words if on testing is needed flake8 it shoulder be blindly executed as command and not checked as module.
Am I right or not? 🤔

@Bachmann1234
Copy link
Owner

Just humble question one more time: why at all this module test procedure needs to check is flake8 installed? 

I mean we are talking about code that was written potentially over a decade ago... and I dont even remember what parts were originally me.... but if im remembering correctly the idea is that diffcover/diffquality does not assume its bundled with anything. All it cares about is the tool it needs to run can be run over the code. So the python that runs diff cover does not need to be the same python that runs flake8 or any of the related tools (hell, some of the tools are not even python tools). so im not confident the python -m foo procedure makes sense in this context.

If this tool was written today it may have been written differently but who knows!.

The check to see if its installed is just running a simple version of the command. Feel free to remove the install check. I dont think it will help you because the main command will fail... likely for the same cause.

As you see pip shows tat flake8 is present and your cede that it is not. Can you explain that? 

I feel like ive tried to explain it. The command is failing, for some reason or another. If the basic --version command fails the code assumes its not installed and throws an os error and says its not installed. The error message is likely misleading. Ive told you what you could do to get a more specific error message but that would involve editing the code to see whats going on.

In other words if on testing is needed flake8 it shoulder be blindly executed as command and not checked as module.
Am I right or not? 🤔

Again, the "check" being run is blindly executing flake8. Executing flake8 is failing and the error the code throws says its not installed. But clearly the language is misleading/wrong because clearly its installed. But for some reason the subprocess command is failing.

@kloczek
Copy link
Author

kloczek commented Apr 17, 2024

I mean we are talking about code that was written potentially over a decade ago... and I dont even remember what parts were originally me.

Please don't get me wrong. I'm not trying to blame/accuse anything or anyone.
I'm only b*dy messenger 😋
"Shit happens .. sometimes" 😄

I feel like ive tried to explain it. The command is failing, for some reason or another. If the basic --version command fails the code assumes its not installed and throws an os error and says its not installed.

Just made another test

+ strace -e trace=execve,fork /usr/bin/pytest -ra -m 'not network' tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist
execve("/usr/bin/pytest", ["/usr/bin/pytest", "-ra", "-m", "not network", "tests/test_violations_reporter.p"...], 0x7fff283d7630 /* 63 vars */) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=35604, si_uid=1000, si_status=128, si_utime=0, si_stime=0} ---
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=35605, si_uid=1000, si_status=255, si_utime=0, si_stime=0} ---
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=35606, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0
benchmark: 4.0.0 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /home/tkloczko/rpmbuild/BUILD/diff_cover-9.0.0
configfile: pyproject.toml
plugins: forked-1.6.0, hypothesis-6.100.0, mock-3.14.0, benchmark-4.0.0, timeout-2.3.1, flaky-3.8.1, subprocess-1.5.0, flake8-1.1.1, datadir-1.5.0
collected 1 item

tests/test_violations_reporter.py --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=33582, si_uid=1000, si_status=1, si_utime=13 /* 0.13 s */, si_stime=2 /* 0.02 s */} ---
F                                                                                                                                                   [100%]

========================================================================================= FAILURES ==========================================================================================
__________________________________________________________________ TestFlake8QualityReporterTest.test_file_does_not_exist ___________________________________________________________________

self = <tests.test_violations_reporter.TestFlake8QualityReporterTest object at 0x7fb3bbd00940>

    @pytest.mark.disable_all_files_exist
    def test_file_does_not_exist(self):
        quality = QualityReporter(flake8_driver)
        file_paths = ["ajshdjlasdhajksdh.py"]
        # Expect that we get no results because that file does not exist
        for path in file_paths:
>           result = quality.violations(path)

tests/test_violations_reporter.py:1109:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <diff_cover.violationsreporters.base.QualityReporter object at 0x7fb3bbd009a0>, src_path = 'ajshdjlasdhajksdh.py'

    def violations(self, src_path):
        """
        Return a list of Violations recorded in `src_path`.
        """
        if not any(src_path.endswith(ext) for ext in self.driver.supported_extensions):
            return []
        if src_path not in self.violations_dict:
            if self.reports:
                self.violations_dict = self.driver.parse_reports(self.reports)
            else:
                if self.driver_tool_installed is None:
                    self.driver_tool_installed = self.driver.installed()
                if not self.driver_tool_installed:
>                   raise OSError(f"{self.driver.name} is not installed")
E                   OSError: flake8 is not installed

diff_cover/violationsreporters/base.py:160: OSError
================================================================================== short test summary info ==================================================================================
FAILED tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist - OSError: flake8 is not installed
===================================================================================== 1 failed in 1.61s =====================================================================================
+++ exited with 1 +++

As you see strace does not show any traces of execve() after pytest execution calls 🤔

@kloczek
Copy link
Author

kloczek commented Apr 17, 2024

Corrected test. I forgot about -f in strace params (trace in forked processes.
Now it shows:

+ strace -fe trace=execve /usr/bin/pytest -ra -m 'not network' tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist
execve("/usr/bin/pytest", ["/usr/bin/pytest", "-ra", "-m", "not network", "tests/test_violations_reporter.p"...], 0x7ffcef4cf390 /* 63 vars */) = 0
strace: Process 36146 attached
[pid 36146] execve("/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/bin/git", ["git", "rev-parse", "--git-dir"], 0x7ffd15933650 /* 63 vars */) = -1 ENOENT (No such file or directory)
[pid 36146] execve("/usr/bin/git", ["git", "rev-parse", "--git-dir"], 0x7ffd15933650 /* 63 vars */) = 0
[pid 36146] +++ exited with 128 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=36146, si_uid=1000, si_status=128, si_utime=0, si_stime=0} ---
strace: Process 36147 attached
[pid 36147] execve("/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/bin/hg", ["hg", "path", "default"], 0x7ffd15933650 /* 63 vars */) = -1 ENOENT (No such file or directory)
[pid 36147] execve("/usr/bin/hg", ["hg", "path", "default"], 0x7ffd15933650 /* 63 vars */) = -1 ENOENT (No such file or directory)
[pid 36147] execve("/usr/sbin/hg", ["hg", "path", "default"], 0x7ffd15933650 /* 63 vars */) = -1 ENOENT (No such file or directory)
[pid 36147] execve("/usr/local/sbin/hg", ["hg", "path", "default"], 0x7ffd15933650 /* 63 vars */) = -1 ENOENT (No such file or directory)
[pid 36147] +++ exited with 255 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=36147, si_uid=1000, si_status=255, si_utime=0, si_stime=0} ---
strace: Process 36148 attached
[pid 36148] execve("/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/bin/file", ["file", "-b", "/usr/bin/python"], 0x55f6303ae080 /* 64 vars */) = -1 ENOENT (No such file or directory)
[pid 36148] execve("/usr/bin/file", ["file", "-b", "/usr/bin/python"], 0x55f6303ae080 /* 64 vars */) = 0
[pid 36148] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=36148, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0
benchmark: 4.0.0 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /home/tkloczko/rpmbuild/BUILD/diff_cover-9.0.0
configfile: pyproject.toml
plugins: forked-1.6.0, hypothesis-6.100.0, mock-3.14.0, benchmark-4.0.0, timeout-2.3.1, flaky-3.8.1, subprocess-1.5.0, flake8-1.1.1, datadir-1.5.0
collected 1 item

tests/test_violations_reporter.py strace: Process 36149 attached
[pid 36149] execve("/home/tkloczko/rpmbuild/BUILDROOT/python-diff-cover-9.0.0-2.fc37.x86_64/usr/bin/flake8", ["flake8", "--version"], 0x55f6303c2c70 /* 64 vars */) = -1 ENOENT (No such file or directory)
[pid 36149] execve("/usr/bin/flake8", ["flake8", "--version"], 0x55f6303c2c70 /* 64 vars */) = 0
[pid 36149] +++ exited with 1 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=36149, si_uid=1000, si_status=1, si_utime=21 /* 0.21 s */, si_stime=4 /* 0.04 s */} ---
F                                                                                                                                                   [100%]

========================================================================================= FAILURES ==========================================================================================
__________________________________________________________________ TestFlake8QualityReporterTest.test_file_does_not_exist ___________________________________________________________________

self = <tests.test_violations_reporter.TestFlake8QualityReporterTest object at 0x7f492c1004f0>

    @pytest.mark.disable_all_files_exist
    def test_file_does_not_exist(self):
        quality = QualityReporter(flake8_driver)
        file_paths = ["ajshdjlasdhajksdh.py"]
        # Expect that we get no results because that file does not exist
        for path in file_paths:
>           result = quality.violations(path)

tests/test_violations_reporter.py:1109:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <diff_cover.violationsreporters.base.QualityReporter object at 0x7f492c1004c0>, src_path = 'ajshdjlasdhajksdh.py'

    def violations(self, src_path):
        """
        Return a list of Violations recorded in `src_path`.
        """
        if not any(src_path.endswith(ext) for ext in self.driver.supported_extensions):
            return []
        if src_path not in self.violations_dict:
            if self.reports:
                self.violations_dict = self.driver.parse_reports(self.reports)
            else:
                if self.driver_tool_installed is None:
                    self.driver_tool_installed = self.driver.installed()
                if not self.driver_tool_installed:
>                   raise OSError(f"{self.driver.name} is not installed")
E                   OSError: flake8 is not installed

diff_cover/violationsreporters/base.py:160: OSError
================================================================================== short test summary info ==================================================================================
FAILED tests/test_violations_reporter.py::TestFlake8QualityReporterTest::test_file_does_not_exist - OSError: flake8 is not installed
===================================================================================== 1 failed in 2.11s =====================================================================================
+++ exited with 1 +++
No traces of executing `flake8` and why this unit is trying to execute git, hg and file is another mystery 😋 🙄

@kloczek
Copy link
Author

kloczek commented Apr 17, 2024

Ops .. sorry ..

[pid 36149] execve("/usr/bin/flake8", ["flake8", "--version"], 0x55f6303c2c70 /* 64 vars */) = 0

but this execution returns 0 exit code 🤔

@Bachmann1234
Copy link
Owner

git, hg, and file could be any of a bunch of setup and fixture stuff...

Now the flake8 --version call returning 0 is very interesting.... and surprising

So we know flake8 is a regex based driver (so no custom stuff going on)

flake8_driver = RegexBasedDriver(
name="flake8",
supported_extensions=["py"],
command=["flake8"],
# Match lines of the form:
# new_file.py:1:17: E231 whitespace
expression=r"^([^:]+):(\d+):(?:\d+): ([a-zA-Z]+\d+.*)$",
command_to_check_install=["flake8", "--version"],
# flake8 exit code is 1 if there are violations
# http://flake8.pycqa.org/en/latest/user/invocation.html
exit_codes=[0, 1],
)

This is the function being called there

return run_command_for_code(self.command_to_check_install) == 0

That function is pretty simple.. if the process return code is 0 then I feel like that must mean this branch got hit, otherwise it would have returned process.returncode would have returned 0

But ill try and find some time tonight to look closer at this test to verify my assumptions about how this traces out are correct.

@kloczek
Copy link
Author

kloczek commented Apr 17, 2024

Am I right thar you are suggesting that to run this test it needs to b installed some flake8 extension? 🤔

My questions about why at all this needs to be executed seem still is valid.
What do you think about that? 🙄

@Bachmann1234
Copy link
Owner

you should not need anything thats not already defined in the toml. You can see githubs action run this build regularly.

flake8 is executed because this is an integration test and mocks would make assumptions about how the tool runs that could be changed over time as versions shift.

If you really wanna dig into whats happening here I suggest editing the lines I suggested in the installed lib and running the test. That way you can see if there is a better error

@kloczek
Copy link
Author

kloczek commented Apr 20, 2024

Again .. executed flake8 script returns 0 status.

@Bachmann1234
Copy link
Owner

Again .. executed flake8 script returns 0 status.

I understand that block of code is either hitting a filenotfound exception or something else is happening.

Whatever is happening is in that block of code and the only way I know to move forward on this is to print stuff in there and see what comes out

@Bachmann1234
Copy link
Owner

Because despite what your test did that function returned 1 at least that's what the test output is implying

1 similar comment
@Bachmann1234
Copy link
Owner

Because despite what your test did that function returned 1 at least that's what the test output is implying

@kloczek
Copy link
Author

kloczek commented Apr 20, 2024

If you have any propositions of some diagnostics please let mi know.

@Bachmann1234
Copy link
Owner

If you have any propositions of some diagnostics please let mi know.

Earlier I suggested sticking a couple of print lines in that function. So that and remove the catch of the filenotfound exception.

That should print out any output from running the command (if any) and if the exception being thrown (which at this point seems more likely)maybe it will provide more context on why.

@kloczek
Copy link
Author

kloczek commented Apr 20, 2024

Honestly .. I have no idea where I can put those lines 😞

@Bachmann1234
Copy link
Owner

Bachmann1234 commented Apr 20, 2024

I traced though the code path earlier

Take this function

def run_command_for_code(command):
"""
Returns command's exit code.
"""
try:
process = subprocess.Popen(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
process.communicate()
except FileNotFoundError:
return 1
return process.returncode

And replace it with this version

def run_command_for_code(command):
    """
    Returns command's exit code.
    """
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = process.communicate()
    print(stdin)
    print(stout)
    return process.returncode

See if the failure output is more interesting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants