Skip to content

Commit

Permalink
fixup! feat: Support inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
pawamoy committed Jun 16, 2023
1 parent 4857c85 commit eb65091
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 2 deletions.
5 changes: 3 additions & 2 deletions src/griffe/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,8 @@ def inherited_members(self) -> dict[str, Alias]:
inherited_members = {}
for base in reversed(self.mro()):
for name, member in base.members.items():
inherited_members[name] = Alias(name, member, parent=self) # type: ignore[arg-type]
if name not in self.members:
inherited_members[name] = Alias(name, member, parent=self) # type: ignore[arg-type]
return inherited_members

@property
Expand Down Expand Up @@ -1420,7 +1421,7 @@ def resolved_bases(self) -> list[Object]:
"""Resolved class bases."""
resolved_bases = []
for base in self.bases:
base_path = self.resolve(base) if isinstance(base, str) else base.full
base_path = base if isinstance(base, str) else base.full
try:
resolved_base = self.modules_collection[base_path]
if resolved_base.is_alias:
Expand Down
80 changes: 80 additions & 0 deletions tests/test_inheritance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""Tests for class inheritance."""

from __future__ import annotations

from typing import Callable

import pytest

from griffe.collections import ModulesCollection
from griffe.tests import temporary_inspected_module, temporary_visited_module


@pytest.mark.parametrize("agent1", [temporary_visited_module, temporary_inspected_module])
@pytest.mark.parametrize("agent2", [temporary_visited_module, temporary_inspected_module])
def test_loading_inherited_members(agent1: Callable, agent2: Callable) -> None:
"""Test class inheritance.
Parameters:
agent1: A parametrized agent to load a module.
agent2: A parametrized agent to load a module.
"""
code1 = """
class A:
attr_from_a = 0
def method_from_a(self): ...
class B(A):
attr_from_a = 1
attr_from_b = 1
def method_from_b(self): ...
"""
code2 = """
from module1 import B
class C(B):
attr_from_c = 2
def method_from_c(self): ...
class D(C):
attr_from_a = 3
attr_from_d = 3
def method_from_d(self): ...
"""
inspection_options = {}
collection = ModulesCollection()

with agent1(code1, module_name="module1", modules_collection=collection) as module1:
if agent2 is temporary_inspected_module:
inspection_options["import_paths"] = [module1.filepath.parent]

with agent2(code2, module_name="module2", modules_collection=collection, **inspection_options) as module2:
collection["module1"] = module1
collection["module2"] = module2

classa = module1["A"]
classb = module1["B"]
classc = module2["C"]
classd = module2["D"]

assert classa in classb.resolved_bases
assert classb in classc.resolved_bases
assert classc in classd.resolved_bases

classd_mro = classd.mro()
assert classa in classd_mro
assert classb in classd_mro
assert classc in classd_mro

inherited_members = classd.inherited_members
assert "attr_from_a" not in inherited_members # overwritten
assert "attr_from_b" in inherited_members
assert "attr_from_c" in inherited_members
assert "attr_from_d" not in inherited_members # own-declared

assert "method_from_a" in inherited_members
assert "method_from_b" in inherited_members
assert "method_from_c" in inherited_members
assert "method_from_d" not in inherited_members # own-declared

assert "attr_from_b" in classd.all_members

0 comments on commit eb65091

Please sign in to comment.