Package pyxb :: Package binding :: Module basis
[hide private]
[frames] | no frames]

Source Code for Module pyxb.binding.basis

   1  # Copyright 2009, Peter A. Bigot 
   2  # 
   3  # Licensed under the Apache License, Version 2.0 (the "License"); you may 
   4  # not use this file except in compliance with the License. You may obtain a 
   5  # copy of the License at: 
   6  # 
   7  #            http://www.apache.org/licenses/LICENSE-2.0 
   8  # 
   9  # Unless required by applicable law or agreed to in writing, software 
  10  # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
  11  # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
  12  # License for the specific language governing permissions and limitations 
  13  # under the License. 
  14   
  15  """This module contains support classes from which schema-specific bindings 
  16  inherit, and that describe the content models of those schema.""" 
  17   
  18  import pyxb 
  19  import xml.dom 
  20  import pyxb.utils.domutils as domutils 
  21  import pyxb.utils.utility as utility 
  22  import types 
  23  import pyxb.namespace 
  24   
  25  BINDING_STYLE_ACCESSOR = 'accessor' 
  26  BINDING_STYLE_PROPERTY = 'property' 
  27   
  28  BINDING_STYLES = (BINDING_STYLE_ACCESSOR, BINDING_STYLE_PROPERTY) 
  29  DEFAULT_BINDING_STYLE = BINDING_STYLE_PROPERTY 
  30  CURRENT_BINDING_STYLE = None 
