diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ee906d5..a19c217 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -24,4 +24,5 @@ - Add feature to parse Python docstrings - Add function to ensure a non-empty string. - Add Python definition documentation generator -- Add function to get the path segments of a path relative to another \ No newline at end of file +- Add function to get the path segments of a path relative to another +- Add Python module documentation generator \ No newline at end of file diff --git a/src/jcloud_docsgen/core/python/_core.py b/src/jcloud_docsgen/core/python/_core.py index 497d364..932a6b5 100644 --- a/src/jcloud_docsgen/core/python/_core.py +++ b/src/jcloud_docsgen/core/python/_core.py @@ -13,8 +13,8 @@ # limitations under the License. from __future__ import annotations -from ...utils import ExistingDirectory, assert_that_is_instance, ExistingFile, non_empty_str -from ...exceptions import PythonArgumentStructureError +from ...utils import ExistingDirectory, assert_that_is_instance, ExistingFile, non_empty_str, get_relative_path_segments +from ...exceptions import PythonArgumentStructureError, InvalidNamespaceError from .namespaces import PythonModuleNamespace, PythonPackageNamespace from .definitions import PythonDefinition, PythonFunctionDefinition, PythonAsyncFunctionDefinition, PythonClassDefinition from .arguments import PythonArgumentKind, PythonFunctionArgument @@ -26,6 +26,7 @@ from enum import Enum import docstring_parser import pathlib import ast +import types __all__ = [ 'PythonDefinitionDocumentationIncludeSections', @@ -255,6 +256,7 @@ class _NoDocstringTemplate: many_returns = [] deprecation = None examples = [] + meta = [] short_description = None long_description = None blank_after_short_description = None @@ -408,8 +410,8 @@ class PythonDefinitionDocumentationGenerator: self, definition: PythonDefinition, include_sections: PythonDefinitionDocumentationIncludeSections = PythonDefinitionDocumentationIncludeSections(), - *, level: int = 1, + *, allow_html: bool = True, allow_tables: bool = False, skip_empty_sections: bool = True, @@ -741,12 +743,49 @@ class PythonModuleDocumentationGenerator: :param module_path: The path of the module file. :type module_path: ExistingFile + :param src_directory: The directory of the source code. It is + optional and only used for making the module + identifiers in the documentation relative. + :type src_directory: Union[ExistingDirectory, None] + :param include_sections: The sections that will be included. + :type include_sections: PythonDefinitionDocumentationIncludeSections + :kwargs: The options for ``PythonDefinitionDocumentationGenerator``. ''' - def __init__(self, module_path: ExistingFile) -> None: + def __init__( + self, + module_path: ExistingFile, + src_directory: Union[ExistingDirectory, None] = None, + include_sections: PythonDefinitionDocumentationIncludeSections = PythonDefinitionDocumentationIncludeSections(), + **kwargs + ) -> None: + assert_that_is_instance(module_path, ExistingFile) + assert_that_is_instance(src_directory, (ExistingDirectory, types.NoneType)) + + if module_path.name.count('.') > 1: + raise InvalidNamespaceError('namespace identifier cannot contain more than one dot', namespace_identifier = module_path.name) self.module_path = pathlib.Path(str(module_path)) + self.src_directory = pathlib.Path(str(src_directory)) if src_directory is not None else None + + self.include_sections = include_sections + self.kwargs = kwargs + + self._source_code_cache = None + self._ast_cache = None + + @property + def _source_code(self) -> str: + if self._source_code_cache is None: + self._source_code_cache = self.module_path.read_text() + return self._source_code_cache + + @property + def _ast(self) -> str: + if self._ast_cache is None: + self._ast_cache = ast.parse(self._source_code) + return self._ast_cache def collect_definitions(self) -> Iterator[PythonDefinition]: ''' @@ -756,10 +795,47 @@ class PythonModuleDocumentationGenerator: :rtype: Iterator[PythonDefinition] ''' - tree = ast.parse(self.module_path.read_text()) + tree = self._ast return _collect_definitions(tree) + def generate_documentation(self) -> str: + ''' + Generates the documentation in the markdown format. + + :return: The documentation. + :rtype: str + ''' + + + md = '# Module `' + + if self.src_directory is not None: + module_identifier = '.'.join(get_relative_path_segments(self.module_path, self.src_directory)) + if module_identifier.endswith('.py'): + md += module_identifier[:-3] + else: + md += module_identifier + else: + md += self.module_path.stem + + md += '`\n\n' + + docstring = ast.get_docstring(self._ast) + if docstring is not None: + md += docstring + '\n\n' + + for definition in self.collect_definitions(): + md += PythonDefinitionDocumentationGenerator( + definition, + self.include_sections, + 2, + **self.kwargs + ).generate_documentation() + '\n\n' + + return md.strip() + + class PythonDocumentationGenerator: ''' The class for the documentation generator. diff --git a/tests/unit/core/python/_core/directory.with.more.than.one.dot/a.b.py b/tests/unit/core/python/_core/directory.with.more.than.one.dot/a.b.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g.h b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g.h new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g.h.py b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g.h.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g.py b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.py b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.py b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.py b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.py b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.py b/tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/core/python/_core/test_PythonModuleDocumentationGenerator.py b/tests/unit/core/python/_core/test_PythonModuleDocumentationGenerator.py new file mode 100644 index 0000000..f5cf865 --- /dev/null +++ b/tests/unit/core/python/_core/test_PythonModuleDocumentationGenerator.py @@ -0,0 +1,964 @@ +# 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. + +from src.jcloud_docsgen.core.python import PythonModuleDocumentationGenerator +from src.jcloud_docsgen.exceptions import InvalidNamespaceError +import pytest +from src.jcloud_docsgen.utils import ExistingFile, ExistingDirectory + +@pytest.mark.parametrize('module_path,src_directory,expected_exception,expected_exception_msg', [ + (1, 1, TypeError, 'expected \'ExistingFile\', got \'int\''), + (1, None, TypeError, 'expected \'ExistingFile\', got \'int\''), + (42, None, TypeError, 'expected \'ExistingFile\', got \'int\''), + (ExistingFile('tests/unit/utils/test_file'), 1, TypeError, 'expected either \'ExistingDirectory\' or \'NoneType\', got \'int\''), + (ExistingDirectory('tests/'), 1, TypeError, 'expected \'ExistingFile\', got \'ExistingDirectory\''), + (ExistingDirectory('tests'), 1, TypeError, 'expected \'ExistingFile\', got \'ExistingDirectory\''), + (1, ExistingDirectory('tests/'), TypeError, 'expected \'ExistingFile\', got \'int\''), + (1, ExistingDirectory('tests'), TypeError, 'expected \'ExistingFile\', got \'int\''), + (None, ExistingDirectory('tests'), TypeError, 'expected \'ExistingFile\', got \'NoneType\''), + (None, None, TypeError, 'expected \'ExistingFile\', got \'NoneType\''), + (1, None, TypeError, 'expected \'ExistingFile\', got \'int\''), + + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.d'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.d.e'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.d.e.f'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.d.e.f.g'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g.h'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.d.e.f.g.h'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g.h.py'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.d.e.f.g.h.py'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.g.py'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.d.e.f.g.py'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.f.py'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.d.e.f.py'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.e.py'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.d.e.py'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.d.py'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.d.py'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.c.py'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.py'), + (ExistingFile('tests/unit/core/python/_core/files_with_more_than_one_dot/a.b.py'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.py'), + (ExistingFile('tests/unit/core/python/_core/directory.with.more.than.one.dot/a.b.py'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.py'), +]) +def test_PythonModuleDocumentationGenerator_exceptions(module_path, src_directory, expected_exception, expected_exception_msg): + with pytest.raises(expected_exception) as exc_info: + PythonModuleDocumentationGenerator(module_path, src_directory) + assert str(exc_info.value) == expected_exception_msg + +@pytest.mark.parametrize('module_documentation_generator,expected', [ + (PythonModuleDocumentationGenerator(ExistingFile('tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py'), ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_2/src/'), allow_tables = True, allow_html = False), '''# Module `pkg.module` + +A test module. + +## Function `add` + +Adds two numbers. + + +### Function signature + +```python +add(a: int | float, b: int | float) -> int | float +``` + +### Returns + +The sum. + +Return type: `int | float` + +### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `a` | `int | float` | normal | -- | The first number. | +| `b` | `int | float` | normal | -- | The second number. | + + + + + + + +### Docstring + +Adds two numbers. + +:param a: The first number. +:type a: int | float +:param b: The second number. +:type b: int | float + +:return: The sum. +:rtype: int | float + +## Class `Animal` + +A class representing an animal. + + + + +### Body + +#### Constructor (method `__init__`) + +##### Method signature + +```python +__init__(self, name: str) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | +| `name` | `str` | normal | -- | -- | + +#### Method `greet` + +Returns a greeting. + + +##### Method signature + +```python +greet(self) +``` + +##### Returns + +The greeting. + +Return type: `str` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | + + + + + + + +##### Docstring + +Returns a greeting. + +:return: The greeting. +:rtype: str + + + + + +### Docstring + +A class representing an animal. + +:param name: Its name. +:type name: str + +## Class `Dog` + +A dog. + +### Base classes + +- `Animal` + +### Body + +#### Method `bark` + +Barks. + +##### Method signature + +```python +bark(self) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | + + + + + + + +##### Docstring + +Barks. + + + + + +### Docstring + +A dog.'''), + + (PythonModuleDocumentationGenerator(ExistingFile('tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py'), None, allow_tables = True, allow_html = False), '''# Module `module` + +A test module. + +## Function `add` + +Adds two numbers. + + +### Function signature + +```python +add(a: int | float, b: int | float) -> int | float +``` + +### Returns + +The sum. + +Return type: `int | float` + +### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `a` | `int | float` | normal | -- | The first number. | +| `b` | `int | float` | normal | -- | The second number. | + + + + + + + +### Docstring + +Adds two numbers. + +:param a: The first number. +:type a: int | float +:param b: The second number. +:type b: int | float + +:return: The sum. +:rtype: int | float + +## Class `Animal` + +A class representing an animal. + + + + +### Body + +#### Constructor (method `__init__`) + +##### Method signature + +```python +__init__(self, name: str) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | +| `name` | `str` | normal | -- | -- | + +#### Method `greet` + +Returns a greeting. + + +##### Method signature + +```python +greet(self) +``` + +##### Returns + +The greeting. + +Return type: `str` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | + + + + + + + +##### Docstring + +Returns a greeting. + +:return: The greeting. +:rtype: str + + + + + +### Docstring + +A class representing an animal. + +:param name: Its name. +:type name: str + +## Class `Dog` + +A dog. + +### Base classes + +- `Animal` + +### Body + +#### Method `bark` + +Barks. + +##### Method signature + +```python +bark(self) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | + + + + + + + +##### Docstring + +Barks. + + + + + +### Docstring + +A dog.'''), + + (PythonModuleDocumentationGenerator(ExistingFile('tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py'), None, allow_tables = True, allow_html = True), '''# Module `module` + +A test module. + +## Function `add` + +Adds two numbers. + + +### Function signature + +```python +add(a: int | float, b: int | float) -> int | float +``` + +### Returns + +The sum. + +Return type: `int | float` + +### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `a` | `int | float` | normal | -- | The first number. | +| `b` | `int | float` | normal | -- | The second number. | + + + + + + + +

