Skip to content

Commit d285be8

Browse files
committed
fixes #209
1 parent bc3b84f commit d285be8

File tree

7 files changed

+302
-209
lines changed

7 files changed

+302
-209
lines changed

fastcore/_nbdev.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"basic_repr": "01_basics.ipynb",
2626
"is_array": "01_basics.ipynb",
2727
"listify": "01_basics.ipynb",
28+
"tuplify": "01_basics.ipynb",
2829
"true": "01_basics.ipynb",
2930
"NullType": "01_basics.ipynb",
3031
"null": "01_basics.ipynb",
@@ -83,6 +84,8 @@
8384
"first": "01_basics.ipynb",
8485
"nested_attr": "01_basics.ipynb",
8586
"nested_idx": "01_basics.ipynb",
87+
"val2idx": "01_basics.ipynb",
88+
"uniqueify": "01_basics.ipynb",
8689
"num_methods": "01_basics.ipynb",
8790
"rnum_methods": "01_basics.ipynb",
8891
"inum_methods": "01_basics.ipynb",
@@ -129,8 +132,6 @@
129132
"dict2obj": "03_xtras.ipynb",
130133
"repr_dict": "03_xtras.ipynb",
131134
"AttrDict.__repr__": "03_xtras.ipynb",
132-
"tuplify": "03_xtras.ipynb",
133-
"uniqueify": "03_xtras.ipynb",
134135
"is_listy": "03_xtras.ipynb",
135136
"shufflish": "03_xtras.ipynb",
136137
"mapped": "03_xtras.ipynb",

fastcore/basics.py

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/01_basics.ipynb (unless otherwise specified).
22

3-
__all__ = ['defaults', 'ifnone', 'maybe_attr', 'basic_repr', 'is_array', 'listify', 'true', 'NullType', 'null',
4-
'tonull', 'get_class', 'mk_class', 'wrap_class', 'ignore_exceptions', 'exec_local', 'risinstance', 'Inf',
5-
'in_', 'lt', 'gt', 'le', 'ge', 'eq', 'ne', 'add', 'sub', 'mul', 'truediv', 'is_', 'is_not', 'in_', 'true',
6-
'stop', 'gen', 'chunked', 'otherwise', 'custom_dir', 'AttrDict', 'type_hints', 'annotations', 'anno_ret',
7-
'argnames', 'with_cast', 'store_attr', 'attrdict', 'properties', 'camel2snake', 'snake2camel', 'class2attr',
8-
'getattrs', 'hasattrs', 'setattrs', 'try_attrs', 'ShowPrint', 'Int', 'Str', 'Float', 'detuplify',
9-
'replicate', 'setify', 'merge', 'range_of', 'groupby', 'last_index', 'filter_dict', 'filter_keys',
10-
'filter_values', 'cycle', 'zip_cycle', 'sorted_ex', 'negate_func', 'argwhere', 'filter_ex', 'range_of',
11-
'renumerate', 'first', 'nested_attr', 'nested_idx', 'num_methods', 'rnum_methods', 'inum_methods',
12-
'fastuple', 'arg0', 'arg1', 'arg2', 'arg3', 'arg4', 'bind', 'map_ex', 'compose', 'maps', 'partialler',
13-
'instantiate', 'using_attr', 'Self', 'Self', 'Stateful', 'PrettyString', 'even_mults', 'num_cpus',
14-
'add_props', 'typed']
3+
__all__ = ['defaults', 'ifnone', 'maybe_attr', 'basic_repr', 'is_array', 'listify', 'tuplify', 'true', 'NullType',
4+
'null', 'tonull', 'get_class', 'mk_class', 'wrap_class', 'ignore_exceptions', 'exec_local', 'risinstance',
5+
'Inf', 'in_', 'lt', 'gt', 'le', 'ge', 'eq', 'ne', 'add', 'sub', 'mul', 'truediv', 'is_', 'is_not', 'in_',
6+
'true', 'stop', 'gen', 'chunked', 'otherwise', 'custom_dir', 'AttrDict', 'type_hints', 'annotations',
7+
'anno_ret', 'argnames', 'with_cast', 'store_attr', 'attrdict', 'properties', 'camel2snake', 'snake2camel',
8+
'class2attr', 'getattrs', 'hasattrs', 'setattrs', 'try_attrs', 'ShowPrint', 'Int', 'Str', 'Float',
9+
'detuplify', 'replicate', 'setify', 'merge', 'range_of', 'groupby', 'last_index', 'filter_dict',
10+
'filter_keys', 'filter_values', 'cycle', 'zip_cycle', 'sorted_ex', 'negate_func', 'argwhere', 'filter_ex',
11+
'range_of', 'renumerate', 'first', 'nested_attr', 'nested_idx', 'val2idx', 'uniqueify', 'num_methods',
12+
'rnum_methods', 'inum_methods', 'fastuple', 'arg0', 'arg1', 'arg2', 'arg3', 'arg4', 'bind', 'map_ex',
13+
'compose', 'maps', 'partialler', 'instantiate', 'using_attr', 'Self', 'Self', 'Stateful', 'PrettyString',
14+
'even_mults', 'num_cpus', 'add_props', 'typed']
1515

