Skip to content

Commit fe16b3b

Browse files
committed
fixes #150
1 parent f6eebf7 commit fe16b3b

File tree

7 files changed

+542
-464
lines changed

7 files changed

+542
-464
lines changed

fastcore/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.2.4"
1+
__version__ = "1.2.5"

fastcore/_nbdev.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
"replicate": "01_basics.ipynb",
5959
"setify": "01_basics.ipynb",
6060
"merge": "01_basics.ipynb",
61-
"range_of": "02_foundation.ipynb",
61+
"range_of": "01_basics.ipynb",
6262
"groupby": "01_basics.ipynb",
6363
"last_index": "01_basics.ipynb",
6464
"filter_dict": "01_basics.ipynb",
@@ -67,10 +67,24 @@
6767
"cycle": "02_foundation.ipynb",
6868
"zip_cycle": "02_foundation.ipynb",
6969
"sorted_ex": "01_basics.ipynb",
70+
"negate_func": "01_basics.ipynb",
71+
"argwhere": "01_basics.ipynb",
72+
"filter_ex": "01_basics.ipynb",
73+
"renumerate": "01_basics.ipynb",
74+
"first": "01_basics.ipynb",
75+
"nested_attr": "01_basics.ipynb",
76+
"nested_idx": "01_basics.ipynb",
7077
"num_methods": "01_basics.ipynb",
7178
"rnum_methods": "01_basics.ipynb",
7279
"inum_methods": "01_basics.ipynb",
7380
"fastuple": "01_basics.ipynb",
81+
"arg0": "01_basics.ipynb",
82+
"arg1": "01_basics.ipynb",
83+
"arg2": "01_basics.ipynb",
84+
"arg3": "01_basics.ipynb",
85+
"arg4": "01_basics.ipynb",
86+
"bind": "01_basics.ipynb",
87+
"map_ex": "01_basics.ipynb",
7488
"compose": "01_basics.ipynb",
7589
"maps": "01_basics.ipynb",
7690
"partialler": "01_basics.ipynb",
@@ -90,26 +104,12 @@
90104
"add_docs": "02_foundation.ipynb",
91105
"docs": "02_foundation.ipynb",
92106
"custom_dir": "02_foundation.ipynb",
93-
"arg0": "02_foundation.ipynb",
94-
"arg1": "02_foundation.ipynb",
95-
"arg2": "02_foundation.ipynb",
96-
"arg3": "02_foundation.ipynb",
97-
"arg4": "02_foundation.ipynb",
98107
"coll_repr": "02_foundation.ipynb",
99108
"is_bool": "02_foundation.ipynb",
100109
"mask2idxs": "02_foundation.ipynb",
101110
"is_indexer": "02_foundation.ipynb",
102-
"negate_func": "02_foundation.ipynb",
103111
"GetAttr": "02_foundation.ipynb",
104112
"delegate_attr": "02_foundation.ipynb",
105-
"bind": "02_foundation.ipynb",
106-
"argwhere": "02_foundation.ipynb",
107-
"map_ex": "02_foundation.ipynb",
108-
"filter_ex": "02_foundation.ipynb",
109-
"listable_types": "02_foundation.ipynb",
110-
"renumerate": "02_foundation.ipynb",
111-
"first": "02_foundation.ipynb",
112-
"nested_attr": "02_foundation.ipynb",
113113
"CollBase": "02_foundation.ipynb",
114114
"L": "02_foundation.ipynb",
115115
"L.__signature__": "02_foundation.ipynb",