Docstring

Adds two numbers. + +:param a: The first number. +:type a: int | float +:param b: The second number. +:type b: int | float + +:return: The sum. +:rtype: int | float
+ +## Class `Animal` + +A class representing an animal. + + + + +### Body + +#### Constructor (method `__init__`) + +##### Method signature + +```python +__init__(self, name: str) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | +| `name` | `str` | normal | -- | -- | + +#### Method `greet` + +Returns a greeting. + + +##### Method signature + +```python +greet(self) +``` + +##### Returns + +The greeting. + +Return type: `str` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | + + + + + + + +
Docstring
Returns a greeting. + +:return: The greeting. +:rtype: str
+ + + + + +

Docstring

A class representing an animal. + +:param name: Its name. +:type name: str
+ +## Class `Dog` + +A dog. + +### Base classes + +- `Animal` + +### Body + +#### Method `bark` + +Barks. + +##### Method signature + +```python +bark(self) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | + + + + + + + +
Docstring
Barks.
+ + + + + +

Docstring

A dog.
'''), + + (PythonModuleDocumentationGenerator(ExistingFile('tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py'), None, allow_tables = False, allow_html = True), '''# Module `module` + +A test module. + +## Function `add` + +Adds two numbers. + + +### Function signature + +```python +add(a: int | float, b: int | float) -> int | float +``` + +### Returns + +The sum. + +Return type: `int | float` + +### Parameters + +- Parameter: `a` + + Type: `int | float` + + Kind: normal + + Default value: -- + + Description: The first number. + +- Parameter: `b` + + Type: `int | float` + + Kind: normal + + Default value: -- + + Description: The second number. + + + + + + + +

Docstring

Adds two numbers. + +:param a: The first number. +:type a: int | float +:param b: The second number. +:type b: int | float + +:return: The sum. +:rtype: int | float
+ +## Class `Animal` + +A class representing an animal. + + + + +### Body + +#### Constructor (method `__init__`) + +##### Method signature + +```python +__init__(self, name: str) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +- Parameter: `self` + + Type: -- + + Kind: normal + + Default value: -- + + Description: -- + +- Parameter: `name` + + Type: `str` + + Kind: normal + + Default value: -- + + Description: -- + +#### Method `greet` + +Returns a greeting. + + +##### Method signature + +```python +greet(self) +``` + +##### Returns + +The greeting. + +Return type: `str` + +##### Parameters + +- Parameter: `self` + + Type: -- + + Kind: normal + + Default value: -- + + Description: -- + + + + + + + +
Docstring
Returns a greeting. + +:return: The greeting. +:rtype: str
+ + + + + +

Docstring

A class representing an animal. + +:param name: Its name. +:type name: str
+ +## Class `Dog` + +A dog. + +### Base classes + +- `Animal` + +### Body + +#### Method `bark` + +Barks. + +##### Method signature + +```python +bark(self) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +- Parameter: `self` + + Type: -- + + Kind: normal + + Default value: -- + + Description: -- + + + + + + + +
Docstring
Barks.
+ + + + + +