1616
# Cell
1717
from .imports import *
@@ -44,13 +44,25 @@ def is_array(x):
4444
return hasattr(x,'__array__') or hasattr(x,'iloc')
4545

4646
# Cell
47-
def listify(o):
47+
def listify(o=None, *rest, use_list=False, match=None):
4848
"Convert `o` to a `list`"
49-
if o is None: return []
50-
if isinstance(o, list): return o
51-
if isinstance(o, str) or is_array(o): return [o]
52-
if is_iter(o): return list(o)
53-
return [o]
49+
if rest: o = (o,)+rest
50+
if use_list: res = list(o)
51+
elif o is None: res = []
52+
elif isinstance(o, list): res = o
53+
elif isinstance(o, str) or is_array(o): res = [o]
54+
elif is_iter(o): res = list(o)
55+
else: res = [o]
56+
if match is not None:
57+
if is_coll(match): match = len(match)
58+
if len(res)==1: res = res*match
59+
else: assert len(res)==match, 'Match length mismatch'
60+
return res
61+
62+
# Cell
63+
def tuplify(o, use_list=False, match=None):
64+
"Make `o` a tuple"
65+
return tuple(listify(o, use_list=use_list, match=match))
5466

5567
# Cell
5668
def true(x):
@@ -262,23 +274,25 @@ def _inner(*args, **kwargs):
262274

263275
# Cell
264276
def _store_attr(self, anno, **attrs):
265-
stored = self.__stored_args__
277+
stored = getattr(self, '__stored_args__', None)
266278
for n,v in attrs.items():
267279
if n in anno: v = anno[n](v)
268280
setattr(self, n, v)
269-
stored[n] = v
281+
if stored is not None: stored[n] = v
270282

271283
# Cell
272-
def store_attr(names=None, self=None, but='', cast=False, **attrs):
284+
def store_attr(names=None, self=None, but='', cast=False, store_args=None, **attrs):
273285
"Store params named in comma-separated `names` from calling context into attrs in `self`"
274286
fr = sys._getframe(1)
275287
args = argnames(fr, True)
276288
if self: args = ('self', *args)
277289
else: self = fr.f_locals[args[0]]
278-
if not hasattr(self, '__stored_args__'): self.__stored_args__ = {}
290+
if store_args is None: store_args = not hasattr(self,'__slots__')
291+
if store_args and not hasattr(self, '__stored_args__'): self.__stored_args__ = {}
279292
anno = annotations(self) if cast else {}
280293
if not attrs:
281-
ns = re.split(', *', names) if names else args[1:]
294+
if names and isinstance(names,str): names = re.split(', *', names)
295+
ns = names if names else args[1:]
282296
attrs = {n:fr.f_locals[n] for n in ns}
283297
if isinstance(but,str): but = re.split(', *', but)
284298
attrs = {k:v for k,v in attrs.items() if k not in but}
@@ -492,6 +506,19 @@ def nested_idx(coll, *idxs):
492506
res = coll.get(idxs[0], None) if hasattr(coll, 'get') else coll[idxs[0]] if idxs[0]<len(coll) else None
493507
return nested_idx(res, *idxs[1:])
494508

509+
# Cell
510+
def val2idx(x):
511+
"Dict from value to index"
512+
return {v:k for k,v in enumerate(x)}
513+
514+
# Cell
515+
def uniqueify(x, sort=False, bidir=False, start=None):
516+
"Unique elements in `x`, optionally `sort`-ed, optionally return reverse correspondence, optionally prepend with elements."
517+
res = list(dict.fromkeys(x))
518+
if start is not None: res = listify(start)+res
519+
if sort: res.sort()
520+
return (res,val2idx(res)) if bidir else res
521+
495522
# Cell
496523
num_methods = """
497524
__add__ __sub__ __mul__ __matmul__ __truediv__ __floordiv__ __mod__ __divmod__ __pow__

fastcore/foundation.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,8 @@ class L(GetAttr, CollBase, metaclass=_L_Meta):
167167
"Behaves like a list of `items` but can also index with list of indices or masks"
168168
_default='items'
169169
def __init__(self, items=None, *rest, use_list=False, match=None):
170-
if rest: items = (items,)+rest
171-
if items is None: items = []
172170
if (use_list is not None) or not is_array(items):
173-
items = list(items) if use_list else listify(items)
174-
if match is not None:
175-
if is_coll(match): match = len(match)
176-
if len(items)==1: items = items*match
177-
else: assert len(items)==match, 'Match length mismatch'
171+
items = listify(items, *rest, use_list=use_list, match=match)
178172
super().__init__(items)
179173

180174
@property
@@ -228,28 +222,27 @@ def argwhere(self, f, negate=False, **kwargs): return self._new(argwhere(self, f
228222
def filter(self, f=noop, negate=False, gen=False, **kwargs):
229223
return self._new(filter_ex(self, f=f, negate=negate, gen=gen, **kwargs))
230224

231-
def unique(self): return L(dict.fromkeys(self).keys())
232225
def enumerate(self): return L(enumerate(self))
233226
def renumerate(self): return L(renumerate(self))
234-
def val2idx(self): return {v:k for k,v in self.enumerate()}
227+
def unique(self, sort=False, bidir=False, start=None): return L(uniqueify(self, sort=sort, bidir=bidir, start=start))
228+
def val2idx(self): return val2idx(self)
229+
def cycle(self): return cycle(self)
230+
def map_dict(self, f=noop, *args, gen=False, **kwargs): return {k:f(k, *args,**kwargs) for k in self}
231+
def map_first(self, f=noop, g=noop, *args, **kwargs):
232+
return first(self.map(f, *args, gen=False, **kwargs), g)
233+
235234
def itemgot(self, *idxs):
236235
x = self
237236
for idx in idxs: x = x.map(itemgetter(idx))
238237
return x
239-
240238
def attrgot(self, k, default=None):
241239
return self.map(lambda o: o.get(k,default) if isinstance(o, dict) else nested_attr(o,k,default))
242-
def cycle(self): return cycle(self)
243-
def map_dict(self, f=noop, *args, gen=False, **kwargs): return {k:f(k, *args,**kwargs) for k in self}
244-
def map_first(self, f=noop, g=noop, *args, **kwargs):
245-
return first(self.map(f, *args, gen=False, **kwargs), g)
246240

247241
def starmap(self, f, *args, **kwargs): return self._new(itertools.starmap(partial(f,*args,**kwargs), self))
248242
def zip(self, cycled=False): return self._new((zip_cycle if cycled else zip)(*self))
249243
def zipwith(self, *rest, cycled=False): return self._new([self, *rest]).zip(cycled=cycled)
250244
def map_zip(self, f, *args, cycled=False, **kwargs): return self.zip(cycled=cycled).starmap(f, *args, **kwargs)
251-
def map_zipwith(self, f, *rest, cycled=False, **kwargs):
252-
return self.zipwith(*rest, cycled=cycled).starmap(f, **kwargs)
245+
def map_zipwith(self, f, *rest, cycled=False, **kwargs): return self.zipwith(*rest, cycled=cycled).starmap(f, **kwargs)
253246
def shuffle(self):
254247
it = copy(self.items)
255248
random.shuffle(it)

fastcore/xtras.py

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/03_xtras.ipynb (unless otherwise specified).
22

3-
__all__ = ['dict2obj', 'repr_dict', 'tuplify', 'uniqueify', 'is_listy', 'shufflish', 'mapped', 'IterLen',
4-
'ReindexCollection', 'open_file', 'save_pickle', 'load_pickle', 'maybe_open', 'image_size', 'bunzip',
5-
'join_path_file', 'urlwrap', 'urlopen', 'urlread', 'urljson', 'urlcheck', 'urlclean', 'urlsave', 'urlvalid',
6-
'untar_dir', 'repo_details', 'run', 'do_request', 'sort_by_run', 'trace', 'round_multiple', 'modified_env',
7-
'ContextManagers', 'str2bool', 'set_num_threads', 'ProcessPoolExecutor', 'ThreadPoolExecutor', 'parallel',
8-
'run_procs', 'parallel_gen', 'threaded']
3+
__all__ = ['dict2obj', 'repr_dict', 'is_listy', 'shufflish', 'mapped', 'IterLen', 'ReindexCollection', 'open_file',
4+
'save_pickle', 'load_pickle', 'maybe_open', 'image_size', 'bunzip', 'join_path_file', 'urlwrap', 'urlopen',
5+
'urlread', 'urljson', 'urlcheck', 'urlclean', 'urlsave', 'urlvalid', 'untar_dir', 'repo_details', 'run',
6+
'do_request', 'sort_by_run', 'trace', 'round_multiple', 'modified_env', 'ContextManagers', 'str2bool',
7+
'set_num_threads', 'ProcessPoolExecutor', 'ThreadPoolExecutor', 'parallel', 'run_procs', 'parallel_gen',
8+
'threaded']
99

1010
# Cell
1111
from .imports import *
@@ -49,20 +49,6 @@ def __repr__(self:AttrDict): return repr_dict(self)
4949

5050
AttrDict._repr_markdown_ = AttrDict.__repr__
5151

52-
# Cell
53-
def tuplify(o, use_list=False, match=None):
54-
"Make `o` a tuple"
55-
return tuple(L(o, use_list=use_list, match=match))
56-
57-
# Cell
58-
def uniqueify(x, sort=False, bidir=False, start=None):
59-
"Unique elements in `x`, optionally `sort`-ed, optionally return reverse correspondence, optionally prepend with elements."
60-
res = L(x).unique()
61-
if start is not None: res = start+res
62-
if sort: res.sort()
63-
if bidir: return res, res.val2idx()
64-
return res
65-
6652
# Cell
6753
def is_listy(x):
6854
"`isinstance(x, (tuple,list,L,slice,Generator))`"

0 commit comments

Comments
 (0)