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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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