-
-
Notifications
You must be signed in to change notification settings - Fork 649
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support to MyPy for first-party plugins (#10755)
Similar to with Pylint plugins, we introduce a new target type `mypy_source_plugin`, along with a new option `--mypy-source-plugins`. The new target type is not strictly necessary; you could use a `python_library`. But, the new target type a) provides clearer modeling of what's going on, e.g. that this is a "root" rather than a typical library; and b) allows us to add instructions via `./pants target-types --details=mypy_source_plugin`. [ci skip-build-wheels] [ci skip-rust]
- Loading branch information
1 parent
9274da4
commit 62810c8
Showing
18 changed files
with
378 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 4 additions & 1 deletion
5
src/python/pants/mypy/BUILD → pants-plugins/mypy_plugins/BUILD
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md). | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
python_library() | ||
mypy_source_plugin( | ||
name="total_ordering", | ||
sources=["total_ordering.py"], | ||
) |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md). | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
# See: https://mypy.readthedocs.io/en/latest/extending_mypy.html#high-level-overview | ||
|
||
from typing import Callable, Optional, Type | ||
|
||
from mypy.nodes import ARG_POS, Argument, TypeInfo, Var | ||
from mypy.plugin import ClassDefContext, Plugin | ||
from mypy.plugins.common import add_method | ||
|
||
|
||
class TotalOrderingPlugin(Plugin): | ||
"""This inserts method type stubs for the "missing" ordering methods that the `@total_ordering` | ||
class decorator will fill in dynamically.""" | ||
|
||
def get_class_decorator_hook( | ||
self, fullname: str | ||
) -> Optional[Callable[[ClassDefContext], None]]: | ||
return adjust_class_def if fullname == "functools.total_ordering" else None | ||
|
||
|
||
def adjust_class_def(class_def_context: ClassDefContext) -> None: | ||
api = class_def_context.api | ||
ordering_other_type = api.named_type("__builtins__.object") | ||
ordering_return_type = api.named_type("__builtins__.bool") | ||
arg = Argument( | ||
variable=Var(name="other", type=ordering_other_type), | ||
type_annotation=ordering_other_type, | ||
initializer=None, | ||
kind=ARG_POS, | ||
) | ||
|
||
type_info: TypeInfo = class_def_context.cls.info | ||
for ordering_method_name in "__lt__", "__le__", "__gt__", "__ge__": | ||
existing_method = type_info.get(ordering_method_name) | ||
if existing_method is None: | ||
add_method( | ||
ctx=class_def_context, | ||
name=ordering_method_name, | ||
args=[arg], | ||
return_type=ordering_return_type, | ||
) | ||
|
||
|
||
def plugin(_version: str) -> Type[Plugin]: | ||
return TotalOrderingPlugin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
src/python/pants/backend/python/typecheck/mypy/plugin_target_type.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md). | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
from pants.backend.python.target_types import COMMON_PYTHON_FIELDS, PythonSources | ||
from pants.engine.target import Dependencies, Target | ||
|
||
|
||
class MyPyPluginSources(PythonSources): | ||
required = True | ||
|
||
|
||
class MyPySourcePlugin(Target): | ||
"""A MyPy plugin loaded through source code. | ||
To load a source plugin: | ||
1. Write your plugin. See https://mypy.readthedocs.io/en/stable/extending_mypy.html. | ||
2. Define a `mypy_source_plugin` target with the plugin's Python file(s) included in the | ||
`sources` field. | ||
3. Add `plugins = path.to.module` to your MyPy config file, using the name of the module | ||
without source roots. For example, if your Python file is called | ||
`pants-plugins/mypy_plugins/custom_plugin.py`, and you set `pants-plugins` as a source root, | ||
then set `plugins = mypy_plugins.custom_plugin`. Set the `config` | ||
option in the `[mypy]` scope to point to your MyPy config file. | ||
5. Set the option `source_plugins` in the `[mypy]` scope to include this target's | ||
address, e.g. `source_plugins = ["build-support/mypy_plugins:plugin"]`. | ||
To instead load a third-party plugin, set the option `extra_requirements` in the `[mypy]` | ||
scope (see https://www.pantsbuild.org/v2.0/docs/python-typecheck-goal). Set `plugins` in | ||
your config file, like you'd do with a source plugin. | ||
This target type is treated similarly to a `python_library` target. For example, Python linters | ||
and formatters will run on this target. | ||
You can include other targets in the `dependencies` field, including third-party requirements | ||
and other source files (even if those source files live in a different directory). | ||
Other targets can depend on this target. This allows you to write a `python_tests` target for | ||
this code or a `python_distribution` target to distribute the plugin externally. | ||
""" | ||
|
||
alias = "mypy_source_plugin" | ||
core_fields = (*COMMON_PYTHON_FIELDS, Dependencies, MyPyPluginSources) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.