Closed JoshMayberry closed 5 years ago
Did you try subscribing a function that takes *args and **kwargs as params? I'm pretty sure this is supported.
The problem is that inspect.getargspec
does not support 'keyword-only parameters', and inspect.getfullargspec
is needed instead.
The following functions fail in the current pypubsub, and pass with the changes I have made (these functions are tested in the test file I created. Other arg and kwarg combinations that do pass are also in that test file):
#test_allKwargs_allDefaults
def myFunction(*, kwarg1 = 1, kwarg2 = 2, kwarg3 = 3): print(kwarg1, kwarg2, kwarg3)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo')
#test_allKwargs_noDefaults
def myFunction(*, kwarg1, kwarg2): print(kwarg1, kwarg2)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', kwarg1 = 1, kwarg2 = 2)
#test_allKwargs_noDefaults_starArgs
def myFunction(*args, kwarg1, kwarg2): print(args, kwarg1, kwarg2)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', kwarg1 = 1, kwarg2 = 2)
#test_allKwargs_noDefaults_starArgs_starStarKwargs
def myFunction(*args, kwarg1, kwarg2, **kwargs): print(args, kwarg1, kwarg2, kwargs)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', kwarg1 = 1, kwarg2 = 2)
#test_allKwargs_noDefaults_starStarKwargs
def myFunction(*, kwarg1, kwarg2, **kwargs): self.answer = (kwarg1, kwarg2, kwargs)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', kwarg1 = 1, kwarg2 = 2)
#test_allKwargs_withDefaults
def myFunction(*, kwarg1, kwarg2 = 2): self.answer = (kwarg1, kwarg2)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', kwarg1 = 1)
#test_allKwargs_withDefaults_starArgs
def myFunction(*args, kwarg1, kwarg2 = 2): self.answer = (args, kwarg1, kwarg2)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', kwarg1 = 1)
#test_allKwargs_withDefaults_starArgs_starStarKwargs
def myFunction(*args, kwarg1, kwarg2 = 2, **kwargs): self.answer = (args, kwarg1, kwarg2, kwargs)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', kwarg1 = 1)
#test_allKwargs_withDefaults_starStarKwargs
def myFunction(*args, kwarg1, kwarg2 = 2, **kwargs): self.answer = (args, kwarg1, kwarg2, kwargs)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', kwarg1 = 1)
#test_args_noDefaults_kwargs_noDefaults
def myFunction(arg1, arg2, *, kwarg1, kwarg2): self.answer = (arg1, arg2, kwarg1, kwarg2)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', arg1 = 1, arg2 = 2, kwarg1 = 3, kwarg2 = 4)
#test_args_noDefaults_kwargs_withDefaults
def myFunction(arg1, arg2, *, kwarg1, kwarg2 = 4): self.answer = (arg1, arg2, kwarg1, kwarg2)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', arg1 = 1, arg2 = 2, kwarg1 = 3)
#test_args_withDefaults_kwargs_noDefaults
def myFunction(arg1, arg2 = 2, *, kwarg1, kwarg2): self.answer = (arg1, arg2, kwarg1, kwarg2)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', arg1 = 1, kwarg1 = 3, kwarg2 = 4)
#test_args_withDefaults_kwargs_withDefaults
def myFunction(arg1, arg2 = 2, *, kwarg1, kwarg2 = 4): self.answer = (arg1, arg2, kwarg1, kwarg2)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', arg1 = 1, kwarg1 = 3)
#test_args_withDefaults_kwargs_withDefaults_starArgs
def myFunction(arg1, arg2 = 2, *args, kwarg1, kwarg2 = 4): self.answer = (arg1, arg2, args, kwarg1, kwarg2)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', arg1 = 1, kwarg1 = 3)
#test_args_withDefaults_kwargs_withDefaults_starArgs_starStarKwargs
def myFunction(arg1, arg2 = 2, *args, kwarg1, kwarg2 = 4, **kwargs): self.answer = (arg1, arg2, args, kwarg1, kwarg2, kwargs)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', arg1 = 1, kwarg1 = 3)
#test_args_withDefaults_kwargs_withDefaults_starStarKwargs
def myFunction(arg1, arg2 = 2, *, kwarg1, kwarg2 = 4, **kwargs): self.answer = (arg1, arg2, kwarg1, kwarg2, kwargs)
pub.subscribe(myFunction, 'echo')
pub.sendMessage('echo', arg1 = 1, kwarg1 = 3)
@schollii what is left to fix / improve so this is accepted?
I have to know that the test suite passes, and that the examples still run in all versions of Python that get tested. The test suite gets run via tox in several Python versions so that one should be easy to execute. The examples are semi automated so probably a half hour of work mostly installing different versions of Python and the latest wxpython and running the example scripts.
I think this will not work for python versions below 3.5.
The need for inspect.getfullargspec
was created by the future versions. So, I do not think this method exists in the inspect
module for early python versions. So, inspect.getargspec
will have to be used for those.
In CallArgsInfo.__setupAutoTopic in callables.py There is the following code on line 214:
{**self.allArgs, **self.allKwargs}
This is a new syntax that allows you to combine two dictionaries. This part will surly fail on python versions below 3.5 There may be more places like this.
I'll try to fix potential version problems like this at lunch today.
Could you have two versions of callables.py and import the correct one based on python version? You'd actually have callables34.py and callables35.py, and callables.py would decide between the two and import all from the one it chooses.
You could go that route with it, but having multiple files might make future changes difficult for you.
I just pushed a commit that modifies the lines that would cause conflicts.
However you decide to address supporting different versions is up to you, because this is your module. I think it would be better for maintainability if you kept it to one file though.
That's fine. Looks like there is some fixing to do based on https://travis-ci.org/schollii/pypubsub/requests. I have activated pull request building so your next push will get built by travis-ci.org, maybe it'll actually show console output indicating failed tests. But probably best for you to install tox and run it locally to fix remaining issues.
@joshmayberry any update on this, are going to be able to check why some tests broke?
@scholli I'm sorry, I don't really know what to do.
@JoshMayberry There's a section in the docs about testing. IIRC (it's been a while) you basically pip install tox, then from root folder, just run "tox", everything else is handled automatically by it (including installing additional versions of Python locally).
@schollii I'm sorry. I've tried to find time to figure this out, but I don't have the time to do so right now. You can close this request and not make the changes if you want. Thank you for your time.
I'd like to keep those changes. It'll just take a bit of time before I can reopen my python devenv and see what the errors are, they might be easy fix. Else I'll create a branch with details about error and will ping you in case you have time to take a look.
This is no longer needed after the other recent fixes.
Resolves #6: Functions that have any combination of arguments and keyword arguments can now be subscribed to. Test cases are included for different argument and keyword argument combinations.