Skip to content

Commit cb20f6e

Browse files
committed
fixes #215
1 parent 0ff4a33 commit cb20f6e

File tree

7 files changed

+383
-369
lines changed

7 files changed

+383
-369
lines changed

fastcore/_nbdev.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,17 @@
103103
"instantiate": "01_basics.ipynb",
104104
"using_attr": "01_basics.ipynb",
105105
"Self": "01_basics.ipynb",
106+
"copy_func": "01_basics.ipynb",
107+
"patch_to": "01_basics.ipynb",
108+
"patch": "01_basics.ipynb",
109+
"patch_property": "01_basics.ipynb",
106110
"Stateful": "01_basics.ipynb",
107111
"PrettyString": "01_basics.ipynb",
108112
"even_mults": "01_basics.ipynb",
109113
"num_cpus": "01_basics.ipynb",
110114
"defaults.cpus": "01_basics.ipynb",
111115
"add_props": "01_basics.ipynb",
112116
"typed": "01_basics.ipynb",
113-
"copy_func": "02_foundation.ipynb",
114-
"patch_to": "02_foundation.ipynb",
115-
"patch": "02_foundation.ipynb",
116-
"patch_property": "02_foundation.ipynb",
117117
"working_directory": "02_foundation.ipynb",
118118
"add_docs": "02_foundation.ipynb",
119119
"docs": "02_foundation.ipynb",

fastcore/basics.py

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
'filter_keys', 'filter_values', 'cycle', 'zip_cycle', 'sorted_ex', 'negate_func', 'argwhere', 'filter_ex',
1111
'range_of', 'renumerate', 'first', 'nested_attr', 'nested_idx', 'val2idx', 'uniqueify', 'num_methods',
1212
'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']
13+
'compose', 'maps', 'partialler', 'instantiate', 'using_attr', 'Self', 'Self', 'copy_func', 'patch_to',
14+
'patch', 'patch_property', 'Stateful', 'PrettyString', 'even_mults', 'num_cpus', 'add_props', 'typed']
1515

1616
# Cell
1717
from .imports import *
18+
import builtins
1819

1920
# Cell
2021
defaults = SimpleNamespace()
@@ -688,6 +689,48 @@ def __call__(self,*args,**kwargs): return self.__getattr__('_call')(*args,**kwar
688689
# Cell
689690
#nbdev_comment _all_ = ['Self']
690691

692+
# Cell
693+
def copy_func(f):
694+
"Copy a non-builtin function (NB `copy.copy` does not work for this)"
695+
if not isinstance(f,FunctionType): return copy(f)
696+
fn = FunctionType(f.__code__, f.__globals__, f.__name__, f.__defaults__, f.__closure__)
697+
fn.__kwdefaults__ = f.__kwdefaults__
698+
fn.__dict__.update(f.__dict__)
699+
return fn
700+
701+
# Cell
702+
def patch_to(cls, as_prop=False, cls_method=False):
703+
"Decorator: add `f` to `cls`"
704+
if not isinstance(cls, (tuple,list)): cls=(cls,)
705+
def _inner(f):
706+
for c_ in cls:
707+
nf = copy_func(f)
708+
nm = f.__name__
709+
# `functools.update_wrapper` when passing patched function to `Pipeline`, so we do it manually
710+
for o in functools.WRAPPER_ASSIGNMENTS: setattr(nf, o, getattr(f,o))
711+
nf.__qualname__ = f"{c_.__name__}.{nm}"
712+
if cls_method:
713+
setattr(c_, nm, MethodType(nf, c_))
714+
else:
715+
setattr(c_, nm, property(nf) if as_prop else nf)
716+
# Avoid clobbering existing functions
717+
return globals().get(nm, builtins.__dict__.get(nm, None))
718+
return _inner
719+
720+
# Cell
721+
def patch(f=None, *, as_prop=False, cls_method=False):
722+
"Decorator: add `f` to the first parameter's class (based on f's type annotations)"
723+
if f is None: return partial(patch, as_prop=as_prop, cls_method=cls_method)
724+
cls = next(iter(f.__annotations__.values()))
725+
return patch_to(cls, as_prop=as_prop, cls_method=cls_method)(f)
726+
727+
# Cell
728+
def patch_property(f):
729+
"Deprecated; use `patch(as_prop=True)` instead"
730+
warnings.warn("`patch_property` is deprecated and will be removed; use `patch(as_prop=True)` instead")
731+
cls = next(iter(f.__annotations__.values()))
732+
return patch_to(cls, as_prop=True)(f)
733+
691734
# Cell
692735
class Stateful:
693736
"A base class/mixin for objects that should not serialize all their state"

fastcore/foundation.py

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
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', 'working_directory', 'add_docs', 'docs', 'coll_repr',
4-
'is_bool', 'mask2idxs', 'cycle', 'zip_cycle', 'is_indexer', 'GetAttr', 'delegate_attr', 'CollBase', 'L',
5-
'save_config_file', 'read_config_file', 'Config']
3+
__all__ = ['working_directory', 'add_docs', 'docs', 'coll_repr', 'is_bool', 'mask2idxs', 'cycle', 'zip_cycle',
4+
'is_indexer', 'GetAttr', 'delegate_attr', 'CollBase', 'L', 'save_config_file', 'read_config_file', 'Config']
65

