00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 import os, sys, warnings
00011 from ZSI import _get_idstr
00012 from ZSI.wstools.logging import getLogger as _GetLogger
00013 from ZSI.wstools import WSDLTools
00014 from ZSI.wstools.WSDLTools import SoapAddressBinding,\
00015 SoapBodyBinding, SoapBinding,MimeContentBinding,\
00016 HttpUrlEncodedBinding
00017 from ZSI.wstools.XMLSchema import SchemaReader, ElementDeclaration, SchemaError
00018 from ZSI.typeinterpreter import BaseTypeInterpreter
00019 from ZSI.generate import WsdlGeneratorError, Wsdl2PythonError
00020 from containers import *
00021 from ZSI.generate import utility
00022 from ZSI.generate.utility import NamespaceAliasDict as NAD
00023 from ZSI.generate.utility import GetModuleBaseNameFromWSDL
00024
00025 """
00026 classes:
00027 WriteServiceModule
00028 -- composes/writes out client stubs and types module.
00029
00030 ServiceDescription
00031 -- represents a single WSDL service.
00032
00033 MessageWriter
00034 -- represents a single WSDL Message and associated bindings
00035 of the port/binding.
00036
00037 SchemaDescription
00038 -- generates classes for defs and decs in the schema instance.
00039
00040 TypeWriter
00041 -- represents a type definition.
00042
00043 ElementWriter
00044 -- represents a element declaration.
00045
00046 """
00047
00048 class WriteServiceModule:
00049 """top level driver class invoked by wsd2py
00050 class variables:
00051 client_module_suffix -- suffix of client module.
00052 types_module_suffix -- suffix of types module.
00053 """
00054 client_module_suffix = '_client'
00055 messages_module_suffix = '_messages'
00056 types_module_suffix = '_types'
00057 logger = _GetLogger("WriteServiceModule")
00058
00059 def __init__(self, wsdl, addressing=False, notification=False,
00060 do_extended=False, extPyClasses=None, configParser = None):
00061 self._wsdl = wsdl
00062 self._addressing = addressing
00063 self._notification = notification
00064 self._configParser = configParser
00065 self.usedNamespaces = None
00066 self.services = []
00067 self.client_module_path = None
00068 self.types_module_name = None
00069 self.types_module_path = None
00070 self.messages_module_path = None
00071 self.do_extended = do_extended
00072 self.extPyClasses = extPyClasses
00073
00074 def getClientModuleName(self):
00075 """client module name.
00076 """
00077 name = GetModuleBaseNameFromWSDL(self._wsdl)
00078 if not name:
00079 raise WsdlGeneratorError, 'could not determine a service name'
00080
00081 if self.client_module_suffix is None:
00082 return name
00083
00084 return '%s%s' %(name, self.client_module_suffix)
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 def setTypesModuleName(self, name):
00100 self.types_module_name = name
00101
00102 def getTypesModuleName(self):
00103 """types module name.
00104 """
00105 if self.types_module_name is not None:
00106 return self.types_module_name
00107
00108 name = GetModuleBaseNameFromWSDL(self._wsdl)
00109 if not name:
00110 raise WsdlGeneratorError, 'could not determine a service name'
00111
00112 if self.types_module_suffix is None:
00113 return name
00114
00115 return '%s%s' %(name, self.types_module_suffix)
00116
00117 def setClientModulePath(self, path):
00118 """setup module path to where client module before calling fromWsdl.
00119 module path to types module eg. MyApp.client
00120 """
00121 self.client_module_path = path
00122
00123 def getTypesModulePath(self):
00124 """module path to types module eg. MyApp.types
00125 """
00126 return self.types_module_path
00127
00128
00129
00130
00131
00132
00133
00134 def setTypesModulePath(self, path):
00135 """setup module path to where service module before calling fromWsdl.
00136 module path to types module eg. MyApp.types
00137 """
00138 self.types_module_path = path
00139
00140
00141
00142
00143
00144
00145
00146 def gatherNamespaces(self):
00147 '''This method must execute once.. Grab all schemas
00148 representing each targetNamespace.
00149 '''
00150 if self.usedNamespaces is not None:
00151 return
00152
00153 self.logger.debug('gatherNamespaces')
00154 self.usedNamespaces = {}
00155
00156
00157
00158 for schema in self._wsdl.types.values():
00159 tns = schema.getTargetNamespace()
00160 self.logger.debug('Register schema(%s) -- TNS(%s)'\
00161 %(_get_idstr(schema), tns),)
00162 if self.usedNamespaces.has_key(tns) is False:
00163 self.usedNamespaces[tns] = []
00164 self.usedNamespaces[tns].append(schema)
00165 NAD.add(tns)
00166
00167
00168
00169 for k,v in SchemaReader.namespaceToSchema.items():
00170 self.logger.debug('Register schema(%s) -- TNS(%s)'\
00171 %(_get_idstr(v), k),)
00172 if self.usedNamespaces.has_key(k) is False:
00173 self.usedNamespaces[k] = []
00174 self.usedNamespaces[k].append(v)
00175 NAD.add(k)
00176
00177 def writeClient(self, fd, sdClass=None, **kw):
00178 """write out client module to file descriptor.
00179 Parameters and Keywords arguments:
00180 fd -- file descriptor
00181 sdClass -- service description class name
00182 imports -- list of imports
00183 readerclass -- class name of ParsedSoap reader
00184 writerclass -- class name of SoapWriter writer
00185 """
00186 sdClass = sdClass or ServiceDescription
00187 assert issubclass(sdClass, ServiceDescription), \
00188 'parameter sdClass must subclass ServiceDescription'
00189
00190
00191
00192 print >>fd, '#'*50
00193 print >>fd, '# file: %s.py' %self.getClientModuleName()
00194 print >>fd, '# '
00195 print >>fd, '# client stubs generated by "%s"' %self.__class__
00196 print >>fd, '# %s' %' '.join(sys.argv)
00197 print >>fd, '# '
00198 print >>fd, '#'*50
00199
00200 self.services = []
00201 for service in self._wsdl.services:
00202 sd = sdClass(self._addressing, do_extended=self.do_extended,
00203 wsdl=self._wsdl)
00204 if len(self._wsdl.types) > 0:
00205 sd.setTypesModuleName(self.getTypesModuleName(),
00206 self.getTypesModulePath())
00207
00208
00209
00210 self.gatherNamespaces()
00211 sd.fromWsdl(service, **kw)
00212 sd.write(fd)
00213 self.services.append(sd)
00214
00215 def writeTypes(self, fd):
00216 """write out types module to file descriptor.
00217 """
00218 print >>fd, '#'*50
00219 print >>fd, '# file: %s.py' %self.getTypesModuleName()
00220 print >>fd, '#'
00221 print >>fd, '# schema types generated by "%s"' %self.__class__
00222 print >>fd, '# %s' %' '.join(sys.argv)
00223 print >>fd, '#'
00224 print >>fd, '#'*50
00225
00226 print >>fd, TypesHeaderContainer()
00227 self.gatherNamespaces()
00228 for l in self.usedNamespaces.values():
00229 sd = SchemaDescription(do_extended=self.do_extended,
00230 extPyClasses=self.extPyClasses)
00231 for schema in l:
00232 sd.fromSchema(schema)
00233 sd.write(fd)
00234
00235
00236 class ServiceDescription:
00237 """client interface - locator, port, etc classes"""
00238 separate_messages = False
00239 logger = _GetLogger("ServiceDescription")
00240
00241 def __init__(self, addressing=False, do_extended=False, wsdl=None):
00242 self.typesModuleName = None
00243 self.messagesModuleName = None
00244 self.wsAddressing = addressing
00245 self.imports = ServiceHeaderContainer()
00246 self.messagesImports = ServiceHeaderContainer()
00247 self.locator = ServiceLocatorContainer()
00248 self.bindings = []
00249 self.messages = []
00250 self.do_extended=do_extended
00251 self._wsdl = wsdl
00252
00253 def setTypesModuleName(self, name, modulePath=None):
00254 """The types module to be imported.
00255 Parameters
00256 name -- name of types module
00257 modulePath -- optional path where module is located.
00258 """
00259 self.typesModuleName = '%s' %name
00260 if modulePath is not None:
00261 self.typesModuleName = '%s.%s' %(modulePath,name)
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 def fromWsdl(self, service, **kw):
00274 self.imports.setTypesModuleName(self.typesModuleName)
00275
00276
00277 self.imports.appendImport(kw.get('imports', []))
00278
00279 self.locator.setUp(service)
00280
00281 try:
00282 bindings = map(lambda p: p.binding, service.ports)
00283 except:
00284 warnings.warn('not all ports have binding declared,')
00285 bindings = ()
00286
00287 for port in service.ports:
00288 if port.binding not in bindings:
00289 continue
00290 while port.binding in bindings:
00291 bindings.remove(port.binding)
00292
00293 desc = BindingDescription(useWSA=self.wsAddressing,
00294 do_extended=self.do_extended,
00295 wsdl=self._wsdl)
00296 try:
00297 desc.setUp(port.getBinding())
00298 except Wsdl2PythonError, ex:
00299 self.logger.warning('Skipping port(%s)' %port.name)
00300 if len(ex.args):
00301 self.logger.warning(ex.args[0])
00302 continue
00303
00304 desc.setReaderClass(kw.get('readerclass'))
00305 desc.setWriterClass(kw.get('writerclass'))
00306 for soc in desc.operations:
00307 if soc.hasInput() is True:
00308 mw = MessageWriter(do_extended=self.do_extended)
00309 mw.setUp(soc, port, input=True)
00310 self.messages.append(mw)
00311
00312 if soc.hasOutput() is True:
00313 mw = MessageWriter(do_extended=self.do_extended)
00314 mw.setUp(soc, port, input=False)
00315 self.messages.append(mw)
00316
00317 self.bindings.append(desc)
00318
00319
00320 def write(self, fd, msg_fd=None):
00321 """write out module to file descriptor.
00322 fd -- file descriptor to write out service description.
00323 msg_fd -- optional file descriptor for messages module.
00324 """
00325
00326
00327
00328
00329 print >>fd, self.imports
00330
00331 print >>fd, self.locator
00332 for m in self.bindings:
00333 print >>fd, m
00334
00335
00336
00337
00338
00339 for m in self.messages:
00340 print >>fd, m
00341
00342
00343 class MessageWriter:
00344 logger = _GetLogger("MessageWriter")
00345
00346 def __init__(self, do_extended=False):
00347 """Representation of a WSDL Message and associated WSDL Binding.
00348 operation --
00349 boperation --
00350 input --
00351 rpc --
00352 literal --
00353 simple --
00354 """
00355 self.content = None
00356 self.do_extended = do_extended
00357
00358 def __str__(self):
00359 if not self.content:
00360 raise Wsdl2PythonError, 'Must call setUp.'
00361 return self.content.getvalue()
00362
00363 def setUp(self, soc, port, input=False):
00364 assert isinstance(soc, ServiceOperationContainer),\
00365 'expecting a ServiceOperationContainer instance'
00366 assert isinstance(port, WSDLTools.Port),\
00367 'expecting a WSDL.Port instance'
00368
00369 rpc,literal = soc.isRPC(), soc.isLiteral(input)
00370 kw,klass = {}, None
00371
00372 if rpc and literal:
00373 klass = ServiceRPCLiteralMessageContainer
00374 elif not rpc and literal:
00375 kw['do_extended'] = self.do_extended
00376 klass = ServiceDocumentLiteralMessageContainer
00377 elif rpc and not literal:
00378 klass = ServiceRPCEncodedMessageContainer
00379 else:
00380 raise WsdlGeneratorError, 'doc/enc not supported.'
00381
00382 self.content = klass(**kw)
00383 self.content.setUp(port, soc, input)
00384
00385
00386 class SchemaDescription:
00387 """generates classes for defs and decs in the schema instance.
00388 """
00389 logger = _GetLogger("SchemaDescription")
00390
00391 def __init__(self, do_extended=False, extPyClasses=None):
00392 self.classHead = NamespaceClassHeaderContainer()
00393 self.classFoot = NamespaceClassFooterContainer()
00394 self.items = []
00395 self.__types = []
00396 self.__elements = []
00397 self.targetNamespace = None
00398 self.do_extended=do_extended
00399 self.extPyClasses = extPyClasses
00400
00401 def fromSchema(self, schema):
00402 ''' Can be called multiple times, but will not redefine a
00403 previously defined type definition or element declaration.
00404 '''
00405 ns = schema.getTargetNamespace()
00406 assert self.targetNamespace is None or self.targetNamespace == ns,\
00407 'SchemaDescription instance represents %s, not %s'\
00408 %(self.targetNamespace, ns)
00409
00410 if self.targetNamespace is None:
00411 self.targetNamespace = ns
00412
00413 self.classHead.ns = self.classFoot.ns = ns
00414 for item in [t for t in schema.types if t.getAttributeName() not in self.__types]:
00415 self.__types.append(item.getAttributeName())
00416 self.items.append(TypeWriter(do_extended=self.do_extended, extPyClasses=self.extPyClasses))
00417 self.items[-1].fromSchemaItem(item)
00418
00419 for item in [e for e in schema.elements if e.getAttributeName() not in self.__elements]:
00420 self.__elements.append(item.getAttributeName())
00421 self.items.append(ElementWriter(do_extended=self.do_extended))
00422 self.items[-1].fromSchemaItem(item)
00423
00424 def getTypes(self):
00425 return self.__types
00426
00427 def getElements(self):
00428 return self.__elements
00429
00430 def write(self, fd):
00431 """write out to file descriptor.
00432 """
00433 print >>fd, self.classHead
00434 for t in self.items:
00435 print >>fd, t
00436 print >>fd, self.classFoot
00437
00438 class SchemaItemWriter:
00439 """contains/generates a single declaration"""
00440 logger = _GetLogger("SchemaItemWriter")
00441
00442 def __init__(self, do_extended=False, extPyClasses=None):
00443 self.content = None
00444 self.do_extended=do_extended
00445 self.extPyClasses=extPyClasses
00446
00447 def __str__(self):
00448 '''this appears to set up whatever is in self.content.localElements,
00449 local elements simpleType|complexType.
00450 '''
00451 assert self.content is not None, 'Must call fromSchemaItem to setup.'
00452 return str(self.content)
00453
00454 def fromSchemaItem(self, item):
00455 raise NotImplementedError, ''
00456
00457
00458 class ElementWriter(SchemaItemWriter):
00459 """contains/generates a single declaration"""
00460 logger = _GetLogger("ElementWriter")
00461
00462 def fromSchemaItem(self, item):
00463 """set up global elements.
00464 """
00465 if item.isElement() is False or item.isLocal() is True:
00466 raise TypeError, 'expecting global element declaration: %s' %item.getItemTrace()
00467
00468 local = False
00469 qName = item.getAttribute('type')
00470 if not qName:
00471 etp = item.content
00472 local = True
00473 else:
00474 etp = item.getTypeDefinition('type')
00475
00476 if etp is None:
00477 if local is True:
00478 self.content = ElementLocalComplexTypeContainer(do_extended=self.do_extended)
00479 else:
00480 self.content = ElementSimpleTypeContainer()
00481 elif etp.isLocal() is False:
00482 self.content = ElementGlobalDefContainer()
00483 elif etp.isSimple() is True:
00484 self.content = ElementLocalSimpleTypeContainer()
00485 elif etp.isComplex():
00486 self.content = ElementLocalComplexTypeContainer(do_extended=self.do_extended)
00487 else:
00488 raise Wsdl2PythonError, "Unknown element declaration: %s" %item.getItemTrace()
00489
00490 self.logger.debug('ElementWriter setUp container "%r", Schema Item "%s"' %(
00491 self.content, item.getItemTrace()))
00492
00493 self.content.setUp(item)
00494
00495
00496 class TypeWriter(SchemaItemWriter):
00497 """contains/generates a single definition"""
00498 logger = _GetLogger("TypeWriter")
00499
00500 def fromSchemaItem(self, item):
00501 if item.isDefinition() is False or item.isLocal() is True:
00502 raise TypeError, \
00503 'expecting global type definition not: %s' %item.getItemTrace()
00504
00505 self.content = None
00506 if item.isSimple():
00507 if item.content.isRestriction():
00508 self.content = RestrictionContainer()
00509 elif item.content.isUnion():
00510 self.content = UnionContainer()
00511 elif item.content.isList():
00512 self.content = ListContainer()
00513 else:
00514 raise Wsdl2PythonError,\
00515 'unknown simple type definition: %s' %item.getItemTrace()
00516
00517 self.content.setUp(item)
00518 return
00519
00520 if item.isComplex():
00521 kw = {}
00522 if item.content is None or item.content.isModelGroup():
00523 self.content = \
00524 ComplexTypeContainer(\
00525 do_extended=self.do_extended,
00526 extPyClasses=self.extPyClasses
00527 )
00528 kw['empty'] = item.content is None
00529 elif item.content.isSimple():
00530 self.content = ComplexTypeSimpleContentContainer()
00531 elif item.content.isComplex():
00532 self.content = \
00533 ComplexTypeComplexContentContainer(\
00534 do_extended=self.do_extended
00535 )
00536 else:
00537 raise Wsdl2PythonError,\
00538 'unknown complex type definition: %s' %item.getItemTrace()
00539
00540 self.logger.debug('TypeWriter setUp container "%r", Schema Item "%s"' %(
00541 self.content, item.getItemTrace()))
00542
00543 try:
00544 self.content.setUp(item, **kw)
00545 except Exception, ex:
00546 args = ['Failure in setUp: %s' %item.getItemTrace()]
00547 args += ex.args
00548 ex.args = tuple(args)
00549 raise
00550
00551 return
00552
00553 raise TypeError,\
00554 'expecting SimpleType or ComplexType: %s' %item.getItemTrace()
00555
00556
00557