Skip to content

Commit

Permalink
Merge pull request #498 from tristanlatr/linker-cache
Browse files Browse the repository at this point in the history
Provides caching for the linker
  • Loading branch information
tristanlatr authored Mar 6, 2022
2 parents c367d21 + 411ae79 commit 1210f94
Show file tree
Hide file tree
Showing 8 changed files with 505 additions and 53 deletions.
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ What's New?
in development
^^^^^^^^^^^^^^
* Add client side search system based on lunr.js.
* Fix broken links in docstring summaries.
* Add cache for the xref linker, reduces the number of identical warnings.

pydoctor 22.2.2
^^^^^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion pydoctor/astbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ def __init__(self, value: Any, ctx: model.Documentable):
The colorized value as L{ParsedDocstring}.
"""

self._linker = epydoc2stan._EpydocLinker(ctx)
self._linker = ctx.docstringlinker
"""
Linker.
"""
Expand Down
279 changes: 254 additions & 25 deletions pydoctor/epydoc2stan.py

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions pydoctor/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from typing_extensions import Literal
from twisted.web.template import Flattenable
from pydoctor.astbuilder import ASTBuilder
from pydoctor import epydoc2stan
else:
Literal = {True: bool, False: bool}
ASTBuilder = object
Expand Down Expand Up @@ -145,6 +146,7 @@ def doctarget(self) -> 'Documentable':

def setup(self) -> None:
self.contents: Dict[str, Documentable] = {}
self._linker: Optional['epydoc2stan.DocstringLinker'] = None

def setDocstring(self, node: ast.Str) -> None:
doc = node.s
Expand Down Expand Up @@ -373,6 +375,19 @@ def report(self, descr: str, section: str = 'parsing', lineno_offset: int = 0) -
f'{self.description}:{linenumber}: {descr}',
thresh=-1)

@property
def docstringlinker(self) -> 'epydoc2stan.DocstringLinker':
"""
Returns an instance of L{epydoc2stan.DocstringLinker} suitable for resolving names
in the context of the object scope.
"""
if self._linker is not None:
return self._linker
# FIXME: avoid cyclic import https://github.com/twisted/pydoctor/issues/507
from pydoctor.epydoc2stan import _CachedEpydocLinker
self._linker = _CachedEpydocLinker(self)
return self._linker


class CanContainImportsDocumentable(Documentable):
def setup(self) -> None:
Expand Down
4 changes: 2 additions & 2 deletions pydoctor/templatewriter/pages/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def format_decorators(obj: Union[model.Function, model.Attribute]) -> Iterator["

# Colorize decorators!
doc = colorize_inline_pyval(dec)
stan = doc.to_stan(epydoc2stan._EpydocLinker(obj))
stan = doc.to_stan(obj.docstringlinker)
# Report eventual warnings. It warns when a regex failed to parse or the html2stan() function fails.
for message in doc.warnings:
obj.report(message)
Expand Down Expand Up @@ -435,7 +435,7 @@ def extras(self) -> List["Flattenable"]:

def classSignature(self) -> "Flattenable":
r: List["Flattenable"] = []
_linker = epydoc2stan._EpydocLinker(self.ob)
_linker = self.ob.docstringlinker
zipped = list(zip(self.ob.rawbases, self.ob.bases))
if zipped:
r.append('(')
Expand Down
12 changes: 11 additions & 1 deletion pydoctor/test/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""PyDoctor's test suite."""

from logging import LogRecord
from typing import Iterable, TYPE_CHECKING, Optional, Sequence
from typing import Any, Iterable, TYPE_CHECKING, Optional, Sequence, Type
import sys
import pytest
from pathlib import Path
import functools

from twisted.web.template import Tag, tags

Expand Down Expand Up @@ -94,3 +95,12 @@ def link_xref(self, target: str, label: "Flattenable", lineno: int) -> Tag:

def resolve_identifier(self, identifier: str) -> Optional[str]:
return None

def partialclass(cls: Type[Any], *args: Any, **kwds: Any) -> Type[Any]:
# mypy gets errors: - Variable "cls" is not valid as a type
# - Invalid base class "cls"
class NewCls(cls): #type: ignore
__init__ = functools.partialmethod(cls.__init__, *args, **kwds) #type: ignore
__class__ = cls
assert isinstance(NewCls, type)
return NewCls
Loading

0 comments on commit 1210f94

Please sign in to comment.