diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e6b05b4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: python -python: - - 3.6 - - 3.7 - - 3.8 - - 3.9 -sudo: false - -install: - - pip install -r requirements_dev.txt - -script: - - python -m unittest discover -p "test*" diff --git a/README.rst b/README.rst index 84159e6..a55dfad 100644 --- a/README.rst +++ b/README.rst @@ -1,9 +1,6 @@ pure-interface ============== -.. image:: https://travis-ci.com/seequent/pure_interface.svg?branch=master - :target: https://travis-ci.com/seequent/pure_interface - A Python interface library that disallows function body content on interfaces and supports adaption. Jump to the `Reference`_. diff --git a/pure_interface.py b/pure_interface.py index be09b8b..24dcbf7 100644 --- a/pure_interface.py +++ b/pure_interface.py @@ -18,7 +18,7 @@ import weakref -__version__ = '5.0.0' +__version__ = '5.0.1' is_development = not hasattr(sys, 'frozen') @@ -629,6 +629,8 @@ def interface_only(cls, implementation): if cls._pi.impl_wrapper_type is None: type_name = '_{}Only'.format(cls.__name__) attributes = {'__module__': cls.__module__} + if '__call__' in cls._pi.interface_names: + attributes['__call__'] = getattr(implementation, '__call__') cls._pi.impl_wrapper_type = type(type_name, (_ImplementationWrapper,), attributes) abc.ABCMeta.register(cls, cls._pi.impl_wrapper_type) return cls._pi.impl_wrapper_type(implementation, cls) diff --git a/setup.cfg b/setup.cfg index 80afc2d..be93c0c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = pure_interface -version = 5.0.0 +version = 5.0.1 description = A Python interface library that disallows function body content on interfaces and supports adaption. keywords = abc interface adapt adaption mapper structural typing dataclass author = Tim Mitchell diff --git a/tests/test_adaption.py b/tests/test_adaption.py index bea4d45..b53b859 100644 --- a/tests/test_adaption.py +++ b/tests/test_adaption.py @@ -114,6 +114,23 @@ def speak(self, volume): super(SleepTalker, self).speak(volume) +class DunderInterface(pure_interface.Interface): + def __call__(self, a): + pass + + def __len__(self): + pass + + +class DunderClass(DunderInterface, object): + + def __call__(self, a): + super().__call__(a) + + def __len__(self): + return 5 + + class TestAdaption(unittest.TestCase): @classmethod def setUpClass(cls): @@ -350,3 +367,16 @@ def test_adapt_interface_only(self): ISpeaker.adapt(talker_only) except: self.fail('adaption of interface only failed.') + + def test_adapt_callable_is_callable(self): + dunder = DunderClass() + dunder_only = DunderInterface.adapt(dunder) + try: + dunder_only(1) + except TypeError: + self.fail('calling interface only failed') + + try: + len(dunder) + except: + self.fail('len() interface only failed') diff --git a/tox.ini b/tox.ini index 73f966a..6ebaa44 100644 --- a/tox.ini +++ b/tox.ini @@ -9,6 +9,6 @@ envlist = py36, py37, py38, py39 [testenv] deps = pycontracts - dataclasses; python_version < 3.7 + dataclasses; python_version < '3.7' commands = python -m unittest discover -p "test*"