Skip to content

Commit bbed891

Browse files
authored
Make mypy.build.build take an extra_plugins argument (#7875)
This allows new plugins to be added by programs (like mypyc) that directly invoke build.
1 parent 6dabd8d commit bbed891

File tree

2 files changed

+40
-14
lines changed

2 files changed

+40
-14
lines changed

mypy/build.py

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import time
2424
import types
2525

26-
from typing import (AbstractSet, Any, Dict, Iterable, Iterator, List,
26+
from typing import (AbstractSet, Any, Dict, Iterable, Iterator, List, Sequence,
2727
Mapping, NamedTuple, Optional, Set, Tuple, Union, Callable, TextIO)
2828
from typing_extensions import ClassVar, Final, TYPE_CHECKING
2929
from mypy_extensions import TypedDict
@@ -126,6 +126,7 @@ def build(sources: List[BuildSource],
126126
fscache: Optional[FileSystemCache] = None,
127127
stdout: Optional[TextIO] = None,
128128
stderr: Optional[TextIO] = None,
129+
extra_plugins: Optional[Sequence[Plugin]] = None,
129130
) -> BuildResult:
130131
"""Analyze a program.
131132
@@ -159,9 +160,12 @@ def default_flush_errors(new_messages: List[str], is_serious: bool) -> None:
159160
flush_errors = flush_errors or default_flush_errors
160161
stdout = stdout or sys.stdout
161162
stderr = stderr or sys.stderr
163+
extra_plugins = extra_plugins or []
162164

163165
try:
164-
result = _build(sources, options, alt_lib_path, flush_errors, fscache, stdout, stderr)
166+
result = _build(
167+
sources, options, alt_lib_path, flush_errors, fscache, stdout, stderr, extra_plugins
168+
)
165169
result.errors = messages
166170
return result
167171
except CompileError as e:
@@ -182,6 +186,7 @@ def _build(sources: List[BuildSource],
182186
fscache: Optional[FileSystemCache],
183187
stdout: TextIO,
184188
stderr: TextIO,
189+
extra_plugins: Sequence[Plugin],
185190
) -> BuildResult:
186191
# This seems the most reasonable place to tune garbage collection.
187192
gc.set_threshold(150 * 1000)
@@ -205,7 +210,7 @@ def _build(sources: List[BuildSource],
205210
options.pretty,
206211
lambda path: read_py_file(path, cached_read, options.python_version),
207212
options.show_absolute_path)
208-
plugin, snapshot = load_plugins(options, errors, stdout)
213+
plugin, snapshot = load_plugins(options, errors, stdout, extra_plugins)
209214

210215
# Construct a build manager object to hold state during the build.
211216
#
@@ -331,23 +336,20 @@ def import_priority(imp: ImportBase, toplevel_priority: int) -> int:
331336
return toplevel_priority
332337

333338

334-
def load_plugins(options: Options,
335-
errors: Errors,
336-
stdout: TextIO,
337-
) -> Tuple[Plugin, Dict[str, str]]:
339+
def load_plugins_from_config(
340+
options: Options, errors: Errors, stdout: TextIO
341+
) -> Tuple[List[Plugin], Dict[str, str]]:
338342
"""Load all configured plugins.
339343
340-
Return a plugin that encapsulates all plugins chained together. Always
341-
at least include the default plugin (it's last in the chain).
344+
Return a list of all the loaded plugins from the config file.
342345
The second return value is a snapshot of versions/hashes of loaded user
343346
plugins (for cache validation).
344347
"""
345348
import importlib
346349
snapshot = {} # type: Dict[str, str]
347350

348-
default_plugin = DefaultPlugin(options) # type: Plugin
349351
if not options.config_file:
350-
return default_plugin, snapshot
352+
return [], snapshot
351353

352354
line = find_config_file_line_number(options.config_file, 'mypy', 'plugins')
353355
if line == -1:
@@ -417,6 +419,30 @@ def plugin_error(message: str) -> None:
417419
print('Error constructing plugin instance of {}\n'.format(plugin_type.__name__),
418420
file=stdout)
419421
raise # Propagate to display traceback
422+
423+
return custom_plugins, snapshot
424+
425+
426+
def load_plugins(options: Options,
427+
errors: Errors,
428+
stdout: TextIO,
429+
extra_plugins: Sequence[Plugin],
430+
) -> Tuple[Plugin, Dict[str, str]]:
431+
"""Load all configured plugins.
432+
433+
Return a plugin that encapsulates all plugins chained together. Always
434+
at least include the default plugin (it's last in the chain).
435+
The second return value is a snapshot of versions/hashes of loaded user
436+
plugins (for cache validation).
437+
"""
438+
custom_plugins, snapshot = load_plugins_from_config(options, errors, stdout)
439+
440+
custom_plugins += extra_plugins
441+
442+
default_plugin = DefaultPlugin(options) # type: Plugin
443+
if not custom_plugins:
444+
return default_plugin, snapshot
445+
420446
# Custom plugins take precedence over the default plugin.
421447
return ChainedPlugin(options, custom_plugins + [default_plugin]), snapshot
422448

mypy/dmypy_server.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,9 +315,9 @@ def cmd_run(self, version: str, args: Sequence[str],
315315
if self.fine_grained_manager:
316316
manager = self.fine_grained_manager.manager
317317
start_plugins_snapshot = manager.plugins_snapshot
318-
_, current_plugins_snapshot = mypy.build.load_plugins(options,
319-
manager.errors,
320-
sys.stdout)
318+
_, current_plugins_snapshot = mypy.build.load_plugins(
319+
options, manager.errors, sys.stdout, extra_plugins=()
320+
)
321321
if current_plugins_snapshot != start_plugins_snapshot:
322322
return {'restart': 'plugins changed'}
323323
except InvalidSourceList as err:

0 commit comments

Comments
 (0)