Merge pull request 'Refactor(utils): mark ExistingDirectory and ExistingFile as deprecated' (#14) from refactor/remove-existing-file-class into main

Reviewed-on: #14
This commit was merged in pull request #14.
This commit is contained in:
jakob.scheid authored and Gitea committed 2026-09-05 14:44:21 +02:00
commit 3cd374c354
9 files changed
+67 -165

No files matched your search

+7
View File
@@ -1,5 +1,12 @@
# Changelog # Changelog
## [Unreleased]
### Deprecated
- utility class for existing directories
- utility class for existing files
## [0.1.0] - 2026-09-01 ## [0.1.0] - 2026-09-01
### Added ### Added
+7 -6
View File
@@ -22,13 +22,14 @@ __all__ = [
import argparse import argparse
import pathlib import pathlib
from .utils import ExistingDirectory
def existing_directory(path: str, *args, **kwargs) -> pathlib.Path: def existing_directory(path: str) -> pathlib.Path:
try: _path = path
return ExistingDirectory(path, *args, **kwargs) path = pathlib.Path(_path)
except (FileNotFoundError, NotADirectoryError) as e: if not path.exists():
raise argparse.ArgumentTypeError(f'{e.filename}{": " + e.args[1] if len(e.args) > 1 else ""}') raise argparse.ArgumentTypeError(f'{_path}: no such file or directory')
if not path.is_dir():
raise argparse.ArgumentTypeError(f'{_path}: not a directory')
def main() -> int: def main() -> int:
argument_parser = argparse.ArgumentParser() argument_parser = argparse.ArgumentParser()
+11 -18
View File
@@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
from __future__ import annotations from __future__ import annotations
from ...utils import ExistingDirectory, assert_that_is_instance, ExistingFile, non_empty_str, get_relative_path_segments from ...utils import non_empty_str, get_relative_path_segments
from ...exceptions import PythonArgumentStructureError, InvalidNamespaceError from ...exceptions import PythonArgumentStructureError, InvalidNamespaceError
from .namespaces import PythonModuleNamespace, PythonPackageNamespace from .namespaces import PythonModuleNamespace, PythonPackageNamespace
from .definitions import PythonDefinition, PythonFunctionDefinition, PythonAsyncFunctionDefinition, PythonClassDefinition from .definitions import PythonDefinition, PythonFunctionDefinition, PythonAsyncFunctionDefinition, PythonClassDefinition
@@ -742,11 +742,11 @@ class PythonModuleDocumentationGenerator:
A documentation generator for a Python module. A documentation generator for a Python module.
:param module_path: The path of the module file. :param module_path: The path of the module file.
:type module_path: ExistingFile :type module_path: pathlib.Path
:param src_directory: The directory of the source code. It is :param src_directory: The directory of the source code. It is
optional and only used for making the module optional and only used for making the module
identifiers in the documentation relative. identifiers in the documentation relative.
:type src_directory: Union[ExistingDirectory, None] :type src_directory: Union[pathlib.Path, None]
:param include_sections: The sections that will be included. :param include_sections: The sections that will be included.
:type include_sections: PythonDefinitionDocumentationIncludeSections :type include_sections: PythonDefinitionDocumentationIncludeSections
:param kwargs: The options for ``PythonDefinitionDocumentationGenerator``. :param kwargs: The options for ``PythonDefinitionDocumentationGenerator``.
@@ -754,15 +754,11 @@ class PythonModuleDocumentationGenerator:
def __init__( def __init__(
self, self,
module_path: ExistingFile, module_path: pathlib.Path,
src_directory: Union[ExistingDirectory, None] = None, src_directory: Union[pathlib.Path, None] = None,
include_sections: PythonDefinitionDocumentationIncludeSections = PythonDefinitionDocumentationIncludeSections(), include_sections: PythonDefinitionDocumentationIncludeSections = PythonDefinitionDocumentationIncludeSections(),
**kwargs **kwargs
) -> None: ) -> None:
assert_that_is_instance(module_path, ExistingFile)
assert_that_is_instance(src_directory, (ExistingDirectory, types.NoneType))
if module_path.name.count('.') > 1: if module_path.name.count('.') > 1:
raise InvalidNamespaceError('namespace identifier cannot contain more than one dot', namespace_identifier = module_path.name) raise InvalidNamespaceError('namespace identifier cannot contain more than one dot', namespace_identifier = module_path.name)
@@ -877,8 +873,8 @@ def _generate_package_namespace_documentation(
documentation_directory / (sub_namespace.name + '.md') documentation_directory / (sub_namespace.name + '.md')
).write_text( ).write_text(
PythonModuleDocumentationGenerator( PythonModuleDocumentationGenerator(
ExistingFile(str(dir / (sub_namespace.name + '.py'))), pathlib.Path(str(dir / (sub_namespace.name + '.py'))),
ExistingDirectory(str(root_directory)), pathlib.Path(str(root_directory)),
include_sections, include_sections,
**kwargs **kwargs
).generate_documentation() ).generate_documentation()
@@ -889,9 +885,9 @@ class PythonDocumentationGenerator:
The class for the documentation generator. The class for the documentation generator.
:param project_directory: The directory of the project. :param project_directory: The directory of the project.
:type project_directory: ExistingDirectory :type project_directory: pathlib.Path
:param docs_directory: The directory for the generated documentation. :param docs_directory: The directory for the generated documentation.
:type docs_directory: ExistingDirectory :type docs_directory: pathlib.Path
:param include_sections: The sections to be included in the documentation. :param include_sections: The sections to be included in the documentation.
:type include_sections: PythonDefinitionDocumentationIncludeSections :type include_sections: PythonDefinitionDocumentationIncludeSections
:param kwargs: The options for ``PythonDefinitionDocumentationGenerator``. :param kwargs: The options for ``PythonDefinitionDocumentationGenerator``.
@@ -899,14 +895,11 @@ class PythonDocumentationGenerator:
def __init__( def __init__(
self, self,
project_directory: ExistingDirectory, project_directory: pathlib.Path,
docs_directory: ExistingDirectory, docs_directory: pathlib.Path,
include_sections: PythonDefinitionDocumentationIncludeSections = PythonDefinitionDocumentationIncludeSections(), include_sections: PythonDefinitionDocumentationIncludeSections = PythonDefinitionDocumentationIncludeSections(),
**kwargs **kwargs
) -> None: ) -> None:
assert_that_is_instance(project_directory, ExistingDirectory)
assert_that_is_instance(docs_directory, ExistingDirectory)
self.project_directory = pathlib.Path(str(project_directory)) self.project_directory = pathlib.Path(str(project_directory))
self.docs_directory = pathlib.Path(str(docs_directory)) self.docs_directory = pathlib.Path(str(docs_directory))
self.include_sections = include_sections self.include_sections = include_sections
+7
View File
@@ -22,6 +22,12 @@ import errno
from typing import Union from typing import Union
import types import types
try:
from warnings import deprecated
except ImportError:
from typing_extensions import deprecated
@deprecated('Use pathlib.Path instead.')
class ExistingDirectory(pathlib.Path): class ExistingDirectory(pathlib.Path):
''' '''
pathlib.Path subclass that is a directory. pathlib.Path subclass that is a directory.
@@ -37,6 +43,7 @@ class ExistingDirectory(pathlib.Path):
raise NotADirectoryError(errno.ENOTDIR, 'not a directory', path) raise NotADirectoryError(errno.ENOTDIR, 'not a directory', path)
super().__init__(*(path, *args), **kwargs) super().__init__(*(path, *args), **kwargs)
@deprecated('Use pathlib.Path instead.')
class ExistingFile(pathlib.Path): class ExistingFile(pathlib.Path):
''' '''
pathlib.Path subclass that is a file. pathlib.Path subclass that is a file.
@@ -14,29 +14,13 @@
from src.jcloud_docsgen.core.python import PythonDocumentationGenerator from src.jcloud_docsgen.core.python import PythonDocumentationGenerator
from src.jcloud_docsgen.core.python.namespaces import PythonModuleNamespace, PythonPackageNamespace from src.jcloud_docsgen.core.python.namespaces import PythonModuleNamespace, PythonPackageNamespace
from src.jcloud_docsgen.utils import ExistingDirectory
import pytest import pytest
import pathlib import pathlib
@pytest.mark.parametrize('project_directory,docs_directory,expected_exception,expected_exception_msg', [
(1, 1, TypeError, 'expected \'ExistingDirectory\', got \'int\''),
(1, None, TypeError, 'expected \'ExistingDirectory\', got \'int\''),
(42, None, TypeError, 'expected \'ExistingDirectory\', got \'int\''),
(ExistingDirectory('tests'), 1, TypeError, 'expected \'ExistingDirectory\', got \'int\''),
(ExistingDirectory('tests/'), 1, TypeError, 'expected \'ExistingDirectory\', got \'int\''),
(1, ExistingDirectory('tests/'), TypeError, 'expected \'ExistingDirectory\', got \'int\''),
(1, ExistingDirectory('tests'), TypeError, 'expected \'ExistingDirectory\', got \'int\''),
(None, ExistingDirectory('tests'), TypeError, 'expected \'ExistingDirectory\', got \'NoneType\''),
])
def test_PythonDocumentationGenerator_exceptions(project_directory, docs_directory, expected_exception, expected_exception_msg):
with pytest.raises(expected_exception) as exc_info:
PythonDocumentationGenerator(project_directory, docs_directory)
assert str(exc_info.value) == expected_exception_msg
@pytest.mark.parametrize('python_documentation_generator,expected', [ @pytest.mark.parametrize('python_documentation_generator,expected', [
(PythonDocumentationGenerator(ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_1'), ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_1/docs')), []), (PythonDocumentationGenerator(pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_1'), pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_1/docs')), []),
(PythonDocumentationGenerator(ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_2'), ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_2/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module')])]), (PythonDocumentationGenerator(pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_2'), pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_2/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module')])]),
(PythonDocumentationGenerator(ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_3'), ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_3/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module'), PythonPackageNamespace('pkg', [PythonModuleNamespace('module2')])])]), (PythonDocumentationGenerator(pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_3'), pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_3/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module'), PythonPackageNamespace('pkg', [PythonModuleNamespace('module2')])])]),
]) ])
def test_PythonDocumentationGenerator_collect_modules(python_documentation_generator: PythonDocumentationGenerator, expected): def test_PythonDocumentationGenerator_collect_modules(python_documentation_generator: PythonDocumentationGenerator, expected):
assert python_documentation_generator.namespace() == expected assert python_documentation_generator.namespace() == expected
@@ -48,14 +32,14 @@ def test_PythonDocumentationGenerator_collect_modules(python_documentation_gener
def test_generate_documentation(dir, expectdir): def test_generate_documentation(dir, expectdir):
with expectdir('test_PythonDocumentationGenerator/test_generate_documentation/' + dir) as d: with expectdir('test_PythonDocumentationGenerator/test_generate_documentation/' + dir) as d:
PythonDocumentationGenerator( PythonDocumentationGenerator(
ExistingDirectory( pathlib.Path(
str( str(
pathlib.Path('tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/') / pathlib.Path('tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/') /
dir / dir /
'project' 'project'
) )
), ),
ExistingDirectory(str(d)), pathlib.Path(str(d)),
allow_tables = True, allow_tables = True,
allow_html = False allow_html = False
).generate_documentation( ).generate_documentation(
@@ -14,36 +14,24 @@
from src.jcloud_docsgen.core.python import PythonModuleDocumentationGenerator from src.jcloud_docsgen.core.python import PythonModuleDocumentationGenerator
from src.jcloud_docsgen.exceptions import InvalidNamespaceError from src.jcloud_docsgen.exceptions import InvalidNamespaceError
import pathlib
import pytest import pytest
from src.jcloud_docsgen.utils import ExistingFile, ExistingDirectory
@pytest.mark.parametrize('module_path,src_directory,expected_exception,expected_exception_msg', [ @pytest.mark.parametrize('module_path,src_directory,expected_exception,expected_exception_msg', [
(1, 1, TypeError, 'expected \'ExistingFile\', got \'int\''), (pathlib.Path('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'),
(1, None, TypeError, 'expected \'ExistingFile\', got \'int\''), (pathlib.Path('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'),
(42, None, TypeError, 'expected \'ExistingFile\', got \'int\''), (pathlib.Path('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/utils/test_file'), 1, TypeError, 'expected either \'ExistingDirectory\' or \'NoneType\', got \'int\''), (pathlib.Path('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'),
(ExistingDirectory('tests/'), 1, TypeError, 'expected \'ExistingFile\', got \'ExistingDirectory\''), (pathlib.Path('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'),
(ExistingDirectory('tests'), 1, TypeError, 'expected \'ExistingFile\', got \'ExistingDirectory\''), (pathlib.Path('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'),
(1, ExistingDirectory('tests/'), TypeError, 'expected \'ExistingFile\', got \'int\''), (pathlib.Path('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'),
(1, ExistingDirectory('tests'), TypeError, 'expected \'ExistingFile\', got \'int\''), (pathlib.Path('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'),
(None, ExistingDirectory('tests'), TypeError, 'expected \'ExistingFile\', got \'NoneType\''), (pathlib.Path('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'),
(None, None, TypeError, 'expected \'ExistingFile\', got \'NoneType\''), (pathlib.Path('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'),
(1, None, TypeError, 'expected \'ExistingFile\', got \'int\''), (pathlib.Path('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'),
(pathlib.Path('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.c'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c'), (pathlib.Path('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/files_with_more_than_one_dot/a.b.c.d'), None, InvalidNamespaceError, 'namespace identifier cannot contain more than one dot: a.b.c.d'), (pathlib.Path('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'),
(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): def test_PythonModuleDocumentationGenerator_exceptions(module_path, src_directory, expected_exception, expected_exception_msg):
with pytest.raises(expected_exception) as exc_info: with pytest.raises(expected_exception) as exc_info:
@@ -51,7 +39,7 @@ def test_PythonModuleDocumentationGenerator_exceptions(module_path, src_director
assert str(exc_info.value) == expected_exception_msg assert str(exc_info.value) == expected_exception_msg
@pytest.mark.parametrize('module_documentation_generator,expected', [ @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` (PythonModuleDocumentationGenerator(pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py'), pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_2/src/'), allow_tables = True, allow_html = False), '''# Module `pkg.module`
A test module. A test module.
@@ -220,7 +208,7 @@ Barks.
A dog.'''), 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` (PythonModuleDocumentationGenerator(pathlib.Path('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. A test module.
@@ -389,7 +377,7 @@ Barks.
A dog.'''), 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` (PythonModuleDocumentationGenerator(pathlib.Path('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. A test module.
@@ -548,7 +536,7 @@ Return type: `None`
<details><summary><h3 style="display:inline">Docstring</h3></summary>A dog.</details>'''), <details><summary><h3 style="display:inline">Docstring</h3></summary>A dog.</details>'''),
(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` (PythonModuleDocumentationGenerator(pathlib.Path('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. A test module.
@@ -749,7 +737,7 @@ Return type: `None`
<details><summary><h3 style="display:inline">Docstring</h3></summary>A dog.</details>'''), <details><summary><h3 style="display:inline">Docstring</h3></summary>A dog.</details>'''),
(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` (PythonModuleDocumentationGenerator(pathlib.Path('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. A test module.
@@ -83,37 +83,36 @@ class Something:
(module('''from src.jcloud_docsgen.core.python import PythonDocumentationGenerator (module('''from src.jcloud_docsgen.core.python import PythonDocumentationGenerator
from src.jcloud_docsgen.core.python.namespaces import PythonModuleNamespace, PythonPackageNamespace from src.jcloud_docsgen.core.python.namespaces import PythonModuleNamespace, PythonPackageNamespace
import pytest import pytest
from src.jcloud_docsgen.utils import ExistingDirectory
@pytest.mark.parametrize('project_directory,docs_directory', [ @pytest.mark.parametrize('project_directory,docs_directory', [
(1, 1), (1, 1),
(1, None), (1, None),
(42, None), (42, None),
(ExistingDirectory('tests'), 1), (pathlib.Path('tests'), 1),
(ExistingDirectory('tests/'), 1), (pathlib.Path('tests/'), 1),
(1, ExistingDirectory('tests/')), (1, pathlib.Path('tests/')),
(1, ExistingDirectory('tests')), (1, pathlib.Path('tests')),
(None, ExistingDirectory('tests')), (None, pathlib.Path('tests')),
]) ])
def test_PythonDocumentationGenerator_type_exceptions(project_directory, docs_directory): def test_PythonDocumentationGenerator_type_exceptions(project_directory, docs_directory):
with pytest.raises(TypeError): with pytest.raises(TypeError):
PythonDocumentationGenerator(project_directory, docs_directory) PythonDocumentationGenerator(project_directory, docs_directory)
@pytest.mark.parametrize('python_documentation_generator,expected', [ @pytest.mark.parametrize('python_documentation_generator,expected', [
(PythonDocumentationGenerator(ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_1'), ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_1/docs')), []), (PythonDocumentationGenerator(pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_1'), pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_1/docs')), []),
(PythonDocumentationGenerator(ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_2'), ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_2/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module')])]), (PythonDocumentationGenerator(pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_2'), pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_2/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module')])]),
(PythonDocumentationGenerator(ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_3'), ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_3/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module'), PythonPackageNamespace('pkg', [PythonModuleNamespace('module2')])])]), (PythonDocumentationGenerator(pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_3'), pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_3/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module'), PythonPackageNamespace('pkg', [PythonModuleNamespace('module2')])])]),
]) ])
def test_PythonDocumentationGenerator_collect_modules(python_documentation_generator: PythonDocumentationGenerator, expected): def test_PythonDocumentationGenerator_collect_modules(python_documentation_generator: PythonDocumentationGenerator, expected):
assert python_documentation_generator.namespace() == expected'''), [ assert python_documentation_generator.namespace() == expected'''), [
PythonFunctionDefinition('test_PythonDocumentationGenerator_type_exceptions', [ PythonFunctionDefinition('test_PythonDocumentationGenerator_type_exceptions', [
PythonFunctionArgument('project_directory', PythonArgumentKind.NORMAL, None, None), PythonFunctionArgument('project_directory', PythonArgumentKind.NORMAL, None, None),
PythonFunctionArgument('docs_directory', PythonArgumentKind.NORMAL, None, None), PythonFunctionArgument('docs_directory', PythonArgumentKind.NORMAL, None, None),
], None, None, ['''pytest.mark.parametrize('project_directory,docs_directory', [(1, 1), (1, None), (42, None), (ExistingDirectory('tests'), 1), (ExistingDirectory('tests/'), 1), (1, ExistingDirectory('tests/')), (1, ExistingDirectory('tests')), (None, ExistingDirectory('tests'))])''']), ], None, None, ['''pytest.mark.parametrize('project_directory,docs_directory', [(1, 1), (1, None), (42, None), (pathlib.Path('tests'), 1), (pathlib.Path('tests/'), 1), (1, pathlib.Path('tests/')), (1, pathlib.Path('tests')), (None, pathlib.Path('tests'))])''']),
PythonFunctionDefinition('test_PythonDocumentationGenerator_collect_modules', [ PythonFunctionDefinition('test_PythonDocumentationGenerator_collect_modules', [
PythonFunctionArgument('python_documentation_generator', PythonArgumentKind.NORMAL, None, 'PythonDocumentationGenerator'), PythonFunctionArgument('python_documentation_generator', PythonArgumentKind.NORMAL, None, 'PythonDocumentationGenerator'),
PythonFunctionArgument('expected', PythonArgumentKind.NORMAL, None, None) PythonFunctionArgument('expected', PythonArgumentKind.NORMAL, None, None)
], None, None, ['''pytest.mark.parametrize('python_documentation_generator,expected', [(PythonDocumentationGenerator(ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_1'), ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_1/docs')), []), (PythonDocumentationGenerator(ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_2'), ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_2/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module')])]), (PythonDocumentationGenerator(ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_3'), ExistingDirectory('tests/unit/core/python/_core/test_project_dirs/pdir_3/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module'), PythonPackageNamespace('pkg', [PythonModuleNamespace('module2')])])])])''']) ], None, None, ['''pytest.mark.parametrize('python_documentation_generator,expected', [(PythonDocumentationGenerator(pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_1'), pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_1/docs')), []), (PythonDocumentationGenerator(pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_2'), pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_2/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module')])]), (PythonDocumentationGenerator(pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_3'), pathlib.Path('tests/unit/core/python/_core/test_project_dirs/pdir_3/docs')), [PythonPackageNamespace('pkg', [PythonModuleNamespace('module'), PythonPackageNamespace('pkg', [PythonModuleNamespace('module2')])])])])'''])
]), ]),
(module('''class C1: (module('''class C1:
class C2: class C2:
@@ -1,42 +0,0 @@
# Copyright 2026 jCloud
# 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.utils import ExistingDirectory
import pytest
import pathlib
@pytest.mark.parametrize('path,expected', [
('tests/unit/utils/test_directory/', 'tests/unit/utils/test_directory'),
('tests/unit/utils/test_directory', 'tests/unit/utils/test_directory'),
('tests/unit/utils/', 'tests/unit/utils'),
('tests/unit/utils', 'tests/unit/utils'),
('/', '/'),
('./', '.'),
('.', '.'),
('../', '..'),
('..', '..'),
])
def test_ExistingDirectory(path, expected):
assert ExistingDirectory(path).as_posix() == expected
@pytest.mark.parametrize('path,expected_exception,expected_exception_message', [
('tests/unit/utils/does_not_exist/', FileNotFoundError, '[Errno 2] no such file or directory: \'tests/unit/utils/does_not_exist/\''),
('tests/unit/utils/does_not_exist', FileNotFoundError, '[Errno 2] no such file or directory: \'tests/unit/utils/does_not_exist\''),
('', FileNotFoundError, '[Errno 2] no such file or directory: \'\''),
('README.md', NotADirectoryError, '[Errno 20] not a directory: \'README.md\''),
])
def test_ExistingDirectory_exceptions(path, expected_exception, expected_exception_message):
with pytest.raises(expected_exception) as exc_info:
ExistingDirectory(path)
assert str(exc_info.value) == expected_exception_message
-35
View File
@@ -1,35 +0,0 @@
# Copyright 2026 jCloud
# 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.utils import ExistingFile
import pytest
import pathlib
@pytest.mark.parametrize('path,expected', [
('tests/unit/utils/test_file', 'tests/unit/utils/test_file'),
])
def test_ExistingDirectory(path, expected):
assert ExistingFile(path).as_posix() == expected
@pytest.mark.parametrize('path,expected_exception,expected_exception_message', [
('tests/unit/utils/does_not_exist', FileNotFoundError, '[Errno 2] no such file or directory: \'tests/unit/utils/does_not_exist\''),
('', FileNotFoundError, '[Errno 2] no such file or directory: \'\''),
('tests/unit/utils/test_directory', IsADirectoryError, '[Errno 21] is a directory: \'tests/unit/utils/test_directory\''),
('.', IsADirectoryError, '[Errno 21] is a directory: \'.\''),
('./', IsADirectoryError, '[Errno 21] is a directory: \'./\''),
])
def test_ExistingDirectory_exceptions(path, expected_exception, expected_exception_message):
with pytest.raises(expected_exception) as exc_info:
ExistingFile(path)
assert str(exc_info.value) == expected_exception_message