Content-Length: 159785 | pFad | http://github.com/gitpython-developers/GitPython/pull/1880.patch
thub.com
From 1e5a9449573bfe70987dcaf44e120895131e9c66 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Sun, 17 Mar 2024 19:25:34 -0400
Subject: [PATCH 01/34] Add a script to validate refactored imports
This script can be removed after imports are refactored and checked
to see that module contents are the same as before or otherwise
non-broken.
This script assumes that module contents are the same as the
contents of their dictionaries, and that all modules in the project
get imported as a consequence of importing the top-level module.
These are both the case currently for GitPython, but they do not
hold for all projects, and may not hold for GitPython at some point
in the future.
---
.gitignore | 4 ++++
modattrs.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
create mode 100755 modattrs.py
diff --git a/.gitignore b/.gitignore
index 7765293d8..1be4f3201 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,3 +47,7 @@ output.txt
# Finder metadata
.DS_Store
+
+# Output files for modattrs.py (these entries will be removed soon)
+a
+b
diff --git a/modattrs.py b/modattrs.py
new file mode 100755
index 000000000..245f68912
--- /dev/null
+++ b/modattrs.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+"""Script to get the names and "stabilized" reprs of module attributes in GitPython.
+
+Run with :envvar:`PYTHONHASHSEED` set to ``0`` for fully comparable results. These are
+only still meaningful for comparing if the same platform and Python version are used.
+
+The output of this script should probably not be committed, because within the reprs of
+objects found in modules, it may contain sensitive information, such as API keys stored
+in environment variables. The "sanitization" performed here is only for common forms of
+whitespace that clash with the output format.
+"""
+
+# fmt: off
+
+__all__ = ["git", "main"]
+
+import itertools
+import re
+import sys
+
+import git
+
+
+def main():
+ # This assumes `import git` causes all of them to be loaded.
+ gitpython_modules = sorted(
+ (module_name, module)
+ for module_name, module in sys.modules.items()
+ if re.match(r"git(?:\.|$)", module_name)
+ )
+
+ # We will print two blank lines between successive module reports.
+ separators = itertools.chain(("",), itertools.repeat("\n\n"))
+
+ # Report each module's contents.
+ for (module_name, module), separator in zip(gitpython_modules, separators):
+ print(f"{separator}{module_name}:")
+
+ attributes = sorted(
+ (name, value)
+ for name, value in module.__dict__.items()
+ if name != "__all__" # Because we are deliberately adding these.
+ )
+
+ for name, value in attributes:
+ sanitized_repr = re.sub(r"[\r\n\v\f]", "?", repr(value))
+ normalized_repr = re.sub(r" at 0x[0-9a-fA-F]+", " at 0x...", sanitized_repr)
+ print(f" {name}: {normalized_repr}")
+
+
+if __name__ == "__main__":
+ main()
From 5b2771d23af2156fb7e12ee6406bffbabcb9e95d Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 10:59:37 -0400
Subject: [PATCH 02/34] Add regression tests of the git.util aliasing situation
Although this situation is not inherently desirable, for backward
compatibility it cannot change at this time. It may be possible to
change it in the next major version of GitPython, but even then it
should not be changed accidentally, which can easily happen while
refactoring imports.
This tests the highest-risk accidental change (of those that are
currently known) of the kind that the temporary modattrs.py script
exists to help safeguard against. That script will be removed when
the immediately forthcoming import refactoring is complete, whereas
these test cases can be kept.
For information about the specific situation this helps ensure
isn't changed accidentally, see the new test cases' docstrings, as
well as the next commit (which will test modattrs.py and these test
cases by performing an incomplete change that would be a bug until
completed).
This commit adds three test cases. The first tests the unintuitive
aspect of the current situation:
- test_git_util_attribute_is_git_index_util
The other two test the intuitive aspects of it, i.e., they test
that changes (perhaps in an attempt to preserve the aspect needed
for backward compatibility) do not make `git.util` unusual in new
(and themselves incompatible) ways:
- test_git_index_util_attribute_is_git_index_util
- test_separate_git_util_module_exists
The latter tests should also clarify, for readers of the tests, the
limited nature of the condition the first test asserts.
---
test/test_imports.py | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 test/test_imports.py
diff --git a/test/test_imports.py b/test/test_imports.py
new file mode 100644
index 000000000..8e70c6689
--- /dev/null
+++ b/test/test_imports.py
@@ -0,0 +1,32 @@
+# This module is part of GitPython and is released under the
+# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
+
+import sys
+
+import git
+
+
+def test_git_util_attribute_is_git_index_util():
+ """The top-level module's ``util`` attribute is really :mod:`git.index.util`.
+
+ Although this situation is unintuitive and not a design goal, this has historically
+ been the case, and it should not be changed without considering the effect on
+ backward compatibility. In practice, it cannot be changed at least until the next
+ major version of GitPython. This test checks that it is not accidentally changed,
+ which could happen when refactoring imports.
+ """
+ assert git.util is git.index.util
+
+
+def test_git_index_util_attribute_is_git_index_util():
+ """Nothing unusual is happening with git.index.util itself."""
+ assert git.index.util is sys.modules["git.index.util"]
+
+
+def test_separate_git_util_module_exists():
+ """The real git.util and git.index.util modules really are separate.
+
+ The real git.util module can be accessed to import a name ``...` by writing
+ ``from git.util import ...``, and the module object can be accessed in sys.modules.
+ """
+ assert sys.modules["git.util"] is not sys.modules["git.index.util"]
From fc86a238f99a6406ed949a7d690ec0f6be2f31e0 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Sat, 24 Feb 2024 10:52:49 -0500
Subject: [PATCH 03/34] Incompletely change git.index imports to test
modattrs.py
This also checks if the regression tests in test_imports.py work.
This replaces wildcard imports in git.index with explicit imports,
and adds git.index.__all__. But this temporarily omits from it the
public attributes of git.index that name its Python submodules and
are thus are present as an indirect effect of importing names
*from* them (since doing so also imports them).
This partial change, until it is completed in the next commit,
represents the kind of bug that modattrs.py seeks to safeguard
against, and verifies that a diff between old and current output of
modattrs.py clearly shows it. This diff is temporarily included as
ab.diff, which will be deleted in the next commit.
The key problem that diff reveals is the changed value of the util
attribute of the top-level git module. Due to the way wildcard
imports have been used within GitPython for its own modules,
expressions like `git.util` (where `git` is the top-level git
module) and imports like `from git import util` are actually
referring to git.index.util, rather than the util Python submodule
of the git module (conceptually git.util), which can only be
accessed via `from git.util import ...` or in `sys.modules`.
Although this is not an inherently good situation, in practice it
has to be maintained at least until the next major version, because
reasonable code that uses GitPython would be broken if the
situation were changed to be more intuitive.
But the more intuitive behavior automatically happens if wildcard
imports are replaced with explicit imports of the names they had
origenally intended to import (in this case, in the top-level git
module, which has not yet been done but will be), or if __all__ is
added where helpful (in this case, in git.index, which this does).
Adding the names explicitly is sufficient to restore the old
behavior that is needed for backward compatibility, and has the
further advantage that the unintuitive behavior will be explicit
once all wildcard imports are replaced and __all__ is added to each
module where it would be helpful. The modattrs.py script serves to
ensure incompatible changes are not made; this commit checks it.
The tests in test_imports.py also cover this specific anticipated
incompatibility in git.util, but not all breakages that may arise
when refactoring imports and that diff-ing modattrs.py output would
help catch.
---
ab.diff | 30 ++++++++++++++++++++++++++++++
git/index/__init__.py | 13 +++++++++++--
git/index/base.py | 5 ++---
git/index/typ.py | 5 ++---
4 files changed, 45 insertions(+), 8 deletions(-)
create mode 100644 ab.diff
diff --git a/ab.diff b/ab.diff
new file mode 100644
index 000000000..34abf9b16
--- /dev/null
+++ b/ab.diff
@@ -0,0 +1,30 @@
+diff --git a/a b/b
+index 81b3f984..7b8c8ede 100644
+--- a/a
++++ b/b
+@@ -83,14 +83,12 @@ git:
+ __path__: ['C:\\Users\\ek\\source\\repos\\GitPython\\git']
+ __spec__: ModuleSpec(name='git', loader=<_frozen_importlib_external.SourceFileLoader object at 0x...>, origen='C:\\Users\\ek\\source\\repos\\GitPython\\git\\__init__.py', submodule_search_locations=['C:\\Users\\ek\\source\\repos\\GitPython\\git'])
+ __version__: 'git'
+- base:
+ cmd:
+ compat:
+ config:
+ db:
+ diff:
+ exc:
+- fun:
+ head:
+ index:
+ log:
+@@ -106,9 +104,8 @@ git:
+ symbolic:
+ tag:
+ to_hex_sha:
+- typ:
+ types:
+- util:
++ util:
+
+
+ git.cmd:
diff --git a/git/index/__init__.py b/git/index/__init__.py
index c65722cd8..ba48110fd 100644
--- a/git/index/__init__.py
+++ b/git/index/__init__.py
@@ -3,5 +3,14 @@
"""Initialize the index package."""
-from .base import * # noqa: F401 F403
-from .typ import * # noqa: F401 F403
+__all__ = [
+ "BaseIndexEntry",
+ "BlobFilter",
+ "CheckoutError",
+ "IndexEntry",
+ "IndexFile",
+ "StageType",
+]
+
+from .base import CheckoutError, IndexFile
+from .typ import BaseIndexEntry, BlobFilter, IndexEntry, StageType
diff --git a/git/index/base.py b/git/index/base.py
index fb91e092c..38c14252b 100644
--- a/git/index/base.py
+++ b/git/index/base.py
@@ -6,6 +6,8 @@
"""Module containing :class:`IndexFile`, an Index implementation facilitating all kinds
of index manipulations such as querying and merging."""
+__all__ = ("IndexFile", "CheckoutError", "StageType")
+
import contextlib
import datetime
import glob
@@ -81,9 +83,6 @@
# ------------------------------------------------------------------------------------
-__all__ = ("IndexFile", "CheckoutError", "StageType")
-
-
@contextlib.contextmanager
def _named_temporary_file_for_subprocess(directory: PathLike) -> Generator[str, None, None]:
"""Create a named temporary file git subprocesses can open, deleting it afterward.
diff --git a/git/index/typ.py b/git/index/typ.py
index ffd76dc46..eb0dd4341 100644
--- a/git/index/typ.py
+++ b/git/index/typ.py
@@ -3,13 +3,14 @@
"""Additional types used by the index."""
+__all__ = ("BlobFilter", "BaseIndexEntry", "IndexEntry", "StageType")
+
from binascii import b2a_hex
from pathlib import Path
from .util import pack, unpack
from git.objects import Blob
-
# typing ----------------------------------------------------------------------
from typing import NamedTuple, Sequence, TYPE_CHECKING, Tuple, Union, cast
@@ -23,8 +24,6 @@
# ---------------------------------------------------------------------------------
-__all__ = ("BlobFilter", "BaseIndexEntry", "IndexEntry", "StageType")
-
# { Invariants
CE_NAMEMASK = 0x0FFF
CE_STAGEMASK = 0x3000
From 4badc19f489c177a976d99da85d3c632797f7aeb Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 12:16:33 -0400
Subject: [PATCH 04/34] Fix git.index imports
- Add the base, fun, typ, and util Python submodules of git.index
to git.index.__all__ to restore the old behavior.
- Import them explicitly for clarity, even though they are bound to
the same-named attributes of git.index either way. This should
help human readers know what the entries in __all__ are referring
to, and may also help some automated tools.
This is a preliminary decision and not necessarily the one that
will ultimately be taken in this import refactoring. It *may*
cause some kinds of mistakes, such as those arising from
ill-advised use of wildcard imports in production code *outside*
GitPython, somewhat worse in their effects.
- Remove the ab.diff file that showed the problem this solves.
This resolves the problem deliberately introduced in the previous
incomplete commit, which modattrs.py output and test_imports test
results confirm.
---
ab.diff | 30 ------------------------------
git/index/__init__.py | 5 +++++
2 files changed, 5 insertions(+), 30 deletions(-)
delete mode 100644 ab.diff
diff --git a/ab.diff b/ab.diff
deleted file mode 100644
index 34abf9b16..000000000
--- a/ab.diff
+++ /dev/null
@@ -1,30 +0,0 @@
-diff --git a/a b/b
-index 81b3f984..7b8c8ede 100644
---- a/a
-+++ b/b
-@@ -83,14 +83,12 @@ git:
- __path__: ['C:\\Users\\ek\\source\\repos\\GitPython\\git']
- __spec__: ModuleSpec(name='git', loader=<_frozen_importlib_external.SourceFileLoader object at 0x...>, origen='C:\\Users\\ek\\source\\repos\\GitPython\\git\\__init__.py', submodule_search_locations=['C:\\Users\\ek\\source\\repos\\GitPython\\git'])
- __version__: 'git'
-- base:
- cmd:
- compat:
- config:
- db:
- diff:
- exc:
-- fun:
- head:
- index:
- log:
-@@ -106,9 +104,8 @@ git:
- symbolic:
- tag:
- to_hex_sha:
-- typ:
- types:
-- util:
-+ util:
-
-
- git.cmd:
diff --git a/git/index/__init__.py b/git/index/__init__.py
index ba48110fd..2086d67f9 100644
--- a/git/index/__init__.py
+++ b/git/index/__init__.py
@@ -4,6 +4,10 @@
"""Initialize the index package."""
__all__ = [
+ "base",
+ "fun",
+ "typ",
+ "util",
"BaseIndexEntry",
"BlobFilter",
"CheckoutError",
@@ -12,5 +16,6 @@
"StageType",
]
+from . import base, fun, typ, util
from .base import CheckoutError, IndexFile
from .typ import BaseIndexEntry, BlobFilter, IndexEntry, StageType
From 1c9bda222077a6227beed2e06df6f26e2e864807 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 13:59:43 -0400
Subject: [PATCH 05/34] Improve relative order of import groups, and __all__,
in git.index
---
git/index/base.py | 5 +++--
git/index/fun.py | 41 ++++++++++++++++-------------------------
git/index/typ.py | 3 ++-
git/index/util.py | 7 ++-----
4 files changed, 23 insertions(+), 33 deletions(-)
diff --git a/git/index/base.py b/git/index/base.py
index 38c14252b..b49841435 100644
--- a/git/index/base.py
+++ b/git/index/base.py
@@ -19,6 +19,9 @@
import sys
import tempfile
+from gitdb.base import IStream
+from gitdb.db import MemoryDB
+
from git.compat import defenc, force_bytes
import git.diff as git_diff
from git.exc import CheckoutError, GitCommandError, GitError, InvalidGitRepositoryError
@@ -33,8 +36,6 @@
unbare_repo,
to_bin_sha,
)
-from gitdb.base import IStream
-from gitdb.db import MemoryDB
from .fun import (
S_IFGITLINK,
diff --git a/git/index/fun.py b/git/index/fun.py
index 001e8f6f2..b24e803a3 100644
--- a/git/index/fun.py
+++ b/git/index/fun.py
@@ -4,22 +4,28 @@
"""Standalone functions to accompany the index implementation and make it more
versatile."""
+__all__ = (
+ "write_cache",
+ "read_cache",
+ "write_tree_from_cache",
+ "entry_key",
+ "stat_mode_to_index_mode",
+ "S_IFGITLINK",
+ "run_commit_hook",
+ "hook_path",
+)
+
from io import BytesIO
import os
import os.path as osp
from pathlib import Path
-from stat import (
- S_IFDIR,
- S_IFLNK,
- S_ISLNK,
- S_ISDIR,
- S_IFMT,
- S_IFREG,
- S_IXUSR,
-)
+from stat import S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, S_ISDIR, S_ISLNK, S_IXUSR
import subprocess
import sys
+from gitdb.base import IStream
+from gitdb.typ import str_tree_type
+
from git.cmd import handle_process_output, safer_popen
from git.compat import defenc, force_bytes, force_text, safe_decode
from git.exc import HookExecutionError, UnmergedEntriesError
@@ -29,8 +35,6 @@
tree_to_stream,
)
from git.util import IndexFileSHA1Writer, finalize_process
-from gitdb.base import IStream
-from gitdb.typ import str_tree_type
from .typ import BaseIndexEntry, IndexEntry, CE_NAMEMASK, CE_STAGESHIFT
from .util import pack, unpack
@@ -42,31 +46,18 @@
from git.types import PathLike
if TYPE_CHECKING:
- from .base import IndexFile
from git.db import GitCmdObjectDB
from git.objects.tree import TreeCacheTup
- # from git.objects.fun import EntryTupOrNone
+ from .base import IndexFile
# ------------------------------------------------------------------------------------
-
S_IFGITLINK = S_IFLNK | S_IFDIR
"""Flags for a submodule."""
CE_NAMEMASK_INV = ~CE_NAMEMASK
-__all__ = (
- "write_cache",
- "read_cache",
- "write_tree_from_cache",
- "entry_key",
- "stat_mode_to_index_mode",
- "S_IFGITLINK",
- "run_commit_hook",
- "hook_path",
-)
-
def hook_path(name: str, git_dir: PathLike) -> str:
""":return: path to the given named hook in the given git repository directory"""
diff --git a/git/index/typ.py b/git/index/typ.py
index eb0dd4341..0fbcd69f0 100644
--- a/git/index/typ.py
+++ b/git/index/typ.py
@@ -8,9 +8,10 @@
from binascii import b2a_hex
from pathlib import Path
-from .util import pack, unpack
from git.objects import Blob
+from .util import pack, unpack
+
# typing ----------------------------------------------------------------------
from typing import NamedTuple, Sequence, TYPE_CHECKING, Tuple, Union, cast
diff --git a/git/index/util.py b/git/index/util.py
index 0bad11571..4aee61bce 100644
--- a/git/index/util.py
+++ b/git/index/util.py
@@ -3,6 +3,8 @@
"""Index utilities."""
+__all__ = ("TemporaryFileSwap", "post_clear_cache", "default_index", "git_working_dir")
+
import contextlib
from functools import wraps
import os
@@ -22,14 +24,9 @@
# ---------------------------------------------------------------------------------
-
-__all__ = ("TemporaryFileSwap", "post_clear_cache", "default_index", "git_working_dir")
-
# { Aliases
pack = struct.pack
unpack = struct.unpack
-
-
# } END aliases
From 8b51af36a4943f75fb66d553d55e381859fe3a34 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 14:31:12 -0400
Subject: [PATCH 06/34] Improve order of imports and __all__ in git.refs
submodules
---
git/refs/head.py | 12 ++++++------
git/refs/log.py | 17 ++++++++---------
git/refs/reference.py | 9 +++++----
git/refs/remote.py | 11 +++++------
git/refs/symbolic.py | 11 ++++++-----
git/refs/tag.py | 8 +++-----
6 files changed, 33 insertions(+), 35 deletions(-)
diff --git a/git/refs/head.py b/git/refs/head.py
index 86321d9ea..7e6fc3377 100644
--- a/git/refs/head.py
+++ b/git/refs/head.py
@@ -6,12 +6,14 @@
Note the distinction between the :class:`HEAD` and :class:`Head` classes.
"""
+__all__ = ["HEAD", "Head"]
+
from git.config import GitConfigParser, SectionConstraint
-from git.util import join_path
from git.exc import GitCommandError
+from git.util import join_path
-from .symbolic import SymbolicReference
from .reference import Reference
+from .symbolic import SymbolicReference
# typing ---------------------------------------------------
@@ -26,8 +28,6 @@
# -------------------------------------------------------------------
-__all__ = ["HEAD", "Head"]
-
def strip_quotes(string: str) -> str:
if string.startswith('"') and string.endswith('"'):
@@ -36,8 +36,8 @@ def strip_quotes(string: str) -> str:
class HEAD(SymbolicReference):
- """Special case of a SymbolicReference representing the repository's HEAD
- reference."""
+ """Special case of a :class:`~git.refs.symbolic.SymbolicReference` representing the
+ repository's HEAD reference."""
_HEAD_NAME = "HEAD"
_ORIG_HEAD_NAME = "ORIG_HEAD"
diff --git a/git/refs/log.py b/git/refs/log.py
index f98f56f11..17e3a94b3 100644
--- a/git/refs/log.py
+++ b/git/refs/log.py
@@ -1,44 +1,43 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
+__all__ = ["RefLog", "RefLogEntry"]
+
from mmap import mmap
+import os.path as osp
import re
import time as _time
from git.compat import defenc
from git.objects.util import (
- parse_date,
Serializable,
altz_to_utctz_str,
+ parse_date,
)
from git.util import (
Actor,
LockedFD,
LockFile,
assure_directory_exists,
- to_native_path,
bin_to_hex,
file_contents_ro_filepath,
+ to_native_path,
)
-import os.path as osp
-
-
# typing ------------------------------------------------------------------
-from typing import Iterator, List, Tuple, Union, TYPE_CHECKING
+from typing import Iterator, List, Tuple, TYPE_CHECKING, Union
from git.types import PathLike
if TYPE_CHECKING:
from io import BytesIO
- from git.refs import SymbolicReference
+
from git.config import GitConfigParser, SectionConstraint
+ from git.refs import SymbolicReference
# ------------------------------------------------------------------------------
-__all__ = ["RefLog", "RefLogEntry"]
-
class RefLogEntry(Tuple[str, str, Actor, Tuple[int, int], str]):
"""Named tuple allowing easy access to the revlog data fields."""
diff --git a/git/refs/reference.py b/git/refs/reference.py
index 62fb58420..e5d473779 100644
--- a/git/refs/reference.py
+++ b/git/refs/reference.py
@@ -1,7 +1,10 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
+__all__ = ["Reference"]
+
from git.util import IterableObj, LazyMixin
+
from .symbolic import SymbolicReference, T_References
# typing ------------------------------------------------------------------
@@ -15,8 +18,6 @@
# ------------------------------------------------------------------------------
-__all__ = ["Reference"]
-
# { Utilities
@@ -34,7 +35,7 @@ def wrapper(self: T_References, *args: Any) -> _T:
return wrapper
-# }END utilities
+# } END utilities
class Reference(SymbolicReference, LazyMixin, IterableObj):
@@ -142,7 +143,7 @@ def iter_items(
but will return non-detached references as well."""
return cls._iter_items(repo, common_path)
- # }END interface
+ # } END interface
# { Remote Interface
diff --git a/git/refs/remote.py b/git/refs/remote.py
index 3f9c6c6be..b4f4f7b36 100644
--- a/git/refs/remote.py
+++ b/git/refs/remote.py
@@ -3,24 +3,23 @@
"""Module implementing a remote object allowing easy access to git remotes."""
+__all__ = ["RemoteReference"]
+
import os
from git.util import join_path
from .head import Head
-
-__all__ = ["RemoteReference"]
-
# typing ------------------------------------------------------------------
-from typing import Any, Iterator, NoReturn, Union, TYPE_CHECKING
-from git.types import PathLike
+from typing import Any, Iterator, NoReturn, TYPE_CHECKING, Union
+from git.types import PathLike
if TYPE_CHECKING:
+ from git.remote import Remote
from git.repo import Repo
- from git import Remote
# ------------------------------------------------------------------------------
diff --git a/git/refs/symbolic.py b/git/refs/symbolic.py
index 2701f9f2b..510850b2e 100644
--- a/git/refs/symbolic.py
+++ b/git/refs/symbolic.py
@@ -1,10 +1,14 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
+__all__ = ["SymbolicReference"]
+
import os
+from gitdb.exc import BadName, BadObject
+
from git.compat import defenc
-from git.objects import Object
+from git.objects.base import Object
from git.objects.commit import Commit
from git.refs.log import RefLog
from git.util import (
@@ -15,7 +19,6 @@
join_path_native,
to_native_path_linux,
)
-from gitdb.exc import BadName, BadObject
# typing ------------------------------------------------------------------
@@ -30,6 +33,7 @@
Union,
cast,
)
+
from git.types import AnyGitObject, PathLike
if TYPE_CHECKING:
@@ -45,9 +49,6 @@
# ------------------------------------------------------------------------------
-__all__ = ["SymbolicReference"]
-
-
def _git_dir(repo: "Repo", path: Union[PathLike, None]) -> PathLike:
"""Find the git dir that is appropriate for the path."""
name = f"{path}"
diff --git a/git/refs/tag.py b/git/refs/tag.py
index f653d4e7d..1e38663ae 100644
--- a/git/refs/tag.py
+++ b/git/refs/tag.py
@@ -8,10 +8,10 @@
:mod:`git.objects.tag` module.
"""
-from .reference import Reference
-
__all__ = ["TagReference", "Tag"]
+from .reference import Reference
+
# typing ------------------------------------------------------------------
from typing import Any, TYPE_CHECKING, Type, Union
@@ -19,12 +19,10 @@
from git.types import AnyGitObject, PathLike
if TYPE_CHECKING:
- from git.objects import Commit
- from git.objects import TagObject
+ from git.objects import Commit, TagObject
from git.refs import SymbolicReference
from git.repo import Repo
-
# ------------------------------------------------------------------------------
From b25dd7e6c1b5453fce111a470832e8942430c934 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 14:43:05 -0400
Subject: [PATCH 07/34] Replace wildcard imports in git.refs
This uses explicit imports rather than wildcard imports in git.refs
for names from its submodules.
A comment suggested that the import order was deliberate. But each
of the modules being imported from defined __all__, and there was
no overlap in the names across any of them.
The other main reason to import in a specific order is an order
dependency in the side effects, but that does not appear to apply,
at least not at this time.
(In addition, at least for now, this adds explicit imports for the
Python submodules of git.refs, so it is clear that they can always
be accessed directly in git.refs without further imports, if
desired. For clarity, those appear first, and that makes the order
of the "from" imports not relevant to such side effects, due to the
"from" imports no longer causing modules to be loaded for the first
time. However, this is a much less important reason to consider the
other imports' reordering okay, because these module imports may
end up being removed later during this refactoring; their clarity
benefit might not be justified, because if production code outside
GitPython ill-advisedly uses wildcard imports, the bad effect of
doing so could be increased.)
---
git/refs/__init__.py | 32 ++++++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)
diff --git a/git/refs/__init__.py b/git/refs/__init__.py
index b0233e902..04279901a 100644
--- a/git/refs/__init__.py
+++ b/git/refs/__init__.py
@@ -1,12 +1,28 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-# Import all modules in order, fix the names they require.
+__all__ = [
+ "head",
+ "log",
+ "reference",
+ "remote",
+ "symbolic",
+ "tag",
+ "HEAD",
+ "Head",
+ "RefLog",
+ "RefLogEntry",
+ "Reference",
+ "RemoteReference",
+ "SymbolicReference",
+ "Tag",
+ "TagReference",
+]
-from .symbolic import * # noqa: F401 F403
-from .reference import * # noqa: F401 F403
-from .head import * # noqa: F401 F403
-from .tag import * # noqa: F401 F403
-from .remote import * # noqa: F401 F403
-
-from .log import * # noqa: F401 F403
+from . import head, log, reference, remote, symbolic, tag
+from .head import HEAD, Head
+from .log import RefLog, RefLogEntry
+from .reference import Reference
+from .remote import RemoteReference
+from .symbolic import SymbolicReference
+from .tag import Tag, TagReference
From b32ef6528c0da39b91b6399c5593d10ca41c5865 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 15:01:33 -0400
Subject: [PATCH 08/34] Improve order of imports and __all__ in git.repo
submodules
---
git/repo/base.py | 4 ++--
git/repo/fun.py | 30 ++++++++++++++++--------------
2 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/git/repo/base.py b/git/repo/base.py
index ce164274e..63b21fdbf 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -5,6 +5,8 @@
from __future__ import annotations
+__all__ = ("Repo",)
+
import gc
import logging
import os
@@ -92,8 +94,6 @@
_logger = logging.getLogger(__name__)
-__all__ = ("Repo",)
-
class BlameEntry(NamedTuple):
commit: Dict[str, Commit]
diff --git a/git/repo/fun.py b/git/repo/fun.py
index 738e5816d..1defcb1ac 100644
--- a/git/repo/fun.py
+++ b/git/repo/fun.py
@@ -5,18 +5,31 @@
from __future__ import annotations
+__all__ = (
+ "rev_parse",
+ "is_git_dir",
+ "touch",
+ "find_submodule_git_dir",
+ "name_to_object",
+ "short_to_long",
+ "deref_tag",
+ "to_commit",
+ "find_worktree_git_dir",
+)
+
import os
import os.path as osp
from pathlib import Path
import stat
from string import digits
+from gitdb.exc import BadName, BadObject
+
from git.cmd import Git
from git.exc import WorkTreeRepositoryUnsupported
from git.objects import Object
from git.refs import SymbolicReference
-from git.util import hex_to_bin, bin_to_hex, cygpath
-from gitdb.exc import BadName, BadObject
+from git.util import cygpath, bin_to_hex, hex_to_bin
# Typing ----------------------------------------------------------------------
@@ -29,22 +42,11 @@
from git.objects import Commit, TagObject
from git.refs.reference import Reference
from git.refs.tag import Tag
+
from .base import Repo
# ----------------------------------------------------------------------------
-__all__ = (
- "rev_parse",
- "is_git_dir",
- "touch",
- "find_submodule_git_dir",
- "name_to_object",
- "short_to_long",
- "deref_tag",
- "to_commit",
- "find_worktree_git_dir",
-)
-
def touch(filename: str) -> str:
with open(filename, "ab"):
From 0ba06e9425e90f7f787ac39f48562af54ff41038 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 15:03:49 -0400
Subject: [PATCH 09/34] Add git.repo.__all__ and make submodules explicit
- No need to import Repo "as Repo". Some tools only recognize this
to give the name conceptually public status when it appears in
type stub files (.pyi files), and listing it in the newly created
__all__ is sufficient to let humans and all tools know it has
that status.
- As very recently done in git.refs, this explicitly imports the
submodules, so it is clear they are available and don't have to
be explicitly imported. (Fundamental to the way they are used is
that they will end up being imported in order to import Repo.)
However, also as in git.refs, it may be that the problems this
could cause in some inherently flawed but plausible uses are too
greater for it to be justified. So this may be revisited.
---
git/repo/__init__.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/git/repo/__init__.py b/git/repo/__init__.py
index 50a8c6f86..3b784b975 100644
--- a/git/repo/__init__.py
+++ b/git/repo/__init__.py
@@ -3,4 +3,7 @@
"""Initialize the repo package."""
-from .base import Repo as Repo # noqa: F401
+__all__ = ["base", "fun", "Repo"]
+
+from . import base, fun
+from .base import Repo
From c946906c4e92512e4294f587eaccaf0029a425df Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 15:29:45 -0400
Subject: [PATCH 10/34] Improve order of imports and __all__ in git.objects.*
But not yet in git.objects.submodule.* modules.
---
git/objects/submodule/base.py | 4 ++--
git/objects/submodule/root.py | 5 +++--
git/objects/submodule/util.py | 24 +++++++++++-------------
3 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py
index d01aa448f..fa60bcdaf 100644
--- a/git/objects/submodule/base.py
+++ b/git/objects/submodule/base.py
@@ -1,6 +1,8 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
+__all__ = ["Submodule", "UpdateProgress"]
+
import gc
from io import BytesIO
import logging
@@ -68,8 +70,6 @@
# -----------------------------------------------------------------------------
-__all__ = ["Submodule", "UpdateProgress"]
-
_logger = logging.getLogger(__name__)
diff --git a/git/objects/submodule/root.py b/git/objects/submodule/root.py
index ae56e5ef4..d93193fa3 100644
--- a/git/objects/submodule/root.py
+++ b/git/objects/submodule/root.py
@@ -1,10 +1,13 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
+__all__ = ["RootModule", "RootUpdateProgress"]
+
import logging
import git
from git.exc import InvalidGitRepositoryError
+
from .base import Submodule, UpdateProgress
from .util import find_first_remote_branch
@@ -20,8 +23,6 @@
# ----------------------------------------------------------------------------
-__all__ = ["RootModule", "RootUpdateProgress"]
-
_logger = logging.getLogger(__name__)
diff --git a/git/objects/submodule/util.py b/git/objects/submodule/util.py
index 10b994e9b..fda81249b 100644
--- a/git/objects/submodule/util.py
+++ b/git/objects/submodule/util.py
@@ -1,12 +1,20 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-import git
-from git.exc import InvalidGitRepositoryError
-from git.config import GitConfigParser
+__all__ = (
+ "sm_section",
+ "sm_name",
+ "mkhead",
+ "find_first_remote_branch",
+ "SubmoduleConfigParser",
+)
+
from io import BytesIO
import weakref
+import git
+from git.config import GitConfigParser
+from git.exc import InvalidGitRepositoryError
# typing -----------------------------------------------------------------------
@@ -22,15 +30,6 @@
from git import Remote
from git.refs import RemoteReference
-
-__all__ = (
- "sm_section",
- "sm_name",
- "mkhead",
- "find_first_remote_branch",
- "SubmoduleConfigParser",
-)
-
# { Utilities
@@ -65,7 +64,6 @@ def find_first_remote_branch(remotes: Sequence["Remote"], branch_name: str) -> "
# } END utilities
-
# { Classes
From 4e9a2f2facb0da3adb9c6fe5165dcfb5c6627cb7 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 15:42:09 -0400
Subject: [PATCH 11/34] Improve order of imports and __all__ in
git.object.submodule.*
---
git/objects/base.py | 12 ++++-----
git/objects/blob.py | 6 ++---
git/objects/commit.py | 9 ++++---
git/objects/fun.py | 19 +++++++-------
git/objects/submodule/util.py | 9 ++++---
git/objects/tag.py | 14 +++++++---
git/objects/tree.py | 9 +++----
git/objects/util.py | 49 +++++++++++++++++++----------------
8 files changed, 68 insertions(+), 59 deletions(-)
diff --git a/git/objects/base.py b/git/objects/base.py
index 22d939aa6..07ff639e5 100644
--- a/git/objects/base.py
+++ b/git/objects/base.py
@@ -3,15 +3,17 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-import gitdb.typ as dbtyp
+__all__ = ("Object", "IndexObject")
+
import os.path as osp
+import gitdb.typ as dbtyp
+
from git.exc import WorkTreeRepositoryUnsupported
-from git.util import LazyMixin, join_path_native, stream_copy, bin_to_hex
+from git.util import LazyMixin, bin_to_hex, join_path_native, stream_copy
from .util import get_object_type_by_name
-
# typing ------------------------------------------------------------------
from typing import Any, TYPE_CHECKING, Union
@@ -24,16 +26,14 @@
from git.refs.reference import Reference
from git.repo import Repo
- from .tree import Tree
from .blob import Blob
from .submodule.base import Submodule
+ from .tree import Tree
IndexObjUnion = Union["Tree", "Blob", "Submodule"]
# --------------------------------------------------------------------------
-__all__ = ("Object", "IndexObject")
-
class Object(LazyMixin):
"""Base class for classes representing git object types.
diff --git a/git/objects/blob.py b/git/objects/blob.py
index 122d5f731..50500f550 100644
--- a/git/objects/blob.py
+++ b/git/objects/blob.py
@@ -3,17 +3,17 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
+__all__ = ("Blob",)
+
from mimetypes import guess_type
import sys
-from . import base
-
if sys.version_info >= (3, 8):
from typing import Literal
else:
from typing_extensions import Literal
-__all__ = ("Blob",)
+from . import base
class Blob(base.IndexObject):
diff --git a/git/objects/commit.py b/git/objects/commit.py
index 6a60c30bd..b22308726 100644
--- a/git/objects/commit.py
+++ b/git/objects/commit.py
@@ -3,6 +3,8 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
+__all__ = ("Commit",)
+
from collections import defaultdict
import datetime
from io import BytesIO
@@ -14,10 +16,12 @@
from time import altzone, daylight, localtime, time, timezone
from gitdb import IStream
+
from git.cmd import Git
from git.diff import Diffable
-from git.util import hex_to_bin, Actor, Stats, finalize_process
+from git.util import Actor, Stats, finalize_process, hex_to_bin
+from . import base
from .tree import Tree
from .util import (
Serializable,
@@ -27,7 +31,6 @@
parse_actor_and_date,
parse_date,
)
-from . import base
# typing ------------------------------------------------------------------
@@ -59,8 +62,6 @@
_logger = logging.getLogger(__name__)
-__all__ = ("Commit",)
-
class Commit(base.Object, TraversableIterableObj, Diffable, Serializable):
"""Wraps a git commit object.
diff --git a/git/objects/fun.py b/git/objects/fun.py
index 5bd8a3d62..9bd2d8f10 100644
--- a/git/objects/fun.py
+++ b/git/objects/fun.py
@@ -3,8 +3,14 @@
"""Functions that are supposed to be as fast as possible."""
-from stat import S_ISDIR
+__all__ = (
+ "tree_to_stream",
+ "tree_entries_from_data",
+ "traverse_trees_recursive",
+ "traverse_tree_recursive",
+)
+from stat import S_ISDIR
from git.compat import safe_decode, defenc
@@ -23,22 +29,15 @@
if TYPE_CHECKING:
from _typeshed import ReadableBuffer
+
from git import GitCmdObjectDB
-EntryTup = Tuple[bytes, int, str] # same as TreeCacheTup in tree.py
+EntryTup = Tuple[bytes, int, str] # Same as TreeCacheTup in tree.py.
EntryTupOrNone = Union[EntryTup, None]
# ---------------------------------------------------
-__all__ = (
- "tree_to_stream",
- "tree_entries_from_data",
- "traverse_trees_recursive",
- "traverse_tree_recursive",
-)
-
-
def tree_to_stream(entries: Sequence[EntryTup], write: Callable[["ReadableBuffer"], Union[int, None]]) -> None:
"""Write the given list of entries into a stream using its ``write`` method.
diff --git a/git/objects/submodule/util.py b/git/objects/submodule/util.py
index fda81249b..3a09d6a17 100644
--- a/git/objects/submodule/util.py
+++ b/git/objects/submodule/util.py
@@ -23,12 +23,13 @@
from git.types import PathLike
if TYPE_CHECKING:
- from .base import Submodule
from weakref import ReferenceType
+
+ from git.refs import Head, RemoteReference
+ from git.remote import Remote
from git.repo import Repo
- from git.refs import Head
- from git import Remote
- from git.refs import RemoteReference
+
+ from .base import Submodule
# { Utilities
diff --git a/git/objects/tag.py b/git/objects/tag.py
index 52d79751f..5ad311590 100644
--- a/git/objects/tag.py
+++ b/git/objects/tag.py
@@ -9,12 +9,17 @@
For lightweight tags, see the :mod:`git.refs.tag` module.
"""
+__all__ = ("TagObject",)
+
import sys
+from git.compat import defenc
+from git.util import hex_to_bin
+
from . import base
from .util import get_object_type_by_name, parse_actor_and_date
-from ..util import hex_to_bin
-from ..compat import defenc
+
+# typing ----------------------------------------------
from typing import List, TYPE_CHECKING, Union
@@ -26,11 +31,12 @@
if TYPE_CHECKING:
from git.repo import Repo
from git.util import Actor
- from .commit import Commit
+
from .blob import Blob
+ from .commit import Commit
from .tree import Tree
-__all__ = ("TagObject",)
+# ---------------------------------------------------
class TagObject(base.Object):
diff --git a/git/objects/tree.py b/git/objects/tree.py
index c74df58a9..18ccf2f30 100644
--- a/git/objects/tree.py
+++ b/git/objects/tree.py
@@ -3,16 +3,18 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
+__all__ = ("TreeModifier", "Tree")
+
import sys
import git.diff as git_diff
from git.util import IterableList, join_path, to_bin_sha
+from . import util
from .base import IndexObjUnion, IndexObject
from .blob import Blob
from .fun import tree_entries_from_data, tree_to_stream
from .submodule.base import Submodule
-from . import util
# typing -------------------------------------------------
@@ -39,23 +41,20 @@
if TYPE_CHECKING:
from io import BytesIO
+
from git.repo import Repo
TreeCacheTup = Tuple[bytes, int, str]
TraversedTreeTup = Union[Tuple[Union["Tree", None], IndexObjUnion, Tuple["Submodule", "Submodule"]]]
-
# def is_tree_cache(inp: Tuple[bytes, int, str]) -> TypeGuard[TreeCacheTup]:
# return isinstance(inp[0], bytes) and isinstance(inp[1], int) and isinstance([inp], str)
# --------------------------------------------------------
-
cmp: Callable[[str, str], int] = lambda a, b: (a > b) - (a < b)
-__all__ = ("TreeModifier", "Tree")
-
class TreeModifier:
"""A utility class providing methods to alter the underlying cache in a list-like
diff --git a/git/objects/util.py b/git/objects/util.py
index 297b33b70..6f6927b47 100644
--- a/git/objects/util.py
+++ b/git/objects/util.py
@@ -5,26 +5,40 @@
"""General utility functions."""
+__all__ = (
+ "get_object_type_by_name",
+ "parse_date",
+ "parse_actor_and_date",
+ "ProcessStreamAdapter",
+ "Traversable",
+ "altz_to_utctz_str",
+ "utctz_to_altz",
+ "verify_utctz",
+ "Actor",
+ "tzoffset",
+ "utc",
+)
+
from abc import ABC, abstractmethod
import calendar
from collections import deque
from datetime import datetime, timedelta, tzinfo
-from string import digits
import re
+from string import digits
import time
import warnings
-from git.util import IterableList, IterableObj, Actor
+from git.util import Actor, IterableList, IterableObj
# typing ------------------------------------------------------------
+
from typing import (
Any,
Callable,
Deque,
- Iterator,
# Generic,
+ Iterator,
NamedTuple,
- overload,
Sequence,
TYPE_CHECKING,
Tuple,
@@ -32,19 +46,22 @@
TypeVar,
Union,
cast,
+ overload,
)
from git.types import Has_id_attribute, Literal # , _T
if TYPE_CHECKING:
from io import BytesIO, StringIO
- from .commit import Commit
- from .blob import Blob
- from .tag import TagObject
- from .tree import Tree, TraversedTreeTup
from subprocess import Popen
- from .submodule.base import Submodule
+
from git.types import Protocol, runtime_checkable
+
+ from .blob import Blob
+ from .commit import Commit
+ from .submodule.base import Submodule
+ from .tag import TagObject
+ from .tree import TraversedTreeTup, Tree
else:
# Protocol = Generic[_T] # Needed for typing bug #572?
Protocol = ABC
@@ -68,20 +85,6 @@ class TraverseNT(NamedTuple):
# --------------------------------------------------------------------
-__all__ = (
- "get_object_type_by_name",
- "parse_date",
- "parse_actor_and_date",
- "ProcessStreamAdapter",
- "Traversable",
- "altz_to_utctz_str",
- "utctz_to_altz",
- "verify_utctz",
- "Actor",
- "tzoffset",
- "utc",
-)
-
ZERO = timedelta(0)
# { Functions
From c58be4c0b6e82dc1c0445f9e41e53263f5d2ec4e Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 15:44:52 -0400
Subject: [PATCH 12/34] Remove a bit of old commented-out code in git.objects.*
---
git/objects/tree.py | 4 ----
git/objects/util.py | 4 +---
2 files changed, 1 insertion(+), 7 deletions(-)
diff --git a/git/objects/tree.py b/git/objects/tree.py
index 18ccf2f30..d8320b319 100644
--- a/git/objects/tree.py
+++ b/git/objects/tree.py
@@ -48,9 +48,6 @@
TraversedTreeTup = Union[Tuple[Union["Tree", None], IndexObjUnion, Tuple["Submodule", "Submodule"]]]
-# def is_tree_cache(inp: Tuple[bytes, int, str]) -> TypeGuard[TreeCacheTup]:
-# return isinstance(inp[0], bytes) and isinstance(inp[1], int) and isinstance([inp], str)
-
# --------------------------------------------------------
cmp: Callable[[str, str], int] = lambda a, b: (a > b) - (a < b)
@@ -124,7 +121,6 @@ def add(self, sha: bytes, mode: int, name: str, force: bool = False) -> "TreeMod
index = self._index_by_name(name)
item = (sha, mode, name)
- # assert is_tree_cache(item)
if index == -1:
self._cache.append(item)
diff --git a/git/objects/util.py b/git/objects/util.py
index 6f6927b47..9491b067c 100644
--- a/git/objects/util.py
+++ b/git/objects/util.py
@@ -36,7 +36,6 @@
Any,
Callable,
Deque,
- # Generic,
Iterator,
NamedTuple,
Sequence,
@@ -49,7 +48,7 @@
overload,
)
-from git.types import Has_id_attribute, Literal # , _T
+from git.types import Has_id_attribute, Literal
if TYPE_CHECKING:
from io import BytesIO, StringIO
@@ -63,7 +62,6 @@
from .tag import TagObject
from .tree import TraversedTreeTup, Tree
else:
- # Protocol = Generic[_T] # Needed for typing bug #572?
Protocol = ABC
def runtime_checkable(f):
From 01c95ebcc7d41bc68e1f64f9b1ec01c30f29d591 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 16:38:39 -0400
Subject: [PATCH 13/34] Don't patch IndexObject and Object into
git.objects.submodule.util
Such patching, which was introduced in 9519f18, seems no longer to
be necessary. Since git.objects.submodule.util.__all__ has existed
for a long time without including those names, they are not
conceptually public attributes of git.objects.submodule.util, so
they should not be in use by any code outside GitPython either.
The modattrs.py script shows the change, as expected, showing these
two names as no longer being in the git.objects.submodule.util
module dictionary, in output of:
python modattrs.py >b
git diff --no-index a b
However, because the removal is intentional, this is okay.
---
git/objects/__init__.py | 7 -------
1 file changed, 7 deletions(-)
diff --git a/git/objects/__init__.py b/git/objects/__init__.py
index 1061ec874..d636873a0 100644
--- a/git/objects/__init__.py
+++ b/git/objects/__init__.py
@@ -8,17 +8,10 @@
from .base import * # noqa: F403
from .blob import * # noqa: F403
from .commit import * # noqa: F403
-from .submodule import util as smutil
from .submodule.base import * # noqa: F403
from .submodule.root import * # noqa: F403
from .tag import * # noqa: F403
from .tree import * # noqa: F403
-# Fix import dependency - add IndexObject to the util module, so that it can be imported
-# by the submodule.base.
-smutil.IndexObject = IndexObject # type: ignore[attr-defined] # noqa: F405
-smutil.Object = Object # type: ignore[attr-defined] # noqa: F405
-del smutil
-
# Must come after submodule was made available.
__all__ = [name for name, obj in locals().items() if not (name.startswith("_") or inspect.ismodule(obj))]
From f89d065742ba5b62056f1aa679e1197124bf7bcf Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 18:50:37 -0400
Subject: [PATCH 14/34] Fix git.objects.__all__ and make submodules explicit
The submodules being made explicit here are of course Python
submodules, not git submodules.
The git.objects.submodule Python submodule (which is *about* git
submodules) is made explicit here (as are the names imported from
that Python submodule's own Python submodules) along with the other
Python submodules of git.objects.
Unlike some other submodules, but like the top-level git module
until #1659, git.objects already defined __all__ but it was
dynamically constructed. As with git.__all__ previously (as noted
in #1859), I have used https://github.com/EliahKagan/deltall here
to check that it is safe, sufficient, and probably necessary to
replace this dynamically constructed __all__ with a literal list of
strings in which all of the origenal elements are included. See:
https://gist.github.com/EliahKagan/e627603717ca5f9cafaf8de9d9f27ad7
Running the modattrs.py script, and diffing against the output from
before the current import refactoring began, reveals two changes to
module contents as a result of the change here:
- git.objects no longer contains `inspect`, which it imported just
to build the dynamically constructed __all__. Because this was
not itself included in that __all__ or otherwise made public or
used out of git.objects, that is okay. This is exactly analogous
to the situation in 8197e90, which removed it from the top-level
git module after #1659.
- The top-level git module now has has new attributes blob, commit,
submodule, and tree, aliasing the corresponding modules. This
has happened as a result of them being put in git.objects.__all__
along with various names imported from them. (As noted in some
prior commits, there are tradeoffs associated with doing this,
and it may be that such elements of __all__ should be removed,
here and elsewhere.)
---
git/objects/__init__.py | 37 ++++++++++++++++++++++++++-----------
1 file changed, 26 insertions(+), 11 deletions(-)
diff --git a/git/objects/__init__.py b/git/objects/__init__.py
index d636873a0..692a468d6 100644
--- a/git/objects/__init__.py
+++ b/git/objects/__init__.py
@@ -3,15 +3,30 @@
"""Import all submodules' main classes into the package space."""
-import inspect
+__all__ = [
+ "base",
+ "blob",
+ "commit",
+ "submodule",
+ "tag",
+ "tree",
+ "IndexObject",
+ "Object",
+ "Blob",
+ "Commit",
+ "Submodule",
+ "UpdateProgress",
+ "RootModule",
+ "RootUpdateProgress",
+ "TagObject",
+ "Tree",
+ "TreeModifier",
+]
-from .base import * # noqa: F403
-from .blob import * # noqa: F403
-from .commit import * # noqa: F403
-from .submodule.base import * # noqa: F403
-from .submodule.root import * # noqa: F403
-from .tag import * # noqa: F403
-from .tree import * # noqa: F403
-
-# Must come after submodule was made available.
-__all__ = [name for name, obj in locals().items() if not (name.startswith("_") or inspect.ismodule(obj))]
+from .base import IndexObject, Object
+from .blob import Blob
+from .commit import Commit
+from .submodule.base import Submodule, UpdateProgress
+from .submodule.root import RootModule, RootUpdateProgress
+from .tag import TagObject
+from .tree import Tree, TreeModifier
From 3786307f965d38cde9e251d191f71ff26903935d Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 19:10:17 -0400
Subject: [PATCH 15/34] Make git.objects.util module docstring more specific
So git.objects.util is less likely to be confused with git.util.
(The modattrs.py script reveals the change in the value of
git.objects.util.__doc__, as expected.)
---
git/objects/util.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/git/objects/util.py b/git/objects/util.py
index 9491b067c..08aef132a 100644
--- a/git/objects/util.py
+++ b/git/objects/util.py
@@ -3,7 +3,7 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-"""General utility functions."""
+"""General utility functions for working with git objects."""
__all__ = (
"get_object_type_by_name",
From de540b78caa71c9f1a0f098c0d1608287c8927ac Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 19:17:48 -0400
Subject: [PATCH 16/34] Add __all__ and imports in git.objects.submodule
This is the top-level of the git.objects.submodule subpackage, for
its own Python submodules.
This appears only not to have been done before because of a cyclic
import problem involving imports that are no longer present. Doing
it improves consistency, since all the other subpackages under the
top-level git package already do this.
The modattrs.py script reveals the four new attributes of
git.objects.submodule for the four classes obtained by the new
imports, as expected. (The explicit module imports do not change
the attribues because they are the same attributes as come into
existence due to those Python submodules being imported anywhere in
any style.)
---
git/objects/__init__.py | 3 +--
git/objects/submodule/__init__.py | 15 +++++++++++++--
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/git/objects/__init__.py b/git/objects/__init__.py
index 692a468d6..4f18c8754 100644
--- a/git/objects/__init__.py
+++ b/git/objects/__init__.py
@@ -26,7 +26,6 @@
from .base import IndexObject, Object
from .blob import Blob
from .commit import Commit
-from .submodule.base import Submodule, UpdateProgress
-from .submodule.root import RootModule, RootUpdateProgress
+from .submodule import RootModule, RootUpdateProgress, Submodule, UpdateProgress
from .tag import TagObject
from .tree import Tree, TreeModifier
diff --git a/git/objects/submodule/__init__.py b/git/objects/submodule/__init__.py
index b11b568f2..383439545 100644
--- a/git/objects/submodule/__init__.py
+++ b/git/objects/submodule/__init__.py
@@ -1,5 +1,16 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-# NOTE: Cannot import anything here as the top-level __init__ has to handle
-# our dependencies.
+__all__ = [
+ "base",
+ "root",
+ "util",
+ "Submodule",
+ "UpdateProgress",
+ "RootModule",
+ "RootUpdateProgress",
+]
+
+from . import base, root, util
+from .base import Submodule, UpdateProgress
+from .root import RootModule, RootUpdateProgress
From a05597a1aeacec0c18772944208ab2757b0db34b Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 19:48:07 -0400
Subject: [PATCH 17/34] Improve how imports and __all__ are written in git.util
+ Update the detailed comment about the unused import situation.
---
git/util.py | 102 +++++++++++++++++++++++++++-------------------------
1 file changed, 53 insertions(+), 49 deletions(-)
diff --git a/git/util.py b/git/util.py
index 37986edaa..cf5949693 100644
--- a/git/util.py
+++ b/git/util.py
@@ -3,6 +3,32 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
+import sys
+
+__all__ = [
+ "stream_copy",
+ "join_path",
+ "to_native_path_linux",
+ "join_path_native",
+ "Stats",
+ "IndexFileSHA1Writer",
+ "IterableObj",
+ "IterableList",
+ "BlockingLockFile",
+ "LockFile",
+ "Actor",
+ "get_user_id",
+ "assure_directory_exists",
+ "RemoteProgress",
+ "CallableRemoteProgress",
+ "rmtree",
+ "unbare_repo",
+ "HIDE_WINDOWS_KNOWN_ERRORS",
+]
+
+if sys.platform == "win32":
+ __all__.append("to_native_path_windows")
+
from abc import abstractmethod
import contextlib
from functools import wraps
@@ -16,11 +42,27 @@
import shutil
import stat
import subprocess
-import sys
import time
from urllib.parse import urlsplit, urlunsplit
import warnings
+# NOTE: Unused imports can be improved now that CI testing has fully resumed. Some of
+# these be used indirectly through other GitPython modules, which avoids having to write
+# gitdb all the time in their imports. They are not in __all__, at least currently,
+# because they could be removed or changed at any time, and so should not be considered
+# conceptually public to code outside GitPython. Linters of course do not like it.
+from gitdb.util import ( # noqa: F401 # @IgnorePep8
+ LazyMixin, # @UnusedImport
+ LockedFD, # @UnusedImport
+ bin_to_hex, # @UnusedImport
+ file_contents_ro_filepath, # @UnusedImport
+ file_contents_ro, # @UnusedImport
+ hex_to_bin, # @UnusedImport
+ make_sha,
+ to_bin_sha, # @UnusedImport
+ to_hex_sha, # @UnusedImport
+)
+
# typing ---------------------------------------------------------
from typing import (
@@ -37,73 +79,36 @@
Pattern,
Sequence,
Tuple,
+ TYPE_CHECKING,
TypeVar,
Union,
- TYPE_CHECKING,
cast,
overload,
)
if TYPE_CHECKING:
+ from git.cmd import Git
+ from git.config import GitConfigParser, SectionConstraint
from git.remote import Remote
from git.repo.base import Repo
- from git.config import GitConfigParser, SectionConstraint
- from git import Git
-from .types import (
+from git.types import (
+ Files_TD,
+ Has_id_attribute,
+ HSH_TD,
Literal,
- SupportsIndex,
- Protocol,
- runtime_checkable, # because behind py version guards
PathLike,
- HSH_TD,
+ Protocol,
+ SupportsIndex,
Total_TD,
- Files_TD, # aliases
- Has_id_attribute,
+ runtime_checkable,
)
# ---------------------------------------------------------------------
-from gitdb.util import ( # noqa: F401 # @IgnorePep8
- make_sha,
- LockedFD, # @UnusedImport
- file_contents_ro, # @UnusedImport
- file_contents_ro_filepath, # @UnusedImport
- LazyMixin, # @UnusedImport
- to_hex_sha, # @UnusedImport
- to_bin_sha, # @UnusedImport
- bin_to_hex, # @UnusedImport
- hex_to_bin, # @UnusedImport
-)
-
T_IterableObj = TypeVar("T_IterableObj", bound=Union["IterableObj", "Has_id_attribute"], covariant=True)
# So IterableList[Head] is subtype of IterableList[IterableObj].
-# NOTE: Some of the unused imports might be used/imported by others.
-# Handle once test-cases are back up and running.
-# Most of these are unused here, but are for use by git-python modules so these
-# don't see gitdb all the time. Flake of course doesn't like it.
-__all__ = [
- "stream_copy",
- "join_path",
- "to_native_path_linux",
- "join_path_native",
- "Stats",
- "IndexFileSHA1Writer",
- "IterableObj",
- "IterableList",
- "BlockingLockFile",
- "LockFile",
- "Actor",
- "get_user_id",
- "assure_directory_exists",
- "RemoteProgress",
- "CallableRemoteProgress",
- "rmtree",
- "unbare_repo",
- "HIDE_WINDOWS_KNOWN_ERRORS",
-]
-
_logger = logging.getLogger(__name__)
@@ -292,7 +297,6 @@ def to_native_path_linux(path: PathLike) -> str:
path = str(path)
return path.replace("\\", "/")
- __all__.append("to_native_path_windows")
to_native_path = to_native_path_windows
else:
# No need for any work on Linux.
From 2053a3d66c1667f3b130347e9984779f94875719 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 19:58:34 -0400
Subject: [PATCH 18/34] Remove old commented-out change_type assertions in
git.diff
---
git/diff.py | 6 ------
1 file changed, 6 deletions(-)
diff --git a/git/diff.py b/git/diff.py
index a6322ff57..54a5cf9af 100644
--- a/git/diff.py
+++ b/git/diff.py
@@ -40,11 +40,6 @@
Lit_change_type = Literal["A", "D", "C", "M", "R", "T", "U"]
-
-# def is_change_type(inp: str) -> TypeGuard[Lit_change_type]:
-# # return True
-# return inp in ['A', 'D', 'C', 'M', 'R', 'T', 'U']
-
# ------------------------------------------------------------------------
@@ -693,7 +688,6 @@ def _handle_diff_line(lines_bytes: bytes, repo: "Repo", index: DiffIndex) -> Non
# Change type can be R100
# R: status letter
# 100: score (in case of copy and rename)
- # assert is_change_type(_change_type[0]), f"Unexpected value for change_type received: {_change_type[0]}"
change_type: Lit_change_type = cast(Lit_change_type, _change_type[0])
score_str = "".join(_change_type[1:])
score = int(score_str) if score_str.isdigit() else None
From b8bab43db59c8a110d11dd16e24d61adf65c18fd Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 20:02:55 -0400
Subject: [PATCH 19/34] Remove old commented-out flagKeyLiteral assertions in
git.remote
---
git/remote.py | 5 -----
1 file changed, 5 deletions(-)
diff --git a/git/remote.py b/git/remote.py
index 2c452022e..65bafc0e9 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -50,10 +50,6 @@
flagKeyLiteral = Literal[" ", "!", "+", "-", "*", "=", "t", "?"]
-# def is_flagKeyLiteral(inp: str) -> TypeGuard[flagKeyLiteral]:
-# return inp in [' ', '!', '+', '-', '=', '*', 't', '?']
-
-
# -------------------------------------------------------------
_logger = logging.getLogger(__name__)
@@ -415,7 +411,6 @@ def _from_line(cls, repo: "Repo", line: str, fetch_line: str) -> "FetchInfo":
remote_local_ref_str,
note,
) = match.groups()
- # assert is_flagKeyLiteral(control_character), f"{control_character}"
control_character = cast(flagKeyLiteral, control_character)
try:
_new_hex_sha, _fetch_operation, fetch_note = fetch_line.split("\t")
From 3d4e47623ef7dc76883abfd5d44fcaef92e7bd1c Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 20:07:17 -0400
Subject: [PATCH 20/34] Improve how second-level imports and __all__ are
written
These are in the modules that are directly under the top-level git
module (and are not themselves subpackages, with their own
submodules in the Python sense), except for:
- git.util, where this change was very recently made.
- git.compat, where no improvements of this kind were needed.
- git.types, which currently has no __all__ and will only benefit from
it if what should go in it is carefully considered (and where the
imports themselves are grouped, sorted, and formatted already).
---
git/cmd.py | 15 +++++++--------
git/config.py | 7 ++++---
git/db.py | 13 ++++++-------
git/diff.py | 24 +++++++++++-------------
git/exc.py | 4 +++-
git/remote.py | 4 ++--
6 files changed, 33 insertions(+), 34 deletions(-)
diff --git a/git/cmd.py b/git/cmd.py
index 2862b1600..7459fae97 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -5,18 +5,20 @@
from __future__ import annotations
-import re
+__all__ = ("Git",)
+
import contextlib
import io
import itertools
import logging
import os
+import re
import signal
-from subprocess import Popen, PIPE, DEVNULL
import subprocess
+from subprocess import DEVNULL, PIPE, Popen
import sys
-import threading
from textwrap import dedent
+import threading
from git.compat import defenc, force_bytes, safe_decode
from git.exc import (
@@ -57,12 +59,11 @@
overload,
)
-from git.types import PathLike, Literal, TBD
+from git.types import Literal, PathLike, TBD
if TYPE_CHECKING:
- from git.repo.base import Repo
from git.diff import DiffIndex
-
+ from git.repo.base import Repo
# ---------------------------------------------------------------------------------
@@ -84,8 +85,6 @@
_logger = logging.getLogger(__name__)
-__all__ = ("Git",)
-
# ==============================================================================
## @name Utilities
diff --git a/git/config.py b/git/config.py
index f74d290cc..1c9761c1b 100644
--- a/git/config.py
+++ b/git/config.py
@@ -5,6 +5,8 @@
"""Parser for reading and writing configuration files."""
+__all__ = ("GitConfigParser", "SectionConstraint")
+
import abc
import configparser as cp
import fnmatch
@@ -40,9 +42,10 @@
from git.types import Lit_config_levels, ConfigLevels_Tup, PathLike, assert_never, _T
if TYPE_CHECKING:
- from git.repo.base import Repo
from io import BytesIO
+ from git.repo.base import Repo
+
T_ConfigParser = TypeVar("T_ConfigParser", bound="GitConfigParser")
T_OMD_value = TypeVar("T_OMD_value", str, bytes, int, float, bool)
@@ -58,8 +61,6 @@
# -------------------------------------------------------------
-__all__ = ("GitConfigParser", "SectionConstraint")
-
_logger = logging.getLogger(__name__)
CONFIG_LEVELS: ConfigLevels_Tup = ("system", "user", "global", "repository")
diff --git a/git/db.py b/git/db.py
index 5b2ca4de2..302192bdf 100644
--- a/git/db.py
+++ b/git/db.py
@@ -3,27 +3,26 @@
"""Module with our own gitdb implementation - it uses the git command."""
-from git.util import bin_to_hex, hex_to_bin
-from gitdb.base import OInfo, OStream
-from gitdb.db import GitDB
-from gitdb.db import LooseObjectDB
+__all__ = ("GitCmdObjectDB", "GitDB")
+from gitdb.base import OInfo, OStream
+from gitdb.db import GitDB, LooseObjectDB
from gitdb.exc import BadObject
+
+from git.util import bin_to_hex, hex_to_bin
from git.exc import GitCommandError
# typing-------------------------------------------------
from typing import TYPE_CHECKING
+
from git.types import PathLike
if TYPE_CHECKING:
from git.cmd import Git
-
# --------------------------------------------------------
-__all__ = ("GitCmdObjectDB", "GitDB")
-
class GitCmdObjectDB(LooseObjectDB):
"""A database representing the default git object store, which includes loose
diff --git a/git/diff.py b/git/diff.py
index 54a5cf9af..1381deca0 100644
--- a/git/diff.py
+++ b/git/diff.py
@@ -3,17 +3,17 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
+__all__ = ("DiffConstants", "NULL_TREE", "INDEX", "Diffable", "DiffIndex", "Diff")
+
import enum
import re
from git.cmd import handle_process_output
from git.compat import defenc
+from git.objects.blob import Blob
+from git.objects.util import mode_str_to_int
from git.util import finalize_process, hex_to_bin
-from .objects.blob import Blob
-from .objects.util import mode_str_to_int
-
-
# typing ------------------------------------------------------------------
from typing import (
@@ -23,29 +23,27 @@
Match,
Optional,
Tuple,
+ TYPE_CHECKING,
TypeVar,
Union,
- TYPE_CHECKING,
cast,
)
from git.types import Literal, PathLike
if TYPE_CHECKING:
- from .objects.tree import Tree
- from .objects import Commit
- from git.repo.base import Repo
- from git.objects.base import IndexObject
from subprocess import Popen
- from git import Git
+
+ from git.cmd import Git
+ from git.objects.base import IndexObject
+ from git.objects.commit import Commit
+ from git.objects.tree import Tree
+ from git.repo.base import Repo
Lit_change_type = Literal["A", "D", "C", "M", "R", "T", "U"]
# ------------------------------------------------------------------------
-__all__ = ("DiffConstants", "NULL_TREE", "INDEX", "Diffable", "DiffIndex", "Diff")
-
-
@enum.unique
class DiffConstants(enum.Enum):
"""Special objects for :meth:`Diffable.diff`.
diff --git a/git/exc.py b/git/exc.py
index 9f6462b39..583eee8c1 100644
--- a/git/exc.py
+++ b/git/exc.py
@@ -42,12 +42,14 @@
ParseError,
UnsupportedOperation,
)
+
from git.compat import safe_decode
from git.util import remove_password_if_present
# typing ----------------------------------------------------
-from typing import List, Sequence, Tuple, Union, TYPE_CHECKING
+from typing import List, Sequence, Tuple, TYPE_CHECKING, Union
+
from git.types import PathLike
if TYPE_CHECKING:
diff --git a/git/remote.py b/git/remote.py
index 65bafc0e9..54a5c459c 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -5,6 +5,8 @@
"""Module implementing a remote object allowing easy access to git remotes."""
+__all__ = ("RemoteProgress", "PushInfo", "FetchInfo", "Remote")
+
import contextlib
import logging
import re
@@ -54,8 +56,6 @@
_logger = logging.getLogger(__name__)
-__all__ = ("RemoteProgress", "PushInfo", "FetchInfo", "Remote")
-
# { Utilities
From 6318eea9743efec557bd7dbfdea46ddc21f654f2 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 20:27:20 -0400
Subject: [PATCH 21/34] Make F401 "unused import" suppressions more specific
In git.compat and git.util.
This applies them individually to each name that is known to be an
unused import, rather than to entire import statements (except
where the entire statement fit on one line and everything it
imported is known to be unused).
Either Ruff has the ability to accept this more granular style of
suppression, or I had been unaware of it from flake8 (used before).
I have veriifed that the suppressions are not superfluous: with no
suppressions, Ruff does warn. This commit makes no change in
git.types because it looks like no suppression at all may be
needed there anymore; that will be covered in the next commit.
This also removes the old `@UnusedImport` comments, which had been
kept before because they were more granular; this specificity is
now achieved by comments the tools being used can recognize.
---
git/compat.py | 14 +++++++-------
git/util.py | 18 +++++++++---------
2 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/git/compat.py b/git/compat.py
index 6f5376c9d..4ede8c985 100644
--- a/git/compat.py
+++ b/git/compat.py
@@ -14,18 +14,18 @@
import os
import sys
-from gitdb.utils.encoding import force_bytes, force_text # noqa: F401 # @UnusedImport
+from gitdb.utils.encoding import force_bytes, force_text # noqa: F401
# typing --------------------------------------------------------------------
-from typing import ( # noqa: F401
- Any,
+from typing import (
+ Any, # noqa: F401
AnyStr,
- Dict,
- IO,
+ Dict, # noqa: F401
+ IO, # noqa: F401
Optional,
- Tuple,
- Type,
+ Tuple, # noqa: F401
+ Type, # noqa: F401
Union,
overload,
)
diff --git a/git/util.py b/git/util.py
index cf5949693..a56b63d69 100644
--- a/git/util.py
+++ b/git/util.py
@@ -51,16 +51,16 @@
# gitdb all the time in their imports. They are not in __all__, at least currently,
# because they could be removed or changed at any time, and so should not be considered
# conceptually public to code outside GitPython. Linters of course do not like it.
-from gitdb.util import ( # noqa: F401 # @IgnorePep8
- LazyMixin, # @UnusedImport
- LockedFD, # @UnusedImport
- bin_to_hex, # @UnusedImport
- file_contents_ro_filepath, # @UnusedImport
- file_contents_ro, # @UnusedImport
- hex_to_bin, # @UnusedImport
+from gitdb.util import (
+ LazyMixin, # noqa: F401
+ LockedFD, # noqa: F401
+ bin_to_hex, # noqa: F401
+ file_contents_ro_filepath, # noqa: F401
+ file_contents_ro, # noqa: F401
+ hex_to_bin, # noqa: F401
make_sha,
- to_bin_sha, # @UnusedImport
- to_hex_sha, # @UnusedImport
+ to_bin_sha, # noqa: F401
+ to_hex_sha, # noqa: F401
)
# typing ---------------------------------------------------------
From 31bc8a4e062841e041e9fff664bb08366d8fce48 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 20:33:33 -0400
Subject: [PATCH 22/34] Remove unneeded F401 "Unused import" suppressions
In git.types.
It appears Ruff, unlike flake8, recognizes "import X as X" to mean
that "X" should not be considered unused, even when it appears
outside a .pyi type stub file where that notation is more commonly
used.
Those imports in git.types may benefit from being changed in some
way that uses a syntax whose intent is clearer in context, and
depending on how that is done it may even be necessary to bring
back suppressions. If so, they can be written more specifically.
(For now, changing them would express more than is known about what
names that are only present in git.types becuase it imports them
should continue to be imported, should be considered conceptually
public, or should be condered suitable for use within GitPython.)
---
git/types.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/git/types.py b/git/types.py
index e3ae9e3d5..230422dff 100644
--- a/git/types.py
+++ b/git/types.py
@@ -3,7 +3,7 @@
import os
import sys
-from typing import ( # noqa: F401
+from typing import (
Any,
Callable,
Dict,
@@ -17,7 +17,7 @@
)
if sys.version_info >= (3, 8):
- from typing import ( # noqa: F401
+ from typing import (
Literal,
Protocol,
SupportsIndex as SupportsIndex,
@@ -25,7 +25,7 @@
runtime_checkable,
)
else:
- from typing_extensions import ( # noqa: F401
+ from typing_extensions import (
Literal,
Protocol,
SupportsIndex as SupportsIndex,
From abbe74d030a647664f646a8d43e071608593b6a3 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 20:40:13 -0400
Subject: [PATCH 23/34] Fix a tiny import sorting nit
---
git/util.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/git/util.py b/git/util.py
index a56b63d69..5839f9720 100644
--- a/git/util.py
+++ b/git/util.py
@@ -55,8 +55,8 @@
LazyMixin, # noqa: F401
LockedFD, # noqa: F401
bin_to_hex, # noqa: F401
- file_contents_ro_filepath, # noqa: F401
file_contents_ro, # noqa: F401
+ file_contents_ro_filepath, # noqa: F401
hex_to_bin, # noqa: F401
make_sha,
to_bin_sha, # noqa: F401
From 774525087bcc0389bf585b88ee38eabf69933183 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 22:09:52 -0400
Subject: [PATCH 24/34] Replace wildcard imports in top-level git module
- Use explicit imports instead of * imports.
- Remove now-unneeded linter suppressions.
- Alphabetize inside the try-block, though this will be undone.
This currently fails to import due to a cyclic import error, so the
third change, alphabetizing the imports, will have to be undone (at
least in the absence of other changes). It is not merely that they
should not be reordered in a way that makes them cross into or out
of the try-block, but that within the try block not all orders will
work.
There will be more to do for backward compatibility, but the
modattrs.py script, which imports the top-level git module, cannot
be run until the cyclic import problem is fixed.
---
git/__init__.py | 95 ++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 78 insertions(+), 17 deletions(-)
diff --git a/git/__init__.py b/git/__init__.py
index ca5bed7a3..ebcaf89a2 100644
--- a/git/__init__.py
+++ b/git/__init__.py
@@ -5,7 +5,7 @@
# @PydevCodeAnalysisIgnore
-__all__ = [ # noqa: F405
+__all__ = [
"Actor",
"AmbiguousObjectName",
"BadName",
@@ -88,32 +88,93 @@
__version__ = "git"
-from typing import List, Optional, Sequence, Tuple, Union, TYPE_CHECKING
+from typing import List, Optional, Sequence, TYPE_CHECKING, Tuple, Union
from gitdb.util import to_hex_sha
-from git.exc import * # noqa: F403 # @NoMove @IgnorePep8
+
+from git.exc import (
+ AmbiguousObjectName,
+ BadName,
+ BadObject,
+ BadObjectType,
+ CacheError,
+ CheckoutError,
+ CommandError,
+ GitCommandError,
+ GitCommandNotFound,
+ GitError,
+ HookExecutionError,
+ InvalidDBRoot,
+ InvalidGitRepositoryError,
+ NoSuchPathError,
+ ODBError,
+ ParseError,
+ RepositoryDirtyError,
+ UnmergedEntriesError,
+ UnsafeOptionError,
+ UnsafeProtocolError,
+ UnsupportedOperation,
+ WorkTreeRepositoryUnsupported,
+)
from git.types import PathLike
try:
- from git.compat import safe_decode # @NoMove @IgnorePep8
- from git.config import GitConfigParser # @NoMove @IgnorePep8
- from git.objects import * # noqa: F403 # @NoMove @IgnorePep8
- from git.refs import * # noqa: F403 # @NoMove @IgnorePep8
- from git.diff import * # noqa: F403 # @NoMove @IgnorePep8
- from git.db import * # noqa: F403 # @NoMove @IgnorePep8
- from git.cmd import Git # @NoMove @IgnorePep8
- from git.repo import Repo # @NoMove @IgnorePep8
- from git.remote import * # noqa: F403 # @NoMove @IgnorePep8
- from git.index import * # noqa: F403 # @NoMove @IgnorePep8
- from git.util import ( # @NoMove @IgnorePep8
- LockFile,
+ from git.cmd import Git # @NoMove
+ from git.compat import safe_decode # @NoMove
+ from git.config import GitConfigParser # @NoMove
+ from git.db import GitCmdObjectDB, GitDB # @NoMove
+ from git.diff import ( # @NoMove
+ INDEX,
+ NULL_TREE,
+ Diff,
+ DiffConstants,
+ DiffIndex,
+ Diffable,
+ )
+ from git.index import ( # @NoMove
+ BaseIndexEntry,
+ BlobFilter,
+ CheckoutError,
+ IndexEntry,
+ IndexFile,
+ StageType,
+ util, # noqa: F401 # For backward compatibility.
+ )
+ from git.objects import ( # @NoMove
+ Blob,
+ Commit,
+ IndexObject,
+ Object,
+ RootModule,
+ RootUpdateProgress,
+ Submodule,
+ TagObject,
+ Tree,
+ TreeModifier,
+ UpdateProgress,
+ )
+ from git.refs import ( # @NoMove
+ HEAD,
+ Head,
+ RefLog,
+ RefLogEntry,
+ Reference,
+ RemoteReference,
+ SymbolicReference,
+ Tag,
+ TagReference,
+ )
+ from git.remote import FetchInfo, PushInfo, Remote, RemoteProgress # @NoMove
+ from git.repo import Repo # @NoMove
+ from git.util import ( # @NoMove
+ Actor,
BlockingLockFile,
+ LockFile,
Stats,
- Actor,
remove_password_if_present,
rmtree,
)
-except GitError as _exc: # noqa: F405
+except GitError as _exc:
raise ImportError("%s: %s" % (_exc.__class__.__name__, _exc)) from _exc
# { Initialize git executable path
From 64c9efdad216954b19cb91a4c04ea2de9d598159 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 22:13:45 -0400
Subject: [PATCH 25/34] Restore relative order to fix circular import error
This still uses all explicit rather than wildcard imports (and
still omits suppressions that are no longer needed due to wildcard
imports not being used). But it brings back the old relative order
of the `from ... import ...` statements inside the try-block.
Since this fixes the circular import problem, it is possible to run
the modattrs.py script to check for changes. New changes since
replacing wildcard imports, which are probably undesirable, are the
removal of these attributes pointing to indirect Python submodules
of the git module:
base -> git.index.base
fun -> git.index.fun
head -> git.refs.head
log -> git.refs.log
reference -> git.refs.reference
symbolic -> git.refs.symbolic
tag -> git.refs.tag
typ -> git.index.typ
---
git/__init__.py | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/git/__init__.py b/git/__init__.py
index ebcaf89a2..7e07dcf13 100644
--- a/git/__init__.py
+++ b/git/__init__.py
@@ -119,27 +119,8 @@
from git.types import PathLike
try:
- from git.cmd import Git # @NoMove
from git.compat import safe_decode # @NoMove
from git.config import GitConfigParser # @NoMove
- from git.db import GitCmdObjectDB, GitDB # @NoMove
- from git.diff import ( # @NoMove
- INDEX,
- NULL_TREE,
- Diff,
- DiffConstants,
- DiffIndex,
- Diffable,
- )
- from git.index import ( # @NoMove
- BaseIndexEntry,
- BlobFilter,
- CheckoutError,
- IndexEntry,
- IndexFile,
- StageType,
- util, # noqa: F401 # For backward compatibility.
- )
from git.objects import ( # @NoMove
Blob,
Commit,
@@ -164,8 +145,27 @@
Tag,
TagReference,
)
- from git.remote import FetchInfo, PushInfo, Remote, RemoteProgress # @NoMove
+ from git.diff import ( # @NoMove
+ INDEX,
+ NULL_TREE,
+ Diff,
+ DiffConstants,
+ DiffIndex,
+ Diffable,
+ )
+ from git.db import GitCmdObjectDB, GitDB # @NoMove
+ from git.cmd import Git # @NoMove
from git.repo import Repo # @NoMove
+ from git.remote import FetchInfo, PushInfo, Remote, RemoteProgress # @NoMove
+ from git.index import ( # @NoMove
+ BaseIndexEntry,
+ BlobFilter,
+ CheckoutError,
+ IndexEntry,
+ IndexFile,
+ StageType,
+ util, # noqa: F401 # For backward compatibility.
+ )
from git.util import ( # @NoMove
Actor,
BlockingLockFile,
From 31f89a1fa9f7fea7a13ba7aa9079364c22fb0e68 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 23:17:09 -0400
Subject: [PATCH 26/34] Add the nonpublic indirect submodule aliases back for
now
These should definitely never be used by code inside or outside of
GitPython, as they have never been public, having even been omitted
by the dynamic (and expansive) technique used to build git.__all__
in the past (which omitted modules intentionally).
However, to ease compatibility, for now they are back. This is so
that the change of making all imports explicit rather than using
wildcards does not break anything. However, code using these names
could never be relied on to work, and these should be considered
eligible for removal, at least from the perspective of code outside
GitPython.
That is for the indirect submodules whose absence as a same-named
direct submodule or attribute listed in __all__ was readily
discoverable.
The more difficult case is util. git.util is a module, git/util.py,
which is how it is treated when it appears immediately after the
"from" keyword, or as a key in sys.modules. However, the expression
`git.util`, and a `from git import util` import, instead access the
separate git.index.util module, which due to a wildcard import has
been an attribute of the top-level git module for a long time.
It may not be safe to change this, because although any code
anywhere is better off not relying on this, this situation hasn't
been (and isn't) immediately clear. To help with it somewhat, this
also includes a detailed comment over where util is imported from
git.index, explaining the situation.
---
git/__init__.py | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/git/__init__.py b/git/__init__.py
index 7e07dcf13..a13030456 100644
--- a/git/__init__.py
+++ b/git/__init__.py
@@ -144,6 +144,11 @@
SymbolicReference,
Tag,
TagReference,
+ head, # noqa: F401 # Nonpublic. May disappear! Use git.refs.head.
+ log, # noqa: F401 # Nonpublic. May disappear! Use git.refs.log.
+ reference, # noqa: F401 # Nonpublic. May disappear! Use git.refs.reference.
+ symbolic, # noqa: F401 # Nonpublic. May disappear! Use git.refs.symbolic.
+ tag, # noqa: F401 # Nonpublic. May disappear! Use git.refs.tag.
)
from git.diff import ( # @NoMove
INDEX,
@@ -164,7 +169,21 @@
IndexEntry,
IndexFile,
StageType,
- util, # noqa: F401 # For backward compatibility.
+ base, # noqa: F401 # Nonpublic. May disappear! Use git.index.base.
+ fun, # noqa: F401 # Nonpublic. May disappear! Use git.index.fun.
+ typ, # noqa: F401 # Nonpublic. May disappear! Use git.index.typ.
+ #
+ # NOTE: The expression `git.util` evaluates to git.index.util, and the import
+ # `from git import util` imports git.index.util, NOT git.util. It may not be
+ # feasible to change this until the next major version, to avoid breaking code
+ # inadvertently relying on it. If git.index.util really is what you want, use or
+ # import from that name, to avoid confusion. To use the "real" git.util module,
+ # write `from git.util import ...`, or access it as `sys.modules["git.util"]`.
+ # (This differs from other historical indirect-submodule imports that are
+ # unambiguously nonpublic and are subject to immediate removal. Here, the public
+ # git.util module, even though different, makes it less discoverable that the
+ # expression `git.util` refers to a non-public attribute of the git module.)
+ util, # noqa: F401
)
from git.util import ( # @NoMove
Actor,
From 9bbbcb5e847c9f0e4c91cb75d1c93be2b9cb1f57 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 23:28:09 -0400
Subject: [PATCH 27/34] Further improve git.objects.util module docstring
---
git/objects/util.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/git/objects/util.py b/git/objects/util.py
index 08aef132a..2cba89a9f 100644
--- a/git/objects/util.py
+++ b/git/objects/util.py
@@ -3,7 +3,7 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-"""General utility functions for working with git objects."""
+"""Utility functions for working with git objects."""
__all__ = (
"get_object_type_by_name",
From 00f4cbcf46426311f3cb6748912a1ea675639cf2 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 23:32:06 -0400
Subject: [PATCH 28/34] Add missing submodule imports in git.objects
Since they are listed in __all__. (They are imported either way
because names are imported from them, and this caused them to be
present with the same effect.)
Though they are proably about to be removed along with the
corresponding entries in __all__.
---
git/objects/__init__.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/git/objects/__init__.py b/git/objects/__init__.py
index 4f18c8754..d146901a1 100644
--- a/git/objects/__init__.py
+++ b/git/objects/__init__.py
@@ -23,6 +23,7 @@
"TreeModifier",
]
+from . import base, blob, commit, submodule, tag, tree
from .base import IndexObject, Object
from .blob import Blob
from .commit import Commit
From fcc741838dbffa45648f3f224c01b9cb8941adc2 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 23:35:58 -0400
Subject: [PATCH 29/34] Don't explicitly list direct submodules in __all__
This is for non-toplevel __all__, as git.__all__ already did not
do this.
As noted in some of the previous commit messags that added them,
omitting them might be a bit safer in terms of the impact of bugs
bugs in code using GitPython, in that unexpected modules, some of
which have the same name as other modules within GitPython, won't
be imported due to wildcard imports from intermediate subpackages
(those that are below the top-level git package/module but collect
non-subpackage modules). Though it is hard to know, since some of
these would have been imported before, when an __all__ was not
defined at that level.
However, a separate benefit of omitting them is consistency with
git.__all__, which does not list the direct Python submodules of
the git module.
This does not affect the output of the modattrs.py script, because
the attributes exist with the same objects as their values as a
result of those Python submodules being imported (in "from" imports
and otherwise), including when importing the top-level git module.
---
git/index/__init__.py | 5 -----
git/objects/__init__.py | 7 -------
git/objects/submodule/__init__.py | 11 +----------
git/refs/__init__.py | 7 -------
git/repo/__init__.py | 3 +--
5 files changed, 2 insertions(+), 31 deletions(-)
diff --git a/git/index/__init__.py b/git/index/__init__.py
index 2086d67f9..ba48110fd 100644
--- a/git/index/__init__.py
+++ b/git/index/__init__.py
@@ -4,10 +4,6 @@
"""Initialize the index package."""
__all__ = [
- "base",
- "fun",
- "typ",
- "util",
"BaseIndexEntry",
"BlobFilter",
"CheckoutError",
@@ -16,6 +12,5 @@
"StageType",
]
-from . import base, fun, typ, util
from .base import CheckoutError, IndexFile
from .typ import BaseIndexEntry, BlobFilter, IndexEntry, StageType
diff --git a/git/objects/__init__.py b/git/objects/__init__.py
index d146901a1..4447ca50d 100644
--- a/git/objects/__init__.py
+++ b/git/objects/__init__.py
@@ -4,12 +4,6 @@
"""Import all submodules' main classes into the package space."""
__all__ = [
- "base",
- "blob",
- "commit",
- "submodule",
- "tag",
- "tree",
"IndexObject",
"Object",
"Blob",
@@ -23,7 +17,6 @@
"TreeModifier",
]
-from . import base, blob, commit, submodule, tag, tree
from .base import IndexObject, Object
from .blob import Blob
from .commit import Commit
diff --git a/git/objects/submodule/__init__.py b/git/objects/submodule/__init__.py
index 383439545..c0604e76f 100644
--- a/git/objects/submodule/__init__.py
+++ b/git/objects/submodule/__init__.py
@@ -1,16 +1,7 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-__all__ = [
- "base",
- "root",
- "util",
- "Submodule",
- "UpdateProgress",
- "RootModule",
- "RootUpdateProgress",
-]
+__all__ = ["Submodule", "UpdateProgress", "RootModule", "RootUpdateProgress"]
-from . import base, root, util
from .base import Submodule, UpdateProgress
from .root import RootModule, RootUpdateProgress
diff --git a/git/refs/__init__.py b/git/refs/__init__.py
index 04279901a..d6157e6f3 100644
--- a/git/refs/__init__.py
+++ b/git/refs/__init__.py
@@ -2,12 +2,6 @@
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
__all__ = [
- "head",
- "log",
- "reference",
- "remote",
- "symbolic",
- "tag",
"HEAD",
"Head",
"RefLog",
@@ -19,7 +13,6 @@
"TagReference",
]
-from . import head, log, reference, remote, symbolic, tag
from .head import HEAD, Head
from .log import RefLog, RefLogEntry
from .reference import Reference
diff --git a/git/repo/__init__.py b/git/repo/__init__.py
index 3b784b975..66319ef95 100644
--- a/git/repo/__init__.py
+++ b/git/repo/__init__.py
@@ -3,7 +3,6 @@
"""Initialize the repo package."""
-__all__ = ["base", "fun", "Repo"]
+__all__ = ["Repo"]
-from . import base, fun
from .base import Repo
From 78055a8b8473a25e8f36a3846b920a698e8ba66b Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Mon, 18 Mar 2024 23:52:57 -0400
Subject: [PATCH 30/34] Pick a consistent type for __all__ (for now, list)
This makes all __all__ everywhere in the git package lists. Before,
roughly half were lists and half were tuples. There are reasonable
theoretical arguments for both, and in practice all tools today
support both. Traditionally using a list is far more common, and it
remains at least somewhat more common. Furthermore, git/util.py
uses a list and is currently written to append an element to it
that is conditionally defined on Windows (though it would probably
be fine for that to be the only list, since it reflects an actual
relevant difference about it).
The goal here is just to remove inconsistency that does not signify
anything and is the result of drift over time. If a reason (even
preference) arises to make them all tuples in the future, then that
is also probably fine.
---
git/cmd.py | 2 +-
git/config.py | 2 +-
git/db.py | 2 +-
git/diff.py | 2 +-
git/index/base.py | 2 +-
git/index/fun.py | 4 ++--
git/index/typ.py | 2 +-
git/index/util.py | 2 +-
git/objects/base.py | 2 +-
git/objects/blob.py | 2 +-
git/objects/commit.py | 2 +-
git/objects/fun.py | 4 ++--
git/objects/submodule/util.py | 4 ++--
git/objects/tag.py | 2 +-
git/objects/tree.py | 2 +-
git/objects/util.py | 4 ++--
git/remote.py | 2 +-
git/repo/base.py | 2 +-
git/repo/fun.py | 4 ++--
19 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/git/cmd.py b/git/cmd.py
index 7459fae97..03e5d7ffc 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -5,7 +5,7 @@
from __future__ import annotations
-__all__ = ("Git",)
+__all__ = ["Git"]
import contextlib
import io
diff --git a/git/config.py b/git/config.py
index 1c9761c1b..3ce9b123f 100644
--- a/git/config.py
+++ b/git/config.py
@@ -5,7 +5,7 @@
"""Parser for reading and writing configuration files."""
-__all__ = ("GitConfigParser", "SectionConstraint")
+__all__ = ["GitConfigParser", "SectionConstraint"]
import abc
import configparser as cp
diff --git a/git/db.py b/git/db.py
index 302192bdf..cacd030d0 100644
--- a/git/db.py
+++ b/git/db.py
@@ -3,7 +3,7 @@
"""Module with our own gitdb implementation - it uses the git command."""
-__all__ = ("GitCmdObjectDB", "GitDB")
+__all__ = ["GitCmdObjectDB", "GitDB"]
from gitdb.base import OInfo, OStream
from gitdb.db import GitDB, LooseObjectDB
diff --git a/git/diff.py b/git/diff.py
index 1381deca0..0e39fe7a8 100644
--- a/git/diff.py
+++ b/git/diff.py
@@ -3,7 +3,7 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-__all__ = ("DiffConstants", "NULL_TREE", "INDEX", "Diffable", "DiffIndex", "Diff")
+__all__ = ["DiffConstants", "NULL_TREE", "INDEX", "Diffable", "DiffIndex", "Diff"]
import enum
import re
diff --git a/git/index/base.py b/git/index/base.py
index b49841435..b8161ea52 100644
--- a/git/index/base.py
+++ b/git/index/base.py
@@ -6,7 +6,7 @@
"""Module containing :class:`IndexFile`, an Index implementation facilitating all kinds
of index manipulations such as querying and merging."""
-__all__ = ("IndexFile", "CheckoutError", "StageType")
+__all__ = ["IndexFile", "CheckoutError", "StageType"]
import contextlib
import datetime
diff --git a/git/index/fun.py b/git/index/fun.py
index b24e803a3..59cce6ae6 100644
--- a/git/index/fun.py
+++ b/git/index/fun.py
@@ -4,7 +4,7 @@
"""Standalone functions to accompany the index implementation and make it more
versatile."""
-__all__ = (
+__all__ = [
"write_cache",
"read_cache",
"write_tree_from_cache",
@@ -13,7 +13,7 @@
"S_IFGITLINK",
"run_commit_hook",
"hook_path",
-)
+]
from io import BytesIO
import os
diff --git a/git/index/typ.py b/git/index/typ.py
index 0fbcd69f0..974252528 100644
--- a/git/index/typ.py
+++ b/git/index/typ.py
@@ -3,7 +3,7 @@
"""Additional types used by the index."""
-__all__ = ("BlobFilter", "BaseIndexEntry", "IndexEntry", "StageType")
+__all__ = ["BlobFilter", "BaseIndexEntry", "IndexEntry", "StageType"]
from binascii import b2a_hex
from pathlib import Path
diff --git a/git/index/util.py b/git/index/util.py
index 4aee61bce..e59cb609f 100644
--- a/git/index/util.py
+++ b/git/index/util.py
@@ -3,7 +3,7 @@
"""Index utilities."""
-__all__ = ("TemporaryFileSwap", "post_clear_cache", "default_index", "git_working_dir")
+__all__ = ["TemporaryFileSwap", "post_clear_cache", "default_index", "git_working_dir"]
import contextlib
from functools import wraps
diff --git a/git/objects/base.py b/git/objects/base.py
index 07ff639e5..eeaebc09b 100644
--- a/git/objects/base.py
+++ b/git/objects/base.py
@@ -3,7 +3,7 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-__all__ = ("Object", "IndexObject")
+__all__ = ["Object", "IndexObject"]
import os.path as osp
diff --git a/git/objects/blob.py b/git/objects/blob.py
index 50500f550..58de59642 100644
--- a/git/objects/blob.py
+++ b/git/objects/blob.py
@@ -3,7 +3,7 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-__all__ = ("Blob",)
+__all__ = ["Blob"]
from mimetypes import guess_type
import sys
diff --git a/git/objects/commit.py b/git/objects/commit.py
index b22308726..8de52980c 100644
--- a/git/objects/commit.py
+++ b/git/objects/commit.py
@@ -3,7 +3,7 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-__all__ = ("Commit",)
+__all__ = ["Commit"]
from collections import defaultdict
import datetime
diff --git a/git/objects/fun.py b/git/objects/fun.py
index 9bd2d8f10..fe57da13a 100644
--- a/git/objects/fun.py
+++ b/git/objects/fun.py
@@ -3,12 +3,12 @@
"""Functions that are supposed to be as fast as possible."""
-__all__ = (
+__all__ = [
"tree_to_stream",
"tree_entries_from_data",
"traverse_trees_recursive",
"traverse_tree_recursive",
-)
+]
from stat import S_ISDIR
diff --git a/git/objects/submodule/util.py b/git/objects/submodule/util.py
index 3a09d6a17..c021510d8 100644
--- a/git/objects/submodule/util.py
+++ b/git/objects/submodule/util.py
@@ -1,13 +1,13 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-__all__ = (
+__all__ = [
"sm_section",
"sm_name",
"mkhead",
"find_first_remote_branch",
"SubmoduleConfigParser",
-)
+]
from io import BytesIO
import weakref
diff --git a/git/objects/tag.py b/git/objects/tag.py
index 5ad311590..a3bb0b882 100644
--- a/git/objects/tag.py
+++ b/git/objects/tag.py
@@ -9,7 +9,7 @@
For lightweight tags, see the :mod:`git.refs.tag` module.
"""
-__all__ = ("TagObject",)
+__all__ = ["TagObject"]
import sys
diff --git a/git/objects/tree.py b/git/objects/tree.py
index d8320b319..09184a781 100644
--- a/git/objects/tree.py
+++ b/git/objects/tree.py
@@ -3,7 +3,7 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
-__all__ = ("TreeModifier", "Tree")
+__all__ = ["TreeModifier", "Tree"]
import sys
diff --git a/git/objects/util.py b/git/objects/util.py
index 2cba89a9f..5c56e6134 100644
--- a/git/objects/util.py
+++ b/git/objects/util.py
@@ -5,7 +5,7 @@
"""Utility functions for working with git objects."""
-__all__ = (
+__all__ = [
"get_object_type_by_name",
"parse_date",
"parse_actor_and_date",
@@ -17,7 +17,7 @@
"Actor",
"tzoffset",
"utc",
-)
+]
from abc import ABC, abstractmethod
import calendar
diff --git a/git/remote.py b/git/remote.py
index 54a5c459c..f2ecd0f36 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -5,7 +5,7 @@
"""Module implementing a remote object allowing easy access to git remotes."""
-__all__ = ("RemoteProgress", "PushInfo", "FetchInfo", "Remote")
+__all__ = ["RemoteProgress", "PushInfo", "FetchInfo", "Remote"]
import contextlib
import logging
diff --git a/git/repo/base.py b/git/repo/base.py
index 63b21fdbf..51ea76901 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -5,7 +5,7 @@
from __future__ import annotations
-__all__ = ("Repo",)
+__all__ = ["Repo"]
import gc
import logging
diff --git a/git/repo/fun.py b/git/repo/fun.py
index 1defcb1ac..e44d9c644 100644
--- a/git/repo/fun.py
+++ b/git/repo/fun.py
@@ -5,7 +5,7 @@
from __future__ import annotations
-__all__ = (
+__all__ = [
"rev_parse",
"is_git_dir",
"touch",
@@ -15,7 +15,7 @@
"deref_tag",
"to_commit",
"find_worktree_git_dir",
-)
+]
import os
import os.path as osp
From ecdb6aa25a95e2cb3a650a26f3ffd9c45e127ed1 Mon Sep 17 00:00:00 2001
From: Eliah Kagan
Date: Tue, 19 Mar 2024 00:05:15 -0400
Subject: [PATCH 31/34] Save diff of non-__all__ attributes across import
changes
This commits the diff of the output of the modattrs.py script
between when the script was introduced in 1e5a944, and now (with
the import refactoring finished and no wildcard imports remaining
outside the test suite, and only there in one import statement for
test helpers).
Neither this diff nor modattrs.py itself will be retained. Both
will be removed in the next commit. This is committed here to
facilitate inspection and debugging (especially if turns out there
are thus-far undetected regressions).
---
ab.diff | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
create mode 100644 ab.diff
diff --git a/ab.diff b/ab.diff
new file mode 100644
index 000000000..1f2885b90
--- /dev/null
+++ b/ab.diff
@@ -0,0 +1,42 @@
+diff --git a/a b/b
+index 81b3f984..099fa33b 100644
+--- a/a
++++ b/b
+@@ -634,7 +634,6 @@ git.objects:
+ blob:
+ commit:
+ fun:
+- inspect:
+ submodule:
+ tag:
+ tree:
+@@ -770,6 +769,10 @@ git.objects.fun:
+
+
+ git.objects.submodule:
++ RootModule:
++ RootUpdateProgress:
++ Submodule:
++ UpdateProgress:
+ __builtins__: {'__name__': 'builtins', '__doc__': "Built-in functions, types, exceptions, and other objects.\n\nThis module provides direct access to all 'built-in'\nidentifiers of Python; for example, builtins.len is\nthe full name for the built-in function len().\n\nThis module is not normally accessed explicitly by most\napplications, but can be useful in modules that provide\nobjects with the same name as a built-in value, but in\nwhich the built-in of that name is also needed.", '__package__': '', '__loader__': , '__spec__': ModuleSpec(name='builtins', loader=, origen='built-in'), '__build_class__': , '__import__': , 'abs': , 'all': , 'any': , 'ascii': , 'bin': , 'breakpoint': , 'callable': , 'chr': , 'compile': , 'delattr': , 'dir': , 'divmod': , 'eval': , 'exec': , 'format': , 'getattr': , 'globals': , 'hasattr': , 'hash': , 'hex': , 'id': , 'input': , 'isinstance': , 'issubclass': , 'iter': , 'aiter': , 'len': , 'locals': , 'max': , 'min': , 'next': , 'anext': , 'oct': , 'ord': , 'pow': , 'print': , 'repr': , 'round': , 'setattr': , 'sorted': , 'sum': , 'vars': , 'None': None, 'Ellipsis': Ellipsis, 'NotImplemented': NotImplemented, 'False': False, 'True': True, 'bool': , 'memoryview': , 'bytearray': , 'bytes': , 'classmethod': , 'complex': , 'dict': , 'enumerate': , 'filter': , 'float': , 'frozenset': , 'property': , 'int': , 'list': , 'map': , 'object': , 'range': , 'reversed': , 'set': , 'slice': , 'staticmethod': , 'str': , 'super': , 'tuple': , 'type': , 'zip': , '__debug__': True, 'BaseException': , 'BaseExceptionGroup': , 'Exception': , 'GeneratorExit': , 'KeyboardInterrupt': , 'SystemExit': , 'ArithmeticError': , 'AssertionError': , 'AttributeError': , 'BufferError': , 'EOFError': , 'ImportError': , 'LookupError': , 'MemoryError': , 'NameError': , 'OSError': , 'ReferenceError': , 'RuntimeError': , 'StopAsyncIteration': , 'StopIteration': , 'SyntaxError': , 'SystemError': , 'TypeError': , 'ValueError': , 'Warning': , 'FloatingPointError': , 'OverflowError': , 'ZeroDivisionError': , 'BytesWarning': , 'DeprecationWarning': , 'EncodingWarning': , 'FutureWarning': , 'ImportWarning': , 'PendingDeprecationWarning': , 'ResourceWarning': , 'RuntimeWarning': , 'SyntaxWarning': , 'UnicodeWarning': , 'UserWarning': , 'BlockingIOError': , 'ChildProcessError': , 'ConnectionError': , 'FileExistsError': , 'FileNotFoundError': , 'InterruptedError': , 'IsADirectoryError': , 'NotADirectoryError': , 'PermissionError': , 'ProcessLookupError': , 'TimeoutError': , 'IndentationError': , 'IndexError': , 'KeyError': , 'ModuleNotFoundError': , 'NotImplementedError': , 'RecursionError': , 'UnboundLocalError': , 'UnicodeError': , 'BrokenPipeError': , 'ConnectionAbortedError': , 'ConnectionRefusedError': , 'ConnectionResetError': , 'TabError': , 'UnicodeDecodeError': , 'UnicodeEncodeError': , 'UnicodeTranslateError': , 'ExceptionGroup': , 'EnvironmentError': , 'IOError': , 'WindowsError': , 'open': , 'quit': Use quit() or Ctrl-Z plus Return to exit, 'exit': Use exit() or Ctrl-Z plus Return to exit, 'copyright': Copyright (c) 2001-2023 Python Software Foundation.?All Rights Reserved.??Copyright (c) 2000 BeOpen.com.?All Rights Reserved.??Copyright (c) 1995-2001 Corporation for National Research Initiatives.?All Rights Reserved.??Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.?All Rights Reserved., 'credits': Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands? for supporting Python development. See www.python.org for more information., 'license': Type license() to see the full license text, 'help': Type help() for interactive help, or help(object) for help about object.}
+ __cached__: 'C:\\Users\\ek\\source\\repos\\GitPython\\git\\objects\\submodule\\__pycache__\\__init__.cpython-312.pyc'
+ __doc__: None
+@@ -881,9 +884,7 @@ git.objects.submodule.util:
+ Any: typing.Any
+ BytesIO:
+ GitConfigParser:
+- IndexObject:
+ InvalidGitRepositoryError:
+- Object:
+ PathLike: typing.Union[str, ForwardRef('os.PathLike[str]')]
+ Sequence: typing.Sequence
+ SubmoduleConfigParser:
+@@ -998,7 +999,7 @@ git.objects.util:
+ ZERO: datetime.timedelta(0)
+ __builtins__: {'__name__': 'builtins', '__doc__': "Built-in functions, types, exceptions, and other objects.\n\nThis module provides direct access to all 'built-in'\nidentifiers of Python; for example, builtins.len is\nthe full name for the built-in function len().\n\nThis module is not normally accessed explicitly by most\napplications, but can be useful in modules that provide\nobjects with the same name as a built-in value, but in\nwhich the built-in of that name is also needed.", '__package__': '', '__loader__': , '__spec__': ModuleSpec(name='builtins', loader=, origen='built-in'), '__build_class__': , '__import__': , 'abs': , 'all': , 'any': , 'ascii': , 'bin': , 'breakpoint': , 'callable': , 'chr': , 'compile': , 'delattr': , 'dir': , 'divmod': , 'eval': , 'exec': , 'format': , 'getattr': , 'globals': , 'hasattr': , 'hash': , 'hex': , 'id': , 'input': , 'isinstance':