47 lines
2.1 KiB
Python
47 lines
2.1 KiB
Python
# this is a hack to monkey patch pytest so it handles tests inside namespace packages without __init__.py properly
|
|
# without it, pytest can't discover the package root for some reason
|
|
# also see https://github.com/karlicoss/pytest_namespace_pkgs for more
|
|
|
|
import os
|
|
import pathlib
|
|
from typing import Optional
|
|
|
|
import _pytest.main
|
|
import _pytest.pathlib
|
|
|
|
# we consider all dirs in repo/ to be namespace packages
|
|
root_dir = pathlib.Path(__file__).absolute().parent.resolve() # / 'src'
|
|
assert root_dir.exists(), root_dir
|
|
|
|
# TODO assert it contains package name?? maybe get it via setuptools..
|
|
|
|
namespace_pkg_dirs = [str(d) for d in root_dir.iterdir() if d.is_dir()]
|
|
|
|
# resolve_package_path is called from _pytest.pathlib.import_path
|
|
# takes a full abs path to the test file and needs to return the path to the 'root' package on the filesystem
|
|
resolve_pkg_path_orig = _pytest.pathlib.resolve_package_path
|
|
def resolve_package_path(path: pathlib.Path) -> Optional[pathlib.Path]:
|
|
result = path # search from the test file upwards
|
|
for parent in result.parents:
|
|
if str(parent) in namespace_pkg_dirs:
|
|
return parent
|
|
if os.name == 'nt':
|
|
# ??? for some reason on windows it is trying to call this against conftest? but not on linux/osx
|
|
if path.name == 'conftest.py':
|
|
return resolve_pkg_path_orig(path)
|
|
raise RuntimeError("Couldn't determine path for ", path)
|
|
_pytest.pathlib.resolve_package_path = resolve_package_path
|
|
|
|
|
|
# without patching, the orig function returns just a package name for some reason
|
|
# (I think it's used as a sort of fallback)
|
|
# so we need to point it at the absolute path properly
|
|
# not sure what are the consequences.. maybe it wouldn't be able to run against installed packages? not sure..
|
|
search_pypath_orig = _pytest.main.search_pypath
|
|
def search_pypath(module_name: str) -> str:
|
|
mpath = root_dir / module_name.replace('.', os.sep)
|
|
if not mpath.is_dir():
|
|
mpath = mpath.with_suffix('.py')
|
|
assert mpath.exists(), mpath # just in case
|
|
return str(mpath)
|
|
_pytest.main.search_pypath = search_pypath
|