Setting config.sources with True raises AttributeError

Issue #565 wontfix
John Vandenberg
created an issue

Recently I have started seeing a problem on our openSUSE Tumbleweed docker build repo while running python3 -m pytest --cov --cov-fail-under=100 on the https://github.com/coala/coala/ repo.

The traceback is huge:

Traceback (most recent call last):
  File "/usr/lib64/python3.5/runpy.py", line 170, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib64/python3.5/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/usr/lib/python3.5/site-packages/pytest.py", line 17, in <module>
    raise SystemExit(pytest.main())
  File "/usr/lib/python3.5/site-packages/_pytest/config.py", line 47, in main
    config = _prepareconfig(args, plugins)
  File "/usr/lib/python3.5/site-packages/_pytest/config.py", line 156, in _prepareconfig
    pluginmanager=pluginmanager, args=args)
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 745, in __call__
    return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 339, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 334, in <lambda>
    _MultiCall(methods, kwargs, hook.spec_opts).execute()
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 613, in execute
    return _wrapped_call(hook_impl.function(*args), self.execute)
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 250, in _wrapped_call
    wrap_controller.send(call_outcome)
  File "/usr/lib/python3.5/site-packages/_pytest/helpconfig.py", line 32, in pytest_cmdline_parse
    config = outcome.get_result()
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 279, in get_result
    raise ex[1].with_traceback(ex[2])
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 265, in __init__
    self.result = func()
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 614, in execute
    res = hook_impl.function(*args)
  File "/usr/lib/python3.5/site-packages/_pytest/config.py", line 923, in pytest_cmdline_parse
    self.parse(args)
  File "/usr/lib/python3.5/site-packages/_pytest/config.py", line 1080, in parse
    self._preparse(args, addopts=addopts)
  File "/usr/lib/python3.5/site-packages/_pytest/config.py", line 1051, in _preparse
    args=args, parser=self._parser)
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 745, in __call__
    return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 339, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 334, in <lambda>
    _MultiCall(methods, kwargs, hook.spec_opts).execute()
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 613, in execute
    return _wrapped_call(hook_impl.function(*args), self.execute)
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 254, in _wrapped_call
    return call_outcome.get_result()
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 279, in get_result
    raise ex[1].with_traceback(ex[2])
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 265, in __init__
    self.result = func()
  File "/usr/lib/python3.5/site-packages/_pytest/vendored_packages/pluggy.py", line 614, in execute
    res = hook_impl.function(*args)
  File "/usr/lib/python3.5/site-packages/pytest_cov/plugin.py", line 95, in pytest_load_initial_conftests
    plugin = CovPlugin(ns, early_config.pluginmanager)
  File "/usr/lib/python3.5/site-packages/pytest_cov/plugin.py", line 150, in __init__
    self.start(engine.Central)
  File "/usr/lib/python3.5/site-packages/pytest_cov/plugin.py", line 171, in start
    self.cov_controller.start()
  File "/usr/lib/python3.5/site-packages/pytest_cov/engine.py", line 141, in start
    self.cov.erase()
  File "/usr/lib/python3.5/site-packages/coverage/control.py", line 727, in erase
    self._init()
  File "/usr/lib/python3.5/site-packages/coverage/control.py", line 246, in _init
    self.source.append(files.canonical_filename(src))
  File "/usr/lib/python3.5/site-packages/coverage/files.py", line 61, in canonical_filename
    if not os.path.isabs(filename):
  File "/usr/lib64/python3.5/posixpath.py", line 64, in isabs
    return s.startswith(sep)
AttributeError: 'bool' object has no attribute 'startswith'

It doesnt cause py.test to fail, but it cant be good.

The most recent build is https://travis-ci.org/jayvdb/docker-coala-base/builds/202465224 pytest reports its environment as environment:

  • platform linux -- Python 3.5.1, pytest-3.0.6, py-1.4.32, pluggy-0.4.0
  • plugins: xdist-1.15.0, timeout-1.2.0, mock-1.5.0, env-0.6.0, cov-2.4.0

And the coverage installed is coverage-4.3.4-cp35-cp35m-manylinux1_x86_64.whl

Recent builds also broken:


A build 10 days ago and 11 days ago didnt have the problem, with the same environment.

  • platform linux -- Python 3.5.1, pytest-3.0.6, py-1.4.32, pluggy-0.4.0
  • plugins: xdist-1.15.0, timeout-1.2.0, mock-1.5.0, env-0.6.0, cov-2.4.0

It installed coverage-4.3.4-cp35-cp35m-manylinux1_x86_64.whl


However ~16 days ago, the problem didn't occur, and pytest reported an identical environment.

  • platform linux -- Python 3.5.1, pytest-3.0.6, py-1.4.32, pluggy-0.4.0
  • plugins: xdist-1.15.0, timeout-1.2.0, mock-1.5.0, env-0.6.0, cov-2.4.0

Earlier in that build, coverage-4.3.4-cp35-cp35m-manylinux1_x86_64.whl was installed.

Another build around 16 days ago, also no problem: https://travis-ci.org/coala/docker-coala-base/builds/197208482

Unfortunately, our builds from 16 days ago to one month ago were broken earlier in the test sequence, so I have no prior data to work from, and I never saw this before then.

Comments (10)

  1. John Vandenberg reporter

    It doesnt cause py.test to fail, but it cant be good.

    Actually it is causing pytest to fail. The pytest that follows in the output is for coala-bears. I can reproduce it on my system, so I am investigating.

  2. John Vandenberg reporter

    The upstream problem is https://github.com/pytest-dev/pytest-cov/issues/151

    This causes the local problem as it sets CovergeConfig.config.source = [True, True] .

    Then it fails because there isnt any checking for bool's around here: https://bitbucket.org/ned/coveragepy/src/195d4e89d11af857d73d3e7a1694c4a1926d0599/coverage/control.py?at=default&fileviewer=file-view-default#control.py-227

    One way to avoid explicit type checking could be to check if the source element exists before asking if it is a directory.

    And that is sort-of what has recently been done; this fixes the problem in that part of the code: https://bitbucket.org/ned/coveragepy/commits/f69876c591ba4db8929404bb43f616604917e726

  3. John Vandenberg reporter

    part of the problem is:

    >>> os.path.exists(True)
    True
    

    I suggest adding package name validation, with basic type sanity checking, into this sequence:

                if os.path.isdir(src):
                    self.source.append(files.canonical_filename(src))
                else:
                    check_package_name(src)
                    self.source_pkgs.append(src)
    

    Where check_package_name(src) raises an ValueError (or similar) exception if a valid package name cant be obtained from the src value.

  4. Ned Batchelder repo owner

    If I understand this, it's that pytest-cov is setting source to a nonsensical value. I don't have much interest in writing defensive code to protect against that. The bug should be fixed in pytest-cov. Unless I've misunderstood?

  5. Ned Batchelder repo owner

    Yes, it would help diagnose this particular mis-use of the API. How many do I add, and where? It's a slippery slope to type-checking everything, which I am not going to do :)

  6. John Vandenberg reporter

    It is definitely a pytest-cov problem, and this issue can be closed as that.

    The suggestion to add check_package_name is to avoid only adding silly type checking, and instead 1. resolve the package name to be a string whilst parsing the config 2. do deeper analysis on the string to confirm it is actually a valid package name, so that a meaningful error message can be emitted if it is not (and the error be emitted from the config area of the code, rather than failures occurring much later).

    As a simple example, / or \\ occurring in the package name probably means the user has mis-typed a directory (isdir returned False) or they misunderstood how to write a package name.

  7. Log in to comment