Skip to content

Commit

Permalink
fix: Don't crash when computing MRO for a class that is named after i…
Browse files Browse the repository at this point in the history
…ts parent
  • Loading branch information
pawamoy committed Nov 8, 2023
1 parent 9c809ee commit a2dd8a6
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 3 deletions.
24 changes: 22 additions & 2 deletions docs/loading.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ in extensions, while visiting or inspecting a module.

### Limitations

Currently, there are two limitations to our class inheritance support:
Currently, there are three limitations to our class inheritance support:

1. when visiting (static analysis), some objects are not yet properly recognized as classes,
for example named tuples. If you inherit from a named tuple,
Expand All @@ -123,7 +123,26 @@ Currently, there are two limitations to our class inheritance support:
...
```

2. when inspecting (dynamic analysis), ephemeral base classes won't be resolved,
2. when visiting (static analysis), subclasses using the same name
as one of their parent class will prevent Griffe from computing the MRO
and therefore the inherited members. To circumvent that, give a
different name to your subclass:

```python
from package import SomeClass


# instead of
class SomeClass(SomeClass):
...


# do
class SomeOtherClass(SomeClass):
...
```

3. when inspecting (dynamic analysis), ephemeral base classes won't be resolved,
and therefore their members won't appear in child classes. To circumvent that,
assign these dynamic classes to variables:

Expand All @@ -141,4 +160,5 @@ Currently, there are two limitations to our class inheritance support:
...
```


We will try to lift these limitations in the future.
7 changes: 6 additions & 1 deletion src/griffe/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,8 +452,13 @@ def inherited_members(self) -> dict[str, Alias]:
"""
if not isinstance(self, Class):
return {}
try:
mro = self.mro()
except ValueError as error:
logger.debug(error)
return {}
inherited_members = {}
for base in reversed(self.mro()):
for base in reversed(mro):
for name, member in base.members.items():
if name not in self.members:
inherited_members[name] = Alias(name, member, parent=self, inherited=True)
Expand Down
2 changes: 2 additions & 0 deletions tests/test_stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ def test_fuzzing_on_stdlib() -> None:
loader.resolve_aliases(implicit=True, external=True)
for module in loader.modules_collection.members.values():
_access_inherited_members(module)

loader.stats()

0 comments on commit a2dd8a6

Please # to comment.