Fixed handling of `:meth:` docstring annotations with relative paths.

This commit is contained in:
Fabio Manganiello 2023-05-22 16:32:30 +02:00
parent 7eca1c27c9
commit a7aabd7c52
Signed by: blacklight
GPG Key ID: D90FBA7F76362774
10 changed files with 61 additions and 29 deletions

View File

@ -1,7 +1,7 @@
import inspect
import json
import re
from typing import Callable, Optional, Type
from typing import Callable, List, Optional, Type
from platypush.backend import Backend
from platypush.message.event import Event
@ -13,6 +13,7 @@ from ._parsers import (
BackendParser,
EventParser,
MethodParser,
Parser,
PluginParser,
ResponseParser,
SchemaParser,
@ -24,7 +25,7 @@ class Model:
Base class for component models.
"""
_parsers = [
_parsers: List[Type[Parser]] = [
BackendParser,
EventParser,
MethodParser,
@ -51,7 +52,9 @@ class Model:
self.package = obj_type.__module__[len(prefix) :]
self.name = name or self.package
self.last_modified = last_modified
self.doc, argsdoc = self._parse_docstring(doc or obj_type.__doc__ or '')
self.doc, argsdoc = self._parse_docstring(
doc or obj_type.__doc__ or '', obj_type=obj_type
)
self.args = {}
self.has_kwargs = False
@ -87,7 +90,7 @@ class Model:
yield attr, getattr(self, attr)
@classmethod
def _parse_docstring(cls, docstring: str):
def _parse_docstring(cls, docstring: str, obj_type: type):
new_docstring = ''
params = {}
cur_param = None
@ -129,14 +132,14 @@ class Model:
params[cur_param] = cur_param_docstring
for param, doc in params.items():
params[param] = cls._post_process_docstring(doc)
params[param] = cls._post_process_docstring(doc, obj_type=obj_type)
return cls._post_process_docstring(new_docstring), params
return cls._post_process_docstring(new_docstring, obj_type=obj_type), params
@classmethod
def _post_process_docstring(cls, docstring: str) -> str:
def _post_process_docstring(cls, docstring: str, obj_type: type) -> str:
for parsers in cls._parsers:
docstring = parsers.parse(docstring)
docstring = parsers.parse(docstring, obj_type=obj_type)
return docstring.strip()

View File

@ -1,4 +1,5 @@
from ._backend import BackendParser
from ._base import Parser
from ._event import EventParser
from ._method import MethodParser
from ._plugin import PluginParser
@ -10,6 +11,7 @@ __all__ = [
'BackendParser',
'EventParser',
'MethodParser',
'Parser',
'PluginParser',
'ResponseParser',
'SchemaParser',

View File

@ -16,7 +16,7 @@ class BackendParser(Parser):
@override
@classmethod
def parse(cls, docstring: str) -> str:
def parse(cls, docstring: str, *_, **__) -> str:
while True:
m = cls._backend_regex.search(docstring)
if not m:

View File

@ -8,5 +8,5 @@ class Parser(ABC):
@classmethod
@abstractmethod
def parse(cls, docstring: str) -> str:
def parse(cls, docstring: str, obj_type: type) -> str:
raise NotImplementedError()

View File

@ -16,7 +16,7 @@ class EventParser(Parser):
@override
@classmethod
def parse(cls, docstring: str) -> str:
def parse(cls, docstring: str, *_, **__) -> str:
while True:
m = cls._event_regex.search(docstring)
if not m:

View File

@ -10,26 +10,53 @@ class MethodParser(Parser):
respective documentation.
"""
_method_regex = re.compile(
_abs_method_regex = re.compile(
r'(\s*):meth:`(platypush\.plugins\.(.+?))`', re.MULTILINE
)
_rel_method_regex = re.compile(r'(\s*):meth:`\.(.+?)`', re.MULTILINE)
@override
@classmethod
def parse(cls, docstring: str) -> str:
def parse(cls, docstring: str, obj_type: type) -> str:
while True:
m = cls._method_regex.search(docstring)
if not m:
break
m = cls._rel_method_regex.search(docstring)
if m:
tokens = m.group(2).split('.')
method = tokens[-1]
package = obj_type.__module__
rel_package = '.'.join(package.split('.')[2:])
full_name = '.'.join(
[
package,
'.'.join(obj_type.__qualname__.split('.')[:-1]),
method,
]
)
tokens = m.group(3).split('.')
method = tokens[-1]
package = '.'.join(tokens[:-2])
docstring = cls._method_regex.sub(
f'{m.group(1)}`{package}.{method} '
f'<https://docs.platypush.tech/platypush/plugins/{package}.html#{m.group(2)}>`_',
docstring,
count=1,
)
docstring = cls._rel_method_regex.sub(
f'{m.group(1)}`{package}.{method} '
f'<https://docs.platypush.tech/platypush/plugins/{rel_package}.html#{full_name}>`_',
docstring,
count=1,
)
continue
m = cls._abs_method_regex.search(docstring)
if m:
tokens = m.group(3).split('.')
method = tokens[-1]
package = '.'.join(tokens[:-2])
docstring = cls._abs_method_regex.sub(
f'{m.group(1)}`{package}.{method} '
f'<https://docs.platypush.tech/platypush/plugins/{package}.html#{m.group(2)}>`_',
docstring,
count=1,
)
continue
break
return docstring

View File

@ -16,7 +16,7 @@ class PluginParser(Parser):
@override
@classmethod
def parse(cls, docstring: str) -> str:
def parse(cls, docstring: str, *_, **__) -> str:
while True:
m = cls._plugin_regex.search(docstring)
if not m:

View File

@ -16,7 +16,7 @@ class ResponseParser(Parser):
@override
@classmethod
def parse(cls, docstring: str) -> str:
def parse(cls, docstring: str, *_, **__) -> str:
while True:
m = cls._response_regex.search(docstring)
if not m:

View File

@ -61,7 +61,7 @@ class SchemaParser(Parser):
@override
@classmethod
def parse(cls, docstring: str) -> str:
def parse(cls, docstring: str, *_, **__) -> str:
while True:
m = cls._schema_regex.search(docstring)
if not m:

View File

@ -378,7 +378,7 @@ class SensorPlugin(RunnablePlugin, SensorEntityManager, ABC):
@action
def get_data(self, *args, **kwargs):
"""
(Deprecated) alias for :meth:`.get_measurement``
(Deprecated) alias for :meth:`.get_measurement`
"""
return self.get_measurement(*args, **kwargs)