diff --git a/charmcraft/templates/init-django-framework/pyproject.toml.j2 b/charmcraft/templates/init-django-framework/pyproject.toml.j2 new file mode 100644 index 000000000..3cb1ce223 --- /dev/null +++ b/charmcraft/templates/init-django-framework/pyproject.toml.j2 @@ -0,0 +1,41 @@ +# Testing tools configuration +[tool.coverage.run] +branch = true + +[tool.coverage.report] +show_missing = true + +[tool.pytest.ini_options] +minversion = "6.0" +log_cli_level = "INFO" + +# Linting tools configuration +[tool.ruff] +line-length = 99 +lint.select = ["E", "W", "F", "C", "N", "D", "I001"] +lint.extend-ignore = [ + "D105", + "D107", + "D203", + "D204", + "D213", + "D215", + "D400", + "D404", + "D406", + "D407", + "D408", + "D409", + "D413", +] +extend-exclude = ["__pycache__", "*.egg_info"] +lint.per-file-ignores = {"tests/*" = ["D100","D101","D102","D103","D104"]} + +[tool.ruff.lint.mccabe] +max-complexity = 10 + +[tool.codespell] +skip = "build,lib,venv,icon.svg,.tox,.git,.mypy_cache,.ruff_cache,.coverage" + +[tool.pyright] +include = ["src/**.py"] diff --git a/charmcraft/templates/init-django-framework/tox.ini.j2 b/charmcraft/templates/init-django-framework/tox.ini.j2 new file mode 100644 index 000000000..351f36085 --- /dev/null +++ b/charmcraft/templates/init-django-framework/tox.ini.j2 @@ -0,0 +1,84 @@ +# Copyright {{ year }} {{ author }} +# See LICENSE file for licensing details. + +[tox] +no_package = True +skip_missing_interpreters = True +env_list = format, lint, static +min_version = 4.0.0 + +[vars] +src_path = {tox_root}/src +;tests_path = {tox_root}/tests +;lib_path = {tox_root}/lib/charms/operator_name_with_underscores +all_path = {[vars]src_path} + +[testenv] +set_env = + PYTHONPATH = {tox_root}/lib:{[vars]src_path} + PYTHONBREAKPOINT=pdb.set_trace + PY_COLORS=1 +pass_env = + PYTHONPATH + CHARM_BUILD_DIR + MODEL_SETTINGS + +[testenv:format] +description = Apply coding style standards to code +deps = + ruff +commands = + ruff format {[vars]all_path} + ruff check --fix {[vars]all_path} + +[testenv:lint] +description = Check code against coding style standards +deps = + ruff + codespell +commands = + # if this charm owns a lib, uncomment "lib_path" variable + # and uncomment the following line + # codespell {[vars]lib_path} + codespell {tox_root} + ruff check {[vars]all_path} + ruff format --check --diff {[vars]all_path} + +[testenv:unit] +description = Run unit tests +deps = + pytest + coverage[toml] + -r {tox_root}/requirements.txt +commands = + coverage run --source={[vars]src_path} \ + -m pytest \ + --tb native \ + -v \ + -s \ + {posargs} \ + {[vars]tests_path}/unit + coverage report + +[testenv:static] +description = Run static type checks +deps = + pyright + -r {tox_root}/requirements.txt +commands = + pyright {posargs} + +[testenv:integration] +description = Run integration tests +deps = + pytest + juju + pytest-operator + -r {tox_root}/requirements.txt +commands = + pytest -v \ + -s \ + --tb native \ + --log-cli-level=INFO \ + {posargs} \ + {[vars]tests_path}/integration diff --git a/charmcraft/templates/init-fastapi-framework/pyproject.toml.j2 b/charmcraft/templates/init-fastapi-framework/pyproject.toml.j2 new file mode 100644 index 000000000..3cb1ce223 --- /dev/null +++ b/charmcraft/templates/init-fastapi-framework/pyproject.toml.j2 @@ -0,0 +1,41 @@ +# Testing tools configuration +[tool.coverage.run] +branch = true + +[tool.coverage.report] +show_missing = true + +[tool.pytest.ini_options] +minversion = "6.0" +log_cli_level = "INFO" + +# Linting tools configuration +[tool.ruff] +line-length = 99 +lint.select = ["E", "W", "F", "C", "N", "D", "I001"] +lint.extend-ignore = [ + "D105", + "D107", + "D203", + "D204", + "D213", + "D215", + "D400", + "D404", + "D406", + "D407", + "D408", + "D409", + "D413", +] +extend-exclude = ["__pycache__", "*.egg_info"] +lint.per-file-ignores = {"tests/*" = ["D100","D101","D102","D103","D104"]} + +[tool.ruff.lint.mccabe] +max-complexity = 10 + +[tool.codespell] +skip = "build,lib,venv,icon.svg,.tox,.git,.mypy_cache,.ruff_cache,.coverage" + +[tool.pyright] +include = ["src/**.py"] diff --git a/charmcraft/templates/init-fastapi-framework/tox.ini.j2 b/charmcraft/templates/init-fastapi-framework/tox.ini.j2 new file mode 100644 index 000000000..351f36085 --- /dev/null +++ b/charmcraft/templates/init-fastapi-framework/tox.ini.j2 @@ -0,0 +1,84 @@ +# Copyright {{ year }} {{ author }} +# See LICENSE file for licensing details. + +[tox] +no_package = True +skip_missing_interpreters = True +env_list = format, lint, static +min_version = 4.0.0 + +[vars] +src_path = {tox_root}/src +;tests_path = {tox_root}/tests +;lib_path = {tox_root}/lib/charms/operator_name_with_underscores +all_path = {[vars]src_path} + +[testenv] +set_env = + PYTHONPATH = {tox_root}/lib:{[vars]src_path} + PYTHONBREAKPOINT=pdb.set_trace + PY_COLORS=1 +pass_env = + PYTHONPATH + CHARM_BUILD_DIR + MODEL_SETTINGS + +[testenv:format] +description = Apply coding style standards to code +deps = + ruff +commands = + ruff format {[vars]all_path} + ruff check --fix {[vars]all_path} + +[testenv:lint] +description = Check code against coding style standards +deps = + ruff + codespell +commands = + # if this charm owns a lib, uncomment "lib_path" variable + # and uncomment the following line + # codespell {[vars]lib_path} + codespell {tox_root} + ruff check {[vars]all_path} + ruff format --check --diff {[vars]all_path} + +[testenv:unit] +description = Run unit tests +deps = + pytest + coverage[toml] + -r {tox_root}/requirements.txt +commands = + coverage run --source={[vars]src_path} \ + -m pytest \ + --tb native \ + -v \ + -s \ + {posargs} \ + {[vars]tests_path}/unit + coverage report + +[testenv:static] +description = Run static type checks +deps = + pyright + -r {tox_root}/requirements.txt +commands = + pyright {posargs} + +[testenv:integration] +description = Run integration tests +deps = + pytest + juju + pytest-operator + -r {tox_root}/requirements.txt +commands = + pytest -v \ + -s \ + --tb native \ + --log-cli-level=INFO \ + {posargs} \ + {[vars]tests_path}/integration diff --git a/charmcraft/templates/init-flask-framework/pyproject.toml.j2 b/charmcraft/templates/init-flask-framework/pyproject.toml.j2 new file mode 100644 index 000000000..3cb1ce223 --- /dev/null +++ b/charmcraft/templates/init-flask-framework/pyproject.toml.j2 @@ -0,0 +1,41 @@ +# Testing tools configuration +[tool.coverage.run] +branch = true + +[tool.coverage.report] +show_missing = true + +[tool.pytest.ini_options] +minversion = "6.0" +log_cli_level = "INFO" + +# Linting tools configuration +[tool.ruff] +line-length = 99 +lint.select = ["E", "W", "F", "C", "N", "D", "I001"] +lint.extend-ignore = [ + "D105", + "D107", + "D203", + "D204", + "D213", + "D215", + "D400", + "D404", + "D406", + "D407", + "D408", + "D409", + "D413", +] +extend-exclude = ["__pycache__", "*.egg_info"] +lint.per-file-ignores = {"tests/*" = ["D100","D101","D102","D103","D104"]} + +[tool.ruff.lint.mccabe] +max-complexity = 10 + +[tool.codespell] +skip = "build,lib,venv,icon.svg,.tox,.git,.mypy_cache,.ruff_cache,.coverage" + +[tool.pyright] +include = ["src/**.py"] diff --git a/charmcraft/templates/init-flask-framework/tox.ini.j2 b/charmcraft/templates/init-flask-framework/tox.ini.j2 new file mode 100644 index 000000000..351f36085 --- /dev/null +++ b/charmcraft/templates/init-flask-framework/tox.ini.j2 @@ -0,0 +1,84 @@ +# Copyright {{ year }} {{ author }} +# See LICENSE file for licensing details. + +[tox] +no_package = True +skip_missing_interpreters = True +env_list = format, lint, static +min_version = 4.0.0 + +[vars] +src_path = {tox_root}/src +;tests_path = {tox_root}/tests +;lib_path = {tox_root}/lib/charms/operator_name_with_underscores +all_path = {[vars]src_path} + +[testenv] +set_env = + PYTHONPATH = {tox_root}/lib:{[vars]src_path} + PYTHONBREAKPOINT=pdb.set_trace + PY_COLORS=1 +pass_env = + PYTHONPATH + CHARM_BUILD_DIR + MODEL_SETTINGS + +[testenv:format] +description = Apply coding style standards to code +deps = + ruff +commands = + ruff format {[vars]all_path} + ruff check --fix {[vars]all_path} + +[testenv:lint] +description = Check code against coding style standards +deps = + ruff + codespell +commands = + # if this charm owns a lib, uncomment "lib_path" variable + # and uncomment the following line + # codespell {[vars]lib_path} + codespell {tox_root} + ruff check {[vars]all_path} + ruff format --check --diff {[vars]all_path} + +[testenv:unit] +description = Run unit tests +deps = + pytest + coverage[toml] + -r {tox_root}/requirements.txt +commands = + coverage run --source={[vars]src_path} \ + -m pytest \ + --tb native \ + -v \ + -s \ + {posargs} \ + {[vars]tests_path}/unit + coverage report + +[testenv:static] +description = Run static type checks +deps = + pyright + -r {tox_root}/requirements.txt +commands = + pyright {posargs} + +[testenv:integration] +description = Run integration tests +deps = + pytest + juju + pytest-operator + -r {tox_root}/requirements.txt +commands = + pytest -v \ + -s \ + --tb native \ + --log-cli-level=INFO \ + {posargs} \ + {[vars]tests_path}/integration diff --git a/charmcraft/templates/init-go-framework/pyproject.toml.j2 b/charmcraft/templates/init-go-framework/pyproject.toml.j2 new file mode 100644 index 000000000..3cb1ce223 --- /dev/null +++ b/charmcraft/templates/init-go-framework/pyproject.toml.j2 @@ -0,0 +1,41 @@ +# Testing tools configuration +[tool.coverage.run] +branch = true + +[tool.coverage.report] +show_missing = true + +[tool.pytest.ini_options] +minversion = "6.0" +log_cli_level = "INFO" + +# Linting tools configuration +[tool.ruff] +line-length = 99 +lint.select = ["E", "W", "F", "C", "N", "D", "I001"] +lint.extend-ignore = [ + "D105", + "D107", + "D203", + "D204", + "D213", + "D215", + "D400", + "D404", + "D406", + "D407", + "D408", + "D409", + "D413", +] +extend-exclude = ["__pycache__", "*.egg_info"] +lint.per-file-ignores = {"tests/*" = ["D100","D101","D102","D103","D104"]} + +[tool.ruff.lint.mccabe] +max-complexity = 10 + +[tool.codespell] +skip = "build,lib,venv,icon.svg,.tox,.git,.mypy_cache,.ruff_cache,.coverage" + +[tool.pyright] +include = ["src/**.py"] diff --git a/charmcraft/templates/init-go-framework/tox.ini.j2 b/charmcraft/templates/init-go-framework/tox.ini.j2 new file mode 100644 index 000000000..351f36085 --- /dev/null +++ b/charmcraft/templates/init-go-framework/tox.ini.j2 @@ -0,0 +1,84 @@ +# Copyright {{ year }} {{ author }} +# See LICENSE file for licensing details. + +[tox] +no_package = True +skip_missing_interpreters = True +env_list = format, lint, static +min_version = 4.0.0 + +[vars] +src_path = {tox_root}/src +;tests_path = {tox_root}/tests +;lib_path = {tox_root}/lib/charms/operator_name_with_underscores +all_path = {[vars]src_path} + +[testenv] +set_env = + PYTHONPATH = {tox_root}/lib:{[vars]src_path} + PYTHONBREAKPOINT=pdb.set_trace + PY_COLORS=1 +pass_env = + PYTHONPATH + CHARM_BUILD_DIR + MODEL_SETTINGS + +[testenv:format] +description = Apply coding style standards to code +deps = + ruff +commands = + ruff format {[vars]all_path} + ruff check --fix {[vars]all_path} + +[testenv:lint] +description = Check code against coding style standards +deps = + ruff + codespell +commands = + # if this charm owns a lib, uncomment "lib_path" variable + # and uncomment the following line + # codespell {[vars]lib_path} + codespell {tox_root} + ruff check {[vars]all_path} + ruff format --check --diff {[vars]all_path} + +[testenv:unit] +description = Run unit tests +deps = + pytest + coverage[toml] + -r {tox_root}/requirements.txt +commands = + coverage run --source={[vars]src_path} \ + -m pytest \ + --tb native \ + -v \ + -s \ + {posargs} \ + {[vars]tests_path}/unit + coverage report + +[testenv:static] +description = Run static type checks +deps = + pyright + -r {tox_root}/requirements.txt +commands = + pyright {posargs} + +[testenv:integration] +description = Run integration tests +deps = + pytest + juju + pytest-operator + -r {tox_root}/requirements.txt +commands = + pytest -v \ + -s \ + --tb native \ + --log-cli-level=INFO \ + {posargs} \ + {[vars]tests_path}/integration diff --git a/charmcraft/templates/init-kubernetes/pyproject.toml.j2 b/charmcraft/templates/init-kubernetes/pyproject.toml.j2 index ceeab132b..3cb1ce223 100644 --- a/charmcraft/templates/init-kubernetes/pyproject.toml.j2 +++ b/charmcraft/templates/init-kubernetes/pyproject.toml.j2 @@ -14,6 +14,8 @@ log_cli_level = "INFO" line-length = 99 lint.select = ["E", "W", "F", "C", "N", "D", "I001"] lint.extend-ignore = [ + "D105", + "D107", "D203", "D204", "D213", @@ -26,7 +28,6 @@ lint.extend-ignore = [ "D409", "D413", ] -lint.ignore = ["E501", "D107"] extend-exclude = ["__pycache__", "*.egg_info"] lint.per-file-ignores = {"tests/*" = ["D100","D101","D102","D103","D104"]} diff --git a/charmcraft/templates/init-machine/pyproject.toml.j2 b/charmcraft/templates/init-machine/pyproject.toml.j2 index ceeab132b..3cb1ce223 100644 --- a/charmcraft/templates/init-machine/pyproject.toml.j2 +++ b/charmcraft/templates/init-machine/pyproject.toml.j2 @@ -14,6 +14,8 @@ log_cli_level = "INFO" line-length = 99 lint.select = ["E", "W", "F", "C", "N", "D", "I001"] lint.extend-ignore = [ + "D105", + "D107", "D203", "D204", "D213", @@ -26,7 +28,6 @@ lint.extend-ignore = [ "D409", "D413", ] -lint.ignore = ["E501", "D107"] extend-exclude = ["__pycache__", "*.egg_info"] lint.per-file-ignores = {"tests/*" = ["D100","D101","D102","D103","D104"]} diff --git a/charmcraft/templates/init-simple/pyproject.toml.j2 b/charmcraft/templates/init-simple/pyproject.toml.j2 index ceeab132b..3cb1ce223 100644 --- a/charmcraft/templates/init-simple/pyproject.toml.j2 +++ b/charmcraft/templates/init-simple/pyproject.toml.j2 @@ -14,6 +14,8 @@ log_cli_level = "INFO" line-length = 99 lint.select = ["E", "W", "F", "C", "N", "D", "I001"] lint.extend-ignore = [ + "D105", + "D107", "D203", "D204", "D213", @@ -26,7 +28,6 @@ lint.extend-ignore = [ "D409", "D413", ] -lint.ignore = ["E501", "D107"] extend-exclude = ["__pycache__", "*.egg_info"] lint.per-file-ignores = {"tests/*" = ["D100","D101","D102","D103","D104"]} diff --git a/pyproject.toml b/pyproject.toml index b9459d15e..2355e36f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,10 +43,8 @@ charmcraft = "charmcraft.application.main:main" [project.optional-dependencies] dev = [ # When updating these, also update the dev/lint/types groups in renovate. "coverage", - "flake8", "freezegun", "hypothesis", - "pydocstyle", "pyfakefs", "pylint", "pytest", diff --git a/requirements-dev.txt b/requirements-dev.txt index 3a34fd65a..275b8926f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -18,7 +18,6 @@ cryptography==43.0.1 dill==0.3.9 distro==1.9.0 docker==7.1.0 -flake8==7.1.1 freezegun==1.5.1 httplib2==0.22.0 humanize==4.10.0 @@ -47,12 +46,10 @@ packaging==24.1 platformdirs==4.3.6 pluggy==1.5.0 protobuf==5.28.2 -pycodestyle==2.12.1 pycparser==2.22 pydantic==2.8.2 pydantic-core==2.20.1 pydantic-yaml==1.3.0 -pydocstyle==6.3.0 pyfakefs==5.6.0 pyflakes==3.2.0 pygit2==1.14.1 diff --git a/tests/integration/commands/test_init.py b/tests/integration/commands/test_init.py index 5bee96aef..9108a7d1e 100644 --- a/tests/integration/commands/test_init.py +++ b/tests/integration/commands/test_init.py @@ -25,7 +25,6 @@ import sys from unittest import mock -import pydocstyle import pytest import pytest_check @@ -291,36 +290,14 @@ def test_tox_success(new_path, init_command, profile): if not (new_path / "tox.ini").exists(): pytest.skip("init template doesn't contain tox.ini file") - result = subprocess.run( - ["tox", "-v"], - cwd=new_path, - env=env, - text=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - check=False, - ) - assert result.returncode == 0, "Tox run failed:\n" + result.stdout - - -@pytest.mark.parametrize("profile", list(commands.init.PROFILES)) -def test_pep257(new_path, init_command, profile): - to_ignore = { - "D105", # Missing docstring in magic method - "D107", # Missing docstring in __init__ - } - to_include = pydocstyle.violations.conventions.pep257 - to_ignore - - init_command.run(create_namespace(profile=profile)) - - python_paths = (str(path) for path in new_path.rglob("*.py")) - python_paths = (path for path in python_paths if "tests" not in path) - errors = list(pydocstyle.check(python_paths, select=to_include)) - - if errors: - report = [ - f"Please fix files as suggested by pydocstyle ({len(errors):d} issues):" - ] - report.extend(str(e) for e in errors) - msg = "\n".join(report) - pytest.fail(msg, pytrace=False) + if list((new_path / "tests").glob("*.py")): # If any tests exist + result = subprocess.run( + ["tox", "-v", "run", "-e", "unit"], + cwd=new_path, + env=env, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=False, + ) + assert result.returncode == 0, "Tox run failed:\n" + result.stdout