Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use operator on a class method fails #23

Closed
jenda1 opened this issue Aug 24, 2018 · 3 comments
Closed

use operator on a class method fails #23

jenda1 opened this issue Aug 24, 2018 · 3 comments

Comments

@jenda1
Copy link

jenda1 commented Aug 24, 2018

I tried to use aiostream.core.operator on a class method:

from aiostream.core import operator

class test(object):
    @operator
    async def testit(self):
        pass

but it fails with error:

$ python3.7 test.py
Traceback (most recent call last):
  File "test.py", line 3, in <module>
    class test(object):
  File "test.py", line 4, in test
    @operator
  File "/home/jlana/Dropbox/vyuka2/venv/lib/python3.7/site-packages/aiostream/core.py", line 333, in operator
    return decorator if func is None else decorator(func)
  File "/home/jlana/Dropbox/vyuka2/venv/lib/python3.7/site-packages/aiostream/core.py", line 279, in decorator
    init.__signature__ = signature.replace(parameters=new_parameters)
  File "/usr/lib/python3.7/inspect.py", line 2843, in replace
    return_annotation=return_annotation)
  File "/usr/lib/python3.7/inspect.py", line 2788, in __init__
    raise ValueError(msg)
ValueError: duplicate parameter name: 'self'

As workaround it is possible to use different name and call the operator with the class instance:

class test(object):
    n = 123

    @operator
    async def testit(myself):
        yield myself.n

async def main():
    t = test()
    await stream.print(t.testit(t))
@vxgmichel
Copy link
Owner

vxgmichel commented Aug 27, 2018

Hi @jenda1, thank you for creating this issue.

The problem here is that the decorated generator becomes a Stream subclass, in order to provide support for pipe-lining (|), slicing ([]) and concatenation (+). That means testit is not a method and this is why you have to pass the t instance explicitly in your workaround.

Instead, you could consider this alternative:

@operator
async def stream_from_test_instance(test):
    yield test.n


class test:
    n = 123

    def testit(self):
        return stream_from_test_instance(self)

Or, since streams are reusable:

class test:

    def __init__(self, n):
        self.n = n
        self.stream = stream_from_test_instance(self)

    def testit(self):
        return self.stream

The error message you got isn't really explaining what's happening though. Let's try to detect self or cls arguments and raise an exception with a proper explanation.

Hope that helps, thanks again.

@jenda1
Copy link
Author

jenda1 commented Aug 27, 2018 via email

@vxgmichel
Copy link
Owner

vxgmichel commented Sep 4, 2018

Let's try to detect self or cls arguments and raise an exception with a proper explanation.

Done ! (see PR #24)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants