-
-
Notifications
You must be signed in to change notification settings - Fork 938
Improve static typing and docstrings related to git object types #1859
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 18 commits
f83b056
01cc8e2
6f3a20f
85889cd
9e47083
3bd8177
f3b9a69
2af7640
2aa053e
15d50de
7166703
1530fd2
2e02b09
012d710
a06f1fc
c93e431
29443ce
b6e3ad2
b5d9198
2212ac9
3c5ca52
43b7f8a
dc95a76
4191f7d
1ef3365
4083dd8
3aeef46
f1cc1fe
e133018
c34a466
4dfd480
e4fd2e3
94344b4
8e8b87a
1cdec7a
ed6ead9
0e1df29
62c0823
7204cc1
2f5e258
65863a2
c9952e1
b8a25df
e49327d
c8ad3a3
3c8cbe9
87b314e
9ed904c
aeacb00
84fc806
96ecc2e
97d9b65
ad00c77
2decbe4
88557bc
7204c13
42e10c0
465ab56
ad8190b
b9d9e56
04a2753
787f65c
1fe4dc8
7328a00
191f4cf
d1ce940
fe42ca7
e66297a
fe7f9f2
ab27827
b4b6e1e
5b2869f
1541c62
1f03e7f
e66b8f1
93d19dc
ebcfced
b070e93
0b99041
011cb0a
74f3c2e
5778b7a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,85 +33,165 @@ | |
runtime_checkable, | ||
) | ||
|
||
# if sys.version_info >= (3, 10): | ||
# from typing import TypeGuard # noqa: F401 | ||
# else: | ||
# from typing_extensions import TypeGuard # noqa: F401 | ||
|
||
PathLike = Union[str, "os.PathLike[str]"] | ||
|
||
if TYPE_CHECKING: | ||
from git.repo import Repo | ||
from git.objects import Commit, Tree, TagObject, Blob | ||
|
||
# from git.refs import SymbolicReference | ||
PathLike = Union[str, "os.PathLike[str]"] | ||
"""A :class:`str` (Unicode) based file or directory path.""" | ||
|
||
TBD = Any | ||
"""Alias of :class:`~typing.Any`, when a type hint is meant to become more specific.""" | ||
|
||
_T = TypeVar("_T") | ||
"""Type variable used internally in GitPython.""" | ||
|
||
Tree_ish = Union["Commit", "Tree"] | ||
"""Union of :class:`~git.objects.base.Object`-based types that are inherently tree-ish. | ||
|
||
See gitglossary(7) on "tree-ish": https://git-scm.com/docs/gitglossary#def_tree-ish | ||
|
||
:note: | ||
This union comprises **only** the :class:`~git.objects.commit.Commit` and | ||
:class:`~git.objects.tree.Tree` classes, **all** of whose instances are tree-ish. | ||
This is done because of the way GitPython uses it as a static type annotation. | ||
|
||
:class:`~git.objects.tag.TagObject`, some but not all of whose instances are | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for mentioning this. It's great that this type includes what GitPython can handle though, as one day it might mean it can be taught to resolve tags as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had avoided changing this since it is not inherently a wrong definition of |
||
tree-ish (those representing git tag objects that ultimately resolve to a tree or | ||
commit), is not covered as part of this union type. | ||
""" | ||
|
||
Commit_ish = Union["Commit", "TagObject", "Blob", "Tree"] | ||
Byron marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"""Union of the :class:`~git.objects.base.Object`-based types that represent git object | ||
types. This union is often usable where a commit-ish is expected, but is not actually | ||
EliahKagan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
limited to types representing commit-ish git objects. | ||
|
||
See gitglossary(7) on: | ||
|
||
* "commit-ish": https://git-scm.com/docs/gitglossary#def_commit-ish | ||
* "object type": https://git-scm.com/docs/gitglossary#def_object_type | ||
|
||
:note: | ||
This union comprises **more** classes than those whose instances really represent | ||
commit-ish git objects: | ||
|
||
* A :class:`~git.objects.commit.Commit` is of course always commit-ish, and a | ||
:class:`~git.objects.tag.TagObject` is commit-ish if, when peeled (recursively | ||
followed), a :class:`~git.objects.commit.Commit` is obtained. | ||
* However, :class:`~git.objects.blob.Blob` and :class:`~git.objects.tree.Tree` are | ||
also included, and they represent git objects that are never really commit-ish. | ||
|
||
This is an inversion of the situation with :class:`Tree_ish`, which is narrower than | ||
all tree-ish objects. It is done for practical reasons including backward | ||
compatibility. | ||
EliahKagan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
|
||
Lit_commit_ish = Literal["commit", "tag", "blob", "tree"] | ||
Byron marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"""Literal strings identifying concrete :class:`~git.objects.base.Object` subtypes | ||
representing git object types. | ||
|
||
See the :class:`Object.type <git.objects.base.Object.type>` attribute. | ||
|
||
:note: | ||
See also :class:`Commit_ish`, a union of the the :class:`~git.objects.base.Object` | ||
subtypes associated with these literal strings. | ||
|
||
:note: | ||
As noted in :class:`Commit_ish`, this is not limited to types of git objects that | ||
are actually commit-ish. | ||
""" | ||
|
||
# Config_levels --------------------------------------------------------- | ||
|
||
Lit_config_levels = Literal["system", "global", "user", "repository"] | ||
"""Type of literal strings naming git configuration levels. | ||
|
||
# Progress parameter type alias ----------------------------------------- | ||
These strings relate to which file a git configuration variable is in. | ||
""" | ||
|
||
CallableProgress = Optional[Callable[[int, Union[str, float], Union[str, float, None], str], None]] | ||
ConfigLevels_Tup = Tuple[Literal["system"], Literal["user"], Literal["global"], Literal["repository"]] | ||
"""Static type of a tuple of the four strings representing configuration levels.""" | ||
|
||
# def is_config_level(inp: str) -> TypeGuard[Lit_config_levels]: | ||
# # return inp in get_args(Lit_config_level) # only py >= 3.8 | ||
# return inp in ("system", "user", "global", "repository") | ||
# Progress parameter type alias ----------------------------------------- | ||
|
||
CallableProgress = Optional[Callable[[int, Union[str, float], Union[str, float, None], str], None]] | ||
"""General type of a progress reporter for cloning. | ||
|
||
ConfigLevels_Tup = Tuple[Literal["system"], Literal["user"], Literal["global"], Literal["repository"]] | ||
This is the type of a function or other callable that reports the progress of a clone, | ||
when passed as a ``progress`` argument to :meth:`Repo.clone <git.repo.base.Repo.clone>` | ||
or :meth:`Repo.clone_from <git.repo.base.Repo.clone_from>`. | ||
""" | ||
|
||
# ----------------------------------------------------------------------------------- | ||
|
||
|
||
def assert_never(inp: NoReturn, raise_error: bool = True, exc: Union[Exception, None] = None) -> None: | ||
"""For use in exhaustive checking of literal or Enum in if/else chain. | ||
"""For use in exhaustive checking of a literal or enum in if/else chains. | ||
|
||
Should only be reached if all members not handled OR attempt to pass non-members through chain. | ||
A call to this function should only be reached if not all members are handled, or if | ||
an attempt is made to pass non-members through the chain. | ||
|
||
If all members handled, type is Empty. Otherwise, will cause mypy error. | ||
:param inp: | ||
If all members are handled, the argument for `inp` will have the | ||
:class:`~typing.Never`/:class:`~typing.NoReturn` type. Otherwise, the type will | ||
mismatch and cause a mypy error. | ||
|
||
If non-members given, should cause mypy error at variable creation. | ||
:param raise_error: | ||
If ``True``, will also raise :class:`ValueError` with a general "unhandled | ||
literal" message, or the exception object passed as `exc`. | ||
|
||
If raise_error is True, will also raise AssertionError or the Exception passed to exc. | ||
:param exc: | ||
It not ``None``, this should be an already-constructed exception object, to be | ||
raised if `raise_error` is ``True``. | ||
""" | ||
if raise_error: | ||
if exc is None: | ||
raise ValueError(f"An unhandled Literal ({inp}) in an if/else chain was found") | ||
raise ValueError(f"An unhandled literal ({inp!r}) in an if/else chain was found") | ||
else: | ||
raise exc | ||
|
||
|
||
class Files_TD(TypedDict): | ||
"""Dictionary with stat counts for the diff of a particular file. | ||
|
||
For the :class:`~git.util.Stats.files` attribute of :class:`~git.util.Stats` | ||
objects. | ||
""" | ||
|
||
insertions: int | ||
deletions: int | ||
lines: int | ||
|
||
|
||
class Total_TD(TypedDict): | ||
"""Dictionary with total stats from any number of files. | ||
|
||
For the :class:`~git.util.Stats.total` attribute of :class:`~git.util.Stats` | ||
objects. | ||
""" | ||
|
||
insertions: int | ||
deletions: int | ||
lines: int | ||
files: int | ||
|
||
|
||
class HSH_TD(TypedDict): | ||
"""Dictionary carrying the same information as a :class:`~git.util.Stats` object.""" | ||
|
||
total: Total_TD | ||
files: Dict[PathLike, Files_TD] | ||
|
||
|
||
@runtime_checkable | ||
class Has_Repo(Protocol): | ||
"""Protocol for having a :attr:`repo` attribute, the repository to operate on.""" | ||
|
||
repo: "Repo" | ||
|
||
|
||
@runtime_checkable | ||
class Has_id_attribute(Protocol): | ||
"""Protocol for having :attr:`_id_attribute_` used in iteration and traversal.""" | ||
|
||
_id_attribute_: str |
Uh oh!
There was an error while loading. Please reload this page.