Skip to content

Commit dbcfc32

Browse files
committed
fix: mypy plugin loading under pre-commit
1 parent e693bb0 commit dbcfc32

File tree

3 files changed

+53
-9
lines changed

3 files changed

+53
-9
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ repos:
2424
- marshmallow-enum
2525
- typeguard
2626
- types-setuptools
27+
- typing-inspect
2728
args: [--show-error-codes]
2829
- repo: https://github.com/asottile/blacken-docs
2930
rev: v1.12.1

mypy_plugin.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""Shim to load the marshmallow_dataclass.mypy plugin.
2+
3+
This shim is needed when running mypy from pre-commit.
4+
5+
Pre-commit runs mypy from its own venv (into which we do not want
6+
to install marshmallow_dataclass). Because of this, loading the plugin
7+
by module name, e.g.
8+
9+
[tool.mypy]
10+
plugins = "marshmallow_dataclass.mypy"
11+
12+
does not work. Mypy also supports specifying a path to the plugin
13+
module source, which would normally get us out of this bind, however,
14+
the fact that our plugin is in a file named "mypy.py" causes issues.
15+
16+
If we set
17+
18+
[tool.mypy]
19+
plugins = "marshmallow_dataclass/mypy.py"
20+
21+
mypy `attempts to load`__ the plugin module by temporarily prepending
22+
``marshmallow_dataclass`` to ``sys.path`` then importing the ``mypy``
23+
module. Sadly, mypy's ``mypy`` module has already been imported,
24+
so this doesn't end well.
25+
26+
__ https://github.com/python/mypy/blob/914901f14e0e6223077a8433388c367138717451/mypy/build.py#L450
27+
28+
29+
Our solution, here, is to manually load the plugin module (with a better
30+
``sys.path``, and import the ``plugin`` from the real plugin module into this one.
31+
32+
Now we can configure mypy to load this file, by path.
33+
34+
[tool.mypy]
35+
plugins = "mypy_plugin.py"
36+
37+
"""
38+
import importlib
39+
import sys
40+
from os import fspath
41+
from pathlib import Path
42+
43+
src = fspath(Path(__file__).parent)
44+
sys.path.insert(0, src)
45+
plugin_module = importlib.import_module("marshmallow_dataclass.mypy")
46+
del sys.path[0]
47+
48+
plugin = plugin_module.plugin

pyproject.toml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,10 @@ packages = [
1212
"marshmallow_dataclass",
1313
"tests",
1414
]
15-
# XXX: Can not load our plugin when running mypy from pre-commit.
16-
# Pre-commit runs mypy from its own venv (into which we do not want
17-
# to install marshmallow_dataclass).
18-
# The fact that our plugin is in a file named "mypy.py" causes issues
19-
# (I think) if we try to load it by path. In that case mypy adds
20-
# the containing directory to sys.path then calls import_module("mypy"),
21-
# which, in turn, finds the already imported sys.modules['mypy'].
22-
#
23-
# plugins = "marshmallow_dataclass.mypy"
15+
# XXX: Specifying the marshmallow_dataclass.mypy plugin directly by
16+
# module name or by path does not work when running mypy from pre-commit.
17+
# (See the docstring in mypy_plugin.py for more.)
18+
plugins = "mypy_plugin.py"
2419

2520
warn_redundant_casts = true
2621
warn_unused_configs = true

0 commit comments

Comments
 (0)