diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f4f5935..d932f06 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,22 +11,23 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook - rev: v9.23.0 + rev: v9.26.0 hooks: - id: commitlint + language_version: 20.17.0 stages: - commit-msg - additional_dependencies: ['conventional-changelog-conventionalcommits'] + additional_dependencies: ['conventional-changelog-conventionalcommits@4.6.3'] - repo: https://github.com/pycqa/isort - rev: 7.0.0 + rev: 9.0.0a3 hooks: - id: isort - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.12.0 + rev: 26.5.1 hooks: - id: black - repo: https://github.com/codespell-project/codespell - rev: v2.4.1 + rev: v2.4.2 hooks: - id: codespell args: ["-x", ".codespellignorelines"] diff --git a/luigi_tools/parameter.py b/luigi_tools/parameter.py index c7dc989..05fcc19 100644 --- a/luigi_tools/parameter.py +++ b/luigi_tools/parameter.py @@ -13,6 +13,7 @@ # limitations under the License. """This module provides some specific luigi parameters.""" + import collections.abc import dataclasses import typing @@ -111,7 +112,7 @@ def __init__(self, cls_type, *args, **kwargs): self._cls_type = cls_type super().__init__(*args, **kwargs) - def normalize(self, value): + def normalize(self, value): # pylint: disable=arguments-renamed """Normalize the given value to a dataclass initialized object.""" if isinstance(value, self._cls_type): value = dataclasses.asdict(value) diff --git a/luigi_tools/target.py b/luigi_tools/target.py index 53193e5..690c553 100644 --- a/luigi_tools/target.py +++ b/luigi_tools/target.py @@ -13,6 +13,7 @@ # limitations under the License. """This module provides some specific luigi targets.""" + from pathlib import Path import luigi diff --git a/luigi_tools/task.py b/luigi_tools/task.py index cd501f7..56eedc6 100644 --- a/luigi_tools/task.py +++ b/luigi_tools/task.py @@ -13,6 +13,7 @@ # limitations under the License. """This module provides some specific luigi tasks and associated tools.""" + import logging import types from copy import deepcopy @@ -276,6 +277,10 @@ def __call__(self, task_that_inherits): # Add it to the inheriting task with new default values setattr(task_that_inherits, param_name, new_param) + # Luigi 3.8+ parameters are descriptors. Class decorators run after class + # creation, so Python does not call __set_name__ for these copied parameters. + set_name = getattr(new_param, "__set_name__", lambda *_args: None) + set_name(task_that_inherits, param_name) # Do not emit warning because of wrong type def _warn_on_wrong_global_param_type(_self, global_param_name, global_param_value): diff --git a/luigi_tools/util.py b/luigi_tools/util.py index 030651a..ea7efe7 100644 --- a/luigi_tools/util.py +++ b/luigi_tools/util.py @@ -13,6 +13,7 @@ # limitations under the License. """This module provides some functions to work with luigi tasks.""" + import configparser import logging import os diff --git a/pyproject.toml b/pyproject.toml index 69992c8..f5ab950 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,9 @@ line_length = 100 force_single_line = true [tool.pytest.ini_options] +addopts = [ + "--code-highlight=no", +] testpaths = [ "tests", ] diff --git a/setup.py b/setup.py index ac2399b..78dbbd7 100644 --- a/setup.py +++ b/setup.py @@ -16,8 +16,8 @@ from pathlib import Path -from setuptools import find_namespace_packages -from setuptools import setup +from setuptools import find_namespace_packages # pylint: disable=import-error +from setuptools import setup # pylint: disable=import-error reqs = [ "luigi>=3.1", @@ -28,7 +28,7 @@ doc_reqs = [ "docutils<0.21", # Temporary fix for m2r2 "m2r2", - "sphinx", + "sphinx>=6.2", "sphinx-bluebrain-theme", ] @@ -60,7 +60,7 @@ install_requires=reqs, extras_require={ "docs": doc_reqs, - "graphviz": ["graphviz"], + "graphviz": ["graphviz>=0.20"], "test": test_reqs, }, include_package_data=True, diff --git a/tests/test_parameter.py b/tests/test_parameter.py index 931d9bf..c9b30ea 100644 --- a/tests/test_parameter.py +++ b/tests/test_parameter.py @@ -1135,33 +1135,21 @@ def output(self): return luigi.LocalTarget("not_existing_file") # Test with values from config - with set_luigi_config( - { - "TaskDataClassParameter": { - "a": """{ + with set_luigi_config({"TaskDataClassParameter": {"a": """{ "a": {"a": 1, "b": "2"}, "b": {"c": 3.0, "d": 4}, "c": {"e": 5, "f": 6}, "d": {"7": 8.0, "9": 10.0} - }""" - } - } - ): + }"""}}): assert luigi.build([TaskDataClassParameter()], local_scheduler=True) # Parsing fails with integer keys - with set_luigi_config( - { - "TaskDataClassParameter": { - "a": """{ + with set_luigi_config({"TaskDataClassParameter": {"a": """{ "a": {"a": 1, "b": "2"}, "b": {"c": 3.0, "d": 4}, "c": {"e": 5, "f": 6}, "d": {7: 8.0, 9: 10.0} - }""" - } - } - ): + }"""}}): with pytest.raises(ValueError): luigi.build([TaskDataClassParameter()], local_scheduler=True) diff --git a/tests/tools.py b/tests/tools.py index 19a6d74..aa9f56f 100644 --- a/tests/tools.py +++ b/tests/tools.py @@ -13,6 +13,7 @@ # limitations under the License. """A few helpers for luigi-tools test suite.""" + from pathlib import Path diff --git a/tox.ini b/tox.ini index b87a674..9ebcefd 100644 --- a/tox.ini +++ b/tox.ini @@ -47,11 +47,16 @@ commands = [testenv:min_versions] basepython = python3.10 deps = - Requirements-Builder + uv +allowlist_externals = uv commands_pre = - requirements-builder --level=min --extras=test -o {envtmpdir}/requirements_min.txt setup.py - pip install -r {envtmpdir}/requirements_min.txt - pip freeze + uv pip compile \ + --resolution lowest-direct \ + --all-extras \ + --output-file {envtmpdir}/requirements_min.txt \ + pyproject.toml + uv pip install --no-cache -r {envtmpdir}/requirements_min.txt + uv pip freeze [testenv:lint] basepython = python3.10