Skip to content

Commit f699a38

Browse files
committed
Fix Git.version_info pickling
For gitpython-developers#1836. This uses a property with the same logic as before for version_info caching, except that the _version_info backing attribute holds the value None, rather than being unset, for the uncomputed state. This rectifies the inconistency between the property's behavior and the way the associated states are represented by its __setstate__ and __getstate__ methods for pickling. Because the Git class only used LazyMixin as an implementation detail of the version_info attribute, it is removed as a subclass.
1 parent 2d6311b commit f699a38

File tree

1 file changed

+14
-18
lines changed

1 file changed

+14
-18
lines changed

git/cmd.py

+14-18
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
UnsafeProtocolError,
2626
)
2727
from git.util import (
28-
LazyMixin,
2928
cygpath,
3029
expand_path,
3130
is_cygwin_git,
@@ -287,7 +286,7 @@ def dict_to_slots_and__excluded_are_none(self: object, d: Mapping[str, Any], exc
287286
## -- End Utilities -- @}
288287

289288

290-
class Git(LazyMixin):
289+
class Git:
291290
"""The Git class manages communication with the Git binary.
292291
293292
It provides a convenient interface to calling the Git binary, such as in::
@@ -784,6 +783,7 @@ def __init__(self, working_dir: Union[None, PathLike] = None):
784783
self._environment: Dict[str, str] = {}
785784

786785
# Cached command slots
786+
self._version_info: Union[Tuple[int, int, int, int], None] = None
787787
self.cat_file_header: Union[None, TBD] = None
788788
self.cat_file_all: Union[None, TBD] = None
789789

@@ -795,8 +795,8 @@ def __getattr__(self, name: str) -> Any:
795795
Callable object that will execute call :meth:`_call_process` with
796796
your arguments.
797797
"""
798-
if name[0] == "_":
799-
return LazyMixin.__getattr__(self, name)
798+
if name.startswith("_"):
799+
return super().__getattribute__(name)
800800
return lambda *args, **kwargs: self._call_process(name, *args, **kwargs)
801801

802802
def set_persistent_git_options(self, **kwargs: Any) -> None:
@@ -811,20 +811,6 @@ def set_persistent_git_options(self, **kwargs: Any) -> None:
811811

812812
self._persistent_git_options = self.transform_kwargs(split_single_char_options=True, **kwargs)
813813

814-
def _set_cache_(self, attr: str) -> None:
815-
if attr == "_version_info":
816-
# We only use the first 4 numbers, as everything else could be strings in fact (on Windows).
817-
process_version = self._call_process("version") # Should be as default *args and **kwargs used.
818-
version_numbers = process_version.split(" ")[2]
819-
820-
self._version_info = cast(
821-
Tuple[int, int, int, int],
822-
tuple(int(n) for n in version_numbers.split(".")[:4] if n.isdigit()),
823-
)
824-
else:
825-
super()._set_cache_(attr)
826-
# END handle version info
827-
828814
@property
829815
def working_dir(self) -> Union[None, PathLike]:
830816
""":return: Git directory we are working on"""
@@ -838,6 +824,16 @@ def version_info(self) -> Tuple[int, int, int, int]:
838824
839825
This value is generated on demand and is cached.
840826
"""
827+
if self._version_info is None:
828+
# We only use the first 4 numbers, as everything else could be strings in fact (on Windows).
829+
process_version = self._call_process("version") # Should be as default *args and **kwargs used.
830+
version_numbers = process_version.split(" ")[2]
831+
832+
self._version_info = cast(
833+
Tuple[int, int, int, int],
834+
tuple(int(n) for n in version_numbers.split(".")[:4] if n.isdigit()),
835+
)
836+
841837
return self._version_info
842838

843839
@overload

0 commit comments

Comments
 (0)