76
# Cell
87
from .imports import *
@@ -13,46 +12,6 @@
1312
from configparser import ConfigParser
1413
import random,pickle
1514

16-
# Cell
17-
def copy_func(f):
18-
"Copy a non-builtin function (NB `copy.copy` does not work for this)"
19-
if not isinstance(f,FunctionType): return copy(f)
20-
fn = FunctionType(f.__code__, f.__globals__, f.__name__, f.__defaults__, f.__closure__)
21-
fn.__kwdefaults__ = f.__kwdefaults__
22-
fn.__dict__.update(f.__dict__)
23-
return fn
24-
25-
# Cell
26-
def patch_to(cls, as_prop=False, cls_method=False):
27-
"Decorator: add `f` to `cls`"
28-
if not isinstance(cls, (tuple,list)): cls=(cls,)
29-
def _inner(f):
30-
for c_ in cls:
31-
nf = copy_func(f)
32-
# `functools.update_wrapper` when passing patched function to `Pipeline`, so we do it manually
33-
for o in functools.WRAPPER_ASSIGNMENTS: setattr(nf, o, getattr(f,o))
34-
nf.__qualname__ = f"{c_.__name__}.{f.__name__}"
35-
if cls_method:
36-
setattr(c_, f.__name__, MethodType(nf, c_))
37-
else:
38-
setattr(c_, f.__name__, property(nf) if as_prop else nf)
39-
return f
40-
return _inner
41-
42-
# Cell
43-
def patch(f=None, *, as_prop=False, cls_method=False):
44-
"Decorator: add `f` to the first parameter's class (based on f's type annotations)"
45-
if f is None: return partial(patch, as_prop=as_prop, cls_method=cls_method)
46-
cls = next(iter(f.__annotations__.values()))
47-
return patch_to(cls, as_prop=as_prop, cls_method=cls_method)(f)
48-
49-
# Cell
50-
def patch_property(f):
51-
"Deprecated; use `patch(as_prop=True)` instead"
52-
warnings.warn("`patch_property` is deprecated and will be removed; use `patch(as_prop=True)` instead")
53-
cls = next(iter(f.__annotations__.values()))
54-
return patch_to(cls, as_prop=True)(f)
55-
5615
# Cell
5716
@contextmanager
5817
def working_directory(path):

fastcore/xtras.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,14 +299,15 @@ def _socket_det(port,host,dgram):
299299
return family,addr,(socket.SOCK_STREAM,socket.SOCK_DGRAM)[dgram]
300300

301301
# Cell
302-
def start_server(port, host=None, dgram=False, n_queue=None):
302+
def start_server(port, host=None, dgram=False, reuse_addr=True, n_queue=None):
303303
"Create a `socket` server on `port`, with optional `host`, of type `dgram`"
304304
listen_args = [n_queue] if n_queue else []
305305
family,addr,typ = _socket_det(port,host,dgram)
306306
if family==socket.AF_UNIX:
307307
if os.path.exists(addr): os.unlink(addr)
308308
assert not os.path.exists(addr), f"{addr} in use"
309309
s = socket.socket(family, typ)
310+
if reuse_addr and family==socket.AF_INET: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
310311
s.bind(addr)
311312
s.listen(*listen_args)
312313
return s

0 commit comments

Comments
 (0)