port interals of tmpdir to a basic pathlib implementation
this is still lacking locking and cleanup of the folders
This commit is contained in:
		
							parent
							
								
									602e74c2a7
								
							
						
					
					
						commit
						b48e23d54c
					
				|  | @ -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: | ||||||
|  |  | ||||||
|  | @ -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)" | ||||||
|  |         ), | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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") | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue