11# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/02_utils.ipynb (unless otherwise specified).
22
33__all__ = ['ifnone' , 'maybe_attr' , 'basic_repr' , 'get_class' , 'mk_class' , 'wrap_class' , 'ignore_exceptions' ,
4- 'exec_local' , 'stop' , 'AttrDict' , 'dict2obj' , 'store_attr' , 'attrdict' , 'properties' , 'camel2snake' ,
5- 'snake2camel' , 'class2attr' , 'hasattrs' , 'setattrs' , 'ShowPrint' , 'Int' , 'Str' , 'Float' , 'tuplify' ,
6- 'detuplify' , 'replicate' , 'uniqueify' , 'setify' , 'merge' , 'is_listy' , 'range_of' , 'groupby' , 'last_index' ,
7- 'shufflish' , 'IterLen' , 'ReindexCollection' , 'num_methods' , 'rnum_methods' , 'inum_methods' , 'fastuple' ,
8- 'Inf' , 'in_' , 'lt' , 'gt' , 'le' , 'ge' , 'eq' , 'ne' , 'add' , 'sub' , 'mul' , 'truediv' , 'is_' , 'is_not' , 'in_' ,
9- 'true' , 'gen' , 'chunked' , 'trace' , 'compose' , 'maps' , 'partialler' , 'mapped' , 'instantiate' , 'using_attr' ,
10- 'Self' , 'Self' , 'remove_patches_path' , 'bunzip' , 'join_path_file' , 'urlread' , 'urljson' , 'run' , 'do_request' ,
11- 'sort_by_run' , 'PrettyString' , 'round_multiple' , 'even_mults' , 'num_cpus' , 'add_props' , 'ContextManagers' ,
12- 'set_num_threads' , 'ProcessPoolExecutor' , 'ThreadPoolExecutor' , 'parallel' , 'run_procs' , 'parallel_gen' ]
4+ 'exec_local' , 'Inf' , 'in_' , 'lt' , 'gt' , 'le' , 'ge' , 'eq' , 'ne' , 'add' , 'sub' , 'mul' , 'truediv' , 'is_' ,
5+ 'is_not' , 'in_' , 'true' , 'stop' , 'gen' , 'chunked' , 'AttrDict' , 'dict2obj' , 'with_cast' , 'store_attr' ,
6+ 'attrdict' , 'properties' , 'camel2snake' , 'snake2camel' , 'class2attr' , 'hasattrs' , 'setattrs' , 'ShowPrint' ,
7+ 'Int' , 'Str' , 'Float' , 'tuplify' , 'detuplify' , 'replicate' , 'uniqueify' , 'setify' , 'merge' , 'is_listy' ,
8+ 'range_of' , 'groupby' , 'last_index' , 'shufflish' , 'IterLen' , 'ReindexCollection' , 'num_methods' ,
9+ 'rnum_methods' , 'inum_methods' , 'fastuple' , 'trace' , 'compose' , 'maps' , 'partialler' , 'mapped' ,
10+ 'instantiate' , 'using_attr' , 'Self' , 'Self' , 'remove_patches_path' , 'bunzip' , 'join_path_file' , 'urlread' ,
11+ 'urljson' , 'run' , 'do_request' , 'sort_by_run' , 'PrettyString' , 'round_multiple' , 'even_mults' , 'num_cpus' ,
12+ 'add_props' , 'ContextManagers' , 'set_num_threads' , 'ProcessPoolExecutor' , 'ThreadPoolExecutor' , 'parallel' ,
13+ 'run_procs' , 'parallel_gen' ]
1314
1415# Cell
1516from .imports import *
@@ -94,11 +95,73 @@ def exec_local(code, var_name):
9495 exec (code , globals (), loc )
9596 return loc [var_name ]
9697
98+ # Cell
99+ #hide
100+ class _InfMeta (type ):
101+ @property
102+ def count (self ): return itertools .count ()
103+ @property
104+ def zeros (self ): return itertools .cycle ([0 ])
105+ @property
106+ def ones (self ): return itertools .cycle ([1 ])
107+ @property
108+ def nones (self ): return itertools .cycle ([None ])
109+
110+ # Cell
111+ class Inf (metaclass = _InfMeta ):
112+ "Infinite lists"
113+ pass
114+
115+ # Cell
116+ def _oper (op ,a ,b = float ('nan' )): return (lambda o :op (o ,a )) if b != b else op (a ,b )
117+
118+ def _mk_op (nm , mod ):
119+ "Create an operator using `oper` and add to the caller's module"
120+ op = getattr (operator ,nm )
121+ def _inner (a ,b = float ('nan' )): return _oper (op , a ,b )
122+ _inner .__name__ = _inner .__qualname__ = nm
123+ _inner .__doc__ = f'Same as `operator.{ nm } `, or returns partial if 1 arg'
124+ mod [nm ] = _inner
125+
126+ # Cell
127+ def in_ (x , a ):
128+ "`True` if `x in a`"
129+ return x in a
130+
131+ operator .in_ = in_
132+
133+ # Cell
134+ #nbdev_comment _all_ = ['lt','gt','le','ge','eq','ne','add','sub','mul','truediv','is_','is_not','in_']
135+
136+ # Cell
137+ for op in ['lt' ,'gt' ,'le' ,'ge' ,'eq' ,'ne' ,'add' ,'sub' ,'mul' ,'truediv' ,'is_' ,'is_not' ,'in_' ]: _mk_op (op , globals ())
138+
139+ # Cell
140+ def true (* args , ** kwargs ):
141+ "Predicate: always `True`"
142+ return True
143+
97144# Cell
98145def stop (e = StopIteration ):
99146 "Raises exception `e` (by default `StopException`)"
100147 raise e
101148
149+ # Cell
150+ def gen (func , seq , cond = true ):
151+ "Like `(func(o) for o in seq if cond(func(o)))` but handles `StopIteration`"
152+ return itertools .takewhile (cond , map (func ,seq ))
153+
154+ # Cell
155+ def chunked (it , chunk_sz = None , drop_last = False , n_chunks = None ):
156+ "Return batches from iterator `it` of size `chunk_sz` (or return `n_chunks` total)"
157+ assert bool (chunk_sz ) ^ bool (n_chunks )
158+ if n_chunks : chunk_sz = math .ceil (len (it )/ n_chunks )
159+ if not isinstance (it , Iterator ): it = iter (it )
160+ while True :
161+ res = list (itertools .islice (it , chunk_sz ))
162+ if res and (len (res )== chunk_sz or not drop_last ): yield res
163+ if len (res )< chunk_sz : return
164+
102165# Cell
103166class AttrDict (dict ):
104167 "`dict` subclass that also provides access to keys as attrs"
@@ -114,22 +177,39 @@ def dict2obj(d):
114177 return AttrDict (** {k :dict2obj (v ) for k ,v in d .items ()})
115178
116179# Cell
117- def _store_attr (self , ** attrs ):
180+ def with_cast (f ):
181+ "Decorator which uses any parameter annotations as preprocessing functions"
182+ anno = f .__annotations__
183+ params = f .__code__ .co_varnames
184+ def _inner (* args , ** kwargs ):
185+ args = list (args )
186+ for i ,v in enumerate (params ):
187+ if v in anno :
188+ c = anno [v ]
189+ if v in kwargs : kwargs [v ] = c (kwargs [v ])
190+ elif i < len (args ): args [i ] = c (args [i ])
191+ return f (* args , ** kwargs )
192+ return _inner
193+
194+ # Cell
195+ def _store_attr (self , anno , ** attrs ):
118196 for n ,v in attrs .items ():
197+ if n in anno : v = anno [n ](v )
119198 setattr (self , n , v )
120199 self .__stored_args__ [n ] = v
121200
122201# Cell
123- def store_attr (names = None , self = None , but = None , ** attrs ):
202+ def store_attr (names = None , self = None , but = None , cast = False , ** attrs ):
124203 "Store params named in comma-separated `names` from calling context into attrs in `self`"
125204 fr = sys ._getframe (1 )
126205 args = fr .f_code .co_varnames [:fr .f_code .co_argcount ]
127206 if self : args = ('self' , * args )
128207 else : self = fr .f_locals [args [0 ]]
129208 if not hasattr (self , '__stored_args__' ): self .__stored_args__ = {}
130- if attrs : return _store_attr (self , ** attrs )
209+ anno = self .__class__ .__init__ .__annotations__ if cast else {}
210+ if attrs : return _store_attr (self , anno , ** attrs )
131211 ns = re .split (', *' , names ) if names else args [1 :]
132- _store_attr (self , ** {n :fr .f_locals [n ] for n in ns if n not in L (but )})
212+ _store_attr (self , anno , ** {n :fr .f_locals [n ] for n in ns if n not in L (but )})
133213
134214# Cell
135215def attrdict (o , * ks ):
@@ -158,10 +238,9 @@ def snake2camel(s):
158238
159239# Cell
160240def class2attr (self , cls_name ):
161- "Return the snake-cased name of the class. Additionally, remove the substring `cls_name` only if it is a substring at the **end** of the string ."
241+ "Return the snake-cased name of the class; strip ending `cls_name` if it exists ."
162242 return camel2snake (re .sub (rf'{ cls_name } $' , '' , self .__class__ .__name__ ) or cls_name .lower ())
163243
164-
165244# Cell
166245def hasattrs (o ,attrs ):
167246 "Test whether `o` contains all `attrs`"
@@ -334,68 +413,6 @@ def _f(self,*args): return self._op(op,*args)
334413setattr (fastuple ,'max' ,_get_op (max ))
335414setattr (fastuple ,'min' ,_get_op (min ))
336415
337- # Cell
338- #hide
339- class _InfMeta (type ):
340- @property
341- def count (self ): return itertools .count ()
342- @property
343- def zeros (self ): return itertools .cycle ([0 ])
344- @property
345- def ones (self ): return itertools .cycle ([1 ])
346- @property
347- def nones (self ): return itertools .cycle ([None ])
348-
349- # Cell
350- class Inf (metaclass = _InfMeta ):
351- "Infinite lists"
352- pass
353-
354- # Cell
355- def _oper (op ,a ,b = float ('nan' )): return (lambda o :op (o ,a )) if b != b else op (a ,b )
356-
357- def _mk_op (nm , mod ):
358- "Create an operator using `oper` and add to the caller's module"
359- op = getattr (operator ,nm )
360- def _inner (a ,b = float ('nan' )): return _oper (op , a ,b )
361- _inner .__name__ = _inner .__qualname__ = nm
362- _inner .__doc__ = f'Same as `operator.{ nm } `, or returns partial if 1 arg'
363- mod [nm ] = _inner
364-
365- # Cell
366- def in_ (x , a ):
367- "`True` if `x in a`"
368- return x in a
369-
370- operator .in_ = in_
371-
372- # Cell
373- #nbdev_comment _all_ = ['lt','gt','le','ge','eq','ne','add','sub','mul','truediv','is_','is_not','in_']
374-
375- # Cell
376- for op in ['lt' ,'gt' ,'le' ,'ge' ,'eq' ,'ne' ,'add' ,'sub' ,'mul' ,'truediv' ,'is_' ,'is_not' ,'in_' ]: _mk_op (op , globals ())
377-
378- # Cell
379- def true (* args , ** kwargs ):
380- "Predicate: always `True`"
381- return True
382-
383- # Cell
384- def gen (func , seq , cond = true ):
385- "Like `(func(o) for o in seq if cond(func(o)))` but handles `StopIteration`"
386- return itertools .takewhile (cond , map (func ,seq ))
387-
388- # Cell
389- def chunked (it , chunk_sz = None , drop_last = False , n_chunks = None ):
390- "Return batches from iterator `it` of size `chunk_sz` (or return `n_chunks` total)"
391- assert bool (chunk_sz ) ^ bool (n_chunks )
392- if n_chunks : chunk_sz = math .ceil (len (it )/ n_chunks )
393- if not isinstance (it , Iterator ): it = iter (it )
394- while True :
395- res = list (itertools .islice (it , chunk_sz ))
396- if res and (len (res )== chunk_sz or not drop_last ): yield res
397- if len (res )< chunk_sz : return
398-
399416# Cell
400417def trace (f ):
401418 "Add `set_trace` to an existing function `f`"
0 commit comments