Roundup Tracker - Issues

Message6017

Author ezio.melotti
Recipients ezio.melotti, rouilj
Date 2017-09-15.00:07:32
Message-id <1505434056.79.0.987991000909.issue2550952@psf.upfronthosting.co.za>
In-reply-to
> Hmm, from https://bugs.python.org/issue20828 we get something like:
>
>    ...
>    if isinstance(fn,
>           (_WrapperDescriptor, _MethodWrapper, _ClassMethodWrapper)):
>        raise ValueError('unsupported callable {!r}'.format(fn))
>    ...

This is probably a bit overkill if getargspec is only going to be used 
for "check functions" in schema.py.  I don't think people are going to 
write C extensions or other complex solutions to check for permissions :)

> [From project xonsh-master, under directory xonsh, in source file
>  inspectors.py.]
>
>     ...
>       if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
>	        obj = obj.__call__
>
>     return inspect.getfullargspec(obj) if ISPY3K else 
inspect.getargspec(obj)

This seems a good compromise between functionality and simplicity and 
should work with callable instances (like the one we had).

>  Add function findargspec to anypy/getarspec_.py that wraps
>    getargspec/getfullargspec and checks for __call__ and uses that
>    if present.
>
>  Use this function in place of inspect.getargspec in security.py

This is an option, especially considering that you are (finally) moving 
on Python 3 :)
However, have you considered other non-LBYL approaches that don't require 
using getargspec()?  Unfortunately the only alternative that comes to 
mind is using a try/except, except that the TypeError you would get is 
not specific enough and you might end up masking unrelated errors -- even 
if you check for the error message.


> If I get this done would you be able to add a couple of test cases to
> the test suit that exercises both forms of __call__ to see if I got
> the code correct?

Right now I'm still busy trying to update our bug tracker, so probably 
not.  Adding these test cases should be quite straightforward though, 
since you can convert any existing:

    def func(args):
        ...

to

    class Foo:
        def __call__(self, args):
            ...

and pass Foo() instead of func.

> Have a great day.

You too :)
History
Date User Action Args
2017-09-15 00:07:36ezio.melottisetmessageid: <1505434056.79.0.987991000909.issue2550952@psf.upfronthosting.co.za>
2017-09-15 00:07:36ezio.melottisetrecipients: + ezio.melotti, rouilj
2017-09-15 00:07:36ezio.melottilinkissue2550952 messages
2017-09-15 00:07:32ezio.melotticreate