tmpdir.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. """ support for providing temporary directories to test functions. """
  2. import re
  3. import pytest
  4. import py
  5. from _pytest.monkeypatch import monkeypatch
  6. class TempdirFactory:
  7. """Factory for temporary directories under the common base temp directory.
  8. The base directory can be configured using the ``--basetemp`` option.
  9. """
  10. def __init__(self, config):
  11. self.config = config
  12. self.trace = config.trace.get("tmpdir")
  13. def ensuretemp(self, string, dir=1):
  14. """ (deprecated) return temporary directory path with
  15. the given string as the trailing part. It is usually
  16. better to use the 'tmpdir' function argument which
  17. provides an empty unique-per-test-invocation directory
  18. and is guaranteed to be empty.
  19. """
  20. #py.log._apiwarn(">1.1", "use tmpdir function argument")
  21. return self.getbasetemp().ensure(string, dir=dir)
  22. def mktemp(self, basename, numbered=True):
  23. """Create a subdirectory of the base temporary directory and return it.
  24. If ``numbered``, ensure the directory is unique by adding a number
  25. prefix greater than any existing one.
  26. """
  27. basetemp = self.getbasetemp()
  28. if not numbered:
  29. p = basetemp.mkdir(basename)
  30. else:
  31. p = py.path.local.make_numbered_dir(prefix=basename,
  32. keep=0, rootdir=basetemp, lock_timeout=None)
  33. self.trace("mktemp", p)
  34. return p
  35. def getbasetemp(self):
  36. """ return base temporary directory. """
  37. try:
  38. return self._basetemp
  39. except AttributeError:
  40. basetemp = self.config.option.basetemp
  41. if basetemp:
  42. basetemp = py.path.local(basetemp)
  43. if basetemp.check():
  44. basetemp.remove()
  45. basetemp.mkdir()
  46. else:
  47. temproot = py.path.local.get_temproot()
  48. user = get_user()
  49. if user:
  50. # use a sub-directory in the temproot to speed-up
  51. # make_numbered_dir() call
  52. rootdir = temproot.join('pytest-of-%s' % user)
  53. else:
  54. rootdir = temproot
  55. rootdir.ensure(dir=1)
  56. basetemp = py.path.local.make_numbered_dir(prefix='pytest-',
  57. rootdir=rootdir)
  58. self._basetemp = t = basetemp.realpath()
  59. self.trace("new basetemp", t)
  60. return t
  61. def finish(self):
  62. self.trace("finish")
  63. def get_user():
  64. """Return the current user name, or None if getuser() does not work
  65. in the current environment (see #1010).
  66. """
  67. import getpass
  68. try:
  69. return getpass.getuser()
  70. except (ImportError, KeyError):
  71. return None
  72. # backward compatibility
  73. TempdirHandler = TempdirFactory
  74. def pytest_configure(config):
  75. """Create a TempdirFactory and attach it to the config object.
  76. This is to comply with existing plugins which expect the handler to be
  77. available at pytest_configure time, but ideally should be moved entirely
  78. to the tmpdir_factory session fixture.
  79. """
  80. mp = monkeypatch()
  81. t = TempdirFactory(config)
  82. config._cleanup.extend([mp.undo, t.finish])
  83. mp.setattr(config, '_tmpdirhandler', t, raising=False)
  84. mp.setattr(pytest, 'ensuretemp', t.ensuretemp, raising=False)
  85. @pytest.fixture(scope='session')
  86. def tmpdir_factory(request):
  87. """Return a TempdirFactory instance for the test session.
  88. """
  89. return request.config._tmpdirhandler
  90. @pytest.fixture
  91. def tmpdir(request, tmpdir_factory):
  92. """return a temporary directory path object
  93. which is unique to each test function invocation,
  94. created as a sub directory of the base temporary
  95. directory. The returned object is a `py.path.local`_
  96. path object.
  97. """
  98. name = request.node.name
  99. name = re.sub("[\W]", "_", name)
  100. MAXVAL = 30
  101. if len(name) > MAXVAL:
  102. name = name[:MAXVAL]
  103. x = tmpdir_factory.mktemp(name, numbered=True)
  104. return x