Skip to content

Commit 80dd203

Browse files
committed
fixes #144
1 parent 746b8eb commit 80dd203

File tree

3 files changed

+44
-16
lines changed

3 files changed

+44
-16
lines changed

fastcore/_nbdev.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@
151151
"threaded": "02_utils.ipynb",
152152
"type_hints": "03_dispatch.ipynb",
153153
"anno_ret": "03_dispatch.ipynb",
154+
"lenient_issubclass": "03_dispatch.ipynb",
154155
"sorted_topologically": "03_dispatch.ipynb",
155156
"TypeDispatch": "03_dispatch.ipynb",
156157
"DispatchReg": "03_dispatch.ipynb",

fastcore/dispatch.py

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

3-
__all__ = ['type_hints', 'anno_ret', 'sorted_topologically', 'TypeDispatch', 'DispatchReg', 'typedispatch', 'cast',
4-
'retain_meta', 'default_set_meta', 'retain_type', 'retain_types', 'explode_types']
3+
__all__ = ['type_hints', 'anno_ret', 'lenient_issubclass', 'sorted_topologically', 'TypeDispatch', 'DispatchReg',
4+
'typedispatch', 'cast', 'retain_meta', 'default_set_meta', 'retain_type', 'retain_types', 'explode_types']
55

66
# Cell
77
from .imports import *
@@ -23,8 +23,9 @@ def anno_ret(func):
2323
return ann.get('return')
2424

2525
# Cell
26-
def _lenient_issubclass(cls, types):
26+
def lenient_issubclass(cls, types):
2727
"If possible return whether `cls` is a subclass of `types`, otherwise return False."
28+
if cls is object and types is type: return False # treat `object` as higher level than `type`
2829
try: return isinstance(cls, types) or issubclass(cls, types)
2930
except: return False
3031

@@ -61,7 +62,7 @@ class _TypeDict:
6162
def __init__(self): self.d,self.cache = {},{}
6263

6364
def _reset(self):
64-
self.d = {k:self.d[k] for k in sorted_topologically(self.d, cmp=_lenient_issubclass)}
65+
self.d = {k:self.d[k] for k in sorted_topologically(self.d, cmp=lenient_issubclass)}
6566
self.cache = {}
6667

6768
def add(self, t, f):
@@ -73,7 +74,7 @@ def add(self, t, f):
7374
def all_matches(self, k):
7475
"Find first matching type that is a super-class of `k`"
7576
if k not in self.cache:
76-
types = [f for f in self.d if k==f or (isinstance(k,type) and issubclass(k,f))]
77+
types = [f for f in self.d if lenient_issubclass(k,f)]
7778
self.cache[k] = [self.d[o] for o in types]
7879
return self.cache[k]
7980

nbs/03_dispatch.ipynb

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,9 @@
201201
"outputs": [],
202202
"source": [
203203
"#export\n",
204-
"def _lenient_issubclass(cls, types):\n",
204+
"def lenient_issubclass(cls, types):\n",
205205
" \"If possible return whether `cls` is a subclass of `types`, otherwise return False.\"\n",
206+
" if cls is object and types is type: return False # treat `object` as higher level than `type`\n",
206207
" try: return isinstance(cls, types) or issubclass(cls, types)\n",
207208
" except: return False"
208209
]
@@ -213,7 +214,7 @@
213214
"metadata": {},
214215
"outputs": [],
215216
"source": [
216-
"# depict the need for _lenient_issubclass:\n",
217+
"# depict the need for lenient_issubclass:\n",
217218
"t = lambda: issubclass(typing.Collection, object)\n",
218219
"test_fail(t, contains='issubclass() arg 1 must be a class')"
219220
]
@@ -224,11 +225,11 @@
224225
"metadata": {},
225226
"outputs": [],
226227
"source": [
227-
"assert not _lenient_issubclass(typing.Collection, list)\n",
228-
"assert _lenient_issubclass(list, typing.Collection)\n",
229-
"assert _lenient_issubclass(typing.Collection, object)\n",
230-
"assert _lenient_issubclass(typing.List, typing.Collection)\n",
231-
"assert not _lenient_issubclass(typing.Collection, typing.List)"
228+
"assert not lenient_issubclass(typing.Collection, list)\n",
229+
"assert lenient_issubclass(list, typing.Collection)\n",
230+
"assert lenient_issubclass(typing.Collection, object)\n",
231+
"assert lenient_issubclass(typing.List, typing.Collection)\n",
232+
"assert not lenient_issubclass(typing.Collection, typing.List)"
232233
]
233234
},
234235
{
@@ -265,7 +266,7 @@
265266
"outputs": [],
266267
"source": [
267268
"td = {int:1, numbers.Number:2, numbers.Integral:3}\n",
268-
"test_eq(sorted_topologically(td, cmp=_lenient_issubclass), [int, numbers.Integral, numbers.Number])"
269+
"test_eq(sorted_topologically(td, cmp=lenient_issubclass), [int, numbers.Integral, numbers.Number])"
269270
]
270271
},
271272
{
@@ -275,7 +276,7 @@
275276
"outputs": [],
276277
"source": [
277278
"td = [numbers.Integral, tuple, list, int, dict]\n",
278-
"td = sorted_topologically(td, cmp=_lenient_issubclass)\n",
279+
"td = sorted_topologically(td, cmp=lenient_issubclass)\n",
279280
"assert td.index(int) < td.index(numbers.Integral)"
280281
]
281282
},
@@ -406,7 +407,7 @@
406407
" def __init__(self): self.d,self.cache = {},{}\n",
407408
"\n",
408409
" def _reset(self):\n",
409-
" self.d = {k:self.d[k] for k in sorted_topologically(self.d, cmp=_lenient_issubclass)}\n",
410+
" self.d = {k:self.d[k] for k in sorted_topologically(self.d, cmp=lenient_issubclass)}\n",
410411
" self.cache = {}\n",
411412
"\n",
412413
" def add(self, t, f):\n",
@@ -418,7 +419,7 @@
418419
" def all_matches(self, k):\n",
419420
" \"Find first matching type that is a super-class of `k`\"\n",
420421
" if k not in self.cache:\n",
421-
" types = [f for f in self.d if k==f or (isinstance(k,type) and issubclass(k,f))]\n",
422+
" types = [f for f in self.d if lenient_issubclass(k,f)]\n",
422423
" self.cache[k] = [self.d[o] for o in types]\n",
423424
" return self.cache[k]\n",
424425
"\n",
@@ -502,6 +503,31 @@
502503
" returns_none=\"Returns `None` if return type annotation is `None` or `NoneType`.\")"
503504
]
504505
},
506+
{
507+
"cell_type": "code",
508+
"execution_count": null,
509+
"metadata": {},
510+
"outputs": [
511+
{
512+
"data": {
513+
"text/plain": [
514+
"<function __main__.a(z: type)>"
515+
]
516+
},
517+
"execution_count": null,
518+
"metadata": {},
519+
"output_type": "execute_result"
520+
}
521+
],
522+
"source": [
523+
"def a(z:type): return 'a'\n",
524+
"def b(z:object): return 'b'\n",
525+
"\n",
526+
"t = TypeDispatch([a,b])\n",
527+
"\n",
528+
"t[TypeDispatch]"
529+
]
530+
},
505531
{
506532
"cell_type": "markdown",
507533
"metadata": {},

0 commit comments

Comments
 (0)