1 # Copyright (c) 2004-2006 The Regents of The University of Michigan
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met: redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer;
8 # redistributions in binary form must reproduce the above copyright
9 # notice, this list of conditions and the following disclaimer in the
10 # documentation and/or other materials provided with the distribution;
11 # neither the name of the copyright holders nor the names of its
12 # contributors may be used to endorse or promote products derived from
13 # this software without specific prior written permission.
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 # Authors: Steve Reinhardt
30 #####################################################################
32 # Proxy object support.
34 #####################################################################
38 class BaseProxy(object):
39 def __init__(self
, search_self
, search_up
):
40 self
._search
_self
= search_self
41 self
._search
_up
= search_up
42 self
._multiplier
= None
45 if self
._search
_self
and not self
._search
_up
:
47 elif not self
._search
_self
and self
._search
_up
:
51 return s
+ '.' + self
.path()
53 def __setattr__(self
, attr
, value
):
54 if not attr
.startswith('_'):
55 raise AttributeError, \
56 "cannot set attribute '%s' on proxy object" % attr
57 super(BaseProxy
, self
).__setattr
__(attr
, value
)
59 # support multiplying proxies by constants
60 def __mul__(self
, other
):
61 if not isinstance(other
, (int, long, float)):
62 raise TypeError, "Proxy multiplier must be integer"
63 if self
._multiplier
== None:
64 self
._multiplier
= other
66 # support chained multipliers
67 self
._multiplier
*= other
72 def _mulcheck(self
, result
):
73 if self
._multiplier
== None:
75 return result
* self
._multiplier
77 def unproxy(self
, base
):
82 result
, done
= self
.find(obj
)
89 result
, done
= self
.find(obj
)
92 raise AttributeError, \
93 "Can't resolve proxy '%s' of type '%s' from '%s'" % \
94 (self
.path(), self
._pdesc
.ptype_str
, base
.path())
96 if isinstance(result
, BaseProxy
):
98 raise RuntimeError, "Cycle in unproxy"
99 result
= result
.unproxy(obj
)
101 return self
._mulcheck
(result
)
103 def getindex(obj
, index
):
111 # if index is 0 and item is not subscriptable, just
112 # use item itself (so cpu[0] works on uniprocessors)
114 getindex
= staticmethod(getindex
)
116 # This method should be called once the proxy is assigned to a
117 # particular parameter or port to set the expected type of the
119 def set_param_desc(self
, pdesc
):
122 class AttrProxy(BaseProxy
):
123 def __init__(self
, search_self
, search_up
, attr
):
124 super(AttrProxy
, self
).__init
__(search_self
, search_up
)
128 def __getattr__(self
, attr
):
129 # python uses __bases__ internally for inheritance
130 if attr
.startswith('_'):
131 return super(AttrProxy
, self
).__getattr
__(self
, attr
)
132 if hasattr(self
, '_pdesc'):
133 raise AttributeError, "Attribute reference on bound proxy"
134 # Return a copy of self rather than modifying self in place
135 # since self could be an indirect reference via a variable or
137 new_self
= copy
.deepcopy(self
)
138 new_self
._modifiers
.append(attr
)
141 # support indexing on proxies (e.g., Self.cpu[0])
142 def __getitem__(self
, key
):
143 if not isinstance(key
, int):
144 raise TypeError, "Proxy object requires integer index"
145 if hasattr(self
, '_pdesc'):
146 raise AttributeError, "Index operation on bound proxy"
147 new_self
= copy
.deepcopy(self
)
148 new_self
._modifiers
.append(key
)
153 val
= getattr(obj
, self
._attr
)
157 val
= val
.unproxy(obj
)
158 for m
in self
._modifiers
:
159 if isinstance(m
, str):
160 val
= getattr(val
, m
)
161 elif isinstance(m
, int):
164 assert("Item must be string or integer")
166 val
= val
.unproxy(obj
)
171 for m
in self
._modifiers
:
172 if isinstance(m
, str):
174 elif isinstance(m
, int):
177 assert("Item must be string or integer")
180 class AnyProxy(BaseProxy
):
182 return obj
.find_any(self
._pdesc
.ptype
)
188 if isinstance(obj
, (BaseProxy
, params
.EthernetAddr
)):
190 elif isinstance(obj
, (list, tuple)):
196 class ProxyFactory(object):
197 def __init__(self
, search_self
, search_up
):
198 self
.search_self
= search_self
199 self
.search_up
= search_up
201 def __getattr__(self
, attr
):
203 return AnyProxy(self
.search_self
, self
.search_up
)
205 return AttrProxy(self
.search_self
, self
.search_up
, attr
)
207 # global objects for handling proxies
208 Parent
= ProxyFactory(search_self
= False, search_up
= True)
209 Self
= ProxyFactory(search_self
= True, search_up
= False)
211 # limit exports on 'from proxy import *'
212 __all__
= ['Parent', 'Self']
214 # see comment on imports at end of __init__.py.
215 import params
# for EthernetAddr