Docstring

A dog.
'''), + + (PythonModuleDocumentationGenerator(ExistingFile('tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py'), None, allow_tables = False, allow_html = False), '''# Module `module` + +A test module. + +## Function `add` + +Adds two numbers. + + +### Function signature + +```python +add(a: int | float, b: int | float) -> int | float +``` + +### Returns + +The sum. + +Return type: `int | float` + +### Parameters + +- Parameter: `a` + + Type: `int | float` + + Kind: normal + + Default value: -- + + Description: The first number. + +- Parameter: `b` + + Type: `int | float` + + Kind: normal + + Default value: -- + + Description: The second number. + + + + + + + +### Docstring + +Adds two numbers. + +:param a: The first number. +:type a: int | float +:param b: The second number. +:type b: int | float + +:return: The sum. +:rtype: int | float + +## Class `Animal` + +A class representing an animal. + + + + +### Body + +#### Constructor (method `__init__`) + +##### Method signature + +```python +__init__(self, name: str) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +- Parameter: `self` + + Type: -- + + Kind: normal + + Default value: -- + + Description: -- + +- Parameter: `name` + + Type: `str` + + Kind: normal + + Default value: -- + + Description: -- + +#### Method `greet` + +Returns a greeting. + + +##### Method signature + +```python +greet(self) +``` + +##### Returns + +The greeting. + +Return type: `str` + +##### Parameters + +- Parameter: `self` + + Type: -- + + Kind: normal + + Default value: -- + + Description: -- + + + + + + + +##### Docstring + +Returns a greeting. + +:return: The greeting. +:rtype: str + + + + + +### Docstring + +A class representing an animal. + +:param name: Its name. +:type name: str + +## Class `Dog` + +A dog. + +### Base classes + +- `Animal` + +### Body + +#### Method `bark` + +Barks. + +##### Method signature + +```python +bark(self) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +- Parameter: `self` + + Type: -- + + Kind: normal + + Default value: -- + + Description: -- + + + + + + + +##### Docstring + +Barks. + + + + + +### Docstring + +A dog.'''), +]) +def test_PythonModuleDocumentationGenerator_exceptions(module_documentation_generator, expected): + assert module_documentation_generator.generate_documentation() == expected \ No newline at end of file diff --git a/tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py b/tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py index e69de29..050fcb4 100644 --- a/tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py +++ b/tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py @@ -0,0 +1,50 @@ +''' +A test module. +''' + +def add(a: int | float, b: int | float) -> int | float: + ''' + Adds two numbers. + + :param a: The first number. + :type a: int | float + :param b: The second number. + :type b: int | float + + :return: The sum. + :rtype: int | float + ''' + + return a + b + +class Animal: + ''' + A class representing an animal. + + :param name: Its name. + :type name: str + ''' + def __init__(self, name: str) -> None: + self.name = name + + def greet(self): + ''' + Returns a greeting. + + :return: The greeting. + :rtype: str + ''' + + return f'Hi there! My name is {self.name}' + +class Dog(Animal): + ''' + A dog. + ''' + + def bark(self) -> None: + ''' + Barks. + ''' + + print('Woof!') \ No newline at end of file