Skip to content

Commit

Permalink
Support pytest8: mokey pathing odoo test python modue using odoo.addo…
Browse files Browse the repository at this point in the history
…ns namespace
  • Loading branch information
petrus-v committed Oct 3, 2024
1 parent c77b28e commit ed297e6
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 86 deletions.
97 changes: 12 additions & 85 deletions pytest_odoo.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import threading
from pathlib import Path
from typing import Optional

from _pytest.config import Config
import _pytest
import _pytest._py.error as error
import _pytest.python
Expand Down Expand Up @@ -140,94 +140,21 @@ def enable_odoo_test_flag():
odoo.tools.config['test_enable'] = False


# Original code of xmo-odoo:
# https://github.com/odoo-dev/odoo/commit/95a131b7f4eebc6e2c623f936283153d62f9e70f
class OdooTestModule(_pytest.python.Module):
""" Should only be invoked for paths inside Odoo addons
"""

def _importtestmodule(self):
# copy/paste/modified from original: removed sys.path injection &
# added Odoo module prefixing so import within modules is correct
try:
pypkgpath = self.fspath.pypkgpath()
pkgroot = pypkgpath.dirpath()
sep = self.fspath.sep
names = self.fspath.new(ext="").relto(pkgroot).split(sep)
if names[-1] == "__init__":
names.pop()
modname = ".".join(names)
# for modules in odoo/addons, since there is a __init__ the
# module name is already fully qualified (maybe?)
if (not modname.startswith('odoo.addons.')
and modname != 'odoo.addons'
and modname != 'odoo'):
modname = 'odoo.addons.' + modname

__import__(modname)
mod = sys.modules[modname]
if self.fspath.basename == "__init__.py":
# we don't check anything as we might
# we in a namespace package ... too icky to check
return mod
modfile = mod.__file__
if modfile[-4:] in ('.pyc', '.pyo'):
modfile = modfile[:-1]
elif modfile.endswith('$py.class'):
modfile = modfile[:-9] + '.py'
if modfile.endswith(os.path.sep + "__init__.py"):
if self.fspath.basename != "__init__.py":
modfile = modfile[:-12]
try:
issame = self.fspath.samefile(modfile)
except error.ENOENT:
issame = False
if not issame:
raise self.fspath.ImportMismatchError(modname, modfile, self)
except SyntaxError as e:
raise self.CollectError(
ExceptionInfo.from_current().getrepr(style="short")
) from e
except self.fspath.ImportMismatchError:
e = sys.exc_info()[1]
raise self.CollectError(
"import file mismatch:\n"
"imported module %r has this __file__ attribute:\n"
" %s\n"
"which is not the same as the test file we want to collect:\n"
" %s\n"
"HINT: remove __pycache__ / .pyc files and/or use a "
"unique basename for your test file modules" % e.args
)
self.config.pluginmanager.consider_module(mod)
return mod

def __repr__(self):
return "<Module %r>" % (getattr(self, "name", None), )


class OdooTestPackage(_pytest.python.Package, OdooTestModule):
"""Package with odoo module lookup.
original_resolve_pkg_root_and_module_name = _pytest.pathlib.resolve_pkg_root_and_module_name

Any python module inside the package will be imported with
the prefix `odoo.addons`.
def resolve_pkg_root_and_module_name(
path: Path, *, consider_namespace_packages: bool = False
) -> "tuple[Path, str]":
pkg_root, module_name = original_resolve_pkg_root_and_module_name(path, consider_namespace_packages=consider_namespace_packages)

This class is used to prevent loading odoo modules in duplicate,
which happens if a module is loaded with and without the prefix.
"""
if not module_name.startswith("odoo.addons"):
manifest = _find_manifest_path(path)
if manifest and manifest.parent.name == module_name.split(".",1)[0]:
module_name = "odoo.addons." + module_name
return pkg_root, module_name

def __repr__(self):
return "<Package %r>" % (getattr(self, "name", None), )


def pytest_pycollect_makemodule(module_path, path, parent):
if not _find_manifest_path(module_path):
return None
if path.basename == "__init__.py":
return OdooTestPackage.from_parent(parent, path=Path(path))
else:
return OdooTestModule.from_parent(parent, path=Path(path))

_pytest.pathlib.resolve_pkg_root_and_module_name= resolve_pkg_root_and_module_name

def _find_manifest_path(collection_path: Path) -> Path:
"""Try to locate an Odoo manifest file in the collection path."""
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
include_package_data=True,
platforms='any',
install_requires=[
'pytest>=7.2.0,<8.0.0',
"pytest>=8"
],
setup_requires=[
'setuptools_scm',
Expand Down

0 comments on commit ed297e6

Please sign in to comment.