summaryrefslogtreecommitdiffstats
path: root/tests/compat.py
blob: dfc57f305ddacc5d452d5f2c9e17195da1917232 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# -*- coding: utf-8 -*-
"""Python compatibility support for CLI Helpers' tests."""

from __future__ import unicode_literals
import os as _os
import shutil as _shutil
import tempfile as _tempfile
import warnings as _warnings

from cli_helpers.compat import PY2


class _TempDirectory(object):
    """Create and return a temporary directory.  This has the same
    behavior as mkdtemp but can be used as a context manager.  For
    example:

        with TemporaryDirectory() as tmpdir:
            ...

    Upon exiting the context, the directory and everything contained
    in it are removed.

    NOTE: Copied from the Python 3 standard library.
    """

    # Handle mkdtemp raising an exception
    name = None
    _closed = False

    def __init__(self, suffix="", prefix="tmp", dir=None):
        self.name = _tempfile.mkdtemp(suffix, prefix, dir)

    def __repr__(self):
        return "<{} {!r}>".format(self.__class__.__name__, self.name)

    def __enter__(self):
        return self.name

    def cleanup(self, _warn=False, _warnings=_warnings):
        if self.name and not self._closed:
            try:
                _shutil.rmtree(self.name)
            except (TypeError, AttributeError) as ex:
                if "None" not in "%s" % (ex,):
                    raise
                self._rmtree(self.name)
            self._closed = True
            if _warn and _warnings.warn:
                _warnings.warn(
                    "Implicitly cleaning up {!r}".format(self), ResourceWarning
                )

    def __exit__(self, exc, value, tb):
        self.cleanup()

    def __del__(self):
        # Issue a ResourceWarning if implicit cleanup needed
        self.cleanup(_warn=True)

    def _rmtree(
        self,
        path,
        _OSError=OSError,
        _sep=_os.path.sep,
        _listdir=_os.listdir,
        _remove=_os.remove,
        _rmdir=_os.rmdir,
    ):
        # Essentially a stripped down version of shutil.rmtree.  We can't
        # use globals because they may be None'ed out at shutdown.
        if not isinstance(path, str):
            _sep = _sep.encode()
        try:
            for name in _listdir(path):
                fullname = path + _sep + name
                try:
                    _remove(fullname)
                except _OSError:
                    self._rmtree(fullname)
            _rmdir(path)
        except _OSError:
            pass


TemporaryDirectory = _TempDirectory if PY2 else _tempfile.TemporaryDirectory