fastcore/basics.py

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
'AttrDict', 'with_cast', 'store_attr', 'attrdict', 'properties', 'camel2snake', 'snake2camel', 'class2attr',
77
'hasattrs', 'setattrs', 'try_attrs', 'ShowPrint', 'Int', 'Str', 'Float', 'detuplify', 'replicate', 'setify',
88
'merge', 'range_of', 'groupby', 'last_index', 'filter_dict', 'filter_keys', 'filter_values', 'cycle',
9-
'zip_cycle', 'sorted_ex', 'num_methods', 'rnum_methods', 'inum_methods', 'fastuple', 'compose', 'maps',
10-
'partialler', 'instantiate', 'using_attr', 'Self', 'Self', 'PrettyString', 'even_mults', 'num_cpus',
11-
'add_props', 'typed']
9+
'zip_cycle', 'sorted_ex', 'negate_func', 'argwhere', 'filter_ex', 'range_of', 'renumerate', 'first',
10+
'nested_attr', 'nested_idx', 'num_methods', 'rnum_methods', 'inum_methods', 'fastuple', 'arg0', 'arg1',
11+
'arg2', 'arg3', 'arg4', 'bind', 'map_ex', 'compose', 'maps', 'partialler', 'instantiate', 'using_attr',
12+
'Self', 'Self', 'PrettyString', 'even_mults', 'num_cpus', 'add_props', 'typed']
1213

1314
# Cell
1415
from .imports import *
@@ -364,6 +365,61 @@ def sorted_ex(iterable, key=None, reverse=False):
364365
else: k=key
365366
return sorted(iterable, key=k, reverse=reverse)
366367

