reproducible on both 3.1.0 and 4.0.0a1 with:
#!/usr/bin/env python
from bloop import BaseModel, Column, Integer
class A(BaseModel):
id_a = Column(Integer, hash_key=True)
class B(A):
id_b = Column(Integer, hash_key=True)
# B still has a ref to B.id_a
assert all(x in dir(B) for x in {"id_a", "id_b"})
# note that this is the **actual parent id_a** and not the copy that was temporarily
# created during BaseModel.__init_subclass__
assert B.id_a is A.id_a
# this will fail
class C(B):
other_field = Column(Integer)
The grandparent is defined correctly, and the parent has the correct hash key (in Meta.keys, Meta.hash_key, Meta.projection, Meta.columns).
However, there are two problems:
B.id_a still exists even though it's not actually a key on the model. This isn't the original parent value but a copy that was made, briefly bound during __init_subclass__ and then unbound.
- When the grandchild class
C is being configured during BaseModel.__init_subclass__ the derived_attrs are defined as "all columns or indexes found with inspect.getmembers that are not also found in cls.__dict__" and this contains both the immediate parents' id_b as well as the grandparents' id_a. Since these are both hash keys, the derived_hash_keys check fails.