1
1
# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/05_transform.ipynb (unless otherwise specified).
2
2
3
+
4
+ from __future__ import annotations
5
+
6
+
3
7
__all__ = ['Transform' , 'InplaceTransform' , 'DisplayedTransform' , 'ItemTransform' , 'get_func' , 'Func' , 'Sig' ,
4
8
'compose_tfms' , 'mk_transform' , 'gather_attrs' , 'gather_attr_names' , 'Pipeline' ]
5
9
6
10
# Cell
11
+ #nbdev_comment from __future__ import annotations
7
12
from .imports import *
8
13
from .foundation import *
9
14
from .utils import *
13
18
from plum import add_conversion_method , dispatch , Dispatcher
14
19
15
20
# Cell
21
+ # TODO: Shouldn't sig of method set first parameter type to self? how do i get that...
22
+ # i.e. self assumes type(self) / self.__class__?
16
23
def _mk_plum_func (d , n , f = None , cls = None ):
17
24
f = (lambda x : x ) if f is None else copy (f )
18
25
f .__name__ = n
19
26
# plum uses __qualname__ to infer f's owner
20
27
f .__qualname__ = n if cls is None else '.' .join ([cls .__name__ ,n ])
28
+ # TODO: Shouldn't we create a Function here and dispatch from that?
29
+ # We don't need this in the dispatch table i think...
30
+ # TODO: Should Function take name qualname etc and have a .from_callable method?
31
+ # since the func isn't even dispatched by default
21
32
pf = d (f )
22
33
if cls is not None :
23
34
setattr (cls ,n ,pf )
24
- # plum uses __set_name__ to resolve a Function's owner.
25
- # since class variable is assigned after class is created , __set_name__ must be called directly
35
+ # plum uses __set_name__ to resolve a plum. Function's owner.
36
+ # since we assign after class creation , __set_name__ must be called directly
26
37
# source: https://docs.python.org/3/reference/datamodel.html#object.__set_name__
27
38
pf .__set_name__ (cls ,n )
28
39
return pf
@@ -33,22 +44,28 @@ def _mk_plum_func(d, n, f=None, cls=None):
33
44
def _is_tfm_method (f ,n ):
34
45
return n in _tfm_methods and callable (f )
35
46
47
+ # TODO: Do we still need this given the fact that plum searches mro without needing them to be Functions?
36
48
class _TfmDict (dict ):
37
49
def __setitem__ (self ,k ,v ):
38
50
if _is_tfm_method (v ,k ): v = dispatch (v )
39
51
super ().__setitem__ (k ,v )
40
52
41
53
# Cell
42
54
class _TfmMeta (type ):
43
- def __new__ (cls , name , bases , dict ):
44
- res = super ().__new__ (cls , name , bases , dict )
45
- res .__signature__ = inspect .signature (res .__init__ )
46
- return res
47
-
55
+ # TODO: commenting since this breaks inspect.signature of Transform instances,
56
+ # which then breaks inspect.signature of a partial of a Transform instance
57
+ #def __new__(cls, name, bases, dict):
58
+ # res = super().__new__(cls, name, bases, dict)
59
+ # res.__signature__ = inspect.signature(res.__init__)
60
+ # return res
61
+
62
+ # TODO: Can we move this to Transform.__init__? Then we don't reeeeeally need a metaclass anymore...?
63
+ # Ohhhhh man, can we dispatch this? If called with callable, do this, and so on
48
64
def __call__ (cls , * args , ** kwargs ):
49
65
f = first (args )
50
66
n = getattr (f ,'__name__' ,None )
51
67
if _is_tfm_method (f ,n ):
68
+ # use __dict__ over hasattr since it excludes parent classes
52
69
if n in cls .__dict__ : return getattr (cls ,n ).dispatch (f )
53
70
return _mk_plum_func (dispatch ,n ,f ,cls )
54
71
return super ().__call__ (* args ,** kwargs )
@@ -76,6 +93,8 @@ def __init__(self, enc=None, dec=None, split_idx=None, order=None):
76
93
if not self .init_enc : return
77
94
78
95
self ._d = Dispatcher () # TODO: do we need to hold this reference?
96
+ # TODO: do u have to set the name from the original func here? for pipelines to work
97
+ # TODO: I don't think this is registering any methods! Why is a func needed then???
79
98
for n in _tfm_methods : setattr (self ,n ,_mk_plum_func (self ._d ,n ))
80
99
if enc :
81
100
self .encodes .dispatch (enc )
@@ -88,7 +107,18 @@ def __init__(self, enc=None, dec=None, split_idx=None, order=None):
88
107
def name (self ): return getattr (self , '_name' , _get_name (self ))
89
108
def __call__ (self , x , ** kwargs ): return self ._call ('encodes' , x , ** kwargs )
90
109
def decode (self , x , ** kwargs ): return self ._call ('decodes' , x , ** kwargs )
91
- def __repr__ (self ): return f'{ self .name } :\n encodes: { self .encodes } decodes: { self .decodes } '
110
+ def __repr__ (self ):
111
+ def _pf_repr (pf ):
112
+ e = []
113
+ for s , (f_ , r ) in self .encodes .methods .items ():
114
+ types = ',' .join (str (o ) for o in s .types )
115
+ types = f'({ types } )'
116
+ e .append (f'{ f_ .__name__ } : { types } -> { r } ' )
117
+ return e
118
+ r = f'{ self .name } :'
119
+ r += '\n encodes:\n ' + '\n ' .join (' ' + o for o in _pf_repr (self .encodes ))
120
+ r += '\n decodes:\n ' + '\n ' .join (' ' + o for o in _pf_repr (self .decodes ))
121
+ return r
92
122
93
123
def setup (self , items = None , train_setup = False ):
94
124
train_setup = train_setup if self .train_setup is None else self .train_setup
0 commit comments