diff --git a/src/jcloud_docsgen/_utils.py b/src/jcloud_docsgen/_utils.py new file mode 100644 index 0000000..76f2219 --- /dev/null +++ b/src/jcloud_docsgen/_utils.py @@ -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. + +''' +The utilities for jcloud_docsgen +''' + +import pathlib +import os +import errno + +class ExistingDirectory(pathlib.Path): + ''' + pathlib.Path subclass that is a directory + + ExistingDirectory represents a filesystem path but it also checks + whether the path exists and is not a file but a directory. It + inherits from pathlib.Path. + ''' + def __init__(self, path, *args, **kwargs) -> None: + if not os.path.exists(path): + raise FileNotFoundError(errno.ENOENT, 'no such file or directory', path) + if not os.path.isdir(path): + raise NotADirectoryError(errno.ENOTDIR, 'not a directory', path) + super().__init__(*(path, *args), **kwargs) \ No newline at end of file diff --git a/tests/unit/_utils/test_ExistingDirectory.py b/tests/unit/_utils/test_ExistingDirectory.py new file mode 100644 index 0000000..4efd821 --- /dev/null +++ b/tests/unit/_utils/test_ExistingDirectory.py @@ -0,0 +1,28 @@ +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 \ No newline at end of file