Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit eecc28d

Browse filesBrowse files
authored
Merge pull request #2086 from George-Ogden/true-pathlike
Respect `os.Pathlike`
2 parents 0fcf291 + 0cb55fb commit eecc28d
Copy full SHA for eecc28d

16 files changed

+417-344Lines changed: 417 additions & 344 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎git/config.py‎

Copy file name to clipboardExpand all lines: git/config.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ def _included_paths(self) -> List[Tuple[str, str]]:
578578
value,
579579
)
580580
if self._repo.git_dir:
581-
if fnmatch.fnmatchcase(str(self._repo.git_dir), value):
581+
if fnmatch.fnmatchcase(os.fspath(self._repo.git_dir), value):
582582
paths += self.items(section)
583583

584584
elif keyword == "onbranch":
Collapse file

‎git/index/base.py‎

Copy file name to clipboardExpand all lines: git/index/base.py
+6-6Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ def raise_exc(e: Exception) -> NoReturn:
407407
r = str(self.repo.working_tree_dir)
408408
rs = r + os.sep
409409
for path in paths:
410-
abs_path = str(path)
410+
abs_path = os.fspath(path)
411411
if not osp.isabs(abs_path):
412412
abs_path = osp.join(r, path)
413413
# END make absolute path
@@ -656,10 +656,10 @@ def _to_relative_path(self, path: PathLike) -> PathLike:
656656
return path
657657
if self.repo.bare:
658658
raise InvalidGitRepositoryError("require non-bare repository")
659-
if not osp.normpath(str(path)).startswith(str(self.repo.working_tree_dir)):
659+
if not osp.normpath(path).startswith(str(self.repo.working_tree_dir)):
660660
raise ValueError("Absolute path %r is not in git repository at %r" % (path, self.repo.working_tree_dir))
661661
result = os.path.relpath(path, self.repo.working_tree_dir)
662-
if str(path).endswith(os.sep) and not result.endswith(os.sep):
662+
if os.fspath(path).endswith(os.sep) and not result.endswith(os.sep):
663663
result += os.sep
664664
return result
665665

