-
Notifications
You must be signed in to change notification settings - Fork 0
/
forward_resolver.py
65 lines (59 loc) · 2.34 KB
/
forward_resolver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#sdobrev 2006
'''forward-declared module.attr resolver.
common between static_type and plainwrap resolvers.
a klas has declarations of references (reftypes), and each of those
has a klas to refer to - or name of it when forward decl.
resolve() walks a namespace, for each klas under control,
for each of its reftypes, resolve it if forward declared,
looking in namespace or in klas.__module__ or extra namespaces.
resolve1() resolves a forward declared reftypes,
looking in namespace or in klas.__module__ or extra namespaces.
'''
from attr import issubclass
import sys
class Resolver( object):
def finisher( me, typ, resolved_klas):
pass
def is_forward_decl( me, typ):
raise NotImplementedError
return name-to-be-resolved or None
def klas_reftype_iterator( me, klas):
raise NotImplementedError
yield only-reference-types
dbgpfx = ''
def resolve( me, namespace,
base_klas,
exclude =(),
debug =False,
*namespaces
):
for klas in namespace.itervalues():
if not issubclass( klas, base_klas): continue
if klas in exclude: continue
modnamespace = sys.modules[ klas.__module__].__dict__
for typ in me.klas_reftype_iterator( klas):
name = me.is_forward_decl( typ)
if name:
who = me._resolve1( name, typ,
namespace, modnamespace, *namespaces,
**dict( debug=debug))
if debug: print me.dbgpfx+'resolve', klas, typ
assert issubclass( who, base_klas)
def resolve1( me, typ, *namespaces, **kargs):
name = me.is_forward_decl( typ)
return me._resolve1( name, typ, *namespaces, **kargs)
def _resolve1( me, name, typ, *namespaces, **kargs):
debug =kargs.get( 'debug', False)
assert name
if '.' in name:
if debug: print me.dbgpfx, 'resolve: ignoring module in', name
mod,name = name.rsplit('.',1)
for namespace in namespaces:
if name in namespace:
who = namespace[ name]
break
else:
raise KeyError, '%(typ)s: cant resolve %(name)s' % locals()
me.finisher( typ, who)
return who
# vim:ts=4:sw=4:expandtab