Skip to content

Commit

Permalink
Do not strore strings in the graph
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanlatr committed Dec 12, 2024
1 parent c838a65 commit 8d46b2b
Showing 1 changed file with 11 additions and 13 deletions.
24 changes: 11 additions & 13 deletions pydoctor/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ def __init__(self, classes: Iterable[Class]) -> None:
# this calls _init_finalbaseobjects for every class and
# create the graph object for the ones that did not raised
# a cycle-error.
self.graph: dict[ClassOrStr, list[ClassOrStr]] = {}
self.graph: dict[Class, list[ClassOrStr]] = {}
self.computed_mros: dict[ClassOrStr, list[ClassOrStr]] = {}

for cls in classes:
Expand All @@ -669,24 +669,19 @@ def __init__(self, classes: Iterable[Class]) -> None:
self.graph[cls] = bases = []
for b in self._getbases(cls):
bases.append(b)

# string should explicitely be part of the graph
if isinstance(b, str):
self.graph[b] = []
self.computed_mros[b] = []

# strings are not part of the graph
# because they always have the same MRO: empty list.

def compute_mros(self) -> None:

# If this raises a CycleError, our code is boggus since we already
# checked for cycles ourself.
static_order: Iterable[ClassOrStr] = topsort(self.graph)

for cls in static_order:
if cls in self.computed_mros:
if cls in self.computed_mros or isinstance(cls, str):
# If it's already computed, it means it's boggus like with cycle or something.
continue
# All strings bases are already pre-computed to the empty list,
# so the cls varible must be a Class at this point
assert isinstance(cls, Class)
self.computed_mros[cls] = cls._mro = self._compute_mro(cls)

def _compute_mro(self, cls: Class) -> list[ClassOrStr]:
Expand All @@ -695,19 +690,22 @@ def _compute_mro(self, cls: Class) -> list[ClassOrStr]:
This assumes that the MRO of the bases of the class
have already been computed and stored in C{self.computed_mros}.
"""
if cls not in self.graph:
raise ValueError

result: list[ClassOrStr] = [cls]

if not (bases:=self.graph[cls]):
return result

# since we compute all MRO in topological order, we can safely assume
# that self.computed_mros contains all the MROs of the bases of this class.
bases_mros = [self.computed_mros[kls] for kls in bases]
bases_mros = [self.computed_mros.get(kls, []) for kls in bases]

# handle multiple typing.Generic case,
# see https://github.com/twisted/pydoctor/issues/846.
# support documenting typing.py module by using allobject.get.
generic = cls.system.allobjects.get(d:='typing.Generic', d)
generic = cls.system.allobjects.get(_d:='typing.Generic', _d)
if generic in bases and any(generic in _mro for _mro in bases_mros):
# this is cafe since we checked 'generic in bases'.
bases.remove(generic) # type: ignore[arg-type]
Expand Down

0 comments on commit 8d46b2b

Please sign in to comment.