@@ -1036,7 +1036,7 @@ def remove(
10361036
args.append("--")
10371037

10381038
# Preprocess paths.
1039-
paths = self._items_to_rela_paths(items)
1039+
paths = list(map(os.fspath, self._items_to_rela_paths(items))) # type: ignore[arg-type]
10401040
removed_paths = self.repo.git.rm(args, paths, **kwargs).splitlines()
10411041

10421042
# Process output to gain proper paths.
@@ -1359,11 +1359,11 @@ def make_exc() -> GitCommandError:
13591359
try:
13601360
self.entries[(co_path, 0)]
13611361
except KeyError:
1362-
folder = str(co_path)
1362+
folder = co_path
13631363
if not folder.endswith("/"):
13641364
folder += "/"
13651365
for entry in self.entries.values():
1366-
if str(entry.path).startswith(folder):
1366+
if os.fspath(entry.path).startswith(folder):
13671367
p = entry.path
13681368
self._write_path_to_stdin(proc, p, p, make_exc, fprogress, read_from_stdout=False)
13691369
checked_out_files.append(p)
Collapse file

‎git/index/fun.py‎

Copy file name to clipboardExpand all lines: git/index/fun.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def run_commit_hook(name: str, index: "IndexFile", *args: str) -> None:
8787
return
8888

8989
env = os.environ.copy()
90-
env["GIT_INDEX_FILE"] = safe_decode(str(index.path))
90+
env["GIT_INDEX_FILE"] = safe_decode(os.fspath(index.path))
9191
env["GIT_EDITOR"] = ":"
9292
cmd = [hp]
9393
try:
Collapse file

‎git/index/util.py‎

Copy file name to clipboardExpand all lines: git/index/util.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
# typing ----------------------------------------------------------------------
1717

18-
from typing import Any, Callable, TYPE_CHECKING, Optional, Type
18+
from typing import Any, Callable, TYPE_CHECKING, Optional, Type, cast
1919

2020
from git.types import Literal, PathLike, _T
2121

@@ -106,7 +106,7 @@ def git_working_dir(func: Callable[..., _T]) -> Callable[..., _T]:
106106
@wraps(func)
107107
def set_git_working_dir(self: "IndexFile", *args: Any, **kwargs: Any) -> _T:
108108
cur_wd = os.getcwd()
109-
os.chdir(str(self.repo.working_tree_dir))
109+
os.chdir(cast(PathLike, self.repo.working_tree_dir))
110110
try:
111111
return func(self, *args, **kwargs)
112112
finally:
Collapse file

‎git/objects/blob.py‎

Copy file name to clipboardExpand all lines: git/objects/blob.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
__all__ = ["Blob"]
77

88
from mimetypes import guess_type
9+
import os
910
import sys
1011

1112
if sys.version_info >= (3, 8):
@@ -44,5 +45,5 @@ def mime_type(self) -> str:
4445
"""
4546
guesses = None
4647
if self.path:
47-
guesses = guess_type(str(self.path))
48+
guesses = guess_type(os.fspath(self.path))
4849
return guesses and guesses[0] or self.DEFAULT_MIME_TYPE
Collapse file

‎git/objects/submodule/base.py‎

Copy file name to clipboardExpand all lines: git/objects/submodule/base.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ def _clone_repo(
352352
module_abspath_dir = osp.dirname(module_abspath)
353353
if not osp.isdir(module_abspath_dir):
354354
os.makedirs(module_abspath_dir)
355-
module_checkout_path = osp.join(str(repo.working_tree_dir), path)
355+
module_checkout_path = osp.join(repo.working_tree_dir, path) # type: ignore[arg-type]
356356

357357
if url.startswith("../"):
358358
remote_name = cast("RemoteReference", repo.active_branch.tracking_branch()).remote_name
@@ -541,7 +541,7 @@ def add(
541541
if sm.exists():
542542
# Reretrieve submodule from tree.
543543
try:
544-
sm = repo.head.commit.tree[str(path)]
544+
sm = repo.head.commit.tree[os.fspath(path)]
545545
sm._name = name
546546
return sm
547547
except KeyError:
Collapse file

‎git/refs/reference.py‎

Copy file name to clipboardExpand all lines: git/refs/reference.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
__all__ = ["Reference"]
55

6+
import os
67
from git.util import IterableObj, LazyMixin
78

89
from .symbolic import SymbolicReference, T_References
@@ -65,7 +66,7 @@ def __init__(self, repo: "Repo", path: PathLike, check_path: bool = True) -> Non
6566
If ``False``, you can provide any path.
6667
Otherwise the path must start with the default path prefix of this type.
6768
"""
68-
if check_path and not str(path).startswith(self._common_path_default + "/"):
69+
if check_path and not os.fspath(path).startswith(self._common_path_default + "/"):
6970
raise ValueError(f"Cannot instantiate {self.__class__.__name__!r} from path {path}")
7071
self.path: str # SymbolicReference converts to string at the moment.
7172
super().__init__(repo, path)
Collapse file

‎git/refs/symbolic.py‎

Copy file name to clipboardExpand all lines: git/refs/symbolic.py
+11-10Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
__all__ = ["SymbolicReference"]
55

66
import os
7+
from pathlib import Path
78

89
from gitdb.exc import BadName, BadObject
910

@@ -76,10 +77,10 @@ class SymbolicReference:
7677

7778
def __init__(self, repo: "Repo", path: PathLike, check_path: bool = False) -> None:
7879
self.repo = repo
79-
self.path = path
80+
self.path: PathLike = path
8081

8182
def __str__(self) -> str:
82-
return str(self.path)
83+
return os.fspath(self.path)
8384

8485
def __repr__(self) -> str:
8586
return '<git.%s "%s">' % (self.__class__.__name__, self.path)
@@ -103,7 +104,7 @@ def name(self) -> str:
103104
In case of symbolic references, the shortest assumable name is the path
104105
itself.
105106
"""
106-
return str(self.path)
107+
return os.fspath(self.path)
107108

108109
@property
109110
def abspath(self) -> PathLike:
@@ -178,7 +179,7 @@ def _check_ref_name_valid(ref_path: PathLike) -> None:
178179
"""
179180
previous: Union[str, None] = None
180181
one_before_previous: Union[str, None] = None
181-
for c in str(ref_path):
182+
for c in os.fspath(ref_path):
182183
if c in " ~^:?*[\\":
183184
raise ValueError(
184185
f"Invalid reference '{ref_path}': references cannot contain spaces, tildes (~), carets (^),"
@@ -212,7 +213,7 @@ def _check_ref_name_valid(ref_path: PathLike) -> None:
212213
raise ValueError(f"Invalid reference '{ref_path}': references cannot end with a forward slash (/)")
213214
elif previous == "@" and one_before_previous is None:
214215
raise ValueError(f"Invalid reference '{ref_path}': references cannot be '@'")
215-
elif any(component.endswith(".lock") for component in str(ref_path).split("/")):
216+
elif any(component.endswith(".lock") for component in Path(ref_path).parts):
216217
raise ValueError(
217218
f"Invalid reference '{ref_path}': references cannot have slash-separated components that end with"
218219
" '.lock'"
@@ -235,7 +236,7 @@ def _get_ref_info_helper(
235236
tokens: Union[None, List[str], Tuple[str, str]] = None
236237
repodir = _git_dir(repo, ref_path)
237238
try:
238-
with open(os.path.join(repodir, str(ref_path)), "rt", encoding="UTF-8") as fp:
239+
with open(os.path.join(repodir, ref_path), "rt", encoding="UTF-8") as fp: # type: ignore[arg-type]
239240
value = fp.read().rstrip()
240241
# Don't only split on spaces, but on whitespace, which allows to parse lines like:
241242
# 60b64ef992065e2600bfef6187a97f92398a9144 branch 'master' of git-server:/path/to/repo
@@ -614,7 +615,7 @@ def to_full_path(cls, path: Union[PathLike, "SymbolicReference"]) -> PathLike:
614615
full_ref_path = path
615616
if not cls._common_path_default:
616617
return full_ref_path
617-
if not str(path).startswith(cls._common_path_default + "/"):
618+
if not os.fspath(path).startswith(cls._common_path_default + "/"):
618619
full_ref_path = "%s/%s" % (cls._common_path_default, path)
619620
return full_ref_path
620621

@@ -706,7 +707,7 @@ def _create(
706707
if not force and os.path.isfile(abs_ref_path):
707708
target_data = str(target)
708709
if isinstance(target, SymbolicReference):
709-
target_data = str(target.path)
710+
target_data = os.fspath(target.path)
710711
if not resolve:
711712
target_data = "ref: " + target_data
712713
with open(abs_ref_path, "rb") as fd:
@@ -842,7 +843,7 @@ def _iter_items(
842843

843844
# Read packed refs.
844845
for _sha, rela_path in cls._iter_packed_refs(repo):
845-
if rela_path.startswith(str(common_path)):
846+
if rela_path.startswith(os.fspath(common_path)):
846847
rela_paths.add(rela_path)
847848
# END relative path matches common path
848849
# END packed refs reading
@@ -930,4 +931,4 @@ def from_path(cls: Type[T_References], repo: "Repo", path: PathLike) -> T_Refere
930931

931932
def is_remote(self) -> bool:
932933
""":return: True if this symbolic reference points to a remote branch"""
933-
return str(self.path).startswith(self._remote_common_path_default + "/")
934+
return os.fspath(self.path).startswith(self._remote_common_path_default + "/")
Collapse file

‎git/repo/base.py‎

Copy file name to clipboardExpand all lines: git/repo/base.py
+9-10Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class Repo:
126126
working_dir: PathLike
127127
"""The working directory of the git command."""
128128

129+
# stored as string for easier processing, but annotated as path for clearer intention
129130
_working_tree_dir: Optional[PathLike] = None
130131

131132
git_dir: PathLike
@@ -215,15 +216,13 @@ def __init__(
215216
epath = path or os.getenv("GIT_DIR")
216217
if not epath:
217218
epath = os.getcwd()
219+
epath = os.fspath(epath)
218220
if Git.is_cygwin():
219221
# Given how the tests are written, this seems more likely to catch Cygwin
220222
# git used from Windows than Windows git used from Cygwin. Therefore
221223
# changing to Cygwin-style paths is the relevant operation.
222-
epath = cygpath(str(epath))
224+
epath = cygpath(epath)
223225

224-
epath = epath or path or os.getcwd()
225-
if not isinstance(epath, str):
226-
epath = str(epath)
227226
if expand_vars and re.search(self.re_envvars, epath):
228227
warnings.warn(
229228
"The use of environment variables in paths is deprecated"
@@ -957,7 +956,7 @@ def is_dirty(
957956
if not submodules:
958957
default_args.append("--ignore-submodules")
959958
if path:
960-
default_args.extend(["--", str(path)])
959+
default_args.extend(["--", os.fspath(path)])
961960
if index:
962961
# diff index against HEAD.
963962
if osp.isfile(self.index.path) and len(self.git.diff("--cached", *default_args)):
@@ -1357,9 +1356,9 @@ def _clone(
13571356
) -> "Repo":
13581357
odbt = kwargs.pop("odbt", odb_default_type)
13591358

1360-
# When pathlib.Path or other class-based path is passed
1361-
if not isinstance(path, str):
1362-
path = str(path)
1359+
# url may be a path and this has no effect if it is a string
1360+
url = os.fspath(url)
1361+
path = os.fspath(path)
13631362

13641363
## A bug win cygwin's Git, when `--bare` or `--separate-git-dir`
13651364
# it prepends the cwd or(?) the `url` into the `path, so::
@@ -1376,7 +1375,7 @@ def _clone(
13761375
multi = shlex.split(" ".join(multi_options))
13771376

13781377
if not allow_unsafe_protocols:
1379-
Git.check_unsafe_protocols(str(url))
1378+
Git.check_unsafe_protocols(url)
13801379
if not allow_unsafe_options:
13811380
Git.check_unsafe_options(options=list(kwargs.keys()), unsafe_options=cls.unsafe_git_clone_options)
13821381
if not allow_unsafe_options and multi_options:
@@ -1385,7 +1384,7 @@ def _clone(
13851384
proc = git.clone(
13861385
multi,
13871386
"--",
1388-
Git.polish_url(str(url)),
1387+
Git.polish_url(url),
13891388
clone_path,
13901389
with_extended_output=True,
13911390
as_process=True,
Collapse file

‎git/util.py‎

Copy file name to clipboardExpand all lines: git/util.py
+12-12Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
import logging
3737
import os
3838
import os.path as osp
39-
import pathlib
39+
from pathlib import Path
4040
import platform
4141
import re
4242
import shutil
@@ -272,9 +272,9 @@ def stream_copy(source: BinaryIO, destination: BinaryIO, chunk_size: int = 512 *
272272
def join_path(a: PathLike, *p: PathLike) -> PathLike:
273273
R"""Join path tokens together similar to osp.join, but always use ``/`` instead of
274274
possibly ``\`` on Windows."""
275-
path = str(a)
275+
path = os.fspath(a)
276276
for b in p:
277-
b = str(b)
277+
b = os.fspath(b)
278278
if not b:
279279
continue
280280
if b.startswith("/"):
@@ -290,18 +290,18 @@ def join_path(a: PathLike, *p: PathLike) -> PathLike:
290290
if sys.platform == "win32":
291291

292292
def to_native_path_windows(path: PathLike) -> PathLike:
293-
path = str(path)
293+
path = os.fspath(path)
294294
return path.replace("/", "\\")
295295

296296
def to_native_path_linux(path: PathLike) -> str:
297-
path = str(path)
297+
path = os.fspath(path)
298298
return path.replace("\\", "/")
299299

300300
to_native_path = to_native_path_windows
301301
else:
302302
# No need for any work on Linux.
303303
def to_native_path_linux(path: PathLike) -> str:
304-
return str(path)
304+
return os.fspath(path)
305305

306306
to_native_path = to_native_path_linux
307307

@@ -372,7 +372,7 @@ def is_exec(fpath: str) -> bool:
372372
progs = []
373373
if not path:
374374
path = os.environ["PATH"]
375-
for folder in str(path).split(os.pathsep):
375+
for folder in os.fspath(path).split(os.pathsep):
376376
folder = folder.strip('"')
377377
if folder:
378378
exe_path = osp.join(folder, program)
@@ -397,7 +397,7 @@ def _cygexpath(drive: Optional[str], path: str) -> str:
397397
p = cygpath(p)
398398
elif drive:
399399
p = "/proc/cygdrive/%s/%s" % (drive.lower(), p)
400-
p_str = str(p) # ensure it is a str and not AnyPath
400+
p_str = os.fspath(p) # ensure it is a str and not AnyPath
401401
return p_str.replace("\\", "/")
402402

403403

@@ -418,7 +418,7 @@ def _cygexpath(drive: Optional[str], path: str) -> str:
418418

419419
def cygpath(path: str) -> str:
420420
"""Use :meth:`git.cmd.Git.polish_url` instead, that works on any environment."""
421-
path = str(path) # Ensure is str and not AnyPath.
421+
path = os.fspath(path) # Ensure is str and not AnyPath.
422422
# Fix to use Paths when 3.5 dropped. Or to be just str if only for URLs?
423423
if not path.startswith(("/cygdrive", "//", "/proc/cygdrive")):
424424
for regex, parser, recurse in _cygpath_parsers:
@@ -438,7 +438,7 @@ def cygpath(path: str) -> str:
438438

439439

440440
def decygpath(path: PathLike) -> str:
441-
path = str(path)
441+
path = os.fspath(path)
442442
m = _decygpath_regex.match(path)
443443
if m:
444444
drive, rest_path = m.groups()
@@ -465,7 +465,7 @@ def _is_cygwin_git(git_executable: str) -> bool:
465465
# Just a name given, not a real path.
466466
uname_cmd = osp.join(git_dir, "uname")
467467

468-
if not (pathlib.Path(uname_cmd).is_file() and os.access(uname_cmd, os.X_OK)):
468+
if not (Path(uname_cmd).is_file() and os.access(uname_cmd, os.X_OK)):
469469
_logger.debug(f"Failed checking if running in CYGWIN: {uname_cmd} is not an executable")
470470
_is_cygwin_cache[git_executable] = is_cygwin
471471
return is_cygwin
@@ -523,7 +523,7 @@ def expand_path(p: PathLike, expand_vars: bool = ...) -> str:
523523

524524

525525
def expand_path(p: Union[None, PathLike], expand_vars: bool = True) -> Optional[PathLike]:
526-
if isinstance(p, pathlib.Path):
526+
if isinstance(p, Path):
527527
return p.resolve()
528528
try:
529529
p = osp.expanduser(p) # type: ignore[arg-type]

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.