31 32 -def ConfigureBindingStyle (style):
33 global CURRENT_BINDING_STYLE 34 simpleTypeDefinition._ConfigureBindingStyle(style) 35 complexTypeDefinition._ConfigureBindingStyle(style) 36 CURRENT_BINDING_STYLE = style
37
38 -class _TypeBinding_mixin (utility.Locatable_mixin):
39 40 _PerformValidation = True 41 #_PerformValidation = False 42 43 _ExpandedName = None 44 """The expanded name of the component.""" 45 46 _ReservedSymbols = set([ 'validateBinding', 'toDOM', 'toxml', 'Factory', 'property' ]) 47
48 - def __setattr__ (self, name, value):
49 if name in self._ReservedSymbols: 50 raise pyxb.BindingError('Attempt to set reserved name %s in instance of %s' % (name, type(self))) 51 return super(_TypeBinding_mixin, self).__setattr__(name, value)
52 53 # @todo: We don't actually use this anymore; get rid of it, just leaving a 54 # comment describing each keyword. 55 _PyXBFactoryKeywords = ( '_dom_node', '_fallback_namespace', '_apply_whitespace_facet', '_validate_constraints', '_require_value', '_nil', '_element' ) 56 """Keywords that are interpreted by __new__ or __init__ in one or more 57 classes in the PyXB type hierarchy. All these keywords must be removed 58 before invoking base Python __init__ or __new__.""" 59 60 # While simple type definitions cannot be abstract, they can appear in 61 # many places where complex types can, so we want it to be legal to test 62 # for abstractness without checking whether the object is a complex type. 63 _Abstract = False 64
65 - def _namespaceContext (self):
66 """Return a L{namespace context <pyxb.binding.NamespaceContext>} 67 associated with the binding instance. 68 69 This will return C{None} unless something has provided a context to 70 the instance. Context is provided when instances are generated by the 71 DOM and SAX-based translators.""" 72 return self.__namespaceContext
73 - def _setNamespaceContext (self, namespace_context):
74 """Associate a L{namespace context <pyxb.binding.NamespaceContext>} 75 with the binding instance.""" 76 self.__namespaceContext = namespace_context 77 return self
78 __namespaceContext = None 79
80 - def _setElement (self, element):
81 """Associate a L{pyxb.binding.basis.element} with the instance.""" 82 self.__element = element 83 return self
84 - def _element (self):
85 """Return a L{pyxb.binding.basis.element} associated with the binding 86 instance. 87 88 This will return C{None} unless an element has been associated. 89 Constructing a binding instance using the element instance will add 90 this association. 91 """ 92 return self.__element
93 __element = None 94 95 __xsiNil = None
96 - def _isNil (self):
97 """Indicate whether this instance is U{nil 98 <http://www.w3.org/TR/xmlschema-1/#xsi_nil>}. 99 100 The value is set by the DOM and SAX parsers when building an instance 101 from a DOM element with U{xsi:nil 102 <http://www.w3.org/TR/xmlschema-1/#xsi_nil>} set to C{true}. 103 104 @return: C{None} if the element used to create the instance is not 105 U{nillable<http://www.w3.org/TR/xmlschema-1/#nillable>}. 106 If it is nillable, returns C{True} or C{False} depending on 107 whether the instance itself is U{nil<http://www.w3.org/TR/xmlschema-1/#xsi_nil>}. 108 """ 109 return self.__xsiNil
110 - def _setIsNil (self):
111 """Set the xsi:nil property of the instance. 112 113 @raise pyxb.NoNillableSupportError: the instance is not associated 114 with an element that is L{nillable 115 <pyxb.binding.basis.element.nillable>}. 116 """ 117 if self.__xsiNil is None: 118 raise pyxb.NoNillableSupportError(type(self)) 119 self.__xsiNil = True 120 self._resetContent()
121
122 - def _resetContent (self):
123 pass
124 125 __constructedWithValue = False
126 - def __checkNilCtor (self, args):
127 self.__constructedWithValue = (0 < len(args)) 128 if self.__xsiNil: 129 if self.__constructedWithValue: 130 raise pyxb.ContentInNilElementError(args[0]) 131 else: 132 # Types that descend from string will, when constructed from an 133 # element with empty content, appear to have no constructor value, 134 # while in fact an empty string should have been passed. 135 if issubclass(type(self), basestring): 136 self.__constructedWithValue = True
137 - def _constructedWithValue (self):
138 return self.__constructedWithValue
139 140 # Flag used to control whether we print a warning when creating a complex 141 # type instance that does not have an associated element. Not sure yet 142 # whether that'll be common practice or common error. 143 __WarnedUnassociatedElement = False 144
145 - def __init__ (self, *args, **kw):
146 # Strip keyword not used above this level. 147 element = kw.pop('_element', None) 148 is_nil = kw.pop('_nil', False) 149 super(_TypeBinding_mixin, self).__init__(*args, **kw) 150 if (element is None) or element.nillable(): 151 self.__xsiNil = is_nil 152 self.__checkNilCtor(args) 153 if element is not None: 154 self._setElement(element)
155 156 @classmethod
157 - def _PreFactory_vx (cls, args, kw):
158 """Method invoked upon entry to the Factory method. 159 160 This method is entitled to modify the keywords array. It can also 161 return a state value which is passed to _postFactory_vx.""" 162 return None
163
164 - def _postFactory_vx (cls, state):
165 """Method invoked prior to leaving the Factory method. 166 167 This is an instance method, and is given the state that was returned 168 by _PreFactory_vx.""" 169 return None
170 171 @classmethod
172 - def Factory (cls, *args, **kw):
173 """Provide a common mechanism to create new instances of this type. 174 175 The class constructor won't do, because you can't create 176 instances of union types. 177 178 This method may be overridden in subclasses (like STD_union). Pre- 179 and post-creation actions can be customized on a per-class instance by 180 overriding the L{_PreFactory_vx} and L{_postFactory_vx} methods. 181 182 @keyword _dom_node: If provided, the value must be a DOM node, the 183 content of which will be used to set the value of the instance. 184 185 @keyword _apply_whitespace_facet: If C{True} and this is a 186 simpleTypeDefinition with a whiteSpace facet, the first argument will 187 be normalized in accordance with that facet prior to invoking the 188 parent constructor. 189 190 @keyword _validate_constraints: If C{True}, any constructed value is 191 checked against constraints applied to the union as well as the member 192 type. 193 194 @keyword _require_value: If C{False} (default), it is permitted to 195 create a value without an initial value. If C{True} and no initial 196 value was provided, causes L{pyxb.MissingContentError} to be raised. 197 Only applies to simpleTypeDefinition instances; this is used when 198 creating values from DOM nodes. 199 """ 200 # Invoke _PreFactory_vx for the superseding class, which is where 201 # customizations will be found. 202 dom_node = kw.get('_dom_node') 203 used_cls = cls._SupersedingClass() 204 state = used_cls._PreFactory_vx(args, kw) 205 rv = cls._DynamicCreate(*args, **kw) 206 rv._postFactory_vx(state) 207 if isinstance(dom_node, utility.Locatable_mixin): 208 rv._setLocation(dom_node.location) 209 return rv
210
211 - def _substitutesFor (self, element):
212 if (element is None) or (self._element() is None): 213 return False 214 return self._element().substitutesFor(element)
215 216 @classmethod
217 - def _RequireXSIType (cls, value_type):
218 return cls._Abstract and value_type != cls._SupersedingClass()
219 220 @classmethod
221 - def _CompatibleValue (cls, value, **kw):
222 """Return a variant of the value that is compatible with this type. 223 224 Compatibility is defined relative to the type definition associated 225 with the element. The value C{None} is always compatible. If 226 C{value} has a Python type (e.g., C{int}) that is a superclass of the 227 required L{_TypeBinding_mixin} class (e.g., C{xs:byte}), C{value} is 228 used as a constructor parameter to return a new instance of the 229 required type. Note that constraining facets are applied here if 230 necessary (e.g., although a Python C{int} with value C{500} is 231 type-compatible with C{xs:byte}, it is outside the value space, and 232 compatibility will fail. 233 234 @keyword convert_string_values: If C{True} (default) and the incoming value is 235 a string, an attempt will be made to form a compatible value by using 236 the string as a constructor argument to the this class. This flag is 237 set to C{False} when testing automaton transitions. 238 239 @raise pyxb.BadTypeValueError: if the value is not both 240 type-consistent and value-consistent with the element's type. 241 """ 242 convert_string_values = kw.get('convert_string_values', True) 243 # None is always None 244 if value is None: 245 return None 246 # Already an instance? 247 if isinstance(value, cls): 248 # @todo: Consider whether we should change the associated _element 249 # of this value. (**Consider** it, don't just do it.) 250 return value 251 value_type = type(value) 252 # All string-based PyXB binding types use unicode, not str 253 if str == value_type: 254 value_type = unicode 255 256 # See if we got passed a Python value which needs to be "downcasted" 257 # to the _TypeBinding_mixin version. 258 if issubclass(cls, value_type): 259 return cls(value) 260 261 # See if we have a numeric type that needs to be cast across the 262 # numeric hierarchy. int to long is the *only* conversion we accept. 263 if isinstance(value, int) and issubclass(cls, long): 264 return cls(value) 265 266 # Same, but for boolean, which Python won't let us subclass 267 if isinstance(value, bool) and issubclass(cls, pyxb.binding.datatypes.boolean): 268 return cls(value) 269 270 # See if we have convert_string_values on, and have a string type that 271 # somebody understands. 272 if convert_string_values and (unicode == value_type): 273 return cls(value) 274 275 # Maybe this is a union? 276 if issubclass(cls, STD_union): 277 for mt in cls._MemberTypes: 278 try: 279 return mt._CompatibleValue(value, **kw) 280 except: 281 pass 282 283 # Any type is compatible with the corresponding ur-type 284 if (pyxb.binding.datatypes.anySimpleType == cls) and issubclass(value_type, simpleTypeDefinition): 285 return value 286 if (pyxb.binding.datatypes.anyType == cls) and issubclass(value_type, complexTypeDefinition): 287 return value 288 289 # Is this the wrapper class that indicates we should create a binding 290 # from arguments? 291 if isinstance(value, pyxb.BIND): 292 return value.createInstance(cls.Factory, **kw) 293 294 # There may be other things that can be converted to the desired type, 295 # but we can't tell that from the type hierarchy. Too many of those 296 # things result in an undesirable loss of information: for example, 297 # when an all model supports both numeric and string transitions, the 298 # candidate is a number, and the string transition is tested first. 299 raise pyxb.BadTypeValueError('No conversion from %s to %s' % (value_type, cls))
300 301 @classmethod
302 - def _IsSimpleTypeContent (cls):
303 """Return True iff the content of this binding object is a simple type. 304 305 This is true only for descendents of simpleTypeDefinition and instances 306 of complexTypeDefinition that have simple type content.""" 307 raise pyxb.LogicError('Failed to override _TypeBinding_mixin._IsSimpleTypeContent')
308
309 - def toDOM (self, bds=None, parent=None, element_name=None):
310 """Convert this instance to a DOM node. 311 312 The name of the top-level element is either the name of the L{element} 313 instance associated with this instance, or the XML name of the type of 314 this instance. 315 316 @param bds: Support for customizing the generated document 317 @type bds: L{pyxb.utils.domutils.BindingDOMSupport} 318 @param parent: If C{None}, a standalone document is created; 319 otherwise, the created element is a child of the given element. 320 @type parent: C{xml.dom.Element} or C{None} 321 @rtype: C{xml.dom.Document} 322 """ 323 324 if bds is None: 325 bds = domutils.BindingDOMSupport() 326 need_xsi_type = bds.requireXSIType() 327 if isinstance(element_name, (str, unicode)): 328 element_name = pyxb.namespace.ExpandedName(bds.defaultNamespace(), element_name) 329 if (element_name is None) and (self._element() is not None): 330 element_binding = self._element() 331 element_name = element_binding.name() 332 need_xsi_type = need_xsi_type or element_binding.typeDefinition()._RequireXSIType(type(self)) 333 if element_name is None: 334 element_name = self._ExpandedName 335 element = bds.createChildElement(element_name, parent) 336 if need_xsi_type: 337 val_type_qname = self._ExpandedName.localName() 338 tns_prefix = bds.namespacePrefix(self._ExpandedName.namespace()) 339 if tns_prefix is not None: 340 val_type_qname = '%s:%s' % (tns_prefix, val_type_qname) 341 bds.addAttribute(element, pyxb.namespace.XMLSchema_instance.createExpandedName('type'), val_type_qname) 342 self._toDOM_csc(bds, element) 343 bds.finalize() 344 return bds.document()
345
346 - def toxml (self, bds=None, root_only=False):
347 """Shorthand to get the object as an XML document. 348 349 If you want to set the default namespace, pass in a pre-configured 350 C{bds}. 351 352 @param bds: Optional L{pyxb.utils.domutils.BindingDOMSupport} instance 353 to use for creation. If not provided (default), a new generic one is 354 created. 355 """ 356 dom = self.toDOM(bds) 357 if root_only: 358 dom = dom.documentElement 359 return dom.toxml()
360
361 - def _toDOM_csc (self, dom_support, parent):
362 assert parent is not None 363 if self.__xsiNil: 364 dom_support.addAttribute(parent, pyxb.namespace.XMLSchema_instance.createExpandedName('nil'), 'true') 365 return getattr(super(_TypeBinding_mixin, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
366
367 - def _validateBinding_vx (self):
368 """Override in subclasses for type-specific validation of instance 369 content. 370 371 @return: C{True} if the instance validates 372 @raise pyxb.BindingValidationError: complex content does not match model 373 @raise pyxb.BadTypeValueError: simple content fails to satisfy constraints 374 """ 375 raise pyxb.IncompleteImplementationError('%s did not override _validateBinding_vx' % (type(self),))
376
377 - def validateBinding (self):
378 """Check whether the binding content matches its content model. 379 380 @return: C{True} if validation succeeds. 381 @raise pyxb.BindingValidationError: complex content does not match model 382 @raise pyxb.BadTypeValueError: simple content fails to satisfy constraints 383 """ 384 if self._PerformValidation: 385 self._validateBinding_vx() 386 return True
387 388 @classmethod
389 - def _Name (cls):
390 if cls._ExpandedName is not None: 391 name = str(cls._ExpandedName) 392 else: 393 name = str(type(cls)) 394 return name
395
396 -class _DynamicCreate_mixin (pyxb.cscRoot):
397 """Helper to allow overriding the implementation class. 398 399 Generally we'll want to augment the generated bindings by subclassing 400 them, and adding functionality to the subclass. This mix-in provides a 401 way to communicate the existence of the superseding subclass back to the 402 binding infrastructure, so that when it creates an instance it uses the 403 subclass rather than the unaugmented binding class. 404 405 When a raw generated binding is subclassed, L{_SetSupersedingClass} should be 406 invoked on the raw class passing in the superseding subclass. E.g.:: 407 408 class mywsdl (raw.wsdl): 409 pass 410 raw.wsdl._SetSupersedingClass(mywsdl) 411 412 """ 413 414 @classmethod
416 return '_%s__SupersedingClass' % (cls.__name__,)
417 418 @classmethod
420 return '_%s__AlternativeConstructor' % (cls.__name__,)
421 422 @classmethod
423 - def _SupersedingClass (cls):
424 """Return the class stored in the class reference attribute.""" 425 return getattr(cls, cls.__SupersedingClassAttribute(), cls)
426 427 @classmethod
428 - def _AlternativeConstructor (cls):
429 """Return the class stored in the class reference attribute.""" 430 rv = getattr(cls, cls.__AlternativeConstructorAttribute(), None) 431 if isinstance(rv, tuple): 432 rv = rv[0] 433 return rv
434 435 @classmethod
436 - def _SetSupersedingClass (cls, superseding):
437 """Set the class reference attribute. 438 439 @param superseding: A Python class that is a subclass of this class. 440 """ 441 assert (superseding is None) or issubclass(superseding, cls) 442 if superseding is None: 443 cls.__dict__.pop(cls.__SupersedingClassAttribute(), None) 444 else: 445 setattr(cls, cls.__SupersedingClassAttribute(), superseding) 446 return superseding
447 448 @classmethod
449 - def _SetAlternativeConstructor (cls, alternative_constructor):
450 attr = cls.__AlternativeConstructorAttribute() 451 if alternative_constructor is None: 452 cls.__dict__.pop(attr, None) 453 else: 454 # Need to use a tuple as the value: if you use an invokable, this 455 # ends up converting it from a function to an unbound method, 456 # which is not what we want. 457 setattr(cls, attr, (alternative_constructor,)) 458 assert cls._AlternativeConstructor() == alternative_constructor 459 return alternative_constructor
460 461 @classmethod
462 - def _DynamicCreate (cls, *args, **kw):
463 """Invoke the constructor for this class or the one that supersedes it.""" 464 ctor = cls._AlternativeConstructor() 465 if ctor is None: 466 ctor = cls._SupersedingClass() 467 try: 468 return ctor(*args, **kw) 469 except TypeError, e: 470 raise pyxb.BadTypeValueError(e)
471
472 -class simpleTypeDefinition (_TypeBinding_mixin, utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
473 """L{simpleTypeDefinition} is a base class that is part of the 474 hierarchy of any class that represents the Python datatype for a 475 L{SimpleTypeDefinition<pyxb.xmlschema.structures.SimpleTypeDefinition>}. 476 477 @note: This class, or a descendent of it, must be the first class 478 in the method resolution order when a subclass has multiple 479 parents. Otherwise, constructor keyword arguments may not be 480 removed before passing them on to Python classes that do not 481 accept them. 482 """ 483 484 # A map from leaf classes in the facets module to instance of 485 # those classes that constrain or otherwise affect the datatype. 486 # Note that each descendent of simpleTypeDefinition has its own map. 487 __FacetMap = {} 488 489 _ReservedSymbols = _TypeBinding_mixin._ReservedSymbols.union(set([ 'XsdLiteral', 'xsdLiteral', 490 'XsdSuperType', 'XsdPythonType', 'XsdConstraintsOK', 491 'xsdConstraintsOK', 'XsdValueLength', 'xsdValueLength', 492 'PythonLiteral', 'pythonLiteral', 493 'SimpleTypeDefinition' ])) 494 """Symbols that remain the responsibility of this class. Any 495 public symbols in generated binding subclasses are deconflicted 496 by providing an alternative name in the subclass. (There 497 currently are no public symbols in generated SimpleTypeDefinion 498 bindings.""" 499 500 501 @classmethod
502 - def _ConfigureBindingStyle (cls, style):
503 if BINDING_STYLE_PROPERTY == style: 504 pass 505 elif BINDING_STYLE_ACCESSOR == style: 506 pass 507 else: 508 raise pyxb.LogicError('Unrecognized binding style %s' % (style,))
509 510 # Determine the name of the class-private facet map. For the base class 511 # this should produce the same attribute name as Python's privatization 512 # scheme. 513 @classmethod
514 - def __FacetMapAttributeName (cls):
515 if cls == simpleTypeDefinition: 516 return '_%s__FacetMap' % (cls.__name__.strip('_'),) 517 518 # It is not uncommon for a class in one namespace to extend a class of 519 # the same name in a different namespace, so encode the namespace URI 520 # in the attribute name (if it is part of a namespace). 521 ns_uri = '' 522 try: 523 ns_uri = cls._ExpandedName.namespaceURI() 524 except Exception, e: 525 pass 526 nm = '_' + utility.MakeIdentifier('%s_%s_FacetMap' % (ns_uri, cls.__name__.strip('_'))) 527 return nm
528 529 530 @classmethod
531 - def _FacetMap (cls):
532 """Return a reference to the facet map for this datatype. 533 534 The facet map is a map from leaf facet classes to instances of those 535 classes that constrain or otherwise apply to the lexical or value 536 space of the datatype. Classes may inherit their facet map from their 537 superclass, or may create a new class instance if the class adds a new 538 constraint type. 539 540 :raise AttributeError: if the facet map has not been defined""" 541 return getattr(cls, cls.__FacetMapAttributeName())
542 543 @classmethod
544 - def _InitializeFacetMap (cls, *args):
545 """Initialize the facet map for this datatype. 546 547 This must be called exactly once, after all facets belonging to the 548 datatype have been created. 549 550 :raise pyxb.LogicError: if called multiple times (on the same class) 551 :raise pyxb.LogicError: if called when a parent class facet map has not been initialized 552 :return: the facet map""" 553 fm = None 554 try: 555 fm = cls._FacetMap() 556 except AttributeError: 557 pass 558 if fm is not None: 559 raise pyxb.LogicError('%s facet map initialized multiple times: %s' % (cls.__name__,cls.__FacetMapAttributeName())) 560 561 # Search up the type hierarchy to find the nearest ancestor that has a 562 # facet map. This gets a bit tricky: if we hit the ceiling early 563 # because the PSTD hierarchy re-based itself on a new Python type, we 564 # have to jump to the XsdSuperType. 565 source_class = cls 566 while fm is None: 567 # Assume we're staying in this hierarchy. Include source_class in 568 # the candidates, since we might have jumped to it. 569 for super_class in source_class.mro(): 570 #print 'Superclass for %s is %s' % (source_class, super_class) 571 assert super_class is not None 572 if (super_class == simpleTypeDefinition): # and (source_class.XsdSuperType() is not None): 573 break 574 if issubclass(super_class, simpleTypeDefinition): 575 try: 576 fm = super_class._FacetMap() 577 #print 'Selected facet map for %s from %s: %s' % (cls, super_class, fm) 578 break 579 except AttributeError: 580 pass 581 if fm is None: 582 try: 583 source_class = source_class.XsdSuperType() 584 except AttributeError: 585 source_class = None 586 #print 'Nothing acceptable found, jumped to %s' % (source_class,) 587 if source_class is None: 588 fm = { } 589 #print 'Done with set' 590 if fm is None: 591 raise pyxb.LogicError('%s is not a child of simpleTypeDefinition' % (cls.__name__,)) 592 fm = fm.copy() 593 #print 'Augmenting %s map had %d elts with %d from args' % (cls, len(fm), len(args)) 594 for facet in args: 595 fm[type(facet)] = facet 596 #for (fc, fi) in fm.items(): 597 # print ' %s : %s' % (fc, fi) 598 setattr(cls, cls.__FacetMapAttributeName(), fm) 599 return fm
600 601 @classmethod
602 - def _ConvertArguments_vx (cls, args, kw):
603 return args
604 605 @classmethod
606 - def _ConvertArguments (cls, args, kw):
607 """Pre-process the arguments. 608 609 This is used before invoking the parent constructor. One application 610 is to apply the whitespace facet processing; if such a request is in 611 the keywords, it is removed so it does not propagate to the 612 superclass. Another application is to convert the arguments from a 613 string to a list. Binding-specific applications are performed in the 614 overloaded L{_ConvertArguments_vx} method.""" 615 dom_node = kw.pop('_dom_node', None) 616 if dom_node is not None: 617 text_content = domutils.ExtractTextContent(dom_node) 618 if text_content is not None: 619 args = (domutils.ExtractTextContent(dom_node),) + args 620 kw['_apply_whitespace_facet'] = True 621 apply_whitespace_facet = kw.pop('_apply_whitespace_facet', True) 622 if (0 < len(args)) and isinstance(args[0], types.StringTypes): 623 cf_whitespace = getattr(cls, '_CF_whiteSpace', None) 624 if cf_whitespace is not None: 625 #print 'Apply whitespace %s to "%s"' % (cf_whitespace, args[0]) 626 norm_str = unicode(cf_whitespace.normalizeString(args[0])) 627 args = (norm_str,) + args[1:] 628 return cls._ConvertArguments_vx(args, kw)
629 630 # Must override new, because new gets invoked before init, and usually 631 # doesn't accept keywords. In case it does (e.g., datetime.datetime), 632 # only remove the ones that would normally be interpreted by this class. 633 # Do the same argument conversion as is done in init. Trap errors and 634 # convert them to BadTypeValue errors. 635 # 636 # Note: We explicitly do not validate constraints here. That's 637 # done in the normal constructor; here, we might be in the process 638 # of building a value that eventually will be legal, but isn't 639 # yet.
640 - def __new__ (cls, *args, **kw):
641 # PyXBFactoryKeywords 642 kw.pop('_validate_constraints', None) 643 kw.pop('_require_value', None) 644 kw.pop('_element', None) 645 kw.pop('_fallback_namespace', None) 646 kw.pop('_nil', None) 647 # ConvertArguments will remove _element and _apply_whitespace_facet 648 args = cls._ConvertArguments(args, kw) 649 assert issubclass(cls, _TypeBinding_mixin) 650 try: 651 rv = super(simpleTypeDefinition, cls).__new__(cls, *args, **kw) 652 return rv 653 except ValueError, e: 654 raise pyxb.BadTypeValueError(e) 655 except OverflowError, e: 656 raise pyxb.BadTypeValueError(e)
657 658 # Validate the constraints after invoking the parent constructor, 659 # unless told not to.
660 - def __init__ (self, *args, **kw):
661 """Initialize a newly created STD instance. 662 663 Usually there is one positional argument, which is a value that can be 664 converted to the underlying Python type. 665 666 @keyword _validate_constraints: If True (default), the newly 667 constructed value is checked against its constraining facets. 668 @type _validate_constraints: C{bool} 669 """ 670 # PyXBFactoryKeywords 671 validate_constraints = kw.pop('_validate_constraints', self._PerformValidation) 672 require_value = kw.pop('_require_value', False) 673 # _ConvertArguments handles _dom_node and _apply_whitespace_facet 674 # TypeBinding_mixin handles _nil and _element 675 args = self._ConvertArguments(args, kw) 676 try: 677 super(simpleTypeDefinition, self).__init__(*args, **kw) 678 except OverflowError, e: 679 raise pyxb.BadTypeValueError(e) 680 if require_value and (not self._constructedWithValue()): 681 raise pyxb.MissingContentError('missing value') 682 683 if validate_constraints: 684 self.xsdConstraintsOK()
685 686 687 # The class attribute name used to store the reference to the STD 688 # component instance must be unique to the class, not to this base class. 689 # Otherwise we mistakenly believe we've already associated a STD instance 690 # with a class (e.g., xsd:normalizedString) when in fact it's associated 691 # with the superclass (e.g., xsd:string) 692 @classmethod
693 - def __STDAttrName (cls):
694 return '_%s__SimpleTypeDefinition' % (cls.__name__,)
695 696 @classmethod
697 - def _SimpleTypeDefinition (cls, std):
698 """Set the L{pyxb.xmlschema.structures.SimpleTypeDefinition} instance 699 associated with this binding.""" 700 attr_name = cls.__STDAttrName() 701 if hasattr(cls, attr_name): 702 old_value = getattr(cls, attr_name) 703 if old_value != std: 704 raise pyxb.LogicError('%s: Attempt to override existing STD %s with %s' % (cls, old_value.name(), std.name())) 705 setattr(cls, attr_name, std)
706 707 @classmethod
708 - def SimpleTypeDefinition (cls):
709 """Return the SimpleTypeDefinition instance for the given 710 class. 711 712 This should only be invoked when generating bindings. 713 714 @raise pyxb.IncompleteImplementationError: no STD instance has been 715 associated with the class. 716 717 """ 718 attr_name = cls.__STDAttrName() 719 if hasattr(cls, attr_name): 720 return getattr(cls, attr_name) 721 raise pyxb.IncompleteImplementationError('%s: No STD available' % (cls,))
722 723 @classmethod
724 - def XsdLiteral (cls, value):
725 """Convert from a python value to a string usable in an XML 726 document. 727 728 This should be implemented in the subclass.""" 729 raise pyxb.LogicError('%s does not implement XsdLiteral' % (cls,))
730
731 - def xsdLiteral (self):
732 """Return text suitable for representing the value of this 733 instance in an XML document. 734 735 The base class implementation delegates to the object class's 736 XsdLiteral method.""" 737 return self.XsdLiteral(self)
738 739 @classmethod
740 - def XsdSuperType (cls):
741 """Find the nearest parent class in the PST hierarchy. 742 743 The value for anySimpleType is None; for all others, it's a 744 primitive or derived PST descendent (including anySimpleType).""" 745 for sc in cls.mro(): 746 if sc == cls: 747 continue 748 if simpleTypeDefinition == sc: 749 # If we hit the PST base, this is a primitive type or 750 # otherwise directly descends from a Python type; return 751 # the recorded XSD supertype. 752 return cls._XsdBaseType 753 if issubclass(sc, simpleTypeDefinition): 754 return sc 755 raise pyxb.LogicError('No supertype found for %s' % (cls,))
756 757 @classmethod
758 - def _XsdConstraintsPreCheck_vb (cls, value):
759 """Pre-extended class method to verify other things before 760 checking constraints. 761 762 This is used for list types, to verify that the values in the 763 list are acceptable, and for token descendents, to check the 764 lexical/value space conformance of the input. 765 """ 766 super_fn = getattr(super(simpleTypeDefinition, cls), '_XsdConstraintsPreCheck_vb', lambda *a,**kw: value) 767 return super_fn(value)
768 769 @classmethod
770 - def XsdConstraintsOK (cls, value):
771 """Validate the given value against the constraints on this class. 772 773 @raise pyxb.BadTypeValueError: if any constraint is violated. 774 """ 775 776 value = cls._XsdConstraintsPreCheck_vb(value) 777 778 facet_values = None 779 780 # When setting up the datatypes, if we attempt to validate 781 # something before the facets have been initialized (e.g., a 782 # nonNegativeInteger used as a length facet for the parent 783 # integer datatype), just ignore that. 784 try: 785 facet_values = cls._FacetMap().values() 786 except AttributeError: 787 return value 788 for f in facet_values: 789 if not f.validateConstraint(value): 790 raise pyxb.BadTypeValueError('%s violation for %s in %s' % (f.Name(), value, cls.__name__)) 791 #print '%s ok for %s' % (f, value) 792 return None
793
794 - def xsdConstraintsOK (self):
795 """Validate the value of this instance against its constraints.""" 796 return self.XsdConstraintsOK(self)
797
798 - def _validateBinding_vx (self):
799 if not self._isNil(): 800 self._checkValidValue() 801 return True
802 803 @classmethod
804 - def XsdValueLength (cls, value):
805 """Return the length of the given value. 806 807 The length is calculated by a subclass implementation of 808 _XsdValueLength_vx in accordance with 809 http://www.w3.org/TR/xmlschema-2/#rf-length. 810 811 The return value is a non-negative integer, or C{None} if length 812 constraints should be considered trivially satisfied (as with 813 QName and NOTATION). 814 815 :raise pyxb.LogicError: the provided value is not an instance of cls. 816 :raise pyxb.LogicError: an attempt is made to calculate a length for 817 an instance of a type that does not support length calculations. 818 """ 819 assert isinstance(value, cls) 820 if not hasattr(cls, '_XsdValueLength_vx'): 821 raise pyxb.LogicError('Class %s does not support length validation' % (cls.__name__,)) 822 return cls._XsdValueLength_vx(value)
823
824 - def xsdValueLength (self):
825 """Return the length of this instance within its value space. 826 827 See XsdValueLength.""" 828 return self.XsdValueLength(self)
829 830 @classmethod
831 - def PythonLiteral (cls, value):
832 """Return a string which can be embedded into Python source to 833 represent the given value as an instance of this class.""" 834 class_name = cls.__name__ 835 return '%s(%s)' % (class_name, repr(value))
836
837 - def pythonLiteral (self):
838 """Return a string which can be embedded into Python source to 839 represent the value of this instance.""" 840 return self.PythonLiteral(self)
841
842 - def _toDOM_csc (self, dom_support, parent):
843 assert parent is not None 844 parent.appendChild(dom_support.document().createTextNode(self.xsdLiteral())) 845 return getattr(super(simpleTypeDefinition, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
846 847 @classmethod
848 - def _IsSimpleTypeContent (cls):
849 """STDs have simple type content.""" 850 return True
851 852 @classmethod
853 - def _IsValidValue (self, value):
854 try: 855 self._CheckValidValue(value) 856 return True 857 except pyxb.PyXBException, e: 858 pass 859 return False
860 861 @classmethod
862 - def _CheckValidValue (cls, value):
863 864 """NB: Invoking this on a value that is a list will, if necessary, 865 replace the members of the list with new values that are of the 866 correct item type. This is permitted because only with lists is it 867 possible to bypass the normal content validation (by invoking 868 append/extend on the list instance).""" 869 if value is None: 870 raise pyxb.BadTypeValueError('None is not a valid instance of %s' % (cls,)) 871 #print 'testing value %s type %s against %s' % (value, type(value), cls) 872 value_class = cls 873 if issubclass(cls, STD_list): 874 #print ' -- checking list of %s' % (cls._ItemType,) 875 try: 876 iter(value) 877 except TypeError, e: 878 raise pyxb.BadTypeValueError('%s cannot have non-iterable value type %s' % (cls, type(value))) 879 for v in value: 880 if not cls._ItemType._IsValidValue(v): 881 raise pyxb.BadTypeValueError('%s cannot have member of type %s (want %s)' % (cls, type(v), cls._ItemType)) 882 else: 883 if issubclass(cls, STD_union): 884 #print ' -- checking union with %d types' % (len(cls._MemberTypes),) 885 value_class = None 886 for mt in cls._MemberTypes: 887 if mt._IsValidValue(value): 888 value_class = mt 889 break 890 if value_class is None: 891 raise pyxb.BadTypeValueError('%s cannot have value type %s' % (cls, type(value))) 892 #if not (isinstance(value, value_class) or issubclass(value_class, type(value))): 893 if not isinstance(value, value_class): 894 raise pyxb.BadTypeValueError('Value type %s is not valid for %s' % (type(value), cls)) 895 value_class.XsdConstraintsOK(value)
896
897 - def _checkValidValue (self):
898 self._CheckValidValue(self)
899
900 - def _isValidValue (self):
901 self._IsValidValue(self)
902 903 @classmethod
904 - def _description (cls, name_only=False, user_documentation=True):
905 name = cls._Name() 906 if name_only: 907 return name 908 desc = [ name, ' restriction of ', cls.XsdSuperType()._description(name_only=True) ] 909 if user_documentation and (cls._Documentation is not None): 910 desc.extend(["\n", cls._Documentation]) 911 return ''.join(desc)
912
913 -class STD_union (simpleTypeDefinition):
914 """Base class for union datatypes. 915 916 This class descends only from simpleTypeDefinition. A pyxb.LogicError is 917 raised if an attempt is made to construct an instance of a subclass of 918 STD_union. Values consistent with the member types are constructed using 919 the Factory class method. Values are validated using the _ValidatedMember 920 class method. 921 922 Subclasses must provide a class variable _MemberTypes which is a 923 tuple of legal members of the union.""" 924 925 _MemberTypes = None 926 """A list of classes which are permitted as values of the union.""" 927 928 # Ick: If we don't declare this here, this class's map doesn't get 929 # initialized. Alternative is to not descend from simpleTypeDefinition. 930 # @todo Ensure that pattern and enumeration are valid constraints 931 __FacetMap = {} 932 933 @classmethod
934 - def Factory (cls, *args, **kw):
935 """Given a value, attempt to create an instance of some member of this 936 union. The first instance which can be legally created is returned. 937 938 @keyword _validate_constraints: If True (default), any constructed 939 value is checked against constraints applied to the union as well as 940 the member type. 941 942 @raise pyxb.BadTypeValueError: no member type will permit creation of 943 an instance from the parameters in C{args} and C{kw}. 944 """ 945 946 used_cls = cls._SupersedingClass() 947 state = used_cls._PreFactory_vx(args, kw) 948 949 rv = None 950 # NB: get, not pop: preserve it for the member type invocations 951 validate_constraints = kw.get('_validate_constraints', cls._PerformValidation) 952 assert isinstance(validate_constraints, bool) 953 if 0 < len(args): 954 arg = args[0] 955 try: 956 rv = cls._ValidatedMember(arg) 957 except pyxb.BadTypeValueError, e: 958 pass 959 if rv is None: 960 kw['_validate_constraints'] = True 961 for mt in cls._MemberTypes: 962 try: 963 rv = mt.Factory(*args, **kw) 964 break 965 except pyxb.BadTypeValueError: 966 pass 967 except ValueError: 968 pass 969 except: 970 pass 971 if rv is not None: 972 if validate_constraints: 973 cls.XsdConstraintsOK(rv) 974 rv._postFactory_vx(state) 975 return rv 976 raise pyxb.BadTypeValueError('%s cannot construct union member from args %s' % (cls.__name__, args))
977 978 @classmethod
979 - def _ValidatedMember (cls, value):
980 """Validate the given value as a potential union member. 981 982 @raise pyxb.BadTypeValueError: the value is not an instance of a 983 member type.""" 984 if not isinstance(value, cls._MemberTypes): 985 for mt in cls._MemberTypes: 986 try: 987 # Force validation so we get the correct type, otherwise 988 # first member will be accepted. 989 value = mt.Factory(value, _validate_constraints=True) 990 return value 991 except (TypeError, pyxb.BadTypeValueError): 992 pass 993 raise pyxb.BadTypeValueError('%s cannot hold a member of type %s' % (cls.__name__, value.__class__.__name__)) 994 return value
995
996 - def __init__ (self, *args, **kw):
997 raise pyxb.LogicError('%s: cannot construct instances of union' % (self.__class__.__name__,))
998 999 @classmethod
1000 - def _description (cls, name_only=False, user_documentation=True):
1001 name = cls._Name() 1002 if name_only: 1003 return name 1004 desc = [ name, ', union of '] 1005 desc.append(', '.join([ _td._description(name_only=True) for _td in cls._MemberTypes ])) 1006 return ''.join(desc)
1007 1008 @classmethod
1009 - def XsdLiteral (cls, value):
1010 """Convert from a binding value to a string usable in an XML document.""" 1011 return cls._ValidatedMember(value).xsdLiteral()
1012
1013 1014 -class STD_list (simpleTypeDefinition, types.ListType):
1015 """Base class for collection datatypes. 1016 1017 This class descends from the Python list type, and incorporates 1018 simpleTypeDefinition. Subclasses must define a class variable _ItemType 1019 which is a reference to the class of which members must be instances.""" 1020 1021 _ItemType = None 1022 """A reference to the binding class for items within this list.""" 1023 1024 # Ick: If we don't declare this here, this class's map doesn't get 1025 # initialized. Alternative is to not descend from simpleTypeDefinition. 1026 __FacetMap = {} 1027 1028 @classmethod
1029 - def _ValidatedItem (cls, value):
1030 """Verify that the given value is permitted as an item of this list. 1031 1032 This may convert the value to the proper type, if it is 1033 compatible but not an instance of the item type. Returns the 1034 value that should be used as the item, or raises an exception 1035 if the value cannot be converted.""" 1036 if isinstance(value, cls._ItemType): 1037 pass 1038 elif issubclass(cls._ItemType, STD_union): 1039 value = cls._ItemType._ValidatedMember(value) 1040 else: 1041 try: 1042 value = cls._ItemType(value) 1043 except (pyxb.BadTypeValueError, TypeError): 1044 raise pyxb.BadTypeValueError('Type %s has member of type %s, must be %s' % (cls.__name__, type(value).__name__, cls._ItemType.__name__)) 1045 return value
1046 1047 @classmethod
1048 - def _ConvertArguments_vx (cls, args, kw):
1049 # If the first argument is a string, split it on spaces and use the 1050 # resulting list of tokens. 1051 if 0 < len(args): 1052 arg1 = args[0] 1053 if isinstance(arg1, types.StringTypes): 1054 args = (arg1.split(),) + args[1:] 1055 arg1 = args[0] 1056 is_iterable = False 1057 try: 1058 iter(arg1) 1059 is_iterable = True 1060 except TypeError: 1061 pass 1062 if is_iterable: 1063 new_arg1 = [] 1064 for i in range(len(arg1)): 1065 new_arg1.append(cls._ValidatedItem(arg1[i])) 1066 args = (new_arg1,) + args[1:] 1067 super_fn = getattr(super(STD_list, cls), '_ConvertArguments_vx', lambda *a,**kw: args) 1068 return super_fn(args, kw)
1069 1070 @classmethod
1071 - def _XsdValueLength_vx (cls, value):
1072 return len(value)
1073 1074 @classmethod
1075 - def XsdLiteral (cls, value):
1076 """Convert from a binding value to a string usable in an XML document.""" 1077 return ' '.join([ cls._ItemType.XsdLiteral(_v) for _v in value ])
1078 1079 @classmethod
1080 - def _description (cls, name_only=False, user_documentation=True):
1081 name = cls._Name() 1082 if name_only: 1083 return name 1084 desc = [ name, ', list of ', cls._ItemType._description(name_only=True) ] 1085 return ''.join(desc)
1086 1087 # Convert a single value to the required type, if not already an instance 1088 @classmethod
1089 - def __ConvertOne (cls, v):
1090 return cls._ValidatedItem(v)
1091 1092 # Convert a sequence of values to the required type, if not already instances
1093 - def __convertMany (self, values):
1094 return [ self._ValidatedItem(_v) for _v in values ]
1095
1096 - def __setitem__ (self, key, value):
1097 if isinstance(key, slice): 1098 super(STD_list, self).__setitem__(key, self.__convertMany(values)) 1099 else: 1100 super(STD_list, self).__setitem__(key, self._ValidatedItem(value))
1101
1102 - def __setslice__ (self, start, end, values):
1103 super(STD_list, self).__setslice__(start, end, self.__convertMany(values))
1104
1105 - def __contains__ (self, item):
1106 return super(STD_list, self).__contains__(self._ValidatedItem(item))
1107 1108 # Standard mutable sequence methods, per Python Library Reference "Mutable Sequence Types" 1109
1110 - def append (self, x):
1111 super(STD_list, self).append(self._ValidatedItem(x))
1112
1113 - def extend (self, x):
1114 super(STD_list, self).extend(self.__convertMany(x))
1115
1116 - def count (self, x):
1117 return super(STD_list, self).count(self._ValidatedItem(x))
1118
1119 - def index (self, x, *args):
1120 return super(STD_list, self).index(self._ValidatedItem(x), *args)
1121
1122 - def insert (self, i, x):
1123 super(STD_list, self).insert(i, self._ValidatedItem(x))
1124
1125 - def remove (self, x):
1126 super(STD_list, self).remove(self._ValidatedItem(x))
1127
1128 -class element (utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
1129 """Class that represents a schema element. 1130 1131 Global and local elements are represented by instances of this class. 1132 """ 1133
1134 - def name (self):
1135 """The expanded name of the element within its scope.""" 1136 return self.__name
1137 __name = None 1138
1139 - def typeDefinition (self):
1140 """The L{_TypeBinding_mixin} subclass for values of this element.""" 1141 return self.__typeDefinition._SupersedingClass()
1142 __typeDefinition = None 1143
1144 - def scope (self):
1145 """The scope of the element. This is either C{None}, representing a 1146 top-level element, or an instance of C{complexTypeDefinition} for 1147 local elements.""" 1148 return self.__scope
1149 __scope = None 1150
1151 - def nillable (self):
1152 """Indicate whether values matching this element can have U{nil 1153 <http://www.w3.org/TR/xmlschema-1/#xsi_nil>} set.""" 1154 return self.__nillable
1155 __nillable = False 1156
1157 - def abstract (self):
1158 """Indicate whether this element is abstract (must use substitution 1159 group members for matches).""" 1160 return self.__abstract
1161 __abstract = False 1162
1163 - def documentation (self):
1164 """Contents of any documentation annotation in the definition.""" 1165 return self.__documentation
1166 __documentation = None 1167
1168 - def defaultValue (self):
1169 return self.__defaultValue
1170 __defaultValue = None 1171
1172 - def substitutionGroup (self):
1173 """The L{element} instance to whose substitution group this element 1174 belongs. C{None} if this element is not part of a substitution 1175 group.""" 1176 return self.__substitutionGroup
1177 - def _setSubstitutionGroup (self, substitution_group):
1178 self.__substitutionGroup = substitution_group 1179 return self
1180 __substitutionGroup = None 1181
1182 - def findSubstituendUse (self, ctd_class):
1183 eu = ctd_class._ElementMap.get(self.name()) 1184 if eu is not None: 1185 return eu 1186 if self.substitutionGroup() is None: 1187 return None 1188 return self.substitutionGroup().findSubstituendUse(ctd_class)
1189
1190 - def substitutesFor (self, other):
1191 """Determine whether an instance of this element can substitute for the other element. 1192 1193 See U{Substitution Group OK<http://www.w3.org/TR/xmlschema-1/#cos-equiv-derived-ok-rec>)}. 1194 1195 @todo: Do something about blocking constraints. This ignores them, as 1196 does everything leading to this point. 1197 """ 1198 if other is None: 1199 return False 1200 assert isinstance(other, element) 1201 # On the first call, other is likely to be the local element. We need 1202 # the global one. 1203 if other.scope() is not None: 1204 other = other.name().elementBinding() 1205 if other is None: 1206 return False 1207 assert other.scope() is None 1208 # Do both these refer to the same (top-level) element? 1209 if self.name().elementBinding() == other: 1210 return True 1211 if self.substitutionGroup() is None: 1212 return False 1213 return (self.substitutionGroup() == other) or self.substitutionGroup().substitutesFor(other)
1214
1215 - def memberElement (self, name):
1216 """Return a reference to the element instance used for the given name 1217 within this element. 1218 1219 The type for this element must be a complex type definition.""" 1220 return self.typeDefinition()._UseForTag(name).elementBinding()
1221
1222 - def __init__ (self, name, type_definition, scope=None, nillable=False, abstract=False, default_value=None, substitution_group=None, documentation=None):
1223 """Create a new element binding. 1224 """ 1225 assert isinstance(name, pyxb.namespace.ExpandedName) 1226 self.__name = name 1227 self.__typeDefinition = type_definition 1228 self.__scope = scope 1229 self.__nillable = nillable 1230 self.__abstract = abstract 1231 self.__defaultValue = default_value 1232 self.__substitutionGroup = substitution_group 1233 self.__documentation = documentation
1234
1235 - def __call__ (self, *args, **kw):
1236 """Invoke the Factory method on the type associated with this element. 1237 1238 @keyword _dom_node: If set, specifies a DOM node that should be used 1239 for initialization. In that case, the L{createFromDOM} method is 1240 invoked instead of the type definition Factory method. 1241 1242 @raise pyxb.AbstractElementError: This element is abstract and no DOM 1243 node was provided. 1244 """ 1245 dom_node = kw.pop('_dom_node', None) 1246 assert dom_node is None, 'Cannot pass DOM node directly to element constructor; use createFromDOM' 1247 if '_element' in kw: 1248 raise pyxb.LogicError('Cannot set _element in element-based instance creation') 1249 kw['_element'] = self 1250 # Can't create instances of abstract elements. 1251 if self.abstract(): 1252 raise pyxb.AbstractElementError(self) 1253 return self.typeDefinition().Factory(*args, **kw)
1254
1255 - def compatibleValue (self, value, **kw):
1256 """Return a variant of the value that is compatible with this element. 1257 1258 This mostly defers to L{_TypeBinding_mixin._CompatibleValue}. 1259 1260 @raise pyxb.BadTypeValueError: if the value is not both 1261 type-consistent and value-consistent with the element's type. 1262 """ 1263 # None is always None 1264 if value is None: 1265 return None 1266 is_plural = kw.get('is_plural', False) 1267 #print 'validating %s against %s, isPlural %s' % (type(value), self.typeDefinition(), is_plural) 1268 if is_plural: 1269 try: 1270 iter(value) 1271 except TypeError: 1272 raise pyxb.BadTypeValueError('Expected plural value, got %s' % (type(value),)) 1273 return [ self.compatibleValue(_v) for _v in value ] 1274 if isinstance(value, _TypeBinding_mixin) and (value._element() is not None) and value._element().substitutesFor(self): 1275 return value 1276 return self.typeDefinition()._CompatibleValue(value, **kw)
1277 1278 # element 1279 @classmethod
1280 - def AnyCreateFromDOM (cls, node, _fallback_namespace):
1281 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1282 node = node.documentElement 1283 expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=_fallback_namespace) 1284 elt = expanded_name.elementBinding() 1285 if elt is None: 1286 raise pyxb.UnrecognizedElementError('No element binding available for %s' % (expanded_name,)) 1287 assert isinstance(elt, pyxb.binding.basis.element) 1288 # Pass on the namespace to use when resolving unqualified qnames as in 1289 # xsi:type 1290 return elt._createFromDOM(node, expanded_name, _fallback_namespace=_fallback_namespace)
1291
1292 - def elementForName (self, name):
1293 """Return the element that should be used if this element binding is 1294 permitted and an element with the given name is encountered. 1295 1296 Normally, the incoming name matches the name of this binding, and 1297 C{self} is returned. If the incoming name is different, it is 1298 expected to be the name of a global element which is within this 1299 element's substitution group. In that case, the binding corresponding 1300 to the named element is return. 1301 1302 @return: An instance of L{element}, or C{None} if no element with the 1303 given name can be found. 1304 """ 1305 1306 # Name match means OK. 1307 if self.name() == name: 1308 return self 1309 # No name match means only hope is a substitution group, for which the 1310 # element must be top-level. 1311 top_elt = self.name().elementBinding() 1312 if top_elt is None: 1313 return None 1314 # Members of the substitution group must also be top-level. NB: If 1315 # named_elt == top_elt, then the adoptName call below improperly 1316 # associated the global namespace with a local element of the same 1317 # name; cf. test-namespace-uu:testBad. 1318 elt_en = top_elt.name().adoptName(name) 1319 assert 'elementBinding' in elt_en.namespace()._categoryMap(), 'No element bindings in %s' % (elt_en.namespace(),) 1320 named_elt = elt_en.elementBinding() 1321 if (named_elt is None) or (named_elt == top_elt): 1322 return None 1323 if named_elt.substitutesFor(top_elt): 1324 return named_elt 1325 return None
1326
1327 - def createFromDOM (self, node, expanded_name=None, fallback_namespace=None, **kw):
1328 """Create a binding instance from the given DOM node. 1329 1330 @keyword expanded_name: Optional name for the DOM node. If not 1331 present, is inferred from C{node}. 1332 1333 @keyword fallback_namespace: Optional namespace to use when resolving 1334 unqualified names. 1335 """ 1336 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1337 node = node.documentElement 1338 if expanded_name is None: 1339 expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=fallback_namespace) 1340 return self._createFromDOM(node, expanded_name, **kw)
1341
1342 - def _createFromDOM (self, node, expanded_name, **kw):
1343 """Create a binding instance from the given DOM node, using the 1344 provided name to identify the correct binding. 1345 1346 The context and information associated with this element is used to 1347 identify the actual element binding to use. By default, C{self} is 1348 used. If this element represents a term in a content model, the name 1349 and namespace of the incoming node may identify a different element. 1350 If that element is a member of this element's substitution group, the 1351 binding associated with the node's name will be used instead. 1352 1353 The type of object returned is determined by the type definition 1354 associated with the element binding and the value of any U{xsi:type 1355 <http://www.w3.org/TR/xmlschema-1/#xsi_type>} attribute found in the 1356 node. 1357 1358 Keyword parameters are passed to the factory method of the type 1359 associated with the selected element binding. See 1360 L{_TypeBinding_mixin} and any specializations of it. 1361 1362 @param expanded_name: The expanded name of the node. If the value is 1363 C{None}, defaults to the name of this element. (In the case of 1364 substitution groups, the default is wrong, but correct inference 1365 depends on context not available here.) 1366 1367 @keyword _fallback_namespace: Optional namespace to use when resolving 1368 unqualified type names. 1369 1370 @param node: The DOM node specifying the element content. If this is 1371 a (top-level) Document node, its element node is used. 1372 @type node: C{xml.dom.Node} 1373 @return: An instance of L{_TypeBinding_mixin} 1374 @raise pyxb.StructuralBadDocumentError: The node's name does identify an element binding. 1375 @raise pyxb.AbstractElementError: The element binding associated with the node is abstract. 1376 @raise pyxb.BadDocumentError: An U{xsi:type <http://www.w3.org/TR/xmlschema-1/#xsi_type>} attribute in the node fails to resolve to a recognized type 1377 @raise pyxb.BadDocumentError: An U{xsi:type <http://www.w3.org/TR/xmlschema-1/#xsi_type>} attribute in the node resolves to a type that is not a subclass of the type of the element binding. 1378 """ 1379 1380 # Bypass the useless top-level node and start with the element beneath 1381 # it. 1382 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1383 node = node.documentElement 1384 1385 # Identify the element binding to be used for the given node. NB: 1386 # Even if found, this may not be equal to self, since we allow you to 1387 # use an abstract substitution group head to create instances from DOM 1388 # nodes that are in that group. 1389 fallback_namespace = kw.pop('_fallback_namespace', None) 1390 element_binding = self.elementForName(expanded_name) 1391 if element_binding is None: 1392 raise pyxb.StructuralBadDocumentError('Element %s cannot create from node %s' % (self.name(), expanded_name)) 1393 1394 # Can't create instances of abstract elements. @todo: Is there any 1395 # way this could be legal given an xsi:type attribute? I'm pretty 1396 # sure "no"... 1397 if element_binding.abstract(): 1398 raise pyxb.AbstractElementError(element_binding) 1399 1400 # Record the element to be associated with the created binding 1401 # instance. 1402 if '_element' in kw: 1403 raise pyxb.LogicError('Cannot set _element in element-based instance creation') 1404 kw['_element'] = element_binding 1405 1406 # Now determine the type binding for the content. If xsi:type is 1407 # used, it won't be the one built into the element binding. 1408 type_class = element_binding.typeDefinition() 1409 xsi_type = pyxb.namespace.ExpandedName(pyxb.namespace.XMLSchema_instance, 'type') 1410 type_name = xsi_type.getAttribute(node) 1411 elt_ns = element_binding.name().namespace() 1412 1413 # Get the namespace context for the value being created. If none is 1414 # associated, one will be created. Do not make assumptions about the 1415 # namespace context; if the user cared, she should have assigned a 1416 # context before calling this. 1417 ns_ctx = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(node) 1418 if type_name is not None: 1419 # xsi:type should only be provided when using an abstract class, 1420 # or a concrete class that happens to be the same, but in practice 1421 # web services tend to set it on nodes just to inform their 1422 # lax-processing clients how to interpret the value. 1423 1424 type_en = ns_ctx.interpretQName(type_name, namespace=fallback_namespace) 1425 try: 1426 alternative_type_class = type_en.typeBinding() 1427 except KeyError, e: 1428 raise pyxb.BadDocumentError('No type binding for %s' % (type_name,)) 1429 if not issubclass(alternative_type_class, type_class): 1430 raise pyxb.BadDocumentError('%s value %s is not subclass of element type %s' % (xsi_type, type_en, type_class._ExpandedName)) 1431 type_class = alternative_type_class 1432 1433 # Pass xsi:nil on to the constructor regardless of whether the element 1434 # is nillable. Another sop to SOAP-encoding WSDL fans who don't 1435 # bother to provide valid schema for their message content. 1436 xsi_nil = pyxb.namespace.ExpandedName(pyxb.namespace.XMLSchema_instance, 'nil') 1437 is_nil = xsi_nil.getAttribute(node) 1438 if is_nil is not None: 1439 kw['_nil'] = pyxb.binding.datatypes.boolean(is_nil) 1440 1441 rv = type_class.Factory(_dom_node=node, _fallback_namespace=fallback_namespace, **kw) 1442 assert rv._element() == element_binding 1443 rv._setNamespaceContext(ns_ctx) 1444 if pyxb._ParsingRequiresValid: 1445 rv.validateBinding() 1446 return rv
1447
1448 - def __str__ (self):
1449 return 'Element %s' % (self.name(),)
1450
1451 - def _description (self, name_only=False, user_documentation=True):
1452 name = str(self.name()) 1453 if name_only: 1454 return name 1455 desc = [ name, ' (', self.typeDefinition()._description(name_only=True), ')' ] 1456 if self.scope() is not None: 1457 desc.extend([', local to ', self.scope()._description(name_only=True) ]) 1458 if self.nillable(): 1459 desc.append(', nillable') 1460 if self.substitutionGroup() is not None: 1461 desc.extend([', substitutes for ', self.substitutionGroup()._description(name_only=True) ]) 1462 if user_documentation and (self.documentation() is not None): 1463 desc.extend(["\n", self.documentation() ]) 1464 return ''.join(desc)
1465
1466 -class enumeration_mixin (pyxb.cscRoot):
1467 """Marker in case we need to know that a PST has an enumeration constraint facet.""" 1468 pass
1469
1470 -class complexTypeDefinition (_TypeBinding_mixin, utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
1471 """Base for any Python class that serves as the binding for an 1472 XMLSchema complexType. 1473 1474 Subclasses should define a class-level _AttributeMap variable which maps 1475 from the unicode tag of an attribute to the AttributeUse instance that 1476 defines it. Similarly, subclasses should define an _ElementMap variable. 1477 """ 1478 1479 _CT_EMPTY = 'EMPTY' #<<< No content 1480 _CT_SIMPLE = 'SIMPLE' #<<< Simple (character) content 1481 _CT_MIXED = 'MIXED' #<<< Children may be elements or other (e.g., character) content 1482 _CT_ELEMENT_ONLY = 'ELEMENT_ONLY' #<<< Expect only element content. 1483 1484 _ContentTypeTag = None 1485 1486 _TypeDefinition = None 1487 """Subclass of simpleTypeDefinition that corresponds to the type content. 1488 Only valid if _ContentTypeTag is _CT_SIMPLE""" 1489 1490 # If the type supports wildcard attributes, this describes their 1491 # constraints. (If it doesn't, this should remain None.) Supporting 1492 # classes should override this value. 1493 _AttributeWildcard = None 1494 1495 _AttributeMap = { } 1496 """Map from expanded names to AttributeUse instances.""" 1497 1498 # A value that indicates whether the content model for this type supports 1499 # wildcard elements. Supporting classes should override this value. 1500 _HasWildcardElement = False 1501 1502 # Map from expanded names to ElementUse instances 1503 _ElementMap = { } 1504 """Map from expanded names to ElementUse instances.""" 1505 1506 # Per-instance map from tags to attribute values for wildcard attributes. 1507 # Value is C{None} if the type does not support wildcard attributes. 1508 __wildcardAttributeMap = None 1509
1510 - def wildcardAttributeMap (self):
1511 """Obtain access to wildcard attributes. 1512 1513 The return value is C{None} if this type does not support wildcard 1514 attributes. If wildcard attributes are allowed, the return value is a 1515 map from QNames to the unicode string value of the corresponding 1516 attribute. 1517 1518 @todo: The map keys should be namespace extended names rather than 1519 QNames, as the in-scope namespace may not be readily available to the 1520 user. 1521 """ 1522 return self.__wildcardAttributeMap
1523 1524 # Per-instance list of DOM nodes interpreted as wildcard elements. 1525 # Value is None if the type does not support wildcard elements. 1526 __wildcardElements = None 1527
1528 - def wildcardElements (self):
1529 """Obtain access to wildcard elements. 1530 1531 The return value is C{None} if the content model for this type does not 1532 support wildcard elements. If wildcard elements are allowed, the 1533 return value is a list of values corresponding to conformant 1534 unrecognized elements, in the order in which they were encountered. 1535 If the containing binding was created from an XML document and enough 1536 information was present to determine the binding of the member 1537 element, the value is a binding instance. Otherwise, the value is the 1538 original DOM Element node. 1539 """ 1540 return self.__wildcardElements
1541 1542 @classmethod
1543 - def _ConfigureBindingStyle (cls, style):
1544 if BINDING_STYLE_PROPERTY == style: 1545 pass 1546 elif BINDING_STYLE_ACCESSOR == style: 1547 pass 1548 else: 1549 raise pyxb.LogicError('Unrecognized binding style %s' % (style,))
1550 1551 __XSINil = pyxb.namespace.XMLSchema_instance.createExpandedName('nil')
1552 - def __init__ (self, *args, **kw):
1553 """Create a new instance of this binding. 1554 1555 Arguments are used as transition values along the content model. 1556 Keywords are passed to the constructor of any simple content, or used 1557 to initialize attribute and element values whose L{id 1558 <content.ElementUse.id>} matches the keyword. 1559 1560 @keyword _dom_node: The node to use as the source of binding content. 1561 @type _dom_node: C{xml.dom.Element} 1562 1563 """ 1564 1565 fallback_namespace = kw.pop('_fallback_namespace', None) 1566 is_nil = False 1567 dom_node = kw.pop('_dom_node', None) 1568 if dom_node is not None: 1569 if isinstance(dom_node, pyxb.utils.utility.Locatable_mixin): 1570 self._setLocation(dom_node.location) 1571 if xml.dom.Node.DOCUMENT_NODE == dom_node.nodeType: 1572 dom_node = dom_node.documentElement 1573 #kw['_validate_constraints'] = False 1574 is_nil = self.__XSINil.getAttribute(dom_node) 1575 if is_nil is not None: 1576 is_nil = kw['_nil'] = pyxb.binding.datatypes.boolean(is_nil) 1577 if self._AttributeWildcard is not None: 1578 self.__wildcardAttributeMap = { } 1579 if self._HasWildcardElement: 1580 self.__wildcardElements = [] 1581 if self._Abstract: 1582 raise pyxb.AbstractInstantiationError(type(self)) 1583 super(complexTypeDefinition, self).__init__(**kw) 1584 self.reset() 1585 # Extract keywords that match field names 1586 attribute_settings = { } 1587 if dom_node is not None: 1588 attribute_settings.update(self.__AttributesFromDOM(dom_node)) 1589 for fu in self._AttributeMap.values(): 1590 iv = kw.get(fu.id()) 1591 if iv is not None: 1592 attribute_settings[fu.name()] = iv 1593 for (attr_en, value) in attribute_settings.items(): 1594 au = self._setAttribute(attr_en, value) 1595 for fu in self._ElementMap.values(): 1596 iv = kw.get(fu.id()) 1597 if iv is not None: 1598 fu.set(self, iv) 1599 if dom_node is not None: 1600 if self._CT_SIMPLE == self._ContentTypeTag: 1601 self.__initializeSimpleContent(args, dom_node) 1602 else: 1603 self._setContentFromDOM(dom_node, fallback_namespace) 1604 elif 0 < len(args): 1605 self.extend(args) 1606 else: 1607 if self._CT_SIMPLE == self._ContentTypeTag: 1608 self.__initializeSimpleContent(args, dom_node)
1609
1610 - def __initializeSimpleContent (self, args, dom_node=None):
1611 # Don't propagate the keywords. Python base simple types usually 1612 # don't like them, and even if they do we're not using them here. (Do 1613 # need to propagate _nil, though, to correctly handle types derived 1614 # from basestring.) 1615 value = self._TypeDefinition.Factory(_require_value=not self._isNil(), _dom_node=dom_node, _nil=self._isNil(), *args) 1616 if value._constructedWithValue(): 1617 if self._isNil(): 1618 raise pyxb.ContentInNilElementError(value) 1619 else: 1620 self.append(value)
1621 1622 # Specify the symbols to be reserved for all CTDs. 1623 _ReservedSymbols = _TypeBinding_mixin._ReservedSymbols.union(set([ 'wildcardElements', 'wildcardAttributeMap', 1624 'xsdConstraintsOK', 'content', 'append', 'extend', 'value', 'reset' ])) 1625 1626 # None, or a reference to a ContentModel instance that defines how to 1627 # reduce a DOM node list to the body of this element. 1628 _ContentModel = None 1629 1630 @classmethod
1631 - def _AddElement (cls, element):
1632 """Method used by generated code to associate the element binding with a use in this type. 1633 1634 This is necessary because all complex type classes appear in the 1635 module prior to any of the element instances (which reference type 1636 classes), so the association must be formed after the element 1637 instances are available.""" 1638 return cls._UseForTag(element.name())._setElementBinding(element)
1639 1640 @classmethod
1641 - def _UseForTag (cls, tag, raise_if_fail=True):
1642 """Return the ElementUse object corresponding to the element name. 1643 1644 @param tag: The L{ExpandedName} of an element in the class.""" 1645 rv = cls._ElementMap.get(tag) 1646 if (rv is None) and raise_if_fail: 1647 raise pyxb.NotAnElementError('Unable to locate element %s in type %s' % (tag, cls._ExpandedName)) 1648 return rv
1649
1650 - def __childrenForDOM (self):
1651 """Generate a list of children in the order in which they should be 1652 added to the parent when creating a DOM representation of this 1653 object. 1654 1655 @note: This is not currently used; it is retained as an example of one 1656 way to override L{_validatedChildren} in cases where content model 1657 validation is not required. 1658 """ 1659 order = [] 1660 for eu in self._ElementMap.values(): 1661 value = eu.value(self) 1662 if value is None: 1663 continue 1664 if isinstance(value, list): 1665 order.extend([ (eu, _v) for _v in value ]) 1666 continue 1667 order.append( (eu, value) ) 1668 return order
1669
1670 - def _validatedChildren (self):
1671 """Provide the child elements and non-element content in an order 1672 consistent with the content model. 1673 1674 Returns a sequence of tuples representing a valid path through the 1675 content model where each transition corresponds to one of the member 1676 element instances within this instance. The tuple is a pair 1677 comprising the L{content.ElementUse} instance and the value for the 1678 transition. 1679 1680 If the content of the instance does not validate against the content 1681 model, C{None} is returned. 1682 1683 The base class implementation uses the 1684 L{content.ContentModel.validate} method. Subclasses may desire to 1685 override this in cases where the desired order is not maintained by 1686 model interpretation (for example, when an "all" model is used and the 1687 original element order is desired). See L{__childrenForDOM} as an 1688 example of an alternative approach. 1689 1690 @return: C{None} or a list as described above. 1691 """ 1692 if self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE): 1693 return [] 1694 1695 if self._ContentModel is None: 1696 raise pyxb.NoContentModel(self) 1697 path = self._ContentModel.validate(self._symbolSet()) 1698 if path is not None: 1699 ( symbols, sequence ) = path 1700 if 0 == len(symbols): 1701 return sequence 1702 raise pyxb.BindingValidationError('Ungenerated symbols: %s' % (symbols,) ) 1703 return None
1704
1705 - def _symbolSet (self):
1706 """Return a map from L{content.ElementUse} instances to a list of 1707 values associated with that use. 1708 1709 This is used as the set of symbols available for transitions when 1710 validating content against a model. Note that the order of values 1711 within a use is likely to be significant, although the model cannot 1712 detect this. 1713 1714 The value C{None} should be used to provide a list of wildcard 1715 members. 1716 1717 If an element use has no associated values, it must not appear in the 1718 returned map. 1719 """ 1720 rv = { } 1721 for eu in self._ElementMap.values(): 1722 value = eu.value(self) 1723 if value is None: 1724 continue 1725 res = None 1726 converter = eu.elementBinding().compatibleValue 1727 if eu.isPlural(): 1728 if 0 < len(value): 1729 rv[eu] = [ converter(_v) for _v in value ] 1730 else: 1731 rv[eu] = [ converter(value)] 1732 wce = self.wildcardElements() 1733 if (wce is not None) and (0 < len(wce)): 1734 rv[None] = wce 1735 return rv
1736
1737 - def _validateAttributes (self):
1738 for au in self._AttributeMap.values(): 1739 au.validate(self)
1740 1741
1742 - def _validateBinding_vx (self):
1743 if self._isNil(): 1744 if (self._IsSimpleTypeContent() and (self.__content is not None)) or self.__content: 1745 raise pyxb.ContentInNilElementError(self._ExpandedName) 1746 return True 1747 if self._IsSimpleTypeContent() and (self.__content is None): 1748 raise pyxb.MissingContentError(self._TypeDefinition) 1749 try: 1750 order = self._validatedChildren() 1751 except Exception, e: 1752 raise pyxb.BindingValidationError('Error matching content to binding model: %s' % (e,)) 1753 if order is None: 1754 raise pyxb.BindingValidationError('Unable to match content to binding model') 1755 for (eu, value) in order: 1756 if isinstance(value, _TypeBinding_mixin): 1757 value.validateBinding() 1758 elif eu is not None: 1759 print 'WARNING: Cannot validate value %s in field %s' % (value, eu.id()) 1760 self._validateAttributes() 1761 return True
1762 1763 @classmethod
1764 - def __AttributesFromDOM (cls, node):
1765 attribute_settings = { } 1766 for ai in range(0, node.attributes.length): 1767 attr = node.attributes.item(ai) 1768 # NB: Specifically do not consider attr's NamespaceContext, since 1769 # attributes do not accept a default namespace. 1770 attr_en = pyxb.namespace.ExpandedName(attr) 1771 1772 # Ignore xmlns and xsi attributes; we've already handled those 1773 if attr_en.namespace() in ( pyxb.namespace.XMLNamespaces, pyxb.namespace.XMLSchema_instance ): 1774 continue 1775 1776 value = attr.value 1777 au = cls._AttributeMap.get(attr_en) 1778 if au is None: 1779 if cls._AttributeWildcard is None: 1780 raise pyxb.UnrecognizedAttributeError('Attribute %s is not permitted in type %s' % (attr_en, cls._ExpandedName)) 1781 attribute_settings[attr_en] = value 1782 return attribute_settings
1783
1784 - def _setAttribute (self, attr_en, value):
1785 au = self._AttributeMap.get(attr_en, None) 1786 if au is None: 1787 if self._AttributeWildcard is None: 1788 raise pyxb.UnrecognizedAttributeError('Attribute %s is not permitted in type %s' % (attr_en, self._ExpandedName)) 1789 self.__wildcardAttributeMap[attr_en] = value 1790 else: 1791 au.set(self, value) 1792 return au
1793
1794 - def __setAttributes (self, attribute_settings, dom_node):
1795 """Initialize the attributes of this element from those of the DOM node. 1796 1797 @raise pyxb.UnrecognizedAttributeError: if the DOM node has attributes 1798 that are not allowed in this type 1799 @raise pyxb.ProhibitedAttributeError: a prohibited attribute was encountered 1800 @raise pyxb.MissingAttributeError: a required attribute could not be found 1801 """ 1802 1803 # Handle all the attributes that are present in the node 1804 attrs_available = set(self._AttributeMap.values()) 1805 for (attr_en, value) in attribute_settings.items(): 1806 au = self._setAttribute(attr_en, value) 1807 if au is not None: 1808 attrs_available.remove(au) 1809 1810 return self
1811
1812 - def xsdConstraintsOK (self):
1813 """Validate the content against the simple type. 1814 1815 @return: C{True} if the content validates against its type. 1816 @raise pyxb.NotSimpleContentError: this type does not have simple content. 1817 @raise pyxb.MissingContentError: the content of this type has not been set 1818 """ 1819 # @todo: type check 1820 if self._CT_SIMPLE != self._ContentTypeTag: 1821 raise pyxb.NotSimpleContentError(self) 1822 if self._isNil(): 1823 return True 1824 if self.value() is None: 1825 raise pyxb.MissingContentError(self) 1826 return self.value().xsdConstraintsOK()
1827 1828 __content = None
1829 - def content (self):
1830 """Return the content of the element. 1831 1832 This must be a complex type with complex content. The return value is 1833 a list of the element and non-element content in the order in which it 1834 was added. 1835 @raise pyxb.NotComplexContentError: this is not a complex type with mixed or element-only content 1836 """ 1837 if self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE): 1838 raise pyxb.NotComplexContentError(str(self._ExpandedName)) 1839 return self.__content
1840
1841 - def value (self):
1842 """Return the value of the element. 1843 1844 This must be a complex type with simple content. The returned value 1845 is expected to be an instance of some L{simpleTypeDefinition} class. 1846 1847 @raise pyxb.NotSimpleContentError: this is not a complex type with simple content 1848 """ 1849 if self._CT_SIMPLE != self._ContentTypeTag: 1850 raise pyxb.NotSimpleContentError('%s (%s)' % (str(self._ExpandedName), type(self))) 1851 return self.__content
1852
1853 - def _resetContent (self):
1854 if self._ContentTypeTag in (self._CT_MIXED, self._CT_ELEMENT_ONLY): 1855 self.__setContent([]) 1856 else: 1857 self.__setContent(None)
1858 1859 __dfaStack = None
1860 - def reset (self):
1861 """Reset the instance. 1862 1863 This resets all element and attribute fields, and discards any 1864 recorded content. It resets the DFA to the initial state of the 1865 content model. 1866 """ 1867 1868 self._resetContent() 1869 for au in self._AttributeMap.values(): 1870 au.reset(self) 1871 for eu in self._ElementMap.values(): 1872 eu.reset(self) 1873 if self._ContentModel is not None: 1874 self.__dfaStack = self._ContentModel.initialDFAStack() 1875 return self
1876 1877 @classmethod
1878 - def _ElementBindingUseForName (cls, element_name):
1879 """Determine what the given name means as an element in this type. 1880 1881 Normally, C{element_name} identifies an element definition within this 1882 type. If so, the returned C{element_use} identifies that definition, 1883 and the C{element_binding} is extracted from that use. 1884 1885 It may also be that the C{element_name} does not appear as an element 1886 definition, but that it identifies a global element. In that case, 1887 the returned C{element_binding} identifies the global element. If, 1888 further, that element is a member of a substitution group which does 1889 have an element definition in this class, then the returned 1890 C{element_use} identifies that definition. 1891 1892 If a non-C{None} C{element_use} is returned, there will be an 1893 associated C{element_binding}. However, it is possible to return a 1894 non-C{None} C{element_binding}, but C{None} as the C{element_use}. In 1895 that case, the C{element_binding} can be used to create a binding 1896 instance, but the content model will have to treat it as a wildcard. 1897 1898 @param element_name: The name of the element in this type, either an 1899 expanded name or a local name if the element has an absent namespace. 1900 1901 @return: C{( element_binding, element_use )} 1902 """ 1903 element_use = cls._ElementMap.get(element_name) 1904 element_binding = None 1905 if element_use is None: 1906 try: 1907 element_binding = element_name.elementBinding() 1908 except pyxb.NamespaceError: 1909 pass 1910 if element_binding is not None: 1911 element_use = element_binding.findSubstituendUse(cls) 1912 else: 1913 element_binding = element_use.elementBinding() 1914 return (element_binding, element_use)
1915
1916 - def append (self, value, element_use=None, maybe_element=True, _fallback_namespace=None, require_validation=True):
1917 """Add the value to the instance. 1918 1919 The value should be a DOM node or other value that is or can be 1920 converted to a binding instance. If the instance has a DFA state, the 1921 value must be permitted by the content model. 1922 1923 @raise pyxb.ExtraContentError: the value is not permitted at the 1924 current state of the content model. 1925 """ 1926 1927 # @todo: Allow caller to provide default element use; it's available 1928 # in saxer. 1929 element_binding = None 1930 if element_use is not None: 1931 import content 1932 assert isinstance(element_use, content.ElementUse) 1933 element_binding = element_use.elementBinding() 1934 assert element_binding is not None 1935 # Convert the value if it's XML and we recognize it. 1936 if isinstance(value, xml.dom.Node): 1937 assert maybe_element 1938 assert element_binding is None 1939 node = value 1940 require_validation = pyxb._ParsingRequiresValid 1941 if xml.dom.Node.COMMENT_NODE == node.nodeType: 1942 # @todo: Note that we're allowing comments inside the bodies 1943 # of simple content elements, which isn't really Hoyle. 1944 return self 1945 if node.nodeType in (xml.dom.Node.TEXT_NODE, xml.dom.Node.CDATA_SECTION_NODE): 1946 value = node.data 1947 maybe_element = False 1948 else: 1949 # Do type conversion here 1950 assert xml.dom.Node.ELEMENT_NODE == node.nodeType 1951 expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=_fallback_namespace) 1952 (element_binding, element_use) = self._ElementBindingUseForName(expanded_name) 1953 if element_binding is not None: 1954 value = element_binding._createFromDOM(node, expanded_name, _fallback_namespace=_fallback_namespace) 1955 else: 1956 # Might be a resolvable wildcard. See if we can convert it to an 1957 # element. 1958 #print 'Attempting to create element from node %s' % (expanded_name,) 1959 try: 1960 ns = expanded_name.namespace() 1961 if ns is not None: 1962 for mr in ns.moduleRecords(): 1963 try: 1964 if (mr.module() is None) and (mr.modulePath() is not None): 1965 print 'Importing %s to get binding for wildcard %s' % (mr.modulePath(), expanded_name) 1966 mod = __import__(mr.modulePath()) 1967 for c in mr.modulePath().split('.')[1:]: 1968 mod = getattr(mod, c) 1969 mr._setModule(mod) 1970 value = mr.module().CreateFromDOM(node) 1971 break 1972 except pyxb.PyXBException, e: 1973 print 'Ignoring creating binding for wildcard %s: %s' % (expanded_name, e) 1974 except AttributeError, e: 1975 # The module holding XMLSchema bindnigs does not 1976 # have a CreateFromDOM method, and shouldn't since 1977 # we need to convert schema instances to DOM more 1978 # carefully. 1979 if mr.namespace() != pyxb.namespace.XMLSchema: 1980 raise 1981 except Exception, e: 1982 print 'WARNING: Unable to convert DOM node %s to Python instance: %s' % (expanded_name, e) 1983 if (not maybe_element) and isinstance(value, basestring) and (self._ContentTypeTag in (self._CT_EMPTY, self._CT_ELEMENT_ONLY)): 1984 if (0 == len(value.strip())) and not self._isNil(): 1985 return self 1986 if self._isNil() and not self._IsSimpleTypeContent(): 1987 raise pyxb.ExtraContentError('%s: Content %s present in element with xsi:nil' % (type(self), value)) 1988 if maybe_element and (self.__dfaStack is not None): 1989 # Allows element content. 1990 if not require_validation: 1991 if element_use is not None: 1992 element_use.setOrAppend(self, value) 1993 return self 1994 raise pyxb.binding.StructuralBadDocumentError('Validation is required when no element_use can be found') 1995 if self.wildcardElements() is not None: 1996 self._appendWildcardElement(value) 1997 return self 1998 else: 1999 if self.__dfaStack.step(self, value, element_use): 2000 return self 2001 # If what we have is element content, we can't accept it, either 2002 # because the type doesn't accept element content or because it does 2003 # and what we got didn't match the content model. 2004 if (element_binding is not None) or isinstance(value, xml.dom.Node): 2005 raise pyxb.ExtraContentError('%s: Extra content starting with %s' % (self._ExpandedName, value,)) 2006 2007 # We have something that doesn't seem to be an element. Are we 2008 # expecting simple content? 2009 if self._IsSimpleTypeContent(): 2010 if self.__content is not None: 2011 raise pyxb.ExtraContentError('Extra content starting with %s (already have %s)' % (value, self.__content)) 2012 if not self._isNil(): 2013 if not isinstance(value, self._TypeDefinition): 2014 value = self._TypeDefinition.Factory(value) 2015 self.__setContent(value) 2016 if require_validation: 2017 # NB: This only validates the value, not any associated 2018 # attributes, which is correct to be parallel to complex 2019 # content validation. 2020 self.xsdConstraintsOK() 2021 return self 2022 2023 # Do we allow non-element content? 2024 if not self._IsMixed(): 2025 raise pyxb.UnexpectedNonElementContentError(value) 2026 if isinstance(value, _TypeBinding_mixin): 2027 raise pyxb.ExtraContentError('Extra content starting with %s' % (value,)) 2028 2029 self._addContent(value, element_binding) 2030 return self
2031
2032 - def _appendWildcardElement (self, value):
2033 wcl = self.wildcardElements() 2034 if wcl is None: 2035 raise pyxb.UnrecognizedContentError(value) 2036 wcl.append(value)
2037
2038 - def extend (self, value_list, _fallback_namespace=None):
2039 """Invoke L{append} for each value in the list, in turn.""" 2040 [ self.append(_v, _fallback_namespace=_fallback_namespace) for _v in value_list ] 2041 return self
2042
2043 - def __setContent (self, value):
2044 self.__content = value
2045
2046 - def _addContent (self, child, element_binding):
2047 # This assert is inadequate in the case of plural/non-plural elements with an STD_list base type. 2048 # Trust that validation elsewhere was done correctly. 2049 #assert self._IsMixed() or (not self._PerformValidation) or isinstance(child, _TypeBinding_mixin) or isinstance(child, types.StringTypes), 'Unrecognized child %s type %s' % (child, type(child)) 2050 assert not (self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE)) 2051 if isinstance(child, _TypeBinding_mixin) and (child._element() is None): 2052 child._setElement(element_binding) 2053 self.__content.append(child)
2054 2055 @classmethod
2056 - def _IsMixed (cls):
2057 return (cls._CT_MIXED == cls._ContentTypeTag)
2058
2059 - def _setContentFromDOM (self, node, _fallback_namespace):
2060 """Initialize the content of this element from the content of the DOM node.""" 2061 2062 self.extend(node.childNodes[:], _fallback_namespace) 2063 if self._PerformValidation and (not self._isNil()) and (self.__dfaStack is not None) and (not self.__dfaStack.isTerminal()): 2064 raise pyxb.MissingContentError() 2065 return self
2066
2067 - def _setDOMFromAttributes (self, dom_support, element):
2068 """Add any appropriate attributes from this instance into the DOM element.""" 2069 for au in self._AttributeMap.values(): 2070 au.addDOMAttribute(dom_support, self, element) 2071 return element
2072
2073 - def _toDOM_csc (self, dom_support, parent):
2074 """Create a DOM element with the given tag holding the content of this instance.""" 2075 element = parent 2076 self._setDOMFromAttributes(dom_support, element) 2077 if self._isNil(): 2078 pass 2079 elif self._CT_EMPTY == self._ContentTypeTag: 2080 pass 2081 elif self._CT_SIMPLE == self._ContentTypeTag: 2082 assert self.value() is not None, '%s has no value' % (self,) 2083 element.appendChild(dom_support.document().createTextNode(self.value().xsdLiteral())) 2084 else: 2085 if pyxb._GenerationRequiresValid: 2086 order = self._validatedChildren() 2087 else: 2088 order = self.__childrenForDOM() 2089 if order is None: 2090 raise pyxb.DOMGenerationError('Binding value inconsistent with content model') 2091 for (eu, v) in order: 2092 assert v != self 2093 if eu is None: 2094 if isinstance(v, xml.dom.Node): 2095 element.appendChild(v) 2096 else: 2097 v.toDOM(dom_support, parent) 2098 else: 2099 eu.toDOM(dom_support, parent, v) 2100 mixed_content = self.content() 2101 for mc in mixed_content: 2102 pass 2103 return getattr(super(complexTypeDefinition, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
2104 2105 @classmethod
2106 - def _IsSimpleTypeContent (cls):
2107 """CTDs with simple content are simple; other CTDs are not.""" 2108 return cls._CT_SIMPLE == cls._ContentTypeTag
2109 2110 @classmethod
2111 - def _description (cls, name_only=False, user_documentation=True):
2112 name = cls._Name() 2113 if name_only: 2114 return name 2115 desc = [ name ] 2116 if cls._CT_EMPTY == cls._ContentTypeTag: 2117 desc.append(', empty content') 2118 elif cls._CT_SIMPLE == cls._ContentTypeTag: 2119 desc.extend([', simple content type ', cls._TypeDefinition._description(name_only=True)]) 2120 else: 2121 if cls._CT_MIXED == cls._ContentTypeTag: 2122 desc.append(', mixed content') 2123 else: 2124 assert cls._CT_ELEMENT_ONLY == cls._ContentTypeTag 2125 desc.append(', element-only content') 2126 if (0 < len(cls._AttributeMap)) or (cls._AttributeWildcard is not None): 2127 desc.append("\nAttributes:\n ") 2128 desc.append("\n ".join([ _au._description(user_documentation=False) for _au in cls._AttributeMap.values() ])) 2129 if cls._AttributeWildcard is not None: 2130 desc.append("\n Wildcard attribute(s)") 2131 if (0 < len(cls._ElementMap)) or cls._HasWildcardElement: 2132 desc.append("\nElements:\n ") 2133 desc.append("\n ".join([ _eu._description(user_documentation=False) for _eu in cls._ElementMap.values() ])) 2134 if cls._HasWildcardElement: 2135 desc.append("\n Wildcard element(s)") 2136 return ''.join(desc)
2137 2138 ConfigureBindingStyle(DEFAULT_BINDING_STYLE) 2139 2140 ## Local Variables: 2141 ## fill-column:78 2142 ## End: 2143