Skip to content

Commit 67ac179

Browse files
deploy: c1cc529
0 parents  commit 67ac179

33 files changed

+13036
-0
lines changed

.nojekyll

Whitespace-only changes.
Loading
Loading

cast.html

Lines changed: 853 additions & 0 deletions
Large diffs are not rendered by default.

cast.html.md

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
# Cast
2+
3+
4+
<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->
5+
6+
``` python
7+
from __future__ import annotations
8+
from nbdev.showdoc import *
9+
from fastcore.test import *
10+
from fastcore.nb_imports import *
11+
```
12+
13+
This module contains some of `fastcore.dispatch`’s utility functions for
14+
type casting. We copy them over here as with `fasttransform`’s release
15+
those modules may be removed from fastcore.
16+
17+
The functions here have not been changed, except for
18+
[`retain_type`](https://AnswerDotAI.github.io/fasttransform/cast.html#retain_type),
19+
which has the same functionality but now accepts the type hints as Plum
20+
dispatch provides them instead of `fastcore.dispatch`’s convention.
21+
22+
## Type casting
23+
24+
Some objects may have a `set_meta` method, such as
25+
[`fastai.torch_core.Tensor`](https://docs.fast.ai/torch_core.html#tensor.set_meta).
26+
When casting these to another type we want to preserve metadata.
27+
28+
------------------------------------------------------------------------
29+
30+
<a
31+
href="https://github.com/AnswerDotAI/fasttransform/blob/main/fasttransform/cast.py#L19"
32+
target="_blank" style="float:right; font-size:smaller">source</a>
33+
34+
### retain_meta
35+
36+
> retain_meta (x, res, as_copy=False)
37+
38+
*Call `res.set_meta(x)`, if it exists*
39+
40+
------------------------------------------------------------------------
41+
42+
<a
43+
href="https://github.com/AnswerDotAI/fasttransform/blob/main/fasttransform/cast.py#L26"
44+
target="_blank" style="float:right; font-size:smaller">source</a>
45+
46+
### default_set_meta
47+
48+
> default_set_meta (x, as_copy=False)
49+
50+
*Copy over `_meta` from `x` to `res`, if it’s missing*
51+
52+
------------------------------------------------------------------------
53+
54+
<a
55+
href="https://github.com/AnswerDotAI/fasttransform/blob/main/fasttransform/cast.py#L36"
56+
target="_blank" style="float:right; font-size:smaller">source</a>
57+
58+
### cast
59+
60+
> cast (x, typ)
61+
62+
*cast `x` to type `typ` (may also change `x` inplace)*
63+
64+
This works both for plain python classes…
65+
66+
``` python
67+
mk_class('_T1', 'a') # mk_class is a fastai utility that constructs a class.
68+
class _T2(_T1): pass
69+
70+
t = _T1(a=1)
71+
t2 = cast(t, _T2)
72+
assert t2 is t # t2 refers to the same object as t
73+
assert isinstance(t, _T2) # t also changed in-place
74+
assert isinstance(t2, _T2)
75+
76+
test_eq_type(_T2(a=1), t2)
77+
```
78+
79+
…as well as for arrays and tensors.
80+
81+
``` python
82+
class _T1(ndarray): pass
83+
84+
t = array([1])
85+
t2 = cast(t, _T1)
86+
test_eq(array([1]), t2)
87+
test_eq(_T1, type(t2))
88+
```
89+
90+
## Retain type
91+
92+
Retain type is a function that’s useful for postprocessing function
93+
outputs. They are used in the
94+
[`Transform`](https://AnswerDotAI.github.io/fasttransform/transform.html#transform)
95+
class.
96+
97+
The conversion priorities are as follows:
98+
99+
1. the function’s return type annotation `ret_type`
100+
2. if there’s no return type annotation (i.e. `ret_type=Any`) then it
101+
will convert back to the input’s (`old`) type, but only if if it was
102+
a subtype of the return value.
103+
3. if the function has return type annotation of None (`ret_type=None`)
104+
then no conversion will be done.
105+
106+
------------------------------------------------------------------------
107+
108+
<a
109+
href="https://github.com/AnswerDotAI/fasttransform/blob/main/fasttransform/cast.py#L47"
110+
target="_blank" style="float:right; font-size:smaller">source</a>
111+
112+
### retain_type
113+
114+
> retain_type (new, old, ret_type=typing.Any, as_copy=False)
115+
116+
*Cast `new` to `ret_type` if given, or `old`’s type if `new` is a
117+
superclass of `old`. No conversion is done if `ret_type=None`*
118+
119+
### Return type annotation conversion
120+
121+
We try and convert new to the return type if it’s given.
122+
123+
``` python
124+
class FS(float):
125+
def __repr__(self): return f'FS({float(self)})'
126+
```
127+
128+
``` python
129+
test_eq(retain_type(1., 2., FS), FS(1.))
130+
```
131+
132+
Even if it won’t work, we’ll let the exception be raised:
133+
134+
``` python
135+
# Raise error if return type is not compatible with new
136+
try: retain_type("a", 2., FS)
137+
except ValueError as e: print(f"Expected error: {e}")
138+
```
139+
140+
Expected error: could not convert string to float: 'a'
141+
142+
### Old type conversion
143+
144+
If the return type is `Any` then new looks at old for conversion
145+
guidance.
146+
147+
``` python
148+
test_eq(retain_type(1., FS(2.), Any), FS(1.))
149+
```
150+
151+
But if new isn’t subclass of old, keep new:
152+
153+
``` python
154+
test_eq(retain_type(FS(1.), 2.0, Any), FS(1.))
155+
test_eq(retain_type("a", 2.0, Any), "a")
156+
```
157+
158+
No casting needed if new is already of type old. Then we return the
159+
original object.
160+
161+
``` python
162+
x = FS(1.)
163+
test_is(retain_type(x, FS(2.), Any), x)
164+
```
165+
166+
### Edge cases with None
167+
168+
We dont convert at all if None is return type annotation:
169+
170+
``` python
171+
test_eq(retain_type(1., FS(2.), NoneType), 1.)
172+
```
173+
174+
None stays None:
175+
176+
``` python
177+
test_eq(retain_type(None,FS(2.), Any), None)
178+
```
179+
180+
If old was None then we just return new.
181+
182+
``` python
183+
test_eq(retain_type(FS(1.), None, Any), FS(1.))
184+
```
185+
186+
### Metadata retention
187+
188+
If old has a \_meta attribute, its content is passed when casting new to
189+
the type of old. In the below example, only the attribute a, but not
190+
other_attr is kept, because other_attr is not in \_meta:
191+
192+
``` python
193+
class _A():
194+
set_meta = default_set_meta
195+
def __init__(self, t): self.t=t
196+
197+
class _B1(_A):
198+
def __init__(self, t, a=1):
199+
super().__init__(t)
200+
self._meta = {'a':a}
201+
self.other_attr = 'Hello' # will not be kept after casting.
202+
203+
x = _B1(1, a=2)
204+
b = _A(1)
205+
c = retain_type(b, old=x)
206+
test_eq(c._meta, {'a': 2})
207+
assert not getattr(c, 'other_attr', None)
208+
```
209+
210+
## Retain types
211+
212+
Cast each item of `new` to type of matching item in `old` if it’s a
213+
superclass.
214+
215+
------------------------------------------------------------------------
216+
217+
<a
218+
href="https://github.com/AnswerDotAI/fasttransform/blob/main/fasttransform/cast.py#L58"
219+
target="_blank" style="float:right; font-size:smaller">source</a>
220+
221+
### retain_types
222+
223+
> retain_types (new, old=None, typs=None)
224+
225+
*Cast each item of `new` to type of matching item in `old` if it’s a
226+
superclass*
227+
228+
``` python
229+
class T(tuple): pass
230+
231+
t1,t2 = retain_types((1,(1,(1,1))), (2,T((2,T((3,4))))))
232+
test_eq_type(t1, 1)
233+
test_eq_type(t2, T((1,T((1,1)))))
234+
235+
t1,t2 = retain_types((1,(1,(1,1))), typs = {tuple: [int, {T: [int, {T: [int,int]}]}]})
236+
test_eq_type(t1, 1)
237+
test_eq_type(t2, T((1,T((1,1)))))
238+
```
239+
240+
------------------------------------------------------------------------
241+
242+
<a
243+
href="https://github.com/AnswerDotAI/fasttransform/blob/main/fasttransform/cast.py#L73"
244+
target="_blank" style="float:right; font-size:smaller">source</a>
245+
246+
### explode_types
247+
248+
> explode_types (o)
249+
250+
*Return the type of `o`, potentially in nested dictionaries for thing
251+
that are listy*
252+
253+
``` python
254+
test_eq(explode_types((2,T((2,T((3,4)))))), {tuple: [int, {T: [int, {T: [int,int]}]}]})
255+
```

0 commit comments

Comments
 (0)