Skip to content

Commit 2f5e258

Browse files
committed
Annotate _process_diff_args without Diffable.Index
This removes the static type of Diffable's nested Index class, Type["Index"], from the Diffable._process_diff_args method, and its override IndexFile._process_diff_args. Further changes related to this remain necessary, and at this time, this adds one mypy error. The _process_diff_args methods did not handle Diffable.Index. The base class method would pass it through, but it would not be usable when then passed to "git diff". Instead, it is handled with correct behavior at runtime in Diffable.diff and its IndexFile.diff override, which handle it themselves and ensure it is never passed to any _process_diff_args implementation. That was already the case. The change here is mostly to type hints, removing it from the _process_diff_args annotations, since those methods have never actually worked with it and it probably wouldn't make sense for them to handle it. However, this does also attempt to help mypy figure out that Diffable.Index cannot end up as an element of its local variable `args`. This attempt is unsuccessful. The problem with the `args` local variable may be the reason including Index in the parameter type annotations appeared correct or necessary before. The issue is that Diffable.Index, even though it ought to be used as an opaque constant, is a class. Its static type is Type[Diffable.Index], but mypy is unable to infer that there are no other objects of that static type, because if Diffable.Index were subclassed, and the type object produced from doing so (i.e. the subclass itself) were passed as an `other` argument to the diff method, then the `other is Diffable.Index` condition would evaluate to False. Therefore to solve this problem it should be sufficient to decorate the Diffable.Index class as `@final`. This works for pyright (and thus also pylance), but it does not work for mypy (even in 1.9.0). So that still has to be solved, and (other than via suppressions) it may be necessary to make Diffable.Index an enumeration constant rather than a class, so it can be annotated as a literal.
1 parent 7204cc1 commit 2f5e258

File tree

3 files changed

+10
-8
lines changed

3 files changed

+10
-8
lines changed

git/diff.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
TYPE_CHECKING,
2929
cast,
3030
)
31-
from git.types import PathLike, Literal
31+
from git.types import Literal, PathLike, final
3232

3333
if TYPE_CHECKING:
3434
from .objects.tree import Tree
@@ -94,13 +94,14 @@ class Diffable:
9494
repo: "Repo"
9595
"""Repository to operate on. Must be provided by subclass or sibling class."""
9696

97+
@final
9798
class Index:
9899
"""Stand-in indicating you want to diff against the index."""
99100

100101
def _process_diff_args(
101102
self,
102-
args: List[Union[PathLike, "Diffable", Type["Index"]]],
103-
) -> List[Union[PathLike, "Diffable", Type["Index"]]]:
103+
args: List[Union[PathLike, "Diffable"]],
104+
) -> List[Union[PathLike, "Diffable"]]:
104105
"""
105106
:return:
106107
Possibly altered version of the given args list.
@@ -161,7 +162,7 @@ def diff(
161162
:class:`~git.objects.tree.Tree` or :class:`~git.objects.commit.Commit`, or a
162163
git command error will occur.
163164
"""
164-
args: List[Union[PathLike, Diffable, Type["Diffable.Index"]]] = []
165+
args: List[Union[PathLike, Diffable]] = []
165166
args.append("--abbrev=40") # We need full shas.
166167
args.append("--full-index") # Get full index paths, not only filenames.
167168

@@ -184,7 +185,7 @@ def diff(
184185
paths = [paths]
185186

186187
diff_cmd = self.repo.git.diff
187-
if other is self.Index:
188+
if other is Diffable.Index:
188189
args.insert(0, "--cached")
189190
elif other is NULL_TREE:
190191
args.insert(0, "-r") # Recursive diff-tree.

git/index/base.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -645,8 +645,8 @@ def write_tree(self) -> Tree:
645645

646646
def _process_diff_args(
647647
self,
648-
args: List[Union[PathLike, "git_diff.Diffable", Type["git_diff.Diffable.Index"]]],
649-
) -> List[Union[PathLike, "git_diff.Diffable", Type["git_diff.Diffable.Index"]]]:
648+
args: List[Union[PathLike, "git_diff.Diffable"]],
649+
) -> List[Union[PathLike, "git_diff.Diffable"]]:
650650
try:
651651
args.pop(args.index(self))
652652
except IndexError:
@@ -1494,7 +1494,6 @@ def diff(
14941494
Will only work with indices that represent the default git index as they
14951495
have not been initialized with a stream.
14961496
"""
1497-
14981497
# Only run if we are the default repository index.
14991498
if self._file_path != self._index_path():
15001499
raise AssertionError("Cannot call %r on indices that do not represent the default git index" % self.diff())

git/types.py

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
TypedDict,
2323
Protocol,
2424
SupportsIndex as SupportsIndex,
25+
final,
2526
runtime_checkable,
2627
)
2728
else:
@@ -30,6 +31,7 @@
3031
SupportsIndex as SupportsIndex,
3132
TypedDict,
3233
Protocol,
34+
final,
3335
runtime_checkable,
3436
)
3537

0 commit comments

Comments
 (0)