1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """
18 The I{service definition} provides a textual representation of a service.
19 """
20
21 from logging import getLogger
22 from suds import *
23 import suds.metrics as metrics
24 from suds.sax import Namespace
25
26 log = getLogger(__name__)
27
29 """
30 A service definition provides an object used to generate a textual description
31 of a service.
32 @ivar wsdl: A wsdl.
33 @type wsdl: L{wsdl.Definitions}
34 @ivar service: The service object.
35 @type service: L{suds.wsdl.Service}
36 @ivar ports: A list of port-tuple: (port, [(method-name, pdef)])
37 @type ports: [port-tuple,..]
38 @ivar prefixes: A list of remapped prefixes.
39 @type prefixes: [(prefix,uri),..]
40 @ivar types: A list of type definitions
41 @type types: [I{Type},..]
42 """
43
45 """
46 @param wsdl: A wsdl object
47 @type wsdl: L{Definitions}
48 @param service: A service B{name}.
49 @type service: str
50 """
51 self.wsdl = wsdl
52 self.service = service
53 self.ports = []
54 self.params = []
55 self.types = []
56 self.prefixes = []
57 self.addports()
58 self.paramtypes()
59 self.publictypes()
60 self.getprefixes()
61 self.pushprefixes()
62
64 """
65 Add our prefixes to the wsdl so that when users invoke methods
66 and reference the prefixes, the will resolve properly.
67 """
68 for ns in self.prefixes:
69 self.wsdl.root.addPrefix(ns[0], ns[1])
70
72 """
73 Look through the list of service ports and construct a list of tuples where
74 each tuple is used to describe a port and it's list of methods as:
75 (port, [method]). Each method is tuple: (name, [pdef,..] where each pdef is
76 a tuple: (param-name, type).
77 """
78 timer = metrics.Timer()
79 timer.start()
80 for port in self.service.ports:
81 p = self.findport(port)
82 for op in port.binding.operations.values():
83 m = p[0].method(op.name)
84 binding = m.binding.input
85 method = (m.name, binding.param_defs(m))
86 p[1].append(method)
87 metrics.log.debug("method '%s' created: %s", m.name, timer)
88 p[1].sort()
89 timer.stop()
90
92 """
93 Find and return a port tuple for the specified port.
94 Created and added when not found.
95 @param port: A port.
96 @type port: I{service.Port}
97 @return: A port tuple.
98 @rtype: (port, [method])
99 """
100 for p in self.ports:
101 if p[0] == p: return p
102 p = (port, [])
103 self.ports.append(p)
104 return p
105
107 """
108 Add prefixes foreach namespace referenced by parameter types.
109 """
110 namespaces = []
111 for l in (self.params, self.types):
112 for t,r in l:
113 ns = r.namespace()
114 if ns[1] is None: continue
115 if ns[1] in namespaces: continue
116 if Namespace.xs(ns) or Namespace.xsd(ns):
117 continue
118 namespaces.append(ns[1])
119 if t == r: continue
120 ns = t.namespace()
121 if ns[1] is None: continue
122 if ns[1] in namespaces: continue
123 namespaces.append(ns[1])
124 i = 0
125 namespaces.sort()
126 for u in namespaces:
127 p = self.nextprefix()
128 ns = (p, u)
129 self.prefixes.append(ns)
130
132 """ get all parameter types """
133 for m in [p[1] for p in self.ports]:
134 for p in [p[1] for p in m]:
135 for pd in p:
136 if pd[1] in self.params: continue
137 item = (pd[1], pd[1].resolve())
138 self.params.append(item)
139
141 """ get all public types """
142 for t in self.wsdl.schema.types.values():
143 if t in self.params: continue
144 if t in self.types: continue
145 item = (t, t)
146 self.types.append(item)
147 tc = lambda x,y: cmp(x[0].name, y[0].name)
148 self.types.sort(cmp=tc)
149
151 """
152 Get the next available prefix. This means a prefix starting with 'ns' with
153 a number appended as (ns0, ns1, ..) that is not already defined on the
154 wsdl document.
155 """
156 used = [ns[0] for ns in self.prefixes]
157 used += [ns[0] for ns in self.wsdl.root.nsprefixes.items()]
158 for n in range(0,1024):
159 p = 'ns%d'%n
160 if p not in used:
161 return p
162 raise Exception('prefixes exhausted')
163
165 """
166 Get the prefix for the specified namespace (uri)
167 @param u: A namespace uri.
168 @type u: str
169 @return: The namspace.
170 @rtype: (prefix, uri).
171 """
172 for ns in Namespace.all:
173 if u == ns[1]: return ns[0]
174 for ns in self.prefixes:
175 if u == ns[1]: return ns[0]
176 raise Exception('ns (%s) not mapped' % u)
177
179 """
180 Get a (namespace) translated I{qualified} name for specified type.
181 @param type: A schema type.
182 @type type: I{suds.xsd.sxbasic.SchemaObject}
183 @return: A translated I{qualified} name.
184 @rtype: str
185 """
186 resolved = type.resolve()
187 name = resolved.name
188 if type.unbounded():
189 name += '[]'
190 ns = resolved.namespace()
191 if ns[1] == self.wsdl.tns[1]:
192 return name
193 prefix = self.getprefix(ns[1])
194 return ':'.join((prefix, name))
195
239
241 return unicode(self).encode('utf-8')
242
244 try:
245 return self.description()
246 except Exception, e:
247 log.exception(e)
248 return tostr(e)
249