Skip to content

Commit c01fe76

Browse files
committed
Deprecate compat.is_<platform>, rewriting all uses
Major changes: - Add a comment in the git.compat module above the definitions of is_win, is_posix, and is_darwin stating that they are deprecated and recommending that os.name (or, where applicable, sys.platform) be used directly instead for clarity (and sometimes accuracy). - Remove all uses of is_win and is_posix in git/ and test/, replacing them with `os.name == "nt"` and `os.name == "posix"`, respectively. There were no uses of is_darwin to be replaced. Although it had been used at one time, the last reference to it appears to have been removed in 4545762 (#1295). This doesn't emit a DeprecationWarning when those attributes are accessed in the git.compat module. (That might be valuable thing to do in the future, if the git.compat module is to remain non-deprecated overall.) Two related less consequential changes are also included: - Improve ordering and grouping of imports, in modules where they were already being changed as a result of no longer needing to import is_<platform> (usually is_win) from git.compat. - Make minor revisions to a few comments, for readability. (This is in addition to somewhat more substantial revisions of comments where rewording was related to replacing uses of is_<platform>.)
1 parent d5fc6e5 commit c01fe76

17 files changed

+118
-128
lines changed

Diff for: .github/workflows/cygwin-test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ jobs:
7272
python --version
7373
python -c 'import sys; print(sys.platform)'
7474
python -c 'import os; print(os.name)'
75-
python -c 'import git; print(git.compat.is_win)'
75+
python -c 'import git; print(git.compat.is_win)' # NOTE: Deprecated. Use os.name directly.
7676
7777
- name: Test with pytest
7878
run: |

Diff for: .github/workflows/pythonpackage.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
python --version
6464
python -c 'import sys; print(sys.platform)'
6565
python -c 'import os; print(os.name)'
66-
python -c 'import git; print(git.compat.is_win)'
66+
python -c 'import git; print(git.compat.is_win)' # NOTE: Deprecated. Use os.name directly.
6767
6868
- name: Check types with mypy
6969
run: |

Diff for: git/cmd.py

+32-32
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,21 @@
1717
import threading
1818
from textwrap import dedent
1919

20-
from git.compat import (
21-
defenc,
22-
force_bytes,
23-
safe_decode,
24-
is_posix,
25-
is_win,
20+
from git.compat import defenc, force_bytes, safe_decode
21+
from git.exc import (
22+
CommandError,
23+
GitCommandError,
24+
GitCommandNotFound,
25+
UnsafeOptionError,
26+
UnsafeProtocolError,
2627
)
27-
from git.exc import CommandError
28-
from git.util import is_cygwin_git, cygpath, expand_path, remove_password_if_present, patch_env
29-
30-
from .exc import GitCommandError, GitCommandNotFound, UnsafeOptionError, UnsafeProtocolError
31-
from .util import (
28+
from git.util import (
3229
LazyMixin,
30+
cygpath,
31+
expand_path,
32+
is_cygwin_git,
33+
patch_env,
34+
remove_password_if_present,
3335
stream_copy,
3436
)
3537

@@ -180,14 +182,13 @@ def pump_stream(
180182
t.start()
181183
threads.append(t)
182184

183-
## FIXME: Why Join?? Will block if `stdin` needs feeding...
184-
#
185+
# FIXME: Why join? Will block if stdin needs feeding...
185186
for t in threads:
186187
t.join(timeout=kill_after_timeout)
187188
if t.is_alive():
188189
if isinstance(process, Git.AutoInterrupt):
189190
process._terminate()
190-
else: # Don't want to deal with the other case
191+
else: # Don't want to deal with the other case.
191192
raise RuntimeError(
192193
"Thread join() timed out in cmd.handle_process_output()."
193194
f" kill_after_timeout={kill_after_timeout} seconds"
@@ -197,11 +198,11 @@ def pump_stream(
197198
"error: process killed because it timed out." f" kill_after_timeout={kill_after_timeout} seconds"
198199
)
199200
if not decode_streams and isinstance(p_stderr, BinaryIO):
200-
# Assume stderr_handler needs binary input
201+
# Assume stderr_handler needs binary input.
201202
error_str = cast(str, error_str)
202203
error_str = error_str.encode()
203204
# We ignore typing on the next line because mypy does not like
204-
# the way we inferred that stderr takes str or bytes
205+
# the way we inferred that stderr takes str or bytes.
205206
stderr_handler(error_str) # type: ignore
206207

207208
if finalizer:
@@ -228,14 +229,12 @@ def dict_to_slots_and__excluded_are_none(self: object, d: Mapping[str, Any], exc
228229
## -- End Utilities -- @}
229230

230231

231-
# value of Windows process creation flag taken from MSDN
232-
CREATE_NO_WINDOW = 0x08000000
233-
234-
## CREATE_NEW_PROCESS_GROUP is needed to allow killing it afterwards,
235-
# see https://docs.python.org/3/library/subprocess.html#subprocess.Popen.send_signal
236-
PROC_CREATIONFLAGS = (
237-
CREATE_NO_WINDOW | subprocess.CREATE_NEW_PROCESS_GROUP if is_win else 0 # type: ignore[attr-defined]
238-
) # mypy error if not Windows.
232+
if os.name == "nt":
233+
# CREATE_NEW_PROCESS_GROUP is needed to allow killing it afterwards. See:
234+
# https://docs.python.org/3/library/subprocess.html#subprocess.Popen.send_signal
235+
PROC_CREATIONFLAGS = subprocess.CREATE_NO_WINDOW | subprocess.CREATE_NEW_PROCESS_GROUP
236+
else:
237+
PROC_CREATIONFLAGS = 0
239238

240239

241240
class Git(LazyMixin):
@@ -551,7 +550,7 @@ def _terminate(self) -> None:
551550
# For some reason, providing None for stdout/stderr still prints something. This is why
552551
# we simply use the shell and redirect to nul. Slower than CreateProcess. The question
553552
# is whether we really want to see all these messages. It's annoying no matter what.
554-
if is_win:
553+
if os.name == "nt":
555554
call(
556555
("TASKKILL /F /T /PID %s 2>nul 1>nul" % str(proc.pid)),
557556
shell=True,
@@ -967,7 +966,7 @@ def execute(
967966
if inline_env is not None:
968967
env.update(inline_env)
969968

970-
if is_win:
969+
if os.name == "nt":
971970
cmd_not_found_exception = OSError
972971
if kill_after_timeout is not None:
973972
raise GitCommandError(
@@ -999,11 +998,11 @@ def execute(
999998
env=env,
1000999
cwd=cwd,
10011000
bufsize=-1,
1002-
stdin=istream or DEVNULL,
1001+
stdin=(istream or DEVNULL),
10031002
stderr=PIPE,
10041003
stdout=stdout_sink,
10051004
shell=shell,
1006-
close_fds=is_posix, # Unsupported on Windows.
1005+
close_fds=(os.name == "posix"), # Unsupported on Windows.
10071006
universal_newlines=universal_newlines,
10081007
creationflags=PROC_CREATIONFLAGS,
10091008
**subprocess_kwargs,
@@ -1073,7 +1072,7 @@ def kill_process(pid: int) -> None:
10731072
)
10741073
if not universal_newlines:
10751074
stderr_value = stderr_value.encode(defenc)
1076-
# strip trailing "\n"
1075+
# Strip trailing "\n".
10771076
if stdout_value.endswith(newline) and strip_newline_in_stdout: # type: ignore
10781077
stdout_value = stdout_value[:-1]
10791078
if stderr_value.endswith(newline): # type: ignore
@@ -1147,11 +1146,11 @@ def update_environment(self, **kwargs: Any) -> Dict[str, Union[str, None]]:
11471146
"""
11481147
old_env = {}
11491148
for key, value in kwargs.items():
1150-
# set value if it is None
1149+
# Set value if it is None.
11511150
if value is not None:
11521151
old_env[key] = self._environment.get(key)
11531152
self._environment[key] = value
1154-
# remove key from environment if its value is None
1153+
# Remove key from environment if its value is None.
11551154
elif key in self._environment:
11561155
old_env[key] = self._environment[key]
11571156
del self._environment[key]
@@ -1330,7 +1329,8 @@ def _parse_object_header(self, header_line: str) -> Tuple[str, str, int]:
13301329
:return: (hex_sha, type_string, size_as_int)
13311330
13321331
:raise ValueError: If the header contains indication for an error due to
1333-
incorrect input sha"""
1332+
incorrect input sha
1333+
"""
13341334
tokens = header_line.split()
13351335
if len(tokens) != 3:
13361336
if not tokens:

Diff for: git/compat.py

+11
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,20 @@
3434
# ---------------------------------------------------------------------------
3535

3636

37+
# DEPRECATED attributes providing shortcuts to operating system checks based on os.name.
38+
#
39+
# - is_win and is_posix are deprecated because it is clearer, and helps avoid bugs, to
40+
# write out the os.name checks explicitly. For example, is_win is False on Cygwin, but
41+
# is often assumed to be True.
42+
#
43+
# - is_darwin is deprecated because it is always False on all systems, as os.name is
44+
# never "darwin". For macOS, you can check for sys.platform == "darwin". (As on other
45+
# Unix-like systems, os.name == "posix" on macOS. This is also the case on Cygwin.)
46+
#
3747
is_win: bool = os.name == "nt"
3848
is_posix = os.name == "posix"
3949
is_darwin = os.name == "darwin"
50+
4051
defenc = sys.getfilesystemencoding()
4152

4253

Diff for: git/config.py

+6-13
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,21 @@
77
"""Module containing module parser implementation able to properly read and write
88
configuration files."""
99

10-
import sys
1110
import abc
11+
import configparser as cp
12+
import fnmatch
1213
from functools import wraps
1314
import inspect
1415
from io import BufferedReader, IOBase
1516
import logging
1617
import os
18+
import os.path as osp
1719
import re
18-
import fnmatch
19-
20-
from git.compat import (
21-
defenc,
22-
force_text,
23-
is_win,
24-
)
20+
import sys
2521

22+
from git.compat import defenc, force_text
2623
from git.util import LockFile
2724

28-
import os.path as osp
29-
30-
import configparser as cp
31-
3225
# typing-------------------------------------------------------
3326

3427
from typing import (
@@ -250,7 +243,7 @@ def items_all(self) -> List[Tuple[str, List[_T]]]:
250243
def get_config_path(config_level: Lit_config_levels) -> str:
251244
# We do not support an absolute path of the gitconfig on Windows.
252245
# Use the global config instead.
253-
if is_win and config_level == "system":
246+
if os.name == "nt" and config_level == "system":
254247
config_level = "global"
255248

256249
if config_level == "system":

Diff for: git/index/fun.py

+7-15
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
# NOTE: Autodoc hates it if this is a docstring.
33

44
from io import BytesIO
5-
from pathlib import Path
65
import os
6+
import os.path as osp
7+
from pathlib import Path
78
from stat import (
89
S_IFDIR,
910
S_IFLNK,
@@ -16,26 +17,17 @@
1617
import subprocess
1718

1819
from git.cmd import PROC_CREATIONFLAGS, handle_process_output
19-
from git.compat import (
20-
defenc,
21-
force_text,
22-
force_bytes,
23-
is_posix,
24-
is_win,
25-
safe_decode,
26-
)
27-
from git.exc import UnmergedEntriesError, HookExecutionError
20+
from git.compat import defenc, force_bytes, force_text, safe_decode
21+
from git.exc import HookExecutionError, UnmergedEntriesError
2822
from git.objects.fun import (
29-
tree_to_stream,
3023
traverse_tree_recursive,
3124
traverse_trees_recursive,
25+
tree_to_stream,
3226
)
3327
from git.util import IndexFileSHA1Writer, finalize_process
3428
from gitdb.base import IStream
3529
from gitdb.typ import str_tree_type
3630

37-
import os.path as osp
38-
3931
from .typ import BaseIndexEntry, IndexEntry, CE_NAMEMASK, CE_STAGESHIFT
4032
from .util import pack, unpack
4133

@@ -96,7 +88,7 @@ def run_commit_hook(name: str, index: "IndexFile", *args: str) -> None:
9688
env["GIT_EDITOR"] = ":"
9789
cmd = [hp]
9890
try:
99-
if is_win and not _has_file_extension(hp):
91+
if os.name == "nt" and not _has_file_extension(hp):
10092
# Windows only uses extensions to determine how to open files
10193
# (doesn't understand shebangs). Try using bash to run the hook.
10294
relative_hp = Path(hp).relative_to(index.repo.working_dir).as_posix()
@@ -108,7 +100,7 @@ def run_commit_hook(name: str, index: "IndexFile", *args: str) -> None:
108100
stdout=subprocess.PIPE,
109101
stderr=subprocess.PIPE,
110102
cwd=index.repo.working_dir,
111-
close_fds=is_posix,
103+
close_fds=(os.name == "posix"),
112104
creationflags=PROC_CREATIONFLAGS,
113105
)
114106
except Exception as ex:

Diff for: git/index/util.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@
22

33
from functools import wraps
44
import os
5+
import os.path as osp
56
import struct
67
import tempfile
78
from types import TracebackType
89

9-
from git.compat import is_win
10-
11-
import os.path as osp
12-
13-
1410
# typing ----------------------------------------------------------------------
1511

1612
from typing import Any, Callable, TYPE_CHECKING, Optional, Type
@@ -58,7 +54,7 @@ def __exit__(
5854
exc_tb: Optional[TracebackType],
5955
) -> bool:
6056
if osp.isfile(self.tmp_file_path):
61-
if is_win and osp.exists(self.file_path):
57+
if os.name == "nt" and osp.exists(self.file_path):
6258
os.remove(self.file_path)
6359
os.rename(self.tmp_file_path, self.file_path)
6460

Diff for: git/objects/submodule/base.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import git
99
from git.cmd import Git
10-
from git.compat import defenc, is_win
10+
from git.compat import defenc
1111
from git.config import GitConfigParser, SectionConstraint, cp
1212
from git.exc import (
1313
BadName,
@@ -353,9 +353,8 @@ def _write_git_file_and_module_config(cls, working_tree_dir: PathLike, module_ab
353353
"""
354354
git_file = osp.join(working_tree_dir, ".git")
355355
rela_path = osp.relpath(module_abspath, start=working_tree_dir)
356-
if is_win:
357-
if osp.isfile(git_file):
358-
os.remove(git_file)
356+
if os.name == "nt" and osp.isfile(git_file):
357+
os.remove(git_file)
359358
with open(git_file, "wb") as fp:
360359
fp.write(("gitdir: %s" % rela_path).encode(defenc))
361360

0 commit comments

Comments
 (0)