diff --git a/README.md b/README.md index 4ffd648..4d87dbd 100644 --- a/README.md +++ b/README.md @@ -1,11 +1 @@ -[![](https://git.klemek.fr/klemek/python-template/actions/workflows/lint.yml/badge.svg?branch=main&style=flat-square)](https://git.klemek.fr/klemek/python-template/actions?workflow=lint.yml) [![](https://git.klemek.fr/klemek/python-template/actions/workflows/test.yml/badge.svg?branch=main&style=flat-square)](https://git.klemek.fr/klemek/python-template/actions?workflow=test.yml) - - -# Python Template - -## Use this template - -- [ ] 1. rename foler `sample` to match project -- [ ] 2. rename project in `pyproject.toml` -- [ ] 3. update `README.md` -- [ ] 4. enjoy +[![](https://git.klemek.fr/klemek/tout-doux/actions/workflows/lint.yml/badge.svg?branch=main&style=flat-square)](https://git.klemek.fr/klemek/tout-doux/actions?workflow=lint.yml) [![](https://git.klemek.fr/klemek/tout-doux/actions/workflows/test.yml/badge.svg?branch=main&style=flat-square)](https://git.klemek.fr/klemek/tout-doux/actions?workflow=test.yml) diff --git a/sample/__init__.py b/app/__init__.py similarity index 100% rename from sample/__init__.py rename to app/__init__.py diff --git a/sample/__main__.py b/app/__main__.py similarity index 100% rename from sample/__main__.py rename to app/__main__.py diff --git a/sample/logs.py b/app/logs.py similarity index 100% rename from sample/logs.py rename to app/logs.py diff --git a/sample/params.py b/app/params.py similarity index 100% rename from sample/params.py rename to app/params.py diff --git a/pyproject.toml b/pyproject.toml index 4e79dc4..bf0c767 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,13 +1,13 @@ [project] -name = "sample" # TODO: 2. rename project +name = "tout-doux" version = "0.0.0" -description = "Add your description here" +description = "" readme = "README.md" requires-python = ">=3.14" dependencies = [] [project.scripts] -sample = "sample.__main__:main" # TODO: 2. rename project +tout-doux = "app.__main__:main" [build-system] requires = ["uv_build>=0.11.7,<0.12"] @@ -26,18 +26,14 @@ add-bounds = "major" [tool.uv.build-backend] module-root = "" -module-name = "sample" # TODO: 2. rename project +module-name = "app" [tool.ruff.lint] select = ["ALL"] ignore = ["D", "E501", "ANN401", "BLE001", "COM812", "S101", "PT"] [tool.ty.src] -include = ["sample", "tests"] # TODO: 2. rename project +include = ["app", "tests"] [tool.ty.environment] python = "./.venv/bin/python3" - -[tool.coverage.run] -source = ["sample"] # TODO: 2. rename project -omit = ["sample/logs.py", "sample/__main__.py"] diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index 37789d2..0000000 --- a/tests/__init__.py +++ /dev/null @@ -1,176 +0,0 @@ -import contextlib -import pathlib -import tempfile -import typing -import unittest -import unittest.mock - -__import__("sys").modules["unittest.util"]._MAX_LENGTH = 999999999 # ty:ignore[unresolved-attribute] # noqa: SLF001 - - -class BaseTestCase(unittest.TestCase): - @typing.override - def __init__(self, *args: typing.Any, **kwargs: typing.Any) -> None: - self.mocks: list[unittest.mock.Mock] = [] - self.tmp_dir: tempfile.TemporaryDirectory | None = None - self.tmp_path: pathlib.Path = pathlib.Path() - super().__init__(*args, **kwargs) - - @typing.override - def tearDown(self) -> None: - if self.tmp_dir is not None: - self.tmp_dir.cleanup() - self.tmp_dir = None - super().tearDown() - - def get_tmp_dir(self) -> str: - self.tmp_dir = tempfile.TemporaryDirectory(delete=False) - self.tmp_path = pathlib.Path(self.tmp_dir.name) - return self.tmp_dir.name - - def new_mock(self, spec: type | None = None) -> unittest.mock.Mock: - mock = unittest.mock.Mock(spec) - self.mocks += [mock] - return mock - - @contextlib.contextmanager - def patch( - self, target: str, return_value: typing.Any = None, count: int = 1 - ) -> typing.Iterator[unittest.mock.Mock]: - with unittest.mock.patch( - target, return_value=return_value, create=True - ) as mock: - yield mock - self.assertEqual(mock.call_count, count, mock) - - @contextlib.contextmanager - def patch_calls( - self, - target: str, - args: list[typing.Iterable[typing.Any]] | None = None, - return_values: list[typing.Any] | None = None, - kwargs: list[dict[str, typing.Any]] | None = None, - ) -> typing.Iterator[unittest.mock.Mock]: - if args is None: - args = [[]] - if return_values is None: - return_values = [None] * len(args) - if kwargs is None: - kwargs = [{}] * len(args) - with unittest.mock.patch( - target, side_effect=return_values, create=True - ) as mock: - yield mock - self.__check_calls(mock, args, kwargs) - - @contextlib.contextmanager - def patch_call( - self, - target: str, - args: typing.Iterable[typing.Any] | None = None, - return_value: typing.Any = None, - kwargs: dict[str, typing.Any] | None = None, - ) -> typing.Iterator[unittest.mock.Mock]: - if args is None: - args = [] - if kwargs is None: - kwargs = {} - with self.patch_calls(target, [args], [return_value], [kwargs]) as mock: - yield mock - - @contextlib.contextmanager - def seal_mocks(self, *extra_mocks: unittest.mock.Mock) -> typing.Iterator[None]: - for mock in self.mocks: - unittest.mock.seal(mock) - for mock in extra_mocks: - unittest.mock.seal(mock) - yield - - @contextlib.contextmanager - def mock_calls( - self, - mock: unittest.mock.Mock, - args: list[typing.Iterable[typing.Any]] | None = None, - return_values: list[typing.Any] | None = None, - kwargs: list[dict[str, typing.Any]] | None = None, - ) -> typing.Iterator[None]: - if args is None: - args = [[]] - if return_values is None: - return_values = [None] * len(args) - if kwargs is None: - kwargs = [{}] * len(args) - mock.side_effect = return_values - mock.reset_mock() - yield - self.__check_calls(mock, args, kwargs) - - @contextlib.contextmanager - def mock_call( - self, - mock: unittest.mock.Mock, - args: typing.Iterable[typing.Any] | None = None, - return_value: typing.Any = None, - kwargs: dict[str, typing.Any] | None = None, - ) -> typing.Iterator[None]: - if args is None: - args = [] - if kwargs is None: - kwargs = {} - with self.mock_calls(mock, [args], [return_value], [kwargs]): - yield - - @contextlib.contextmanager - def mock_calls_unchecked( - self, - mock: unittest.mock.Mock, - count: int = 1, - return_values: list[typing.Any] | None = None, - ) -> typing.Iterator[None]: - if return_values is None: - return_values = [None] * count - mock.side_effect = return_values - mock.reset_mock() - yield - self.assertEqual(mock.call_count, count, mock) - - @contextlib.contextmanager - def mock_call_unchecked( - self, - mock: unittest.mock.Mock, - return_value: typing.Any = None, - ) -> typing.Iterator[None]: - with self.mock_calls_unchecked(mock, 1, [return_value]): - yield - - def assert_file_content(self, file: pathlib.Path, *expected_content: str) -> None: - assert file.parent.is_dir(), file - assert file.exists(), file - assert file.is_file(), file - with file.open() as file_content: - self.assertEqual(file_content.read(), "\n".join(expected_content)) - - def __check_calls( - self, - mock: unittest.mock.Mock, - args: list[typing.Iterable[typing.Any]], - kwargs: list[dict[str, typing.Any]], - ) -> None: - total_rows = max(len(args), len(mock.method_calls), len(kwargs)) - missing_calls = max(0, total_rows - len(mock.mock_calls)) - missing_args = max(0, total_rows - len(args)) - missing_kwargs = max(0, total_rows - len(kwargs)) - for i, values in enumerate( - zip( - mock.mock_calls + [None] * missing_calls, - args + [[]] * missing_args, - kwargs + [{}] * missing_kwargs, - strict=False, - ) - ): - real_call, expected_args, expected_kwargs = values - self.assertEqual( - real_call, - unittest.mock.call(*expected_args, **expected_kwargs), - f"{i + 1}: {mock}", - ) diff --git a/tests/test_sample.py b/tests/test_sample.py deleted file mode 100644 index 5e39f89..0000000 --- a/tests/test_sample.py +++ /dev/null @@ -1,6 +0,0 @@ -from . import BaseTestCase - - -class TestSample(BaseTestCase): - def test_sample(self) -> None: - self.skipTest("TODO") diff --git a/uv.lock b/uv.lock index dd41c04..7d8d21f 100644 --- a/uv.lock +++ b/uv.lock @@ -128,7 +128,7 @@ wheels = [ ] [[package]] -name = "sample" +name = "tout-doux" version = "0.0.0" source = { editable = "." } @@ -144,10 +144,10 @@ dev = [ [package.metadata.requires-dev] dev = [ - { name = "coverage", specifier = ">=7.13.5" }, - { name = "pytest", specifier = ">=9.0.3" }, - { name = "ruff", specifier = ">=0.15.10" }, - { name = "ty", specifier = ">=0.0.29" }, + { name = "coverage", specifier = ">=7.13.5,<8.0.0" }, + { name = "pytest", specifier = ">=9.0.3,<10.0.0" }, + { name = "ruff", specifier = ">=0.15.12,<0.16.0" }, + { name = "ty", specifier = ">=0.0.34,<0.0.35" }, ] [[package]]