diff --git a/gokart/mypy.py b/gokart/mypy.py index 82b37716..93a3067e 100644 --- a/gokart/mypy.py +++ b/gokart/mypy.py @@ -9,6 +9,7 @@ import re from typing import Callable, Final, Iterator, Literal, Optional +import luigi from mypy.expandtype import expand_type, expand_type_by_instance from mypy.nodes import ( ARG_NAMED_OPT, @@ -56,6 +57,7 @@ METADATA_TAG: Final[str] = 'task_on_kart' PARAMETER_FULLNAME_MATCHER: Final = re.compile(r'^(gokart|luigi)(\.parameter)?\.\w*Parameter$') +PARAMETER_TMP_MATCHER: Final = re.compile(r'^\w*Parameter$') class TaskOnKartPlugin(Plugin): @@ -413,6 +415,16 @@ def is_parameter_call(expr: Expression) -> bool: if isinstance(type_info, TypeInfo): return PARAMETER_FULLNAME_MATCHER.match(type_info.fullname) is not None + + # Currently, luigi doesn't provide py.typed. it will be released next to 3.5.1. + # https://github.com/spotify/luigi/pull/3297 + # With the following code, we can't assume correctly. + # + # from luigi import Parameter + # class MyTask(gokart.TaskOnKart): + # param = Parameter() + if isinstance(type_info, Var) and luigi.__version__ <= '3.5.1': + return PARAMETER_TMP_MATCHER.match(type_info.name) is not None return False diff --git a/test/test_mypy.py b/test/test_mypy.py index fabfcb6e..7bd0d4a8 100644 --- a/test/test_mypy.py +++ b/test/test_mypy.py @@ -10,6 +10,7 @@ class TestMyMypyPlugin(unittest.TestCase): def test_plugin_no_issue(self): test_code = """ import luigi +from luigi import Parameter import gokart @@ -18,11 +19,12 @@ class MyTask(gokart.TaskOnKart): foo: int = luigi.IntParameter() # type: ignore bar: str = luigi.Parameter() # type: ignore baz: bool = gokart.ExplicitBoolParameter() + qux: str = Parameter() # TaskOnKart parameters: # - `complete_check_at_run` -MyTask(foo=1, bar='bar', baz=False, complete_check_at_run=False) +MyTask(foo=1, bar='bar', baz=False, qux='qux', complete_check_at_run=False) """ with tempfile.NamedTemporaryFile(suffix='.py') as test_file: