|
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