repo.index.commit fails on python 3.10.0-rc2 (but not 3.10.0-rc1)
This is an excerpt of Hopic's pytest run in the python:3.10.0rc2-slim docker image. With python:3.10.0rc1-slim this same error does not occur.
I don't have the time right now to fully analyze this. But it looks suspiciously similar to a problem that I observed in Hopic itself and fixed with tomtom-international/hopic@a0f5a93b6c2efbfcd607e4a4927b655984564fb9. That one was triggered by this Python change: https://bugs.python.org/issue44806 / python/cpython@2cc19a5463c804b2f39b94de896d55dcb57a364c.
This if failing in a different location in the same function. But given the CPython commit message it seems to me that it's somehow achieving the opposite of its intent: it looks like non-protocol classes do call the __init__ method (via super) of the protocol class they inherit from.
> repo.index.commit(message='Initial commit', **_commitargs) [2921/9962]
hopic/test/test_version_bump.py:173:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.tox/py310/lib/python3.10/site-packages/git/index/base.py:1002: in commit
rval = Commit.create_from_tree(self.repo, tree, message, parent_commits,
.tox/py310/lib/python3.10/site-packages/git/objects/commit.py:459: in create_from_tree
new_commit = cls(repo, cls.NULL_BIN_SHA, tree,
.tox/py310/lib/python3.10/site-packages/git/objects/commit.py:130: in __init__
super(Commit, self).__init__(repo, binsha)
.tox/py310/lib/python3.10/site-packages/git/objects/base.py:57: in __init__ super(Object, self).__init__()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'Commit' object has no attribute 'binsha'") raised in repr()] Commit object at 0x7f669cbdc8b0>, args = (), kwargs = {}
cls = <class 'git.objects.commit.Commit'>, base = <class 'git.objects.commit.Commit'>, init = <function Commit.__init__ at 0x7f669d820af0>
def _no_init_or_replace_init(self, *args, **kwargs):
cls = type(self)
if cls._is_protocol:
raise TypeError('Protocols cannot be instantiated')
# Initially, `__init__` of a protocol subclass is set to `_no_init_or_replace_init`.
# The first instantiation of the subclass will call `_no_init_or_replace_init` which
# searches for a proper new `__init__` in the MRO. The new `__init__`
# replaces the subclass' old `__init__` (ie `_no_init_or_replace_init`). Subsequent
# instantiation of the protocol subclass will thus use the new
# `__init__` and no longer call `_no_init_or_replace_init`.
for base in cls.__mro__:
init = base.__dict__.get('__init__', _no_init_or_replace_init)
if init is not _no_init_or_replace_init:
cls.__init__ = init
break
else:
# should not happen
cls.__init__ = object.__init__
> cls.__init__(self, *args, **kwargs)
E TypeError: Commit.__init__() missing 2 required positional arguments: 'repo' and 'binsha'
/usr/local/lib/python3.10/typing.py:1422: TypeError
Thanks for reporting. I wouldn't know how to go about this though. Is it a bug in the upcoming python release and thus should be reported there? Or is it a 'breaking-change-in-minor-release' that is justified as bugfix so GitPython should be adjusted?
Admittedly, GItPython clearly fell into the OO trap and probably pays for that more than a decade later, so cleaning this up is probably merely paying tech debt (with a lot of accumulated compound interest ;)).
Yeah, i think this is the same issue with Protocol classes that cropped up a few times. #1332 Our Protocol classes worked for 3.10.0.b4, then broke in rc1. I fixed that, and then it broke again in rc2 😭.
I have to check if we can just revert to the our original code or it needs a different fix. I might end up just stripping Protocols back out like I did for TypeGuard, until python changes calm down. Either way, we'll need a new GitPython release for py 3.10.0 compat (due Oct 4th).
Having a similar issue with Python 3.9.7. Is it related or should I open a new issue?
> repo.index.commit("First commit")
test/test_lib.py:960:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../.cache/pypoetry/virtualenvs/arduino-cli-P0JdEWiU-py3.9/lib/python3.9/site-packages/git/index/base.py:1000: in commit
tree = self.write_tree()
../../.cache/pypoetry/virtualenvs/arduino-cli-P0JdEWiU-py3.9/lib/python3.9/site-packages/git/index/base.py:574: in write_tree
root_tree = Tree(self.repo, binsha, path='')
../../.cache/pypoetry/virtualenvs/arduino-cli-P0JdEWiU-py3.9/lib/python3.9/site-packages/git/objects/tree.py:215: in __init__
super(Tree, self).__init__(repo, binsha, mode, path)
../../.cache/pypoetry/virtualenvs/arduino-cli-P0JdEWiU-py3.9/lib/python3.9/site-packages/git/objects/base.py:168: in __init__
super(IndexObject, self).__init__(repo, binsha)
../../.cache/pypoetry/virtualenvs/arduino-cli-P0JdEWiU-py3.9/lib/python3.9/site-packages/git/objects/base.py:56: in __init__
super(Object, self).__init__()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError('binsha') raised in repr()] Tree object at 0x7f5858690db0>, args = (), kwargs = {}
def _no_init(self, *args, **kwargs):
> raise TypeError('Protocols cannot be instantiated')
E TypeError: Protocols cannot be instantiated
/usr/lib/python3.9/typing.py:1083: TypeError
@silvanocerza different stack trace but the same issue as far as I can tell (i.e. triggered by inheritance from typing.Protocol).
The issue is not present in Python 3.9.6 by the way.
I also got the error in the original post with Python 3.10.0-rc2. But it worked fine with the final release of Python 3.10.0, which I guess explains why this issue hasn't had any activity over the last year. So I think it can be closed.