pyramid
pyramid copied to clipboard
partials as view callables behave differently under python 2.7 and python 3.4
Compare
Python 2.7.3 (default, Aug 1 2012, 05:14:39)
[GCC 4.6.3] on linux2
>>> from pyramid.config.util import takes_one_arg
>>> from functools import partial
>>> def v(a, b, c):
... return
...
>>> takes_one_arg(partial(v, 1))
False
>>> takes_one_arg(partial(v, 1, 2))
False
>>> takes_one_arg(partial(v, 1, 2, 3))
False
with
Python 3.4.1 (default, Jul 7 2014, 09:21:41)
[GCC 4.6.3] on linux
>>> from pyramid.config.util import takes_one_arg
>>> from functools import partial
>>> def v(a, b, c):
... return
...
>>> takes_one_arg(partial(v, 1))
True
>>> takes_one_arg(partial(v, 1, 2))
True
>>> takes_one_arg(partial(v, 1, 2, 3))
True
I was using a partial accepting two positional arguments as callable and my tests failed on python 3.4. So I think either partials should be disallowed as view callables, or takes_one_arg
should be fixed to exhibit the same behaviour under both python 2.7 and python 3.4.
FWIW, the difference lies in the Python stdlib. Under Python 3.3.:
-> argspec = inspect.getargspec(fn)
(Pdb)
TypeError: <method-wrapper '__call__' of functools.partial object at ...> is not a Python function
while under Python 3.4:
-> argspec = inspect.getargspec(fn)
(Pdb)
-> args = argspec[0]
(Pdb) pp argspec
ArgSpec(args=['self'], varargs='args', keywords='kwargs', defaults=None)
hmmm, this one is a little bit tricky, partial from python2.7 is implemented as a C module, but since 3 it's in pure python code. Not sure if I can manage to fix this, I think the best solution I can think of is to try to see if it's a partial, and if it is.
https://github.com/python/cpython/blob/3.6/Lib/functools.py#L246
try to get func
, args
, calculate how many arguments left after partial's decoration.
after looking into it a while, I felt the situation is a little bit overwhelming complex, given there is anattr
argument, not sure how that should be applied on functools.partial
object. will leave it here and trying to pick up other stuff first.
I am addressing this on https://github.com/Pylons/pyramid/pull/3378