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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
# Copyright 2007 Nanorex, Inc. See LICENSE file for details.
"""
command_registry.py
$Id$
register the types & commands [stub]
"""
from exprs.instance_helpers import InstanceOrExpr
###e THIS WILL BE REFACTORED before it is ever used, probably into a plain old dict, fully global for now, for the app object later,
# (later to be replaced by a kind of dict that can track its changes)
# plus per-module funcs to add things to that dict (modifying their source info as needed)
# plus code to extract useful summaries from it, eventually used to make demo_ui toolbars,
# but first just used to make a command menu of some sort.
# (Initially, we might deepcopy the dict into _app in order to notice when the whole thing changes,
# like we do with redraw_counter.)
#e can't we just make a tree of exprs which do things like union some dicts and modify nicknames for uniqueness?
# then each module just sets the value of its own dict of names...
# and a recompute rule figures out what that means for the toplevel summary...
# ==
# but for now, here's the code we have for this, imported & partly called but not yet usefully used.
# do dir() and globals() correspond?? yes, both 1244.
## print "len dir() = %d, len(globals()) = %d" % (len(dir()), len(globals()))
# ==
class CommandRegistry: #e rename?
def __init__(self):
self.class_for_name = {}
#e that should also register this registry with a more global one!
def register(self, name, val, warn_if_not_registerable = True ):
"#doc ... by default, warn if val is not registerable due to lacking some required decls"
# figure out the kind of class val is, by its decls, and register as appropriate
# print "nim: register %s = %r" % (name, val) # this gets called for what's expected, e.g. CommandWithItsOwnEditMode
# now record the interesting decls which let something know what to do with the class
motopic = getattr(val, '_e_model_object_topic', None)
###WRONG: only do following if we decide val is registerable
self.class_for_name[name] = val # stub [btw should we be a UserDict? that depends -- are we dictlike in any sensible way?]
pass #stub
def command_for_toolname(self, toolname): #e rename to say "main"?
assert 0 # nim # not possible, for subtools... might work for main tools. not sure!
def subtools_for_command(self, command): #e rename command -> main_command? (in method, not arg)
assert 0 # nim
# for subtools, the alg needs to be, figure out the set you want, get their nicknames, disambiguate or discard dups...
# return a name list and name->cmd mapping, but the mapping is not determined just from self
# even given the set of cmds in it or set of names in it, so no method can do what this one says (except for fullnames).
pass
def auto_register( namespace, registry = None, modulename = None): ###e this function needs a more explicit name
"""###doc this better -- it's correct and complete, but very unclear:
Register with registry (or with a global registry, if registry arg is not provided)
every public name/value pair in namespace (typically, globals() for the calling module)
whose value is a registerable class which (according to standard attrs such as __module__)
says it was defined in a module with the given (dotted) modulename (namespace['__name__'] by default).
This means that passing globals() of some module works as a way of providing that module's name.
(The precise comparison, for val being worth considering, is val.__module__ == modulename.)
(A public name is a name that doesn't start with '_'.)
(A registerable class is one of a set of certain kinds of subclass of InstanceOrExpr (basically, ones which
define any of several known interfaces for self-registration) -- see code comments for details.)
"""
#e permit namespace to be a list of names instead? but how would they be looked up? add another arg for the names?
if modulename is None:
# assume namespace is globals() of a module
modulename = namespace['__name__']
# print "auto_register, modulename = %r" % (modulename,)
if registry is None:
registry = find_or_make_global_command_registry()
for name in namespace.keys():
if not name.startswith('_'):
wantit = False # set to True if name names a registratable class defined in the namespace (not just imported into it)
try:
val = 'bug' # for error message, in case of exception
val = namespace[name] # should not fail
if issubclass(val, InstanceOrExpr) and val.__module__ == modulename: # often fails for various reasons
wantit = True
except:
if 'Polyline' in name:
raise ####### show silly bugs like not importing InstanceOrExpr
pass # note: this will happen a lot (since issubclass raises an exception for a non-class val)
if wantit:
registry.register(name, val, warn_if_not_registerable = False )
else:
if 'Polyline' in name:
print "not registering %r = %r" % (name,val,) #####
pass
continue
return
# ==
def find_or_make_global_command_registry( remake = False ):
"""[with remake = True: to be called once per session, or per reload of exprs module; with it False - call as needed to find it]
###doc
"""
# it doesn't really matter where we store __main__._exprs__registry --
# a global in this module might make more sense, if reload issues are ok ... #k
import __main__
if remake:
__main__._exprs__registry = None
del __main__._exprs__registry
try:
return __main__._exprs__registry
except AttributeError:
__main__._exprs__registry = CommandRegistry()
return __main__._exprs__registry
pass
# end
|