dgilland / pydash

The kitchen sink of Python utility libraries for doing "stuff" in a functional way. Based on the Lo-Dash Javascript library.

Home Page:http://pydash.readthedocs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

pydash.find does not support filtering with __call__

fredtsun opened this issue · comments

Python 3.8.4 (default, Jul 14 2020, 02:58:48)
[Clang 11.0.3 (clang-1103.0.32.62)] on darwin
Type "help", "copyright", "credits" or "license" for more information.


>>> import pydash
>>> class Filter(object):
...   def __init__(self, num):
...     self.num = num
...   def __call__(self, i):
...     return i > self.num
...
>>> pydash.find([0, 1, 2], Filter(1))


Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "path/lib/python3.8/site-packages/pydash/collections.py", line 211, in find
    return next(search, None)
  File "path/lib/python3.8/site-packages/pydash/collections.py", line 208, in <genexpr>
    search = (value
  File "path/lib/python3.8/site-packages/pydash/helpers.py", line 97, in iteriteratee
    yield (callit(cbk, item, key, obj, argcount=argcount),
  File "path/lib/python3.8/site-packages/pydash/helpers.py", line 38, in callit
    return iteratee(*args[:argstop])
TypeError: __call__() takes 2 positional arguments but 3 were given

It seems like the current implementation incorrectly identifies self as an needed argument

Looks like the issue is due to pydash using inspect.getfullargspec on the callback where the args list includes the "self" argument. Pydash counts that as a passable argument, and instead of passing a single argument (the item), it passes the item and the index.

Workaround would be to add *args to the __call__() function or use a function object instead of callable class.

A possible fix in pydash would be to use inspect.signature instead of inspect.getfullargspec. The Signature object has the correct number of arguments in the parameters attribute. This would be a Python3-only fix though since Python2 doesn't have inspect.signature. Might have to backport inspect.signature for Python2 but I haven't looked into inspect.signature to see what it actually does and whether it would work on Python2. Or could just not fix this on Python2 since it's EOL anyway.

@fredtsun This should be fixed in cb1d35b but only for Python 3 since the fix relies on inspect.signature which isn't available in Python 2.7.