From 0365e5c3a0cf62cdf9328131ea05f7557f969d9e Mon Sep 17 00:00:00 2001 From: holger krekel Date: Wed, 2 Apr 2014 22:30:45 +0200 Subject: [PATCH] cleanup internal conftest handling and avoid the strange None entry in the conftest cache. (There is basically no reason to ask for conftestmodules without specifying a path.) --HG-- branch : conftest-clean --- _pytest/config.py | 66 ++++++++++++------------------------- _pytest/main.py | 2 +- testing/test_config.py | 42 ++++-------------------- testing/test_conftest.py | 70 +++++++++++++--------------------------- 4 files changed, 50 insertions(+), 130 deletions(-) diff --git a/_pytest/config.py b/_pytest/config.py index 066cd6624..cc958f675 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -477,7 +477,7 @@ class Conftest(object): self._try_load_conftest(current) def _try_load_conftest(self, anchor): - self._path2confmods[None] = self.getconftestmodules(anchor) + self.getconftestmodules(anchor) # let's also consider test* subdirs if anchor.check(dir=1): for x in anchor.listdir("test*"): @@ -486,10 +486,8 @@ class Conftest(object): def getconftestmodules(self, path): try: - clist = self._path2confmods[path] + return self._path2confmods[path] except KeyError: - if path is None: - raise ValueError("missing default conftest.") clist = [] for parent in path.parts(): if self._confcutdir and self._confcutdir.relto(parent): @@ -498,16 +496,11 @@ class Conftest(object): if conftestpath.check(file=1): clist.append(self.importconftest(conftestpath)) self._path2confmods[path] = clist - return clist + return clist - def rget(self, name, path=None): - mod, value = self.rget_with_confmod(name, path) - return value - - def rget_with_confmod(self, name, path=None): + def rget_with_confmod(self, name, path): modules = self.getconftestmodules(path) - modules.reverse() - for mod in modules: + for mod in reversed(modules): try: return mod, getattr(mod, name) except AttributeError: @@ -515,7 +508,6 @@ class Conftest(object): raise KeyError(name) def importconftest(self, conftestpath): - assert conftestpath.check(), conftestpath try: return self._conftestpath2mod[conftestpath] except KeyError: @@ -529,13 +521,10 @@ class Conftest(object): if path and path.relto(dirpath) or path == dirpath: assert mod not in mods mods.append(mod) - self._postimport(mod) + if self._onimport: + self._onimport(mod) return mod - def _postimport(self, mod): - if self._onimport: - self._onimport(mod) - return mod def _ensure_removed_sysmodule(modname): try: @@ -550,6 +539,7 @@ class CmdOptions(object): def __repr__(self): return "" %(self.__dict__,) +notset = object() FILE_OR_DIR = 'file_or_dir' class Config(object): """ access to configuration values, pluginmanager and plugin hooks. """ @@ -757,7 +747,7 @@ class Config(object): assert type is None return value - def _getconftest_pathlist(self, name, path=None): + def _getconftest_pathlist(self, name, path): try: mod, relroots = self._conftest.rget_with_confmod(name, path) except KeyError: @@ -771,47 +761,31 @@ class Config(object): l.append(relroot) return l - def _getconftest(self, name, path=None, check=False): - if check: - self._checkconftest(name) - return self._conftest.rget(name, path) - - def getoption(self, name): + def getoption(self, name, default=notset, skip=False): """ return command line option value. :arg name: name of the option. You may also specify the literal ``--OPT`` option instead of the "dest" option name. + :arg default: default value if no option of that name exists. + :arg skip: if True raise pytest.skip if not option exists. """ name = self._opt2dest.get(name, name) try: return getattr(self.option, name) except AttributeError: + if default is not notset: + return default + if skip: + py.test.skip("no %r option found" %(name,)) raise ValueError("no option named %r" % (name,)) def getvalue(self, name, path=None): - """ return command line option value. - - :arg name: name of the command line option - - (deprecated) if we can't find the option also lookup - the name in a matching conftest file. - """ - try: - return getattr(self.option, name) - except AttributeError: - return self._getconftest(name, path, check=False) + """ (deprecated, use getoption()) """ + return self.getoption(name) def getvalueorskip(self, name, path=None): - """ (deprecated) return getvalue(name) or call - pytest.skip if no value exists. """ - __tracebackhide__ = True - try: - val = self.getvalue(name, path) - if val is None: - raise KeyError(name) - return val - except KeyError: - py.test.skip("no %r value found" %(name,)) + """ (deprecated, use getoption(skip=True)) """ + return self.getoption(name, skip=True) def exists(path, ignore=EnvironmentError): try: diff --git a/_pytest/main.py b/_pytest/main.py index b4cea1ca0..4ba8253d7 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -144,7 +144,7 @@ def pytest_ignore_collect(path, config): p = path.dirpath() ignore_paths = config._getconftest_pathlist("collect_ignore", path=p) ignore_paths = ignore_paths or [] - excludeopt = config.getvalue("ignore") + excludeopt = config.getoption("ignore") if excludeopt: ignore_paths.extend([py.path.local(x) for x in excludeopt]) return path in ignore_paths diff --git a/testing/test_config.py b/testing/test_config.py index 11a57fa0c..524d60cac 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -89,20 +89,6 @@ class TestConfigAPI: assert len(l) == 1 assert l[0] == "hello [config]\n" - def test_config_getvalue_honours_conftest(self, testdir): - testdir.makepyfile(conftest="x=1") - testdir.mkdir("sub").join("conftest.py").write("x=2 ; y = 3") - config = testdir.parseconfig() - o = testdir.tmpdir - assert config.getvalue("x") == 1 - assert config.getvalue("x", o.join('sub')) == 2 - pytest.raises(KeyError, "config.getvalue('y')") - config = testdir.parseconfigure(str(o.join('sub'))) - assert config.getvalue("x") == 2 - assert config.getvalue("y") == 3 - assert config.getvalue("x", o) == 1 - pytest.raises(KeyError, 'config.getvalue("y", o)') - def test_config_getoption(self, testdir): testdir.makeconftest(""" def pytest_addoption(parser): @@ -130,34 +116,20 @@ class TestConfigAPI: "config.getvalueorskip('hello')") verbose = config.getvalueorskip("verbose") assert verbose == config.option.verbose - config.option.hello = None - try: - config.getvalueorskip('hello') - except KeyboardInterrupt: - raise - except: - excinfo = py.code.ExceptionInfo() - frame = excinfo.traceback[-2].frame - assert frame.code.name == "getvalueorskip" - assert frame.eval("__tracebackhide__") - def test_config_overwrite(self, testdir): - o = testdir.tmpdir - o.ensure("conftest.py").write("x=1") - config = testdir.parseconfig(str(o)) - assert config.getvalue('x') == 1 - config.option.x = 2 - assert config.getvalue('x') == 2 - config = testdir.parseconfig(str(o)) - assert config.getvalue('x') == 1 + def test_getoption(self, testdir): + config = testdir.parseconfig() + with pytest.raises(ValueError): + config.getvalue('x') + assert config.getoption("x", 1) == 1 def test_getconftest_pathlist(self, testdir, tmpdir): somepath = tmpdir.join("x", "y", "z") p = tmpdir.join("conftest.py") p.write("pathlist = ['.', %r]" % str(somepath)) config = testdir.parseconfigure(p) - assert config._getconftest_pathlist('notexist') is None - pl = config._getconftest_pathlist('pathlist') + assert config._getconftest_pathlist('notexist', path=tmpdir) is None + pl = config._getconftest_pathlist('pathlist', path=tmpdir) print(pl) assert len(pl) == 2 assert pl[0] == tmpdir diff --git a/testing/test_conftest.py b/testing/test_conftest.py index 09c21c027..96df19550 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -1,22 +1,17 @@ import py, pytest from _pytest.config import Conftest -def pytest_generate_tests(metafunc): - if "basedir" in metafunc.fixturenames: - metafunc.addcall(param="global") - metafunc.addcall(param="inpackage") -def pytest_funcarg__basedir(request): - def basedirmaker(request): - d = request.getfuncargvalue("tmpdir") - d.ensure("adir/conftest.py").write("a=1 ; Directory = 3") - d.ensure("adir/b/conftest.py").write("b=2 ; a = 1.5") - if request.param == "inpackage": - d.ensure("adir/__init__.py") - d.ensure("adir/b/__init__.py") - return d - return request.cached_setup( - lambda: basedirmaker(request), extrakey=request.param) +@pytest.fixture(scope="module", params=["global", "inpackage"]) +def basedir(request): + from _pytest.tmpdir import tmpdir + tmpdir = tmpdir(request) + tmpdir.ensure("adir/conftest.py").write("a=1 ; Directory = 3") + tmpdir.ensure("adir/b/conftest.py").write("b=2 ; a = 1.5") + if request.param == "inpackage": + tmpdir.ensure("adir/__init__.py") + tmpdir.ensure("adir/b/__init__.py") + return tmpdir def ConftestWithSetinitial(path): conftest = Conftest() @@ -33,17 +28,17 @@ def conftest_setinitial(conftest, args, confcutdir=None): class TestConftestValueAccessGlobal: def test_basic_init(self, basedir): conftest = Conftest() - conftest_setinitial(conftest, [basedir.join("adir")]) - assert conftest.rget("a") == 1 + p = basedir.join("adir") + assert conftest.rget_with_confmod("a", p)[1] == 1 def test_onimport(self, basedir): l = [] conftest = Conftest(onimport=l.append) - conftest_setinitial(conftest, [basedir.join("adir"), - '--confcutdir=%s' % basedir]) + adir = basedir.join("adir") + conftest_setinitial(conftest, [adir], confcutdir=basedir) assert len(l) == 1 - assert conftest.rget("a") == 1 - assert conftest.rget("b", basedir.join("adir", "b")) == 2 + assert conftest.rget_with_confmod("a", adir)[1] == 1 + assert conftest.rget_with_confmod("b", adir.join("b"))[1] == 2 assert len(l) == 2 def test_immediate_initialiation_and_incremental_are_the_same(self, basedir): @@ -57,37 +52,16 @@ class TestConftestValueAccessGlobal: conftest.getconftestmodules(basedir.join('b')) assert len(conftest._path2confmods) == snap1 + 2 - def test_default_has_lower_prio(self, basedir): - conftest = ConftestWithSetinitial(basedir.join("adir")) - assert conftest.rget('Directory') == 3 - #assert conftest.lget('Directory') == pytest.Directory - def test_value_access_not_existing(self, basedir): conftest = ConftestWithSetinitial(basedir) - pytest.raises(KeyError, lambda: conftest.rget('a')) - #pytest.raises(KeyError, "conftest.lget('a')") + with pytest.raises(KeyError): + conftest.rget_with_confmod('a', basedir) def test_value_access_by_path(self, basedir): conftest = ConftestWithSetinitial(basedir) - assert conftest.rget("a", basedir.join('adir')) == 1 - #assert conftest.lget("a", basedir.join('adir')) == 1 - assert conftest.rget("a", basedir.join('adir', 'b')) == 1.5 - #assert conftest.lget("a", basedir.join('adir', 'b')) == 1 - #assert conftest.lget("b", basedir.join('adir', 'b')) == 2 - #assert pytest.raises(KeyError, - # 'conftest.lget("b", basedir.join("a"))' - #) - - def test_value_access_with_init_one_conftest(self, basedir): - conftest = ConftestWithSetinitial(basedir.join('adir')) - assert conftest.rget("a") == 1 - #assert conftest.lget("a") == 1 - - def test_value_access_with_init_two_conftests(self, basedir): - conftest = ConftestWithSetinitial(basedir.join("adir", "b")) - conftest.rget("a") == 1.5 - #conftest.lget("a") == 1 - #conftest.lget("b") == 1 + adir = basedir.join("adir") + assert conftest.rget_with_confmod("a", adir)[1] == 1 + assert conftest.rget_with_confmod("a", adir.join("b"))[1] == 1.5 def test_value_access_with_confmod(self, basedir): startdir = basedir.join("adir", "b") @@ -111,7 +85,7 @@ def test_doubledash_considered(testdir): conf.join("conftest.py").ensure() conftest = Conftest() conftest_setinitial(conftest, [conf.basename, conf.basename]) - l = conftest.getconftestmodules(None) + l = conftest.getconftestmodules(conf) assert len(l) == 1 def test_issue151_load_all_conftests(testdir):