From: <bov...@us...> - 2006-10-19 22:31:20
|
Revision: 1270 http://svn.sourceforge.net/pywebsvcs/?rev=1270&view=rev Author: boverhof Date: 2006-10-19 15:31:07 -0700 (Thu, 19 Oct 2006) Log Message: ----------- M test/test_t8.py M ZSI/__init__.py A ZSI/schema.py M ZSI/generate/containers.py M ZSI/TC.py M ZSI/TCcompound.py M ZSI/writer.py M ZSI/address.py -- Moved all schema instance stuff into a new module "schema", Modified Paths: -------------- trunk/zsi/ZSI/TC.py trunk/zsi/ZSI/TCcompound.py trunk/zsi/ZSI/__init__.py trunk/zsi/ZSI/address.py trunk/zsi/ZSI/generate/containers.py trunk/zsi/ZSI/writer.py trunk/zsi/test/test_t8.py Added Paths: ----------- trunk/zsi/ZSI/schema.py Modified: trunk/zsi/ZSI/TC.py =================================================================== --- trunk/zsi/ZSI/TC.py 2006-10-18 22:55:32 UTC (rev 1269) +++ trunk/zsi/ZSI/TC.py 2006-10-19 22:31:07 UTC (rev 1270) @@ -10,7 +10,7 @@ _find_xmlns_prefix, _get_element_nsuri_name, _get_idstr, \ _Node, EvaluateException, \ _valid_encoding, ParseException - + from ZSI.wstools.Namespaces import SCHEMA, SOAP from ZSI.wstools.Utility import SplitQName from ZSI.wstools.c14n import Canonicalize @@ -22,13 +22,14 @@ from urllib import unquote as urldecode, quote as urlencode from binascii import unhexlify as hexdecode, hexlify as hexencode -UNBOUNDED = 'unbounded' _is_xsd_or_soap_ns = lambda ns: ns in [ SCHEMA.XSD3, SOAP.ENC, SCHEMA.XSD1, SCHEMA.XSD2, ] _find_nil = lambda E: _find_xsi_attr(E, "null") or _find_xsi_attr(E, "nil") def _get_xsitype(pyclass): + '''returns the xsi:type as a tuple, coupled with ZSI.schema + ''' if hasattr(pyclass,'type') and type(pyclass.type) in _seqtypes: return pyclass.type elif hasattr(pyclass,'type') and hasattr(pyclass, 'schema'): @@ -36,168 +37,12 @@ return (None,None) -def _get_type_definition(namespaceURI, name, **kw): - return SchemaInstanceType.getTypeDefinition(namespaceURI, name, **kw) -def _get_global_element_declaration(namespaceURI, name, **kw): - return SchemaInstanceType.getElementDeclaration(namespaceURI, name, **kw) +# value returned when xsi:nil="true" +Nilled = None +UNBOUNDED = 'unbounded' -def _get_substitute_element(elt, what): - raise NotImplementedError, 'Not implemented' -def _has_type_definition(namespaceURI, name): - return SchemaInstanceType.getTypeDefinition(namespaceURI, name) is not None - - -# -# functions for retrieving schema items from -# the global schema instance. -# -GED = _get_global_element_declaration -GTD = _get_type_definition - - -class SchemaInstanceType(type): - '''Register all types/elements, when hit already defined - class dont create a new one just give back reference. Thus - import order determines which class is loaded. - - class variables: - types -- dict of typecode classes definitions - representing global type definitions. - elements -- dict of typecode classes representing - global element declarations. - element_typecode_cache -- dict of typecode instances - representing global element declarations. - ''' - types = {} - elements = {} - element_typecode_cache = {} - - def __new__(cls,classname,bases,classdict): - '''If classdict has literal and schema register it as a - element declaration, else if has type and schema register - it as a type definition. - ''' - if classname in ['ElementDeclaration', 'TypeDefinition']: - return type.__new__(cls,classname,bases,classdict) - - if ElementDeclaration in bases: - if classdict.has_key('schema') is False or classdict.has_key('literal') is False: - raise AttributeError, 'ElementDeclaration must define schema and literal attributes' - - key = (classdict['schema'],classdict['literal']) - if SchemaInstanceType.elements.has_key(key) is False: - SchemaInstanceType.elements[key] = type.__new__(cls,classname,bases,classdict) - return SchemaInstanceType.elements[key] - - if TypeDefinition in bases: - if classdict.has_key('type') is None: - raise AttributeError, 'TypeDefinition must define type attribute' - - key = classdict['type'] - if SchemaInstanceType.types.has_key(key) is False: - SchemaInstanceType.types[key] = type.__new__(cls,classname,bases,classdict) - return SchemaInstanceType.types[key] - - raise TypeError, 'SchemaInstanceType must be an ElementDeclaration or TypeDefinition ' - - def getTypeDefinition(cls, namespaceURI, name, lazy=False): - '''Grab a type definition, returns a typecode class definition - because the facets (name, minOccurs, maxOccurs) must be provided. - - Parameters: - namespaceURI -- - name -- - ''' - klass = cls.types.get((namespaceURI, name), None) - if lazy and klass is not None: - return _Mirage(klass) - return klass - getTypeDefinition = classmethod(getTypeDefinition) - - def getElementDeclaration(cls, namespaceURI, name, isref=False, lazy=False): - '''Grab an element declaration, returns a typecode instance - representation or a typecode class definition. An element - reference has its own facets, and is local so it will not be - cached. - - Parameters: - namespaceURI -- - name -- - isref -- if element reference, return class definition. - ''' - key = (namespaceURI, name) - if isref: - klass = cls.elements.get(key,None) - if klass is not None and lazy is True: - return _Mirage(klass) - return klass - - typecode = cls.element_typecode_cache.get(key, None) - if typecode is None: - tcls = cls.elements.get(key,None) - if tcls is not None: - typecode = cls.element_typecode_cache[key] = tcls() - typecode.typed = False - - return typecode - getElementDeclaration = classmethod(getElementDeclaration) - - -class ElementDeclaration: - '''Typecodes subclass to represent a Global Element Declaration by - setting class variables schema and literal. - - schema = namespaceURI - literal = NCName - ''' - __metaclass__ = SchemaInstanceType - - -class TypeDefinition: - '''Typecodes subclass to represent a Global Type Definition by - setting class variable type. - - type = (namespaceURI, NCName) - ''' - __metaclass__ = SchemaInstanceType - - def getSubstituteType(self, elt, ps): - '''if xsi:type does not match the instance type attr, - check to see if it is a derived type substitution. - - DONT Return the element's type. - - Parameters: - elt -- the DOM element being parsed - ps -- the ParsedSoap object. - ''' - pyclass = SchemaInstanceType.getTypeDefinition(*self.type) - if pyclass is None: - raise EvaluateException( - 'No Type registed for xsi:type=(%s, %s)' % - (self.type[0], self.type[1]), ps.Backtrace(elt)) - - typeName = _find_type(elt) - prefix,typeName = SplitQName(typeName) - uri = ps.GetElementNSdict(elt).get(prefix) - subclass = SchemaInstanceType.getTypeDefinition(uri, typeName) - if subclass is None: - raise EvaluateException( - 'No registered xsi:type=(%s, %s), substitute for xsi:type=(%s, %s)' % - (uri, typeName, self.type[0], self.type[1]), ps.Backtrace(elt)) - - if not issubclass(subclass, pyclass) and subclass(None) and not issubclass(subclass, pyclass): - raise TypeError( - 'Substitute Type (%s, %s) is not derived from %s' % - (self.type[0], self.type[1], pyclass), ps.Backtrace(elt)) - - return subclass((self.nspname, self.pname)) - - -Nilled = None - class TypeCode: '''The parent class for all parseable SOAP types. Class data: @@ -1482,14 +1327,6 @@ return # Namespace if element AnyType was namespaced. -# if self.nspname != what.nspname: -# what.nspname = self.nspname -# -# if self.pname != what.pname: -# raise EvaluateException, \ -# 'element name of typecode(%s) must match element name of AnyType(%s)' \ -# %(what.pname,self.pname) - what.serialize(elt, sw, pyobj, name=(self.nspname or what.nspname, self.pname or what.pname), **kw) @@ -1503,7 +1340,7 @@ #locate xsi:type prefix, typeName = SplitQName(_find_type(elt)) namespaceURI = _resolve_prefix(elt, prefix) - pyclass = _get_type_definition(namespaceURI, typeName) + pyclass = GTD(namespaceURI, typeName) if not pyclass: if _is_xsd_or_soap_ns(namespaceURI): pyclass = _AnyStrict @@ -1577,14 +1414,14 @@ ''' skip = self.processContents == 'skip' nspname,pname = _get_element_nsuri_name(elt) - what = _get_global_element_declaration(nspname, pname) + what = GED(nspname, pname) if not skip and what is not None: pyobj = what.parse(elt, ps) try: pyobj.typecode = what except AttributeError, ex: # Assume this means builtin type. - pyobj = _GetPyobjWrapper.Wrap(pyobj, what) + pyobj = WrapImmutable(pyobj, what) return pyobj # Allow use of "<any>" element declarations w/ local @@ -1594,14 +1431,14 @@ namespaceURI = _resolve_prefix(elt, prefix or 'xmlns') # First look thru user defined namespaces, if don't find # look for 'primitives'. - pyclass = _get_type_definition(namespaceURI, typeName) or Any + pyclass = GTD(namespaceURI, typeName) or Any what = pyclass(pname=(nspname,pname)) pyobj = what.parse(elt, ps) try: pyobj.typecode = what except AttributeError, ex: # Assume this means builtin type. - pyobj = Wrap(pyobj, what) + pyobj = WrapImmutable(pyobj, what) what.typed = True return pyobj @@ -1619,7 +1456,7 @@ self.logger.error("Give up, parse (%s,%s) as a String", what.nspname, what.pname) what = String(pname=(nspname,pname), typed=False) - pyobj = Wrap(what.parse(elt, ps), what) + pyobj = WrapImmutable(what.parse(elt, ps), what) return pyobj @@ -1643,7 +1480,7 @@ if self.__class__.memberTypes is None: raise EvaluateException, 'uninitialized class variable memberTypes [(namespace,name),]' for nsuri,name in self.__class__.memberTypes: - tcclass = _get_type_definition(nsuri,name) + tcclass = GTD(nsuri,name) if tcclass is None: tc = Any.parsemap.get((nsuri,name)) typecode = tc.__class__(pname=(self.nspname,self.pname)) @@ -1734,7 +1571,7 @@ if type(self.itemTypeCode) in _seqtypes: namespaceURI,name = self.itemTypeCode try: - itemTypeCode = _get_type_definition(*self.itemType)(None) + itemTypeCode = GTD(*self.itemType)(None) except: if _is_xsd_or_soap_ns(namespaceURI) is False: raise @@ -1926,150 +1763,6 @@ return self.checktype(elt, ps) -class _Mirage: - '''Used with SchemaInstanceType for lazy evaluation, eval during serialize or - parse as needed. Mirage is callable, TypeCodes are not. When called it returns the - typecode. Tightly coupled with generated code. - - NOTE: **Must Use ClassType** for intended MRO of __call__ since setting it in - an instance attribute rather than a class attribute (will not work for object). - ''' - def __init__(self, klass): - self.klass = klass - self.__reveal = False - self.__cache = None - if issubclass(klass, ElementDeclaration): - self.__call__ = self._hide_element - - def __str__(self): - msg = "<Mirage id=%s, Local Element %s>" - if issubclass(self.klass, ElementDeclaration): - msg = "<Mirage id=%s, GED %s>" - return msg %(id(self), self.klass) - - def _hide_type(self, pname, aname, minOccurs=0, maxOccurs=1, nillable=False, - **kw): - self.__call__ = self._reveal_type - self.__reveal = True - - # store all attributes, make some visable for pyclass_type - self.__kw = kw - self.minOccurs,self.maxOccurs,self.nillable = minOccurs,maxOccurs,nillable - self.nspname,self.pname,self.aname = None,pname,aname - if type(self.pname) in (tuple,list): - self.nspname,self.pname = pname - - return self - - def _hide_element(self, minOccurs=0, maxOccurs=1, nillable=False, **kw): - self.__call__ = self._reveal_element - self.__reveal = True - - # store all attributes, make some visable for pyclass_type - self.__kw = kw - self.nspname = self.klass.schema - self.pname = self.klass.literal - #TODO: Fix hack - #self.aname = '_%s' %self.pname - self.minOccurs,self.maxOccurs,self.nillable = minOccurs,maxOccurs,nillable - - return self - - def _reveal_type(self): - if self.__cache is None: - self.__cache = self.klass(pname=self.pname, - aname=self.aname, minOccurs=self.minOccurs, - maxOccurs=self.maxOccurs, nillable=self.nillable, - **self.__kw) - return self.__cache - - def _reveal_element(self): - if self.__cache is None: - self.__cache = self.klass(minOccurs=self.minOccurs, - maxOccurs=self.maxOccurs, nillable=self.nillable, - **self.__kw) - return self.__cache - - __call__ = _hide_type - - -class _GetPyobjWrapper: - '''Get a python object that wraps data and typecode. Used by - <any> parse routine, so that typecode information discovered - during parsing is retained in the pyobj representation - and thus can be serialized. - ''' - types_dict = {} - - def RegisterBuiltin(cls, arg): - '''register a builtin, create a new wrapper. - ''' - if arg in cls.types_dict: - raise RuntimeError, '%s already registered' %arg - class _Wrapper(arg): - 'Wrapper for builtin %s\n%s' %(arg, cls.__doc__) - _Wrapper.__name__ = '_%sWrapper' %arg - cls.types_dict[arg] = _Wrapper - RegisterBuiltin = classmethod(RegisterBuiltin) - - def RegisterAnyElement(cls): - '''clobber all existing entries in Any serialmap, - replace with Wrapper classes. - ''' - for k,v in cls.types_dict.items(): - what = Any.serialmap.get(k) - if what is None: continue - if v in what.__class__.seriallist: continue - what.__class__.seriallist.append(v) - RegisterType(what.__class__, clobber=1) - RegisterAnyElement = classmethod(RegisterAnyElement) - - def Wrap(cls, pyobj, what): - '''return a wrapper for pyobj, with typecode attribute set. - Parameters: - pyobj -- instance of builtin type (immutable) - what -- typecode describing the data - ''' - d = cls.types_dict - if type(pyobj) is bool: - pyclass = d[int] - elif d.has_key(type(pyobj)) is True: - pyclass = d[type(pyobj)] - else: - raise TypeError,\ - 'Expecting a built-in type in %s (got %s).' %( - d.keys(),type(pyobj)) - - newobj = pyclass(pyobj) - newobj.typecode = what - return newobj - Wrap = classmethod(Wrap) - - -def Wrap(pyobj, what): - '''Wrap immutable instance so a typecode can be - set, making it self-describing ie. serializable. - ''' - return _GetPyobjWrapper.Wrap(pyobj, what) - - -def RegisterBuiltin(arg): - '''Add a builtin to be registered, and register it - with the Any typecode. - ''' - _GetPyobjWrapper.RegisterBuiltin(arg) - _GetPyobjWrapper.RegisterAnyElement() - - -def RegisterAnyElement(): - '''register all Wrapper classes with the Any typecode. - This allows instances returned by Any to be self-describing. - ie. serializable. AnyElement falls back on Any to parse - anything it doesn't understand. - ''' - return _GetPyobjWrapper.RegisterAnyElement() - - def RegisterType(C, clobber=0, *args, **keywords): instance = apply(C, args, keywords) for t in C.__dict__.get('parselist', []): @@ -2097,19 +1790,18 @@ Any.serialmap[key] = instance -# Load up Wrappers for builtin types -for i in [int,float,str,tuple,list,unicode]: - _GetPyobjWrapper.RegisterBuiltin(i) - - from TCnumbers import * from TCtimes import * +from schema import GTD, GED, WrapImmutable from TCcompound import * from TCapache import * - +# aliases backwards compatiblity +_get_type_definition, _get_global_element_declaration, Wrap = GTD, GED, WrapImmutable + f = lambda x: type(x) == types.ClassType and issubclass(x, TypeCode) and getattr(x, 'type', None) is not None TYPES = filter(f, map(lambda y:eval(y),dir())) + if __name__ == '__main__': print _copyright Modified: trunk/zsi/ZSI/TCcompound.py =================================================================== --- trunk/zsi/ZSI/TCcompound.py 2006-10-18 22:55:32 UTC (rev 1269) +++ trunk/zsi/ZSI/TCcompound.py 2006-10-19 22:31:07 UTC (rev 1270) @@ -7,10 +7,14 @@ _inttypes, _stringtypes, _seqtypes, _find_arraytype, _find_href, \ _find_type, _find_xmlns_prefix, _get_idstr, EvaluateException, \ ParseException -from ZSI.TC import _get_element_nsuri_name, \ - _get_substitute_element, _get_type_definition, _get_xsitype, \ - TypeCode, Any, AnyElement, AnyType, ElementDeclaration, TypeDefinition, \ - Nilled + +from TC import _get_element_nsuri_name, \ + _get_xsitype, TypeCode, Any, AnyElement, AnyType, \ + Nilled, UNBOUNDED + +from schema import ElementDeclaration, TypeDefinition, \ + _get_substitute_element, _get_type_definition + from ZSI.wstools.Namespaces import SCHEMA, SOAP from ZSI.wstools.Utility import SplitQName from ZSI.wstools.logging import getLogger as _GetLogger @@ -236,7 +240,7 @@ v[any.aname] = [] for j,c_elt in [ (j, c[j]) for j in crange if c[j] ]: value = any.parse(c_elt, ps) - if any.maxOccurs == 'unbounded' or any.maxOccurs > 1: + if any.maxOccurs == UNBOUNDED or any.maxOccurs > 1: v[any.aname].append(value) else: v[any.aname] = value @@ -246,7 +250,7 @@ # No such thing as nillable <any> if any.maxOccurs == 1 and occurs == 0: v[any.aname] = None - elif occurs < any.minOccurs or (any.maxOccurs!='unbounded' and any.maxOccurs<occurs): + elif occurs < any.minOccurs or (any.maxOccurs!=UNBOUNDED and any.maxOccurs<occurs): raise EvaluateException('occurances of <any> elements(#%d) bound by (%d,%s)' %( occurs, any.minOccurs,str(any.maxOccurs)), ps.Backtrace(elt)) @@ -667,5 +671,4 @@ position += 1 - if __name__ == '__main__': print _copyright Modified: trunk/zsi/ZSI/__init__.py =================================================================== --- trunk/zsi/ZSI/__init__.py 2006-10-18 22:55:32 UTC (rev 1269) +++ trunk/zsi/ZSI/__init__.py 2006-10-19 22:31:07 UTC (rev 1270) @@ -412,11 +412,22 @@ TC.RegisterType(TC.gDay, minOccurs=0, nillable=False) TC.RegisterType(TC.gTime, minOccurs=0, nillable=False) TC.RegisterType(TC.Apache.Map, minOccurs=0, nillable=False) -TC.RegisterAnyElement() -try: - from ServiceProxy import * -except: - pass +## +## Register Wrappers for builtin types. +## TC.AnyElement wraps builtins so element name information can be saved +## +import schema +for i in [int,float,str,tuple,list,unicode]: + schema._GetPyobjWrapper.RegisterBuiltin(i) +## Load up Wrappers for builtin types +schema.RegisterAnyElement() + + +#try: +# from ServiceProxy import * +#except: +# pass + if __name__ == '__main__': print _copyright Modified: trunk/zsi/ZSI/address.py =================================================================== --- trunk/zsi/ZSI/address.py 2006-10-18 22:55:32 UTC (rev 1269) +++ trunk/zsi/ZSI/address.py 2006-10-19 22:31:07 UTC (rev 1270) @@ -5,8 +5,8 @@ import time, urlparse, socket from ZSI import _seqtypes, EvaluateException, WSActionException -from ZSI.TC import _get_global_element_declaration as GED, _get_type_definition as GTD, \ - _has_type_definition, AnyElement, AnyType, TypeCode +from TC import AnyElement, AnyType, TypeCode +from schema import GED, GTD, _has_type_definition from ZSI.TCcompound import ComplexType from ZSI.wstools.Namespaces import WSA_LIST Modified: trunk/zsi/ZSI/generate/containers.py =================================================================== --- trunk/zsi/ZSI/generate/containers.py 2006-10-18 22:55:32 UTC (rev 1269) +++ trunk/zsi/ZSI/generate/containers.py 2006-10-19 22:31:07 UTC (rev 1270) @@ -1047,8 +1047,7 @@ imports = [ 'import ZSI', 'import ZSI.TCcompound', - 'from ZSI.TC import ElementDeclaration,TypeDefinition', - 'from ZSI.TC import _get_type_definition as GTD, _get_global_element_declaration as GED', + 'from ZSI.schema import LocalElementDeclaration, ElementDeclaration, TypeDefinition, GTD, GED', ] logger = _GetLogger("TypesHeaderContainer") Added: trunk/zsi/ZSI/schema.py =================================================================== --- trunk/zsi/ZSI/schema.py (rev 0) +++ trunk/zsi/ZSI/schema.py 2006-10-19 22:31:07 UTC (rev 1270) @@ -0,0 +1,327 @@ +#! /usr/bin/env python +# $Header$ +'''XML Schema support +''' + +from ZSI import _copyright, _seqtypes, _find_type, EvaluateException +from ZSI.wstools.Namespaces import SCHEMA, SOAP +from ZSI.wstools.Utility import SplitQName + + +def _get_type_definition(namespaceURI, name, **kw): + return SchemaInstanceType.getTypeDefinition(namespaceURI, name, **kw) + +def _get_global_element_declaration(namespaceURI, name, **kw): + return SchemaInstanceType.getElementDeclaration(namespaceURI, name, **kw) + +def _get_substitute_element(elt, what): + raise NotImplementedError, 'Not implemented' + +def _has_type_definition(namespaceURI, name): + return SchemaInstanceType.getTypeDefinition(namespaceURI, name) is not None + + +# +# functions for retrieving schema items from +# the global schema instance. +# +GED = _get_global_element_declaration +GTD = _get_type_definition + + +def WrapImmutable(pyobj, what): + '''Wrap immutable instance so a typecode can be + set, making it self-describing ie. serializable. + ''' + return _GetPyobjWrapper.WrapImmutable(pyobj, what) + +def RegisterBuiltin(arg): + '''Add a builtin to be registered, and register it + with the Any typecode. + ''' + _GetPyobjWrapper.RegisterBuiltin(arg) + _GetPyobjWrapper.RegisterAnyElement() + +def RegisterAnyElement(): + '''register all Wrapper classes with the Any typecode. + This allows instances returned by Any to be self-describing. + ie. serializable. AnyElement falls back on Any to parse + anything it doesn't understand. + ''' + return _GetPyobjWrapper.RegisterAnyElement() + + +class SchemaInstanceType(type): + '''Register all types/elements, when hit already defined + class dont create a new one just give back reference. Thus + import order determines which class is loaded. + + class variables: + types -- dict of typecode classes definitions + representing global type definitions. + elements -- dict of typecode classes representing + global element declarations. + element_typecode_cache -- dict of typecode instances + representing global element declarations. + ''' + types = {} + elements = {} + element_typecode_cache = {} + + def __new__(cls,classname,bases,classdict): + '''If classdict has literal and schema register it as a + element declaration, else if has type and schema register + it as a type definition. + ''' + if classname in ['ElementDeclaration', 'TypeDefinition', 'LocalElementDeclaration',]: + return type.__new__(cls,classname,bases,classdict) + + if ElementDeclaration in bases: + if classdict.has_key('schema') is False or classdict.has_key('literal') is False: + raise AttributeError, 'ElementDeclaration must define schema and literal attributes' + + key = (classdict['schema'],classdict['literal']) + if SchemaInstanceType.elements.has_key(key) is False: + SchemaInstanceType.elements[key] = type.__new__(cls,classname,bases,classdict) + return SchemaInstanceType.elements[key] + + if TypeDefinition in bases: + if classdict.has_key('type') is None: + raise AttributeError, 'TypeDefinition must define type attribute' + + key = classdict['type'] + if SchemaInstanceType.types.has_key(key) is False: + SchemaInstanceType.types[key] = type.__new__(cls,classname,bases,classdict) + return SchemaInstanceType.types[key] + + if LocalElementDeclaration in bases: + return type.__new__(cls,classname,bases,classdict) + + raise TypeError, 'SchemaInstanceType must be an ElementDeclaration or TypeDefinition ' + + def getTypeDefinition(cls, namespaceURI, name, lazy=False): + '''Grab a type definition, returns a typecode class definition + because the facets (name, minOccurs, maxOccurs) must be provided. + + Parameters: + namespaceURI -- + name -- + ''' + klass = cls.types.get((namespaceURI, name), None) + if lazy and klass is not None: + return _Mirage(klass) + return klass + getTypeDefinition = classmethod(getTypeDefinition) + + def getElementDeclaration(cls, namespaceURI, name, isref=False, lazy=False): + '''Grab an element declaration, returns a typecode instance + representation or a typecode class definition. An element + reference has its own facets, and is local so it will not be + cached. + + Parameters: + namespaceURI -- + name -- + isref -- if element reference, return class definition. + ''' + key = (namespaceURI, name) + if isref: + klass = cls.elements.get(key,None) + if klass is not None and lazy is True: + return _Mirage(klass) + return klass + + typecode = cls.element_typecode_cache.get(key, None) + if typecode is None: + tcls = cls.elements.get(key,None) + if tcls is not None: + typecode = cls.element_typecode_cache[key] = tcls() + typecode.typed = False + + return typecode + getElementDeclaration = classmethod(getElementDeclaration) + + +class ElementDeclaration: + '''Typecodes subclass to represent a Global Element Declaration by + setting class variables schema and literal. + + schema = namespaceURI + literal = NCName + ''' + __metaclass__ = SchemaInstanceType + + +class LocalElementDeclaration: + '''Typecodes subclass to represent a Local Element Declaration. + ''' + __metaclass__ = SchemaInstanceType + + +class TypeDefinition: + '''Typecodes subclass to represent a Global Type Definition by + setting class variable type. + + type = (namespaceURI, NCName) + ''' + __metaclass__ = SchemaInstanceType + + def getSubstituteType(self, elt, ps): + '''if xsi:type does not match the instance type attr, + check to see if it is a derived type substitution. + + DONT Return the element's type. + + Parameters: + elt -- the DOM element being parsed + ps -- the ParsedSoap object. + ''' + pyclass = SchemaInstanceType.getTypeDefinition(*self.type) + if pyclass is None: + raise EvaluateException( + 'No Type registed for xsi:type=(%s, %s)' % + (self.type[0], self.type[1]), ps.Backtrace(elt)) + + typeName = _find_type(elt) + prefix,typeName = SplitQName(typeName) + uri = ps.GetElementNSdict(elt).get(prefix) + subclass = SchemaInstanceType.getTypeDefinition(uri, typeName) + if subclass is None: + raise EvaluateException( + 'No registered xsi:type=(%s, %s), substitute for xsi:type=(%s, %s)' % + (uri, typeName, self.type[0], self.type[1]), ps.Backtrace(elt)) + + if not issubclass(subclass, pyclass) and subclass(None) and not issubclass(subclass, pyclass): + raise TypeError( + 'Substitute Type (%s, %s) is not derived from %s' % + (self.type[0], self.type[1], pyclass), ps.Backtrace(elt)) + + return subclass((self.nspname, self.pname)) + + + +class _Mirage: + '''Used with SchemaInstanceType for lazy evaluation, eval during serialize or + parse as needed. Mirage is callable, TypeCodes are not. When called it returns the + typecode. Tightly coupled with generated code. + + NOTE: **Must Use ClassType** for intended MRO of __call__ since setting it in + an instance attribute rather than a class attribute (will not work for object). + ''' + def __init__(self, klass): + self.klass = klass + self.__reveal = False + self.__cache = None + if issubclass(klass, ElementDeclaration): + self.__call__ = self._hide_element + + def __str__(self): + msg = "<Mirage id=%s, Local Element %s>" + if issubclass(self.klass, ElementDeclaration): + msg = "<Mirage id=%s, GED %s>" + return msg %(id(self), self.klass) + + def _hide_type(self, pname, aname, minOccurs=0, maxOccurs=1, nillable=False, + **kw): + self.__call__ = self._reveal_type + self.__reveal = True + + # store all attributes, make some visable for pyclass_type + self.__kw = kw + self.minOccurs,self.maxOccurs,self.nillable = minOccurs,maxOccurs,nillable + self.nspname,self.pname,self.aname = None,pname,aname + if type(self.pname) in (tuple,list): + self.nspname,self.pname = pname + + return self + + def _hide_element(self, minOccurs=0, maxOccurs=1, nillable=False, **kw): + self.__call__ = self._reveal_element + self.__reveal = True + + # store all attributes, make some visable for pyclass_type + self.__kw = kw + self.nspname = self.klass.schema + self.pname = self.klass.literal + #TODO: Fix hack + #self.aname = '_%s' %self.pname + self.minOccurs,self.maxOccurs,self.nillable = minOccurs,maxOccurs,nillable + + return self + + def _reveal_type(self): + if self.__cache is None: + self.__cache = self.klass(pname=self.pname, + aname=self.aname, minOccurs=self.minOccurs, + maxOccurs=self.maxOccurs, nillable=self.nillable, + **self.__kw) + return self.__cache + + def _reveal_element(self): + if self.__cache is None: + self.__cache = self.klass(minOccurs=self.minOccurs, + maxOccurs=self.maxOccurs, nillable=self.nillable, + **self.__kw) + return self.__cache + + __call__ = _hide_type + + +class _GetPyobjWrapper: + '''Get a python object that wraps data and typecode. Used by + <any> parse routine, so that typecode information discovered + during parsing is retained in the pyobj representation + and thus can be serialized. + ''' + types_dict = {} + + def RegisterBuiltin(cls, arg): + '''register a builtin, create a new wrapper. + ''' + if arg in cls.types_dict: + raise RuntimeError, '%s already registered' %arg + class _Wrapper(arg): + 'Wrapper for builtin %s\n%s' %(arg, cls.__doc__) + _Wrapper.__name__ = '_%sWrapper' %arg.__name__ + cls.types_dict[arg] = _Wrapper + RegisterBuiltin = classmethod(RegisterBuiltin) + + def RegisterAnyElement(cls): + '''If find registered TypeCode instance, add Wrapper class + to TypeCode class serialmap and Re-RegisterType. Provides + Any serialzation of any instances of the Wrapper. + ''' + for k,v in cls.types_dict.items(): + what = Any.serialmap.get(k) + if what is None: continue + if v in what.__class__.seriallist: continue + what.__class__.seriallist.append(v) + RegisterType(what.__class__, clobber=1, **what.__dict__) + RegisterAnyElement = classmethod(RegisterAnyElement) + + def WrapImmutable(cls, pyobj, what): + '''return a wrapper for pyobj, with typecode attribute set. + Parameters: + pyobj -- instance of builtin type (immutable) + what -- typecode describing the data + ''' + d = cls.types_dict + if type(pyobj) is bool: + pyclass = d[int] + elif d.has_key(type(pyobj)) is True: + pyclass = d[type(pyobj)] + else: + raise TypeError,\ + 'Expecting a built-in type in %s (got %s).' %( + d.keys(),type(pyobj)) + + newobj = pyclass(pyobj) + newobj.typecode = what + return newobj + WrapImmutable = classmethod(WrapImmutable) + + +from TC import Any, RegisterType + +if __name__ == '__main__': print _copyright + Modified: trunk/zsi/ZSI/writer.py =================================================================== --- trunk/zsi/ZSI/writer.py 2006-10-18 22:55:32 UTC (rev 1269) +++ trunk/zsi/ZSI/writer.py 2006-10-19 22:31:07 UTC (rev 1270) @@ -5,7 +5,6 @@ from ZSI import _copyright, _get_idstr, ZSI_SCHEMA_URI from ZSI import _backtrace, _stringtypes, _seqtypes -from ZSI.TC import AnyElement, TypeCode from ZSI.wstools.Utility import MessageInterface, ElementProxy from ZSI.wstools.Namespaces import XMLNS, SOAP, SCHEMA from ZSI.wstools.c14n import Canonicalize Modified: trunk/zsi/test/test_t8.py =================================================================== --- trunk/zsi/test/test_t8.py 2006-10-18 22:55:32 UTC (rev 1269) +++ trunk/zsi/test/test_t8.py 2006-10-19 22:31:07 UTC (rev 1270) @@ -1,6 +1,6 @@ #!/usr/bin/env python -import unittest, sys -from ZSI import * +import unittest, sys, types, time +from ZSI import TC, SoapWriter, ParsedSoap, EvaluateException from ZSI.wstools.Namespaces import SCHEMA, SOAP NSDICT = {'tns':'xmlns:tns="urn:a"', @@ -39,7 +39,7 @@ sw.serialize(None, typecode=tc, typed=True) soap = str(sw) ps = ParsedSoap(soap) - parsed = ps.Parse(Any()) + parsed = ps.Parse(TC.Any()) self.assertEqual(None, parsed) def check_parse_empty_string(self): @@ -50,7 +50,7 @@ sw.serialize("", typecode=tc, typed=True) soap = str(sw) ps = ParsedSoap(soap) - parsed = ps.Parse(Any()) + parsed = ps.Parse(TC.Any()) self.assertEqual("", parsed) def check_builtins(self): @@ -59,10 +59,10 @@ orig = [myInt,myLong,myStr,myDate,myFloat] sw = SoapWriter() - sw.serialize(orig, typecode=Any(pname="builtins", aslist=True)) + sw.serialize(orig, typecode=TC.Any(pname="builtins", aslist=True)) ps = ParsedSoap(str(sw)) - parsed = ps.Parse(Any()) + parsed = ps.Parse(TC.Any()) self.assertEqual(len(orig), len(parsed)) self.assertEqual(myInt, parsed[0]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |