~divmod-dev/divmod.org/no-addperson-2190

« back to all changes in this revision

Viewing changes to Imaginary/imagination/simdata.py

  • Committer: exarkun
  • Date: 2006-02-26 02:37:39 UTC
  • Revision ID: svn-v4:866e43f7-fbfc-0310-8f2a-ec88d1da2979:trunk:4991
Merge move-pottery-to-trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- test-case-name: imagination.test -*-
 
2
import os, types
 
3
 
 
4
from twisted.python import  reflect, log, util as tputil
 
5
from imagination.facets import Faceted
 
6
 
 
7
__metaclass__ = type
 
8
 
 
9
 
 
10
def lazy(adapter, kw):
 
11
    def doLazyAdapt(original):
 
12
        return adapter(original, **kw)
 
13
    return doLazyAdapt
 
14
 
 
15
 
 
16
def lazyApply(interface, methodName, args, kw):
 
17
    def doLazyApply(original):
 
18
        component = interface(original)
 
19
        return getattr(component, methodName)(*args, **kw)
 
20
    return doLazyApply
 
21
 
 
22
 
 
23
class ThingTemplate:
 
24
    """
 
25
    A facilitate creation of templates. Do something like this.
 
26
 
 
27
    SomeThing = thingTemplateInstance[
 
28
        IFoo: iFooAdapterFactory,
 
29
        (IBar, IBaz): wrc(iMultiFactory, arg1, arg2),
 
30
        ]
 
31
    # 'template' will then be a callable object
 
32
    someThing = SomeThing()
 
33
    IFoo(someThing) -> iFooAdapter
 
34
    """
 
35
 
 
36
    ObjectFactory = Faceted
 
37
 
 
38
    def __init__(self, templateList=None, templateMap=None, order=None):
 
39
        """Create a new template.
 
40
 
 
41
        @param templateList: A list of two-tuples.  The first element
 
42
        of each two-tuple must be a tuple consisting of only Interface
 
43
        subclasses.  The second element of each two-tuple must be a
 
44
        one-argument callable which will be called with an object to
 
45
        be adapted and which will return a component implementing all
 
46
        of the Interfaces present in the first element of the
 
47
        two-tuple.
 
48
        """
 
49
        if templateMap is None:
 
50
            templateMap = {}
 
51
        self.templateMap = templateMap
 
52
        if order is None:
 
53
            order = []
 
54
        self.order = order
 
55
        if templateList:
 
56
            for (ifaces, adapter) in templateList:
 
57
                self.order.extend(ifaces)
 
58
                for iface in ifaces:
 
59
                    self.templateMap[iface] = (ifaces, adapter)
 
60
 
 
61
    def __getitem__(self, items):
 
62
        """Create a new ThingTemplate based on, but not identical to, this one.
 
63
        """
 
64
        map = self.templateMap.copy()
 
65
        order = self.order[:]
 
66
        if not isinstance(items, (list, tuple)):
 
67
            items = [items]
 
68
        for slice in items:
 
69
            ifaces = slice.start
 
70
            adapter = slice.stop
 
71
            if not isinstance(ifaces, (list, tuple)):
 
72
                ifaces = [ifaces]
 
73
            for iface in ifaces:
 
74
                if iface in map:
 
75
                    previousGroup = map[iface][0]
 
76
                    for prevIface in previousGroup:
 
77
                        if prevIface not in ifaces:
 
78
                            raise ValueError(
 
79
                                "Interfaces in a group must be changed "
 
80
                                "all at once or not at all: %s not in %s"
 
81
                                % (prevIface, ifaces))
 
82
                else:
 
83
                    order.append(iface)
 
84
                map[iface] = (ifaces, adapter)
 
85
        return ThingTemplate(templateMap=map, order=order)
 
86
 
 
87
    def fill(self, interfaces, **kw):
 
88
        if not isinstance(interfaces, (list, tuple)):
 
89
            interfaces = [interfaces]
 
90
        map = self.templateMap.copy()
 
91
        ifmap = {}
 
92
        for iface in interfaces:
 
93
            for identicalIface in map.get(iface, ((),))[0]:
 
94
                ifmap[identicalIface] = 1
 
95
        interfaces = ifmap.keys()
 
96
        order = self.order[:]
 
97
        for iface in interfaces:
 
98
            map[iface] = (map[iface][0], lazy(map[iface][1], kw))
 
99
        return ThingTemplate(templateMap=map, order=order)
 
100
 
 
101
    def apply(self, methodClass, methodName, *args, **kw):
 
102
        map = self.templateMap.copy()
 
103
        order = self.order[:]
 
104
        order.append(
 
105
            lazyApply(methodClass, methodName, args, kw))
 
106
        return ThingTemplate(templateMap=map, order=order)
 
107
 
 
108
    def copy(self):
 
109
        return self.__getitem__(())
 
110
 
 
111
    def new(self):
 
112
        """
 
113
        Instantiate the template.
 
114
        """
 
115
        o = self.ObjectFactory()
 
116
        skip = {}
 
117
        for iface in self.order:
 
118
            if isinstance(iface, types.FunctionType):
 
119
                ## Apply a lazy method invocation
 
120
                iface(o)
 
121
                continue
 
122
            if iface in skip:
 
123
                continue
 
124
            value = self.templateMap[iface]
 
125
            if isinstance(value, types.FunctionType):
 
126
                ## Apply a lazy component construction
 
127
                comp = value(o)
 
128
                ifaces = [iface]
 
129
            else:
 
130
                ifaces, adapter = value
 
131
                comp = adapter(o)
 
132
            for iface in ifaces:
 
133
                o[iface] = comp
 
134
                skip[iface] = None
 
135
        return o
 
136
 
 
137
try:
 
138
    baseTemplate
 
139
except NameError:
 
140
    baseTemplate = ThingTemplate()