Skip to content

Commit

Permalink
Merge pull request #353 from eriknw/explicit_curried
Browse files Browse the repository at this point in the history
Explicitly import and curry objects in `toolz.curried` for nicer IDE …
  • Loading branch information
eriknw committed Nov 3, 2016
2 parents fe56571 + 20d8aef commit d8c0d50
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 25 deletions.
95 changes: 70 additions & 25 deletions toolz/curried/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,78 @@
See Also:
toolz.functoolz.curry
"""
from . import exceptions
from . import operator
import toolz
from . import operator
from toolz import (
comp,
complement,
compose,
concat,
concatv,
count,
curry,
diff,
dissoc,
first,
flip,
frequencies,
identity,
interleave,
isdistinct,
isiterable,
juxt,
last,
memoize,
merge_sorted,
peek,
pipe,
second,
thread_first,
thread_last,
)
from .exceptions import merge, merge_with

accumulate = toolz.curry(toolz.accumulate)
assoc = toolz.curry(toolz.assoc)
assoc_in = toolz.curry(toolz.assoc_in)
cons = toolz.curry(toolz.cons)
countby = toolz.curry(toolz.countby)
do = toolz.curry(toolz.do)
drop = toolz.curry(toolz.drop)
excepts = toolz.curry(toolz.excepts)
filter = toolz.curry(toolz.filter)
get = toolz.curry(toolz.get)
get_in = toolz.curry(toolz.get_in)
groupby = toolz.curry(toolz.groupby)
interpose = toolz.curry(toolz.interpose)
itemfilter = toolz.curry(toolz.itemfilter)
itemmap = toolz.curry(toolz.itemmap)
iterate = toolz.curry(toolz.iterate)
join = toolz.curry(toolz.join)
keyfilter = toolz.curry(toolz.keyfilter)
keymap = toolz.curry(toolz.keymap)
map = toolz.curry(toolz.map)
mapcat = toolz.curry(toolz.mapcat)
nth = toolz.curry(toolz.nth)
partial = toolz.curry(toolz.partial)
partition = toolz.curry(toolz.partition)
partition_all = toolz.curry(toolz.partition_all)
partitionby = toolz.curry(toolz.partitionby)
pluck = toolz.curry(toolz.pluck)
random_sample = toolz.curry(toolz.random_sample)
reduce = toolz.curry(toolz.reduce)
reduceby = toolz.curry(toolz.reduceby)
remove = toolz.curry(toolz.remove)
sliding_window = toolz.curry(toolz.sliding_window)
sorted = toolz.curry(toolz.sorted)
tail = toolz.curry(toolz.tail)
take = toolz.curry(toolz.take)
take_nth = toolz.curry(toolz.take_nth)
topk = toolz.curry(toolz.topk)
unique = toolz.curry(toolz.unique)
update_in = toolz.curry(toolz.update_in)
valfilter = toolz.curry(toolz.valfilter)
valmap = toolz.curry(toolz.valmap)

def _should_curry(func):
if not callable(func) or isinstance(func, toolz.curry):
return False
nargs = toolz.functoolz.num_required_args(func)
if nargs is None or nargs > 1:
return True
return nargs == 1 and toolz.functoolz.has_keywords(func)


def _curry_namespace(ns):
return dict(
(name, toolz.curry(f) if _should_curry(f) else f)
for name, f in ns.items() if '__' not in name
)


locals().update(toolz.merge(
_curry_namespace(vars(toolz)),
_curry_namespace(vars(exceptions)),
))

# Clean up the namespace.
del _should_curry
del exceptions
del toolz
1 change: 1 addition & 0 deletions toolz/curried/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ def merge_with(func, d, *dicts, **kwargs):
def merge(d, *dicts, **kwargs):
return toolz.merge(d, *dicts, **kwargs)


merge_with.__doc__ = toolz.merge_with.__doc__
merge.__doc__ = toolz.merge.__doc__
49 changes: 49 additions & 0 deletions toolz/tests/test_curried.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import toolz.curried
from toolz.curried import (take, first, second, sorted, merge_with, reduce,
merge, operator as cop)
from toolz.compatibility import import_module
from collections import defaultdict
from operator import add

Expand Down Expand Up @@ -62,3 +63,51 @@ def test_curried_operator():

# Make sure this isn't totally empty.
assert len(set(vars(cop)) & set(['add', 'sub', 'mul'])) == 3


def test_curried_namespace():
exceptions = import_module('toolz.curried.exceptions')
namespace = {}

def should_curry(func):
if not callable(func) or isinstance(func, toolz.curry):
return False
nargs = toolz.functoolz.num_required_args(func)
if nargs is None or nargs > 1:
return True
return nargs == 1 and toolz.functoolz.has_keywords(func)


def curry_namespace(ns):
return dict(
(name, toolz.curry(f) if should_curry(f) else f)
for name, f in ns.items() if '__' not in name
)

from_toolz = curry_namespace(vars(toolz))
from_exceptions = curry_namespace(vars(exceptions))
namespace.update(toolz.merge(from_toolz, from_exceptions))

namespace = toolz.valfilter(callable, namespace)
curried_namespace = toolz.valfilter(callable, toolz.curried.__dict__)

if namespace != curried_namespace:
missing = set(namespace) - set(curried_namespace)
if missing:
raise AssertionError('There are missing functions in toolz.curried:\n %s'
% ' \n'.join(sorted(missing)))
extra = set(curried_namespace) - set(namespace)
if extra:
raise AssertionError('There are extra functions in toolz.curried:\n %s'
% ' \n'.join(sorted(extra)))
unequal = toolz.merge_with(list, namespace, curried_namespace)
unequal = toolz.valfilter(lambda x: x[0] != x[1], unequal)
messages = []
for name, (orig_func, auto_func) in sorted(unequal.items()):
if name in from_exceptions:
messages.append('%s should come from toolz.curried.exceptions' % name)
elif should_curry(getattr(toolz, name)):
messages.append('%s should be curried from toolz' % name)
else:
messages.append('%s should come from toolz and NOT be curried' % name)
raise AssertionError('\n'.join(messages))

0 comments on commit d8c0d50

Please sign in to comment.