port interals of tmpdir to a basic pathlib implementation

this is still lacking locking and cleanup of the folders
This commit is contained in:
Ronny Pfannschmidt 2018-09-15 22:30:44 +02:00
parent 602e74c2a7
commit b48e23d54c
4 changed files with 109 additions and 47 deletions

View File

@ -20,7 +20,9 @@ repos:
- id: check-yaml - id: check-yaml
- id: debug-statements - id: debug-statements
exclude: _pytest/debugging.py exclude: _pytest/debugging.py
language_version: python3
- id: flake8 - id: flake8
language_version: python3
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v1.8.0 rev: v1.8.0
hooks: hooks:

View File

@ -156,7 +156,10 @@ def pytest_addoption(parser):
dest="basetemp", dest="basetemp",
default=None, default=None,
metavar="dir", metavar="dir",
help="base temporary directory for this test run.", help=(
"base temporary directory for this test run."
"(warning: this directory is removed if it exists)"
),
) )

View File

@ -6,17 +6,110 @@ import re
import pytest import pytest
import py import py
from _pytest.monkeypatch import MonkeyPatch from _pytest.monkeypatch import MonkeyPatch
from .compat import Path
import attr
import shutil
import tempfile
def make_numbered_dir(root, prefix):
l_prefix = prefix.lower()
def parse_num(p, cut=len(l_prefix)):
maybe_num = p.name[cut:]
try:
return int(maybe_num)
except ValueError:
return -1
for i in range(10):
# try up to 10 times to create the folder
max_existing = max(
(
parse_num(x)
for x in root.iterdir()
if x.name.lower().startswith(l_prefix)
),
default=-1,
)
new_number = max_existing + 1
new_path = root.joinpath("{}{}".format(prefix, new_number))
try:
new_path.mkdir()
except Exception:
pass
else:
return new_path
def make_numbered_dir_with_cleanup(root, prefix, keep, consider_lock_dead_after):
p = make_numbered_dir(root, prefix)
# todo cleanup
return p
@attr.s
class TempPathFactory(object):
"""docstring for ClassName"""
given_basetemp = attr.ib()
trace = attr.ib()
_basetemp = attr.ib(default=None)
@classmethod
def from_config(cls, config):
return cls(
given_basetemp=config.option.basetemp, trace=config.trace.get("tmpdir")
)
def mktemp(self, basename, numbered=True):
if not numbered:
p = self.getbasetemp().joinpath(basename)
p.mkdir()
else:
p = make_numbered_dir(root=self.getbasetemp(), prefix=basename)
self.trace("mktemp", p)
return p
def getbasetemp(self):
""" return base temporary directory. """
if self._basetemp is None:
if self.given_basetemp:
basetemp = Path(self.given_basetemp)
if basetemp.exists():
shutil.rmtree(str(basetemp))
basetemp.mkdir()
else:
temproot = Path(tempfile.gettempdir())
user = get_user()
if user:
# use a sub-directory in the temproot to speed-up
# make_numbered_dir() call
rootdir = temproot.joinpath("pytest-of-{}".format(user))
else:
rootdir = temproot
rootdir.mkdir(exist_ok=True)
basetemp = make_numbered_dir_with_cleanup(
prefix="pytest-",
root=rootdir,
keep=None,
consider_lock_dead_after=None,
)
self._basetemp = t = basetemp
self.trace("new basetemp", t)
return t
else:
return self._basetemp
@attr.s
class TempdirFactory(object): class TempdirFactory(object):
"""Factory for temporary directories under the common base temp directory. """Factory for temporary directories under the common base temp directory.
The base directory can be configured using the ``--basetemp`` option. The base directory can be configured using the ``--basetemp`` option.
""" """
def __init__(self, config): tmppath_factory = attr.ib()
self.config = config
self.trace = config.trace.get("tmpdir")
def ensuretemp(self, string, dir=1): def ensuretemp(self, string, dir=1):
""" (deprecated) return temporary directory path with """ (deprecated) return temporary directory path with
@ -33,46 +126,13 @@ class TempdirFactory(object):
If ``numbered``, ensure the directory is unique by adding a number If ``numbered``, ensure the directory is unique by adding a number
prefix greater than any existing one. prefix greater than any existing one.
""" """
basetemp = self.getbasetemp() return py.path.local(self.tmppath_factory.mktemp(basename, numbered).resolve())
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): def getbasetemp(self):
""" return base temporary directory. """ return py.path.local(self.tmppath_factory.getbasetemp().resolve())
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:
temproot = py.path.local.get_temproot()
user = get_user()
if user:
# use a sub-directory in the temproot to speed-up
# make_numbered_dir() call
rootdir = temproot.join("pytest-of-%s" % user)
else:
rootdir = temproot
rootdir.ensure(dir=1)
basetemp = py.path.local.make_numbered_dir(
prefix="pytest-", rootdir=rootdir
)
self._basetemp = t = basetemp.realpath()
self.trace("new basetemp", t)
return t
def finish(self): def finish(self):
self.trace("finish") self.tmppath_factory.trace("finish")
def get_user(): def get_user():
@ -87,10 +147,6 @@ def get_user():
return None return None
# backward compatibility
TempdirHandler = TempdirFactory
def pytest_configure(config): def pytest_configure(config):
"""Create a TempdirFactory and attach it to the config object. """Create a TempdirFactory and attach it to the config object.
@ -99,7 +155,8 @@ def pytest_configure(config):
to the tmpdir_factory session fixture. to the tmpdir_factory session fixture.
""" """
mp = MonkeyPatch() mp = MonkeyPatch()
t = TempdirFactory(config) tmppath_handler = TempPathFactory.from_config(config)
t = TempdirFactory(tmppath_handler)
config._cleanup.extend([mp.undo, t.finish]) config._cleanup.extend([mp.undo, t.finish])
mp.setattr(config, "_tmpdirhandler", t, raising=False) mp.setattr(config, "_tmpdirhandler", t, raising=False)
mp.setattr(pytest, "ensuretemp", t.ensuretemp, raising=False) mp.setattr(pytest, "ensuretemp", t.ensuretemp, raising=False)

View File

@ -19,11 +19,11 @@ def test_ensuretemp(recwarn):
class TestTempdirHandler(object): class TestTempdirHandler(object):
def test_mktemp(self, testdir): def test_mktemp(self, testdir):
from _pytest.tmpdir import TempdirFactory from _pytest.tmpdir import TempdirFactory, TempPathFactory
config = testdir.parseconfig() config = testdir.parseconfig()
config.option.basetemp = testdir.mkdir("hello") config.option.basetemp = testdir.mkdir("hello")
t = TempdirFactory(config) t = TempdirFactory(TempPathFactory.from_config(config))
tmp = t.mktemp("world") tmp = t.mktemp("world")
assert tmp.relto(t.getbasetemp()) == "world0" assert tmp.relto(t.getbasetemp()) == "world0"
tmp = t.mktemp("this") tmp = t.mktemp("this")