From f456e376b99722f8e094ac52698e0fa9252ae686 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Sun, 21 Nov 2010 17:43:18 +0100 Subject: [PATCH] refine tmpdir handling and docs - clear tmpdir specified with --basetemp - remove config.mktmp and config.getbasetemp methods --- _pytest/config.py | 27 +---------------- _pytest/pytester.py | 12 ++++++-- _pytest/tmpdir.py | 61 +++++++++++++++++++++++++++++++++----- doc/index.txt | 4 +-- doc/tmpdir.txt | 10 ++----- testing/acceptance_test.py | 10 ------- testing/test_config.py | 27 ----------------- testing/test_tmpdir.py | 50 ++++++++++++++++++++++++++++++- tox.ini | 1 - 9 files changed, 116 insertions(+), 86 deletions(-) diff --git a/_pytest/config.py b/_pytest/config.py index ba929eb28..ff2d0478d 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -1,4 +1,4 @@ -""" command line configuration, ini-file and conftest.py processing. """ +""" command line options, ini-file and conftest.py processing. """ import py import sys, os @@ -245,8 +245,6 @@ class CmdOptions(object): class Config(object): """ access to configuration values, pluginmanager and plugin hooks. """ - basetemp = None - def __init__(self, pluginmanager=None): #: command line option values, usually added via parser.addoption(...) #: or parser.getgroup(...).addoption(...) calls @@ -330,29 +328,6 @@ class Config(object): args.append(py.std.os.getcwd()) self.args = args - def ensuretemp(self, string, dir=True): - return self.getbasetemp().ensure(string, dir=dir) - - def getbasetemp(self): - if self.basetemp is None: - basetemp = self.option.basetemp - if basetemp: - basetemp = py.path.local(basetemp) - if not basetemp.check(dir=1): - basetemp.mkdir() - else: - basetemp = py.path.local.make_numbered_dir(prefix='pytest-') - self.basetemp = basetemp - return self.basetemp - - def mktemp(self, basename, numbered=False): - basetemp = self.getbasetemp() - if not numbered: - return basetemp.mkdir(basename) - else: - return py.path.local.make_numbered_dir(prefix=basename, - keep=0, rootdir=basetemp, lock_timeout=None) - def getini(self, name): """ return configuration value from an ini file. If the specified name hasn't been registered through a prior ``parse.addini`` diff --git a/_pytest/pytester.py b/_pytest/pytester.py index 35d05b0af..06f0c095b 100644 --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -173,7 +173,7 @@ class TmpTestdir: self.Config = request.config.__class__ self._pytest = request.getfuncargvalue("_pytest") # XXX remove duplication with tmpdir plugin - basetmp = request.config.ensuretemp("testdir") + basetmp = request.config._tmpdirhandler.ensuretemp("testdir") name = request.function.__name__ for i in range(100): try: @@ -350,7 +350,12 @@ class TmpTestdir: if not args: args = (self.tmpdir,) config = self.config_preparse() - args = list(args) + ["--basetemp=%s" % self.tmpdir.dirpath('basetemp')] + args = list(args) + for x in args: + if str(x).startswith('--basetemp'): + break + else: + args.append("--basetemp=%s" % self.tmpdir.dirpath('basetemp')) config.parse(args) return config @@ -361,7 +366,8 @@ class TmpTestdir: oldconfig = getattr(py.test, 'config', None) try: c = py.test.config = self.Config() - c.basetemp = oldconfig.mktemp("reparse", numbered=True) + c.basetemp = py.path.local.make_numbered_dir(prefix="reparse", + keep=0, rootdir=self.tmpdir, lock_timeout=None) c.parse(args) return c finally: diff --git a/_pytest/tmpdir.py b/_pytest/tmpdir.py index 738304442..9eab52d54 100644 --- a/_pytest/tmpdir.py +++ b/_pytest/tmpdir.py @@ -1,17 +1,61 @@ """ support for providing temporary directories to test functions. """ import pytest, py +from _pytest.monkeypatch import monkeypatch -def pytest_configure(config): - def ensuretemp(string, dir=1): +class TempdirHandler: + def __init__(self, config): + self.config = config + self.trace = config.trace.get("tmpdir") + + def ensuretemp(self, string, dir=1): """ (deprecated) return temporary directory path with the given string as the trailing part. It is usually - better to use the 'tmpdir' function argument which will - take care to provide empty unique directories for each - test call even if the test is called multiple times. + better to use the 'tmpdir' function argument which + provides an empty unique-per-test-invocation directory + and is guaranteed to be empty. """ #py.log._apiwarn(">1.1", "use tmpdir function argument") - return config.ensuretemp(string, dir=dir) - pytest.ensuretemp = ensuretemp + return self.getbasetemp().ensure(string, dir=dir) + + def mktemp(self, basename, numbered=True): + basetemp = self.getbasetemp() + if not numbered: + p = basetemp.mkdir(basename) + else: + p = py.path.local.make_numbered_dir(prefix=basename, + keep=0, rootdir=basetemp, lock_timeout=None) + self.trace("mktemp", p) + return p + + def getbasetemp(self): + """ return base temporary directory. """ + try: + return self._basetemp + except AttributeError: + basetemp = self.config.option.basetemp + if basetemp: + basetemp = py.path.local(basetemp) + if basetemp.check(): + basetemp.remove() + basetemp.mkdir() + else: + basetemp = py.path.local.make_numbered_dir(prefix='pytest-') + self._basetemp = t = basetemp + self.trace("new basetemp", t) + return t + + def finish(self): + self.trace("finish") + +def pytest_configure(config): + config._mp = mp = monkeypatch() + t = TempdirHandler(config) + mp.setattr(config, '_tmpdirhandler', t, raising=False) + mp.setattr(pytest, 'ensuretemp', t.ensuretemp, raising=False) + +def pytest_unconfigure(config): + config._tmpdirhandler.finish() + config._mp.undo() def pytest_funcarg__tmpdir(request): """return a temporary directory path object @@ -22,5 +66,6 @@ def pytest_funcarg__tmpdir(request): """ name = request._pyfuncitem.name name = py.std.re.sub("[\W]", "_", name) - x = request.config.mktemp(name, numbered=True) + x = request.config._tmpdirhandler.mktemp(name, numbered=True) return x.realpath() + diff --git a/doc/index.txt b/doc/index.txt index 544bf8309..c42176950 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -5,8 +5,8 @@ py.test: no-boilerplate testing with Python .. note:: version 2.0 introduces ``pytest`` as the main Python import name - but for compatibility reasons you can continue to use ``import py`` - and ``py.test.XYZ`` to access :ref:`pytest helpers` in your test code. + in examples but you can continue to use ``import py`` and + ``py.test.XYZ`` to access :ref:`pytest helpers` in your test code. Welcome to ``py.test`` documentation: diff --git a/doc/tmpdir.txt b/doc/tmpdir.txt index f515337ed..7461c8d17 100644 --- a/doc/tmpdir.txt +++ b/doc/tmpdir.txt @@ -54,18 +54,12 @@ Running this would result in a passed test except for the last the default base temporary directory ----------------------------------------------- -.. - You can create directories by calling one of two methods - on the config object: - - ``config.mktemp(basename)``: create and return a new tempdir - - ``config.ensuretemp(basename)``: create or return a new tempdir - Temporary directories are by default created as sub directories of -the system temporary directory. The name will be ``pytest-NUM`` where +the system temporary directory. The base name will be ``pytest-NUM`` where ``NUM`` will be incremenated with each test run. Moreover, entries older than 3 temporary directories will be removed. -You can override the default temporary directory logic and set it like this:: +You can override the default temporary directory setting like this:: py.test --basetemp=mydir diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index dab0654a2..42c133f98 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -33,16 +33,6 @@ class TestGeneralUsage: '*1 passed*', ]) - def test_basetemp(self, testdir): - mytemp = testdir.tmpdir.mkdir("mytemp") - p = testdir.makepyfile(""" - def test_1(pytestconfig): - pytestconfig.getbasetemp().ensure("hello") - """) - result = testdir.runpytest(p, '--basetemp=%s' % mytemp) - assert result.ret == 0 - assert mytemp.join('hello').check() - def test_assertion_magic(self, testdir): p = testdir.makepyfile(""" def test_this(): diff --git a/testing/test_config.py b/testing/test_config.py index cc65e752a..a15e6001a 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -81,33 +81,6 @@ class TestConfigCmdlineParsing: pytest.raises(AssertionError, "config.parse([])") -class TestConfigTmpdir: - def test_getbasetemp(self, testdir): - config = testdir.Config() - config.basetemp = "hello" - config.getbasetemp() == "hello" - - def test_mktemp(self, testdir): - config = testdir.Config() - config.basetemp = testdir.mkdir("hello") - tmp = config.mktemp("world") - assert tmp.relto(config.basetemp) == "world" - tmp = config.mktemp("this", numbered=True) - assert tmp.relto(config.basetemp).startswith("this") - tmp2 = config.mktemp("this", numbered=True) - assert tmp2.relto(config.basetemp).startswith("this") - assert tmp2 != tmp - - def test_reparse(self, testdir): - config2 = testdir.reparseconfig([]) - config3 = testdir.reparseconfig([]) - assert config2.getbasetemp() != config3.getbasetemp() - assert not config2.getbasetemp().relto(config3.getbasetemp()) - assert not config3.getbasetemp().relto(config2.getbasetemp()) - - def test_reparse_filename_too_long(self, testdir): - config = testdir.reparseconfig(["--basetemp=%s" % ("123"*300)]) - class TestConfigAPI: def test_config_trace(self, testdir): diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 9fe09f3f0..0f5ec1521 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -1,6 +1,6 @@ import py, pytest -from _pytest.tmpdir import pytest_funcarg__tmpdir +from _pytest.tmpdir import pytest_funcarg__tmpdir, TempdirHandler from _pytest.python import FuncargRequest def test_funcarg(testdir): @@ -27,3 +27,51 @@ def test_ensuretemp(recwarn): assert d1 == d2 assert d1.check(dir=1) +class TestTempdirHandler: + def test_mktemp(self, testdir): + config = testdir.Config() + config.option.basetemp = testdir.mkdir("hello") + t = TempdirHandler(config) + tmp = t.mktemp("world") + assert tmp.relto(t.getbasetemp()) == "world0" + tmp = t.mktemp("this") + assert tmp.relto(t.getbasetemp()).startswith("this") + tmp2 = t.mktemp("this") + assert tmp2.relto(t.getbasetemp()).startswith("this") + assert tmp2 != tmp + +class TestConfigTmpdir: + def test_getbasetemp_custom_removes_old(self, testdir): + p = testdir.tmpdir.join("xyz") + config = testdir.parseconfigure("--basetemp=xyz") + b = config._tmpdirhandler.getbasetemp() + assert b == p + h = b.ensure("hello") + config._tmpdirhandler.getbasetemp() + assert h.check() + config = testdir.parseconfigure("--basetemp=xyz") + b2 = config._tmpdirhandler.getbasetemp() + assert b2.check() + assert not h.check() + + def test_reparse(self, testdir): + config2 = testdir.reparseconfig([]) + config3 = testdir.reparseconfig([]) + assert config2.basetemp != config3.basetemp + assert not config2.basetemp.relto(config3.basetemp) + assert not config3.basetemp.relto(config2.basetemp) + + def test_reparse_filename_too_long(self, testdir): + config = testdir.reparseconfig(["--basetemp=%s" % ("123"*300)]) + + +def test_basetemp(testdir): + mytemp = testdir.tmpdir.mkdir("mytemp") + p = testdir.makepyfile(""" + import pytest + def test_1(): + pytest.ensuretemp("hello") + """) + result = testdir.runpytest(p, '--basetemp=%s' % mytemp) + assert result.ret == 0 + assert mytemp.join('hello').check() diff --git a/tox.ini b/tox.ini index 37bac7162..5bd8183c2 100644 --- a/tox.ini +++ b/tox.ini @@ -66,4 +66,3 @@ minversion=2.0 plugins=pytester addopts= -rxf --pyargs --doctest-modules rsyncdirs=tox.ini pytest.py _pytest testing -