insolite / graphene-peewee-async

Graphene peewee-async integration
37 stars 9 forks source link

Doesn't work when package dependencies 'promise' is the latest version(2.2.1) #11

Closed chiaki64 closed 5 years ago

chiaki64 commented 5 years ago

I try to use the middleware in /graphene-peewee-async/test/common/api_test like

@asyncio.coroutine
    def query(self, query, variables={}):

        class TestMiddleware(object):
            def resolve(self, next, root, info, **args):
                return next(root, info, **args)

        pre_result = self.schema.execute(
            ...
            middleware=[TestMiddleware()]
        )
       ...

but it raise an exception

Exception: Received incompatible instance "<generator object PeeweeNodeField.node_resolver at 0x1082b6930>".

It seems like this promise commit cause the problem.(it works on promise==2.2.0 but doesn't work in 2.2.1)

The trackback shows the function is_valid_peewee_model raise this exception, we can see the correct type of type(root) should return some models like <class 'tests.common.models.Author'>,but now it will only return <class 'generator'>

# graphene-peewee-async/graphene_peewee_async/types.py
@classmethod
    def is_type_of(cls, root, info, **args):
        ...
        if not is_valid_peewee_model(type(root)):
            raise Exception((
                'Received incompatible instance "{}".'
            ).format(root))
        ...

Can it be solved only by fixed version with promise<=2.2.0?

insolite commented 5 years ago

Thanks for reporting and so deep investigation into this issue! What I've found is that there's a difference in how asyncio's and inpect's iscoroutine decides on "old-style" coroutines, created using decorators. inspect's version doesn't consider generators as coroutines while asyncio's version (which was used in promise==2.2.0) does. We can simply upgrade to async/await here and here to make it work, but I'll think a bit more about backward compatibility for Python 3.4 and reply back in few days.

insolite commented 5 years ago

Yes, seems like a promise==2.2.1 compatibility issue with generator-based coroutines (as well as with Python 3.4). I've opened an issue for it: syrusakbary/promise#69. So yes, it can be solved by downgrading promise package or by monkey-patching it if you really need >=2.2.1:

from promise import promise
try:
    from inspect import isawaitable as iscoroutine
except ImportError:
    from asyncio import iscoroutine
promise.iscoroutine = iscoroutine
insolite commented 5 years ago

promise dependency version is now restricted in v2.2.1 (don't be confused by promise's v2.2.1 :slightly_smiling_face:)