Add class for Python docstrings

This commit is contained in:
2026-04-13 14:15:49 +02:00
parent 7f02b5b7ec
commit 16852f3d68
7 changed files with 86 additions and 31 deletions
+29 -10
View File
@@ -16,8 +16,11 @@ from __future__ import annotations
from typing import Union
import ast
from .arguments import PythonFunctionArgument, PythonASTArgumentsListParser
from .docstrings import PythonDocstring
import keyword
from ...exceptions import InvalidPythonIdentifierError
from ...utils import assert_that_is_instance
import types
__all__ = [
'PythonDefinition',
@@ -26,6 +29,20 @@ __all__ = [
'PythonClassDefinition'
]
def _python_docstring(doc: Union[str, None]) -> Union[PythonDocstring, None]:
'''
Returns the PythonDocstring object if the docstring is a string and
not ``None``.
:param doc: The docstring.
:type doc: Union[str, None]
:return: The PythonDocstring object or ``None``.
:rtype: Union[PythonDocstring, None]
'''
return PythonDocstring(doc) if doc is not None else None
class PythonDefinition:
'''
A base class for Python definition (a class, function or asynchronous
@@ -34,7 +51,7 @@ class PythonDefinition:
:param name: The name of the definition.
:type name: str
:param doc: The docstring.
:type doc: Union[str, None]
:type doc: Union[PythonDocstring, None]
:param decorators: The definition decorators.
:type decorators: list[str]
@@ -42,10 +59,12 @@ class PythonDefinition:
Python identifier.
'''
def __init__(self, name: str, doc: Union[str, None], decorators: list[str]) -> None:
def __init__(self, name: str, doc: Union[PythonDocstring, None], decorators: list[str]) -> None:
if keyword.iskeyword(name) or not name.isidentifier() or not name:
raise InvalidPythonIdentifierError('invalid identifier', identifier = name)
assert_that_is_instance(doc, (PythonDocstring, types.NoneType))
self.name = name
self.doc = doc
self.decorators = decorators
@@ -71,7 +90,7 @@ class PythonDefinition:
return cls(
node.name,
ast.get_docstring(node),
_python_docstring(ast.get_docstring(node)),
[ast.unparse(d) for d in node.decorator_list]
)
@@ -92,7 +111,7 @@ class PythonFunctionDefinition(PythonDefinition):
:param returns: The return type of the function or class.
:type returns: Union[str, None]
:param doc: The docstring.
:type doc: Union[str, None]
:type doc: Union[PythonDocstring, None]
:param decorators: The definition decorators.
:type decorators: list[str]
@@ -100,7 +119,7 @@ class PythonFunctionDefinition(PythonDefinition):
Python identifier.
'''
def __init__(self, name: str, args: list[PythonFunctionArgument], returns: Union[str, None], doc: Union[str, None], decorators: list[str]) -> None:
def __init__(self, name: str, args: list[PythonFunctionArgument], returns: Union[str, None], doc: Union[PythonDocstring, None], decorators: list[str]) -> None:
super().__init__(name, doc, decorators)
self.args = args
self.returns = returns
@@ -127,7 +146,7 @@ class PythonFunctionDefinition(PythonDefinition):
node.name,
PythonASTArgumentsListParser(node.args).to_argument_list(),
ast.unparse(node.returns) if node.returns is not None else None,
ast.get_docstring(node),
_python_docstring(ast.get_docstring(node)),
[ast.unparse(d) for d in node.decorator_list]
)
@@ -143,7 +162,7 @@ class PythonAsyncFunctionDefinition(PythonFunctionDefinition):
:param returns: The return type of the function or class.
:type returns: Union[str, None]
:param doc: The docstring.
:type doc: Union[str, None]
:type doc: Union[PythonDocstring, None]
:param decorators: The definition decorators.
:type decorators: list[str]
@@ -160,7 +179,7 @@ class PythonClassDefinition(PythonDefinition):
:param bases: The base classes.
:type bases: list[str]
:param doc: The docstring.
:type doc: Union[str, None]
:type doc: Union[PythonDocstring, None]
:param decorators: The definition decorators.
:type decorators: list[str]
:param body:
@@ -170,7 +189,7 @@ class PythonClassDefinition(PythonDefinition):
Python identifier.
'''
def __init__(self, name: str, bases: list[str], doc: Union[str, None], decorators: list[str], body: list[PythonDefinition]) -> None:
def __init__(self, name: str, bases: list[str], doc: Union[PythonDocstring, None], decorators: list[str], body: list[PythonDefinition]) -> None:
super().__init__(name, doc, decorators)
self.bases = bases
self.body = body
@@ -196,7 +215,7 @@ class PythonClassDefinition(PythonDefinition):
return cls(
node.name,
[ast.unparse(b) for b in node.bases],
ast.get_docstring(node),
_python_docstring(ast.get_docstring(node)),
[ast.unparse(d) for d in node.decorator_list],
[
PythonFunctionDefinition.from_node(expr)
@@ -0,0 +1,36 @@
# Copyright 2026 jCloud Services GbR
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__all__ = [
'PythonDocstring'
]
class PythonDocstring:
'''
Represents a Python docstring.
:param docstring: The docstring as a string.
:type docstring: str
'''
def __init__(self, docstring: str) -> None:
self.docstring = docstring
def __repr__(self) -> str:
return type(self).__name__ + '(' + repr(self.docstring) + ')'
def __eq__(self, value) -> bool:
if not isinstance(value, type(self)):
return False
return self.docstring == value.docstring