diff --git a/mypy-abstracts/README.rst b/mypy-abstracts/README.rst new file mode 100644 index 000000000..ba4fab609 --- /dev/null +++ b/mypy-abstracts/README.rst @@ -0,0 +1,5 @@ + +mypy-abstracts +============== + +mypy plugin to recognize classes decorated with ``abstracts.implementer``. diff --git a/mypy-abstracts/VERSION b/mypy-abstracts/VERSION new file mode 100644 index 000000000..8acdd82b7 --- /dev/null +++ b/mypy-abstracts/VERSION @@ -0,0 +1 @@ +0.0.1 diff --git a/mypy-abstracts/mypy_abstracts/plugin.py b/mypy-abstracts/mypy_abstracts/plugin.py new file mode 100644 index 000000000..593b88ea8 --- /dev/null +++ b/mypy-abstracts/mypy_abstracts/plugin.py @@ -0,0 +1,28 @@ +from mypy.plugin import Plugin +from mypy.nodes import SymbolTable, TypeInfo +from mypy.types import Instance + + +class AbstractionPlugin(Plugin): + + def get_class_decorator_hook(self, fullname: str): + + def _decorator_hook(*la): + impl = la[0].cls.info + iface = la[0].reason.args[0].node + try: + promote = Instance(iface, []) + except TypeError: + return + if not any(ti._promote == promote for ti in impl.mro): + faketi = TypeInfo(SymbolTable(), iface.defn, iface.module_name) + faketi._promote = promote + impl.mro.append(faketi) + + if fullname == "abstracts.decorators.implementer": + return _decorator_hook + + +def plugin(version: str): + # ignore version argument if the plugin works with all mypy versions. + return AbstractionPlugin diff --git a/mypy-abstracts/setup.py b/mypy-abstracts/setup.py new file mode 100644 index 000000000..1a35601c9 --- /dev/null +++ b/mypy-abstracts/setup.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python + +import os +import codecs +from setuptools import setup # type:ignore + + +DESCRIPTION = ( + "A patches test fixture which provides a contextmanager for handling " + "multiple mock patches") + + +def read(fname): + file_path = os.path.join(os.path.dirname(__file__), fname) + return codecs.open(file_path, encoding='utf-8').read() + + +setup( + name='mypy-abstracts', + version=read("VERSION"), + author='Ryan Northey', + author_email='ryan@synca.io', + maintainer='Ryan Northey', + maintainer_email='ryan@synca.io', + license='Apache Software License 2.0', + url='https://github.com/envoyproxy/pytooling/mypy-abstracts', + description=DESCRIPTION, + long_description=read('README.rst'), + py_modules=['mypy_abstracts'], + python_requires='>=3.5', + install_requires=['mypy'], + extras_require={ + "test": [ + "pytest", + "pytest-coverage"], + "lint": ['flake8'], + "publish": ['wheel'], + }, + classifiers=[ + 'Development Status :: 4 - Beta', + 'Framework :: Pytest', + 'Intended Audience :: Developers', + 'Topic :: Software Development :: Testing', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3 :: Only', + 'Programming Language :: Python :: Implementation :: CPython', + 'Operating System :: OS Independent', + 'License :: OSI Approved :: Apache Software License', + ], + entry_points={ + 'pytest11': [ + 'patches = pytest_patches', + ], + }, +)