368+
# Cell
369+
def negate_func(f):
370+
"Create new function that negates result of `f`"
371+
def _f(*args, **kwargs): return not f(*args, **kwargs)
372+
return _f
373+
374+
# Cell
375+
def argwhere(iterable, f, negate=False, **kwargs):
376+
"Like `filter_ex`, but return indices for matching items"
377+
if kwargs: f = partial(f,**kwargs)
378+
if negate: f = negate_func(f)
379+
return [i for i,o in enumerate(iterable) if f(o)]
380+
381+
# Cell
382+
def filter_ex(iterable, f=noop, negate=False, gen=False, **kwargs):
383+
"Like `filter`, but passing `kwargs` to `f`, defaulting `f` to `noop`, and adding `negate` and `gen`"
384+
if kwargs: f = partial(f,**kwargs)
385+
if negate: f = negate_func(f)
386+
res = filter(f, iterable)
387+
if gen: return res
388+
return list(res)
389+
390+
# Cell
391+
def range_of(a, b=None, step=None):
392+
"All indices of collection `a`, if `a` is a collection, otherwise `range`"
393+
if is_coll(a): a = len(a)
394+
return list(range(a,b,step) if step is not None else range(a,b) if b is not None else range(a))
395+
396+
# Cell
397+
def renumerate(iterable, start=0):
398+
"Same as `enumerate`, but returns index as 2nd element instead of 1st"
399+
return ((o,i) for i,o in enumerate(iterable, start=start))
400+
401+
# Cell
402+
def first(x):
403+
"First element of `x`, or None if missing"
404+
try: return next(iter(x))
405+
except StopIteration: return None
406+
407+
# Cell
408+
def nested_attr(o, attr, default=None):
409+
"Same as `getattr`, but if `attr` includes a `.`, then looks inside nested objects"
410+
try:
411+
for a in attr.split("."): o = getattr(o, a)
412+
except AttributeError: return default
413+
return o
414+
415+
# Cell
416+
def nested_idx(coll, *idxs):
417+
"Index into nested collections, dicts, etc, with `idxs`"
418+
if not coll or not idxs: return coll
419+
if isinstance(coll,str) or not isinstance(coll, typing.Collection): return None
420+
res = coll.get(idxs[0], None) if hasattr(coll, 'get') else coll[idxs[0]] if idxs[0]<len(coll) else None
421+
return nested_idx(res, *idxs[1:])
422+
367423
# Cell
368424
num_methods = """
369425
__add__ __sub__ __mul__ __matmul__ __truediv__ __floordiv__ __mod__ __divmod__ __pow__
@@ -415,6 +471,40 @@ def _f(self,*args): return self._op(op,*args)
415471
setattr(fastuple,'max',_get_op(max))
416472
setattr(fastuple,'min',_get_op(min))
417473

474+
# Cell
475+
class _Arg:
476+
def __init__(self,i): self.i = i
477+
arg0 = _Arg(0)
478+
arg1 = _Arg(1)
479+
arg2 = _Arg(2)
480+
arg3 = _Arg(3)
481+
arg4 = _Arg(4)
482+
483+
# Cell
484+
class bind:
485+
"Same as `partial`, except you can use `arg0` `arg1` etc param placeholders"
486+
def __init__(self, fn, *pargs, **pkwargs):
487+
self.fn,self.pargs,self.pkwargs = fn,pargs,pkwargs
488+
self.maxi = max((x.i for x in pargs if isinstance(x, _Arg)), default=-1)
489+
490+
def __call__(self, *args, **kwargs):
491+
args = list(args)
492+
kwargs = {**self.pkwargs,**kwargs}
493+
for k,v in kwargs.items():
494+
if isinstance(v,_Arg): kwargs[k] = args.pop(v.i)
495+
fargs = [args[x.i] if isinstance(x, _Arg) else x for x in self.pargs] + args[self.maxi+1:]
496+
return self.fn(*fargs, **kwargs)
497+
498+
# Cell
499+
def map_ex(iterable, f, *args, gen=False, **kwargs):
500+
"Like `map`, but use `bind`, and supports `str` and indexing"
501+
g = (bind(f,*args,**kwargs) if callable(f)
502+
else f.format if isinstance(f,str)
503+
else f.__getitem__)
504+
res = map(g, iterable)
505+
if gen: return res
506+
return list(res)
507+
418508
# Cell
419509
def compose(*funcs, order=None):
420510
"Create a function that composes all functions in `funcs`, passing along remaining `*args` and `**kwargs` to all"

fastcore/foundation.py

Lines changed: 3 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/02_foundation.ipynb (unless otherwise specified).
22

3-
__all__ = ['copy_func', 'patch_to', 'patch', 'patch_property', 'add_docs', 'docs', 'custom_dir', 'arg0', 'arg1', 'arg2',
4-
'arg3', 'arg4', 'coll_repr', 'is_bool', 'mask2idxs', 'cycle', 'zip_cycle', 'is_indexer', 'negate_func',
5-
'GetAttr', 'delegate_attr', 'bind', 'argwhere', 'map_ex', 'filter_ex', 'range_of', 'listable_types',
6-
'renumerate', 'first', 'nested_attr', 'CollBase', 'L', 'save_config_file', 'read_config_file', 'Config']
3+
__all__ = ['copy_func', 'patch_to', 'patch', 'patch_property', 'add_docs', 'docs', 'custom_dir', 'coll_repr', 'is_bool',
4+
'mask2idxs', 'cycle', 'zip_cycle', 'is_indexer', 'GetAttr', 'delegate_attr', 'CollBase', 'L',
5+
'save_config_file', 'read_config_file', 'Config']
76

87
# Cell
98
from .imports import *
@@ -79,15 +78,6 @@ def custom_dir(c, add:list):
7978
"Implement custom `__dir__`, adding `add` to `cls`"
8079
return dir(type(c)) + list(c.__dict__.keys()) + add
8180

82-
# Cell
83-
class _Arg:
84-
def __init__(self,i): self.i = i
85-
arg0 = _Arg(0)
86-
arg1 = _Arg(1)
87-
arg2 = _Arg(2)
88-
arg3 = _Arg(3)
89-
arg4 = _Arg(4)
90-
9181
# Cell
9282
def coll_repr(c, max_n=10):
9383
"String repr of up to `max_n` items of (possibly lazy) collection `c`"
@@ -126,12 +116,6 @@ def is_indexer(idx):
126116
"Test whether `idx` will index a single item in a list"
127117
return isinstance(idx,int) or not getattr(idx,'ndim',1)
128118

129-
# Cell
130-
def negate_func(f):
131-
"Create new function that negates result of `f`"
132-
def _f(*args, **kwargs): return not f(*args, **kwargs)
133-
return _f
134-
135119
# Cell
136120
class GetAttr:
137121
"Inherit from this to have all attr accesses in `self._xtra` passed down to `self.default`"
@@ -157,75 +141,6 @@ def delegate_attr(self, k, to):
157141
try: return getattr(getattr(self,to), k)
158142
except AttributeError: raise AttributeError(k) from None
159143

160-
# Cell
161-
class bind:
162-
"Same as `partial`, except you can use `arg0` `arg1` etc param placeholders"
163-
def __init__(self, fn, *pargs, **pkwargs):
164-
self.fn,self.pargs,self.pkwargs = fn,pargs,pkwargs
165-
self.maxi = max((x.i for x in pargs if isinstance(x, _Arg)), default=-1)
166-
167-
def __call__(self, *args, **kwargs):
168-
args = list(args)
169-
kwargs = {**self.pkwargs,**kwargs}
170-
for k,v in kwargs.items():
171-
if isinstance(v,_Arg): kwargs[k] = args.pop(v.i)
172-
fargs = [args[x.i] if isinstance(x, _Arg) else x for x in self.pargs] + args[self.maxi+1:]
173-
return self.fn(*fargs, **kwargs)
174-
175-
# Cell
176-
def argwhere(iterable, f, negate=False, **kwargs):
177-
"Like `filter_ex`, but return indices for matching items"
178-
if kwargs: f = partial(f,**kwargs)
179-
if negate: f = negate_func(f)
180-
return [i for i,o in enumerate(iterable) if f(o)]
181-
182-
# Cell
183-
def map_ex(iterable, f, *args, gen=False, **kwargs):
184-
"Like `map`, but use `bind`, and supports `str` and indexing"
185-
g = (bind(f,*args,**kwargs) if callable(f)
186-
else f.format if isinstance(f,str)
187-
else f.__getitem__)
188-
res = map(g, iterable)
189-
if gen: return res
190-
return list(res)
191-
192-
# Cell
193-
def filter_ex(iterable, f=noop, negate=False, gen=False, **kwargs):
194-
"Like `filter`, but passing `kwargs` to `f`, defaulting `f` to `noop`, and adding `negate` and `gen`"
195-
if kwargs: f = partial(f,**kwargs)
196-
if negate: f = negate_func(f)
197-
res = filter(f, iterable)
198-
if gen: return res
199-
return list(res)
200-
201-
# Cell
202-
def range_of(a, b=None, step=None):
203-
"All indices of collection `a`, if `a` is a collection, otherwise `range`"
204-
if is_coll(a): a = len(a)
205-
return list(range(a,b,step) if step is not None else range(a,b) if b is not None else range(a))
206-
207-
# Cell
208-
listable_types = typing.Collection,Generator,map,filter,zip
209-
210-
# Cell
211-
def renumerate(iterable, start=0):
212-
"Same as `enumerate`, but returns index as 2nd element instead of 1st"
213-
return ((o,i) for i,o in enumerate(iterable, start=start))
214-
215-
# Cell
216-
def first(x):
217-
"First element of `x`, or None if missing"
218-
try: return next(iter(x))
219-
except StopIteration: return None
220-
221-
# Cell
222-
def nested_attr(o, attr, default=None):
223-
"Same as `getattr`, but if `attr` includes a `.`, then looks inside nested objects"
224-
try:
225-
for a in attr.split("."): o = getattr(o, a)
226-
except AttributeError: return default
227-
return o
228-
229144
# Cell
230145
class CollBase:
231146
"Base class for composing a list of `items`"

0 commit comments

Comments
 (0)