diff --git a/mypy/build.py b/mypy/build.py index f68aabe5e440..76cad734636a 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -50,7 +50,7 @@ from mypy.stats import dump_type_stats from mypy.types import Type from mypy.version import __version__ -from mypy.plugin import Plugin, ChainedPlugin, plugin_types, ReportConfigContext +from mypy.plugin import Plugin, ChainedPlugin, ReportConfigContext from mypy.plugins.default import DefaultPlugin from mypy.fscache import FileSystemCache from mypy.metastore import MetadataStore, FilesystemMetadataStore, SqliteMetadataStore @@ -423,7 +423,7 @@ def plugin_error(message: str) -> None: plugin_error( 'Type object expected as the return value of "plugin"; got {!r} (in {})'.format( plugin_type, plugin_path)) - if not issubclass(plugin_type, plugin_types): + if not issubclass(plugin_type, Plugin): plugin_error( 'Return value of "plugin" must be a subclass of "mypy.plugin.Plugin" ' '(in {})'.format(plugin_path)) diff --git a/mypy/interpreted_plugin.py b/mypy/interpreted_plugin.py deleted file mode 100644 index eca6d231c1e4..000000000000 --- a/mypy/interpreted_plugin.py +++ /dev/null @@ -1,91 +0,0 @@ -"""Hack for handling non-mypyc compiled plugins with a mypyc-compiled mypy""" - -from typing import Optional, Callable, Any, Dict, List, Tuple -from typing_extensions import TYPE_CHECKING - -from mypy.options import Options -from mypy.types import Type, CallableType -from mypy.nodes import SymbolTableNode, MypyFile -from mypy.lookup import lookup_fully_qualified - -if TYPE_CHECKING: - import mypy.plugin - - -class InterpretedPlugin: - """Base class of type checker plugins as exposed to external code. - - This is a hack around mypyc not currently supporting interpreted subclasses - of compiled classes. - mypy.plugin will arrange for interpreted code to be find this class when it looks - for Plugin, and this class has a __new__ method that returns a WrapperPlugin object - that proxies to this interpreted version. - """ - - # ... mypy doesn't like these shenanigans so we have to type ignore it! - def __new__(cls, *args: Any, **kwargs: Any) -> 'mypy.plugin.Plugin': # type: ignore - from mypy.plugin import WrapperPlugin - plugin = object.__new__(cls) - plugin.__init__(*args, **kwargs) - return WrapperPlugin(plugin) - - def __init__(self, options: Options) -> None: - self.options = options - self.python_version = options.python_version - self._modules = None # type: Optional[Dict[str, MypyFile]] - - def set_modules(self, modules: Dict[str, MypyFile]) -> None: - self._modules = modules - - def lookup_fully_qualified(self, fullname: str) -> Optional[SymbolTableNode]: - assert self._modules is not None - return lookup_fully_qualified(fullname, self._modules) - - def report_config_data(self, ctx: 'mypy.plugin.ReportConfigContext') -> Any: - return None - - def get_additional_deps(self, file: MypyFile) -> List[Tuple[int, str, int]]: - return [] - - def get_type_analyze_hook(self, fullname: str - ) -> Optional[Callable[['mypy.plugin.AnalyzeTypeContext'], Type]]: - return None - - def get_function_hook(self, fullname: str - ) -> Optional[Callable[['mypy.plugin.FunctionContext'], Type]]: - return None - - def get_method_signature_hook(self, fullname: str - ) -> Optional[Callable[['mypy.plugin.MethodSigContext'], - CallableType]]: - return None - - def get_method_hook(self, fullname: str - ) -> Optional[Callable[['mypy.plugin.MethodContext'], Type]]: - return None - - def get_attribute_hook(self, fullname: str - ) -> Optional[Callable[['mypy.plugin.AttributeContext'], Type]]: - return None - - def get_class_decorator_hook(self, fullname: str - ) -> Optional[Callable[['mypy.plugin.ClassDefContext'], None]]: - return None - - def get_metaclass_hook(self, fullname: str - ) -> Optional[Callable[['mypy.plugin.ClassDefContext'], None]]: - return None - - def get_base_class_hook(self, fullname: str - ) -> Optional[Callable[['mypy.plugin.ClassDefContext'], None]]: - return None - - def get_customize_class_mro_hook(self, fullname: str - ) -> Optional[Callable[['mypy.plugin.ClassDefContext'], - None]]: - return None - - def get_dynamic_class_hook(self, fullname: str - ) -> Optional[Callable[['mypy.plugin.DynamicClassDefContext'], - None]]: - return None diff --git a/mypy/plugin.py b/mypy/plugin.py index 3482fabe72e4..74dc99b7bd98 100644 --- a/mypy/plugin.py +++ b/mypy/plugin.py @@ -119,11 +119,9 @@ class C: pass semantic analyzer is enabled (it's always true in mypy 0.730 and later). """ -import types - from abc import abstractmethod, abstractproperty from typing import Any, Callable, List, Tuple, Optional, NamedTuple, TypeVar, Dict -from mypy_extensions import trait +from mypy_extensions import trait, mypyc_attr from mypy.nodes import ( Expression, Context, ClassDef, SymbolTableNode, MypyFile, CallExpr @@ -134,7 +132,6 @@ class C: pass from mypy.options import Options from mypy.lookup import lookup_fully_qualified from mypy.errorcodes import ErrorCode -import mypy.interpreted_plugin @trait @@ -182,7 +179,7 @@ def analyze_callable_args(self, arglist: TypeList) -> Optional[Tuple[List[Type], ('api', TypeAnalyzerPluginInterface)]) -@trait +@mypyc_attr(allow_interpreted_subclasses=True) class CommonPluginApi: """ A common plugin API (shared between semantic analysis and type checking phases) @@ -445,6 +442,7 @@ def final_iteration(self) -> bool: ]) +@mypyc_attr(allow_interpreted_subclasses=True) class Plugin(CommonPluginApi): """Base class of all type checker plugins. @@ -683,74 +681,6 @@ def get_dynamic_class_hook(self, fullname: str T = TypeVar('T') -class WrapperPlugin(Plugin): - """A plugin that wraps an interpreted plugin. - - This is a ugly workaround the limitation that mypyc-compiled - classes can't be subclassed by interpreted ones, so instead we - create a new class for interpreted clients to inherit from and - dispatch to it from here. - - Eventually mypyc ought to do something like this automatically. - """ - - def __init__(self, plugin: mypy.interpreted_plugin.InterpretedPlugin) -> None: - super().__init__(plugin.options) - self.plugin = plugin - - def set_modules(self, modules: Dict[str, MypyFile]) -> None: - self.plugin.set_modules(modules) - - def lookup_fully_qualified(self, fullname: str) -> Optional[SymbolTableNode]: - return self.plugin.lookup_fully_qualified(fullname) - - def report_config_data(self, ctx: ReportConfigContext) -> Any: - return self.plugin.report_config_data(ctx) - - def get_additional_deps(self, file: MypyFile) -> List[Tuple[int, str, int]]: - return self.plugin.get_additional_deps(file) - - def get_type_analyze_hook(self, fullname: str - ) -> Optional[Callable[[AnalyzeTypeContext], Type]]: - return self.plugin.get_type_analyze_hook(fullname) - - def get_function_hook(self, fullname: str - ) -> Optional[Callable[[FunctionContext], Type]]: - return self.plugin.get_function_hook(fullname) - - def get_method_signature_hook(self, fullname: str - ) -> Optional[Callable[[MethodSigContext], CallableType]]: - return self.plugin.get_method_signature_hook(fullname) - - def get_method_hook(self, fullname: str - ) -> Optional[Callable[[MethodContext], Type]]: - return self.plugin.get_method_hook(fullname) - - def get_attribute_hook(self, fullname: str - ) -> Optional[Callable[[AttributeContext], Type]]: - return self.plugin.get_attribute_hook(fullname) - - def get_class_decorator_hook(self, fullname: str - ) -> Optional[Callable[[ClassDefContext], None]]: - return self.plugin.get_class_decorator_hook(fullname) - - def get_metaclass_hook(self, fullname: str - ) -> Optional[Callable[[ClassDefContext], None]]: - return self.plugin.get_metaclass_hook(fullname) - - def get_base_class_hook(self, fullname: str - ) -> Optional[Callable[[ClassDefContext], None]]: - return self.plugin.get_base_class_hook(fullname) - - def get_customize_class_mro_hook(self, fullname: str - ) -> Optional[Callable[[ClassDefContext], None]]: - return self.plugin.get_customize_class_mro_hook(fullname) - - def get_dynamic_class_hook(self, fullname: str - ) -> Optional[Callable[[DynamicClassDefContext], None]]: - return self.plugin.get_dynamic_class_hook(fullname) - - class ChainedPlugin(Plugin): """A plugin that represents a sequence of chained plugins. @@ -831,18 +761,3 @@ def _find_hook(self, lookup: Callable[[Plugin], T]) -> Optional[T]: if hook: return hook return None - - -def _dummy() -> None: - """Only used to test whether we are running in compiled mode.""" - - -# This is an incredibly frumious hack. If this module is compiled by mypyc, -# set the module 'Plugin' attribute to point to InterpretedPlugin. This means -# that anything interpreted that imports Plugin will get InterpretedPlugin -# while anything compiled alongside this module will get the real Plugin. -if isinstance(_dummy, types.BuiltinFunctionType): - plugin_types = (Plugin, mypy.interpreted_plugin.InterpretedPlugin) # type: Tuple[type, ...] - globals()['Plugin'] = mypy.interpreted_plugin.InterpretedPlugin -else: - plugin_types = (Plugin,) diff --git a/setup.py b/setup.py index b11cc5bf0560..1a66f51c5bed 100644 --- a/setup.py +++ b/setup.py @@ -91,9 +91,6 @@ def run(self): 'sitepkgs.py', os.path.join('dmypy', '__main__.py'), - # Needs to be interpreted to provide a hook to interpreted plugins - 'interpreted_plugin.py', - # Uses __getattr__/__setattr__ 'split_namespace.py',