summaryrefslogtreecommitdiff
path: root/cad/src/exprs/command_registry.py
blob: 4de9def39d124bd6779f1a90a451ce1c3c3a6241 (plain)
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