|
5 | 5 | # the BSD License: https://opensource.org/license/bsd-3-clause/ |
6 | 6 |
|
7 | 7 | from abc import abstractmethod |
8 | | -import os.path as osp |
9 | | -from .compat import is_win |
10 | 8 | import contextlib |
11 | 9 | from functools import wraps |
12 | 10 | import getpass |
13 | 11 | import logging |
14 | 12 | import os |
| 13 | +import os.path as osp |
| 14 | +import pathlib |
15 | 15 | import platform |
16 | | -import subprocess |
17 | 16 | import re |
18 | 17 | import shutil |
19 | 18 | import stat |
20 | | -from sys import maxsize |
| 19 | +import subprocess |
| 20 | +import sys |
21 | 21 | import time |
22 | 22 | from urllib.parse import urlsplit, urlunsplit |
23 | 23 | import warnings |
24 | 24 |
|
25 | | -# from git.objects.util import Traversable |
| 25 | +from .compat import is_win |
26 | 26 |
|
27 | 27 | # typing --------------------------------------------------------- |
28 | 28 |
|
|
42 | 42 | Tuple, |
43 | 43 | TypeVar, |
44 | 44 | Union, |
45 | | - cast, |
46 | 45 | TYPE_CHECKING, |
| 46 | + cast, |
47 | 47 | overload, |
48 | 48 | ) |
49 | 49 |
|
50 | | -import pathlib |
51 | | - |
52 | 50 | if TYPE_CHECKING: |
53 | 51 | from git.remote import Remote |
54 | 52 | from git.repo.base import Repo |
55 | 53 | from git.config import GitConfigParser, SectionConstraint |
56 | 54 | from git import Git |
57 | 55 |
|
58 | | - # from git.objects.base import IndexObject |
59 | | - |
60 | | - |
61 | 56 | from .types import ( |
62 | 57 | Literal, |
63 | 58 | SupportsIndex, |
|
75 | 70 |
|
76 | 71 | # --------------------------------------------------------------------- |
77 | 72 |
|
78 | | - |
79 | 73 | from gitdb.util import ( # NOQA @IgnorePep8 |
80 | 74 | make_sha, |
81 | 75 | LockedFD, # @UnusedImport |
|
88 | 82 | hex_to_bin, # @UnusedImport |
89 | 83 | ) |
90 | 84 |
|
91 | | - |
92 | 85 | # NOTE: Some of the unused imports might be used/imported by others. |
93 | 86 | # Handle once test-cases are back up and running. |
94 | 87 | # Most of these are unused here, but are for use by git-python modules so these |
|
116 | 109 |
|
117 | 110 | log = logging.getLogger(__name__) |
118 | 111 |
|
119 | | -# types############################################################ |
| 112 | + |
| 113 | +def _read_env_flag(name: str, default: bool) -> bool: |
| 114 | + try: |
| 115 | + value = os.environ[name] |
| 116 | + except KeyError: |
| 117 | + return default |
| 118 | + |
| 119 | + log.warning( |
| 120 | + "The %s environment variable is deprecated. Its effect has never been documented and changes without warning.", |
| 121 | + name, |
| 122 | + ) |
| 123 | + |
| 124 | + adjusted_value = value.strip().lower() |
| 125 | + |
| 126 | + if adjusted_value in {"", "0", "false", "no"}: |
| 127 | + return False |
| 128 | + if adjusted_value in {"1", "true", "yes"}: |
| 129 | + return True |
| 130 | + log.warning("%s has unrecognized value %r, treating as %r.", name, value, default) |
| 131 | + return default |
120 | 132 |
|
121 | 133 |
|
122 | 134 | #: We need an easy way to see if Appveyor TCs start failing, |
123 | 135 | #: so the errors marked with this var are considered "acknowledged" ones, awaiting remedy, |
124 | 136 | #: till then, we wish to hide them. |
125 | | -HIDE_WINDOWS_KNOWN_ERRORS = is_win and os.environ.get("HIDE_WINDOWS_KNOWN_ERRORS", True) |
126 | | -HIDE_WINDOWS_FREEZE_ERRORS = is_win and os.environ.get("HIDE_WINDOWS_FREEZE_ERRORS", True) |
| 137 | +HIDE_WINDOWS_KNOWN_ERRORS = is_win and _read_env_flag("HIDE_WINDOWS_KNOWN_ERRORS", True) |
| 138 | +HIDE_WINDOWS_FREEZE_ERRORS = is_win and _read_env_flag("HIDE_WINDOWS_FREEZE_ERRORS", True) |
127 | 139 |
|
128 | 140 | # { Utility Methods |
129 | 141 |
|
@@ -177,25 +189,29 @@ def patch_env(name: str, value: str) -> Generator[None, None, None]: |
177 | 189 |
|
178 | 190 |
|
179 | 191 | def rmtree(path: PathLike) -> None: |
180 | | - """Remove the given recursively. |
| 192 | + """Remove the given directory tree recursively. |
181 | 193 |
|
182 | | - :note: we use shutil rmtree but adjust its behaviour to see whether files that |
183 | | - couldn't be deleted are read-only. Windows will not remove them in that case""" |
| 194 | + :note: We use :func:`shutil.rmtree` but adjust its behaviour to see whether files that |
| 195 | + couldn't be deleted are read-only. Windows will not remove them in that case.""" |
184 | 196 |
|
185 | | - def onerror(func: Callable, path: PathLike, exc_info: str) -> None: |
186 | | - # Is the error an access error ? |
| 197 | + def handler(function: Callable, path: PathLike, _excinfo: Any) -> None: |
| 198 | + """Callback for :func:`shutil.rmtree`. Works either as ``onexc`` or ``onerror``.""" |
| 199 | + # Is the error an access error? |
187 | 200 | os.chmod(path, stat.S_IWUSR) |
188 | 201 |
|
189 | 202 | try: |
190 | | - func(path) # Will scream if still not possible to delete. |
191 | | - except Exception as ex: |
| 203 | + function(path) |
| 204 | + except PermissionError as ex: |
192 | 205 | if HIDE_WINDOWS_KNOWN_ERRORS: |
193 | 206 | from unittest import SkipTest |
194 | 207 |
|
195 | | - raise SkipTest("FIXME: fails with: PermissionError\n {}".format(ex)) from ex |
| 208 | + raise SkipTest(f"FIXME: fails with: PermissionError\n {ex}") from ex |
196 | 209 | raise |
197 | 210 |
|
198 | | - return shutil.rmtree(path, False, onerror) |
| 211 | + if sys.version_info >= (3, 12): |
| 212 | + shutil.rmtree(path, onexc=handler) |
| 213 | + else: |
| 214 | + shutil.rmtree(path, onerror=handler) |
199 | 215 |
|
200 | 216 |
|
201 | 217 | def rmfile(path: PathLike) -> None: |
@@ -995,7 +1011,7 @@ def __init__( |
995 | 1011 | self, |
996 | 1012 | file_path: PathLike, |
997 | 1013 | check_interval_s: float = 0.3, |
998 | | - max_block_time_s: int = maxsize, |
| 1014 | + max_block_time_s: int = sys.maxsize, |
999 | 1015 | ) -> None: |
1000 | 1016 | """Configure the instance |
1001 | 1017 |
|
|
0 commit comments