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  from pyxb.namespace.builtin import XMLSchema_instance as XSI 
  25   
  26  BINDING_STYLE_ACCESSOR = 'accessor' 
  27  BINDING_STYLE_PROPERTY = 'property' 
  28   
  29  BINDING_STYLES = (BINDING_STYLE_ACCESSOR, BINDING_STYLE_PROPERTY) 
  30  DEFAULT_BINDING_STYLE = BINDING_STYLE_PROPERTY 
  31  CURRENT_BINDING_STYLE = None 
32 33 -def ConfigureBindingStyle (style):
34 global CURRENT_BINDING_STYLE 35 simpleTypeDefinition._ConfigureBindingStyle(style) 36 complexTypeDefinition._ConfigureBindingStyle(style) 37 CURRENT_BINDING_STYLE = style
38
39 -class _TypeBinding_mixin (utility.Locatable_mixin):
40 41 @classmethod
42 - def _PerformValidation (cls):
43 """Determine whether the content model should be validated. 44 45 Proper validation is not yet supported in PyXB. The low level binding 46 material consults this function, but not always in a context where the 47 direction of translation is clear. Conseequently, this method 48 indicates that validation should be performed only when both 49 generation and parsing validation are enabled.""" 50 # return True 51 return pyxb._GenerationRequiresValid and pyxb._ParsingRequiresValid
52 53 _ExpandedName = None 54 """The expanded name of the component.""" 55 56 _ReservedSymbols = set([ 'validateBinding', 'toDOM', 'toxml', 'Factory', 'property' ]) 57
58 - def __setattr__ (self, name, value):
59 if name in self._ReservedSymbols: 60 raise pyxb.BindingError('Attempt to set reserved name %s in instance of %s' % (name, type(self))) 61 return super(_TypeBinding_mixin, self).__setattr__(name, value)
62 63 # @todo: We don't actually use this anymore; get rid of it, just leaving a 64 # comment describing each keyword. 65 _PyXBFactoryKeywords = ( '_dom_node', '_fallback_namespace', '_apply_whitespace_facet', '_validate_constraints', '_require_value', '_nil', '_element' ) 66 """Keywords that are interpreted by __new__ or __init__ in one or more 67 classes in the PyXB type hierarchy. All these keywords must be removed 68 before invoking base Python __init__ or __new__.""" 69 70 # While simple type definitions cannot be abstract, they can appear in 71 # many places where complex types can, so we want it to be legal to test 72 # for abstractness without checking whether the object is a complex type. 73 _Abstract = False 74
75 - def _namespaceContext (self):
76 """Return a L{namespace context <pyxb.binding.NamespaceContext>} 77 associated with the binding instance. 78 79 This will return C{None} unless something has provided a context to 80 the instance. Context is provided when instances are generated by the 81 DOM and SAX-based translators.""" 82 return self.__namespaceContext
83 - def _setNamespaceContext (self, namespace_context):
84 """Associate a L{namespace context <pyxb.binding.NamespaceContext>} 85 with the binding instance.""" 86 self.__namespaceContext = namespace_context 87 return self
88 __namespaceContext = None 89
90 - def _setElement (self, element):
91 """Associate a L{pyxb.binding.basis.element} with the instance.""" 92 self.__element = element 93 return self
94 - def _element (self):
95 """Return a L{pyxb.binding.basis.element} associated with the binding 96 instance. 97 98 This will return C{None} unless an element has been associated. 99 Constructing a binding instance using the element instance will add 100 this association. 101 """ 102 return self.__element
103 __element = None 104 105 __xsiNil = None
106 - def _isNil (self):
107 """Indicate whether this instance is U{nil 108 <http://www.w3.org/TR/xmlschema-1/#xsi_nil>}. 109 110 The value is set by the DOM and SAX parsers when building an instance 111 from a DOM element with U{xsi:nil 112 <http://www.w3.org/TR/xmlschema-1/#xsi_nil>} set to C{true}. 113 114 @return: C{None} if the element used to create the instance is not 115 U{nillable<http://www.w3.org/TR/xmlschema-1/#nillable>}. 116 If it is nillable, returns C{True} or C{False} depending on 117 whether the instance itself is U{nil<http://www.w3.org/TR/xmlschema-1/#xsi_nil>}. 118 """ 119 return self.__xsiNil
120 - def _setIsNil (self):
121 """Set the xsi:nil property of the instance. 122 123 @raise pyxb.NoNillableSupportError: the instance is not associated 124 with an element that is L{nillable 125 <pyxb.binding.basis.element.nillable>}. 126 """ 127 if self.__xsiNil is None: 128 raise pyxb.NoNillableSupportError(type(self)) 129 self.__xsiNil = True 130 self._resetContent()
131
132 - def _resetContent (self):
133 pass
134 135 __constructedWithValue = False
136 - def __checkNilCtor (self, args):
137 self.__constructedWithValue = (0 < len(args)) 138 if self.__xsiNil: 139 if self.__constructedWithValue: 140 raise pyxb.ContentInNilElementError(args[0]) 141 else: 142 # Types that descend from string will, when constructed from an 143 # element with empty content, appear to have no constructor value, 144 # while in fact an empty string should have been passed. 145 if issubclass(type(self), basestring): 146 self.__constructedWithValue = True
147 - def _constructedWithValue (self):
148 return self.__constructedWithValue
149 150 # Flag used to control whether we print a warning when creating a complex 151 # type instance that does not have an associated element. Not sure yet 152 # whether that'll be common practice or common error. 153 __WarnedUnassociatedElement = False 154
155 - def __init__ (self, *args, **kw):
156 # Strip keyword not used above this level. 157 element = kw.pop('_element', None) 158 is_nil = kw.pop('_nil', False) 159 super(_TypeBinding_mixin, self).__init__(*args, **kw) 160 if (element is None) or element.nillable(): 161 self.__xsiNil = is_nil 162 self.__checkNilCtor(args) 163 if element is not None: 164 self._setElement(element)
165 166 @classmethod
167 - def _PreFactory_vx (cls, args, kw):
168 """Method invoked upon entry to the Factory method. 169 170 This method is entitled to modify the keywords array. It can also 171 return a state value which is passed to _postFactory_vx.""" 172 return None
173
174 - def _postFactory_vx (cls, state):
175 """Method invoked prior to leaving the Factory method. 176 177 This is an instance method, and is given the state that was returned 178 by _PreFactory_vx.""" 179 return None
180 181 @classmethod
182 - def Factory (cls, *args, **kw):
183 """Provide a common mechanism to create new instances of this type. 184 185 The class constructor won't do, because you can't create 186 instances of union types. 187 188 This method may be overridden in subclasses (like STD_union). Pre- 189 and post-creation actions can be customized on a per-class instance by 190 overriding the L{_PreFactory_vx} and L{_postFactory_vx} methods. 191 192 @keyword _dom_node: If provided, the value must be a DOM node, the 193 content of which will be used to set the value of the instance. 194 195 @keyword _apply_whitespace_facet: If C{True} and this is a 196 simpleTypeDefinition with a whiteSpace facet, the first argument will 197 be normalized in accordance with that facet prior to invoking the 198 parent constructor. 199 200 @keyword _validate_constraints: If C{True}, any constructed value is 201 checked against constraints applied to the union as well as the member 202 type. 203 204 @keyword _require_value: If C{False} (default), it is permitted to 205 create a value without an initial value. If C{True} and no initial 206 value was provided, causes L{pyxb.MissingContentError} to be raised. 207 Only applies to simpleTypeDefinition instances; this is used when 208 creating values from DOM nodes. 209 """ 210 # Invoke _PreFactory_vx for the superseding class, which is where 211 # customizations will be found. 212 dom_node = kw.get('_dom_node') 213 used_cls = cls._SupersedingClass() 214 state = used_cls._PreFactory_vx(args, kw) 215 rv = cls._DynamicCreate(*args, **kw) 216 rv._postFactory_vx(state) 217 if isinstance(dom_node, utility.Locatable_mixin): 218 rv._setLocation(dom_node.location) 219 return rv
220
221 - def _substitutesFor (self, element):
222 if (element is None) or (self._element() is None): 223 return False 224 return self._element().substitutesFor(element)
225 226 @classmethod
227 - def _RequireXSIType (cls, value_type):
228 return cls._Abstract and value_type != cls._SupersedingClass()
229 230 @classmethod
231 - def _CompatibleValue (cls, value, **kw):
232 """Return a variant of the value that is compatible with this type. 233 234 Compatibility is defined relative to the type definition associated 235 with the element. The value C{None} is always compatible. If 236 C{value} has a Python type (e.g., C{int}) that is a superclass of the 237 required L{_TypeBinding_mixin} class (e.g., C{xs:byte}), C{value} is 238 used as a constructor parameter to return a new instance of the 239 required type. Note that constraining facets are applied here if 240 necessary (e.g., although a Python C{int} with value C{500} is 241 type-compatible with C{xs:byte}, it is outside the value space, and 242 compatibility will fail. 243 244 @keyword convert_string_values: If C{True} (default) and the incoming value is 245 a string, an attempt will be made to form a compatible value by using 246 the string as a constructor argument to the this class. This flag is 247 set to C{False} when testing automaton transitions. 248 249 @raise pyxb.BadTypeValueError: if the value is not both 250 type-consistent and value-consistent with the element's type. 251 """ 252 convert_string_values = kw.get('convert_string_values', True) 253 # None is always None 254 if value is None: 255 return None 256 # Already an instance? 257 if isinstance(value, cls): 258 # @todo: Consider whether we should change the associated _element 259 # of this value. (**Consider** it, don't just do it.) 260 return value 261 value_type = type(value) 262 # All string-based PyXB binding types use unicode, not str 263 if str == value_type: 264 value_type = unicode 265 266 # See if we got passed a Python value which needs to be "downcasted" 267 # to the _TypeBinding_mixin version. 268 if issubclass(cls, value_type): 269 return cls(value) 270 271 # See if we have a numeric type that needs to be cast across the 272 # numeric hierarchy. int to long is the *only* conversion we accept. 273 if isinstance(value, int) and issubclass(cls, long): 274 return cls(value) 275 276 # Same, but for boolean, which Python won't let us subclass 277 if isinstance(value, bool) and issubclass(cls, pyxb.binding.datatypes.boolean): 278 return cls(value) 279 280 # See if we have convert_string_values on, and have a string type that 281 # somebody understands. 282 if convert_string_values and (unicode == value_type): 283 return cls(value) 284 285 # Maybe this is a union? 286 if issubclass(cls, STD_union): 287 for mt in cls._MemberTypes: 288 try: 289 return mt._CompatibleValue(value, **kw) 290 except: 291 pass 292 293 # Any type is compatible with the corresponding ur-type 294 if (pyxb.binding.datatypes.anySimpleType == cls) and issubclass(value_type, simpleTypeDefinition): 295 return value 296 if (pyxb.binding.datatypes.anyType == cls) and issubclass(value_type, complexTypeDefinition): 297 return value 298 299 # Is this the wrapper class that indicates we should create a binding 300 # from arguments? 301 if isinstance(value, pyxb.BIND): 302 return value.createInstance(cls.Factory, **kw) 303 304 # There may be other things that can be converted to the desired type, 305 # but we can't tell that from the type hierarchy. Too many of those 306 # things result in an undesirable loss of information: for example, 307 # when an all model supports both numeric and string transitions, the 308 # candidate is a number, and the string transition is tested first. 309 raise pyxb.BadTypeValueError('No conversion from %s to %s' % (value_type, cls))
310 311 @classmethod
312 - def _IsSimpleTypeContent (cls):
313 """Return True iff the content of this binding object is a simple type. 314 315 This is true only for descendents of simpleTypeDefinition and instances 316 of complexTypeDefinition that have simple type content.""" 317 raise pyxb.LogicError('Failed to override _TypeBinding_mixin._IsSimpleTypeContent')
318
319 - def toDOM (self, bds=None, parent=None, element_name=None):
320 """Convert this instance to a DOM node. 321 322 The name of the top-level element is either the name of the L{element} 323 instance associated with this instance, or the XML name of the type of 324 this instance. 325 326 @param bds: Support for customizing the generated document 327 @type bds: L{pyxb.utils.domutils.BindingDOMSupport} 328 @param parent: If C{None}, a standalone document is created; 329 otherwise, the created element is a child of the given element. 330 @type parent: C{xml.dom.Element} or C{None} 331 @rtype: C{xml.dom.Document} 332 """ 333 334 if bds is None: 335 bds = domutils.BindingDOMSupport() 336 need_xsi_type = bds.requireXSIType() 337 if isinstance(element_name, (str, unicode)): 338 element_name = pyxb.namespace.ExpandedName(bds.defaultNamespace(), element_name) 339 if (element_name is None) and (self._element() is not None): 340 element_binding = self._element() 341 element_name = element_binding.name() 342 need_xsi_type = need_xsi_type or element_binding.typeDefinition()._RequireXSIType(type(self)) 343 if element_name is None: 344 element_name = self._ExpandedName 345 element = bds.createChildElement(element_name, parent) 346 if need_xsi_type: 347 val_type_qname = self._ExpandedName.localName() 348 tns_prefix = bds.namespacePrefix(self._ExpandedName.namespace()) 349 if tns_prefix is not None: 350 val_type_qname = '%s:%s' % (tns_prefix, val_type_qname) 351 bds.addAttribute(element, XSI.type, val_type_qname) 352 self._toDOM_csc(bds, element) 353 bds.finalize() 354 return bds.document()
355
356 - def toxml (self, bds=None, root_only=False):
357 """Shorthand to get the object as an XML document. 358 359 If you want to set the default namespace, pass in a pre-configured 360 C{bds}. 361 362 @param bds: Optional L{pyxb.utils.domutils.BindingDOMSupport} instance 363 to use for creation. If not provided (default), a new generic one is 364 created. 365 """ 366 dom = self.toDOM(bds) 367 if root_only: 368 dom = dom.documentElement 369 return dom.toxml()
370
371 - def _toDOM_csc (self, dom_support, parent):
372 assert parent is not None 373 if self.__xsiNil: 374 dom_support.addAttribute(parent, XSI.nil, 'true') 375 return getattr(super(_TypeBinding_mixin, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
376
377 - def _validateBinding_vx (self):
378 """Override in subclasses for type-specific validation of instance 379 content. 380 381 @return: C{True} if the instance validates 382 @raise pyxb.BindingValidationError: complex content does not match model 383 @raise pyxb.BadTypeValueError: simple content fails to satisfy constraints 384 """ 385 raise pyxb.IncompleteImplementationError('%s did not override _validateBinding_vx' % (type(self),))
386
387 - def validateBinding (self):
388 """Check whether the binding content matches its content model. 389 390 @return: C{True} if validation succeeds. 391 @raise pyxb.BindingValidationError: complex content does not match model 392 @raise pyxb.BadTypeValueError: simple content fails to satisfy constraints 393 """ 394 if self._PerformValidation(): 395 self._validateBinding_vx() 396 return True
397 398 @classmethod
399 - def _Name (cls):
400 if cls._ExpandedName is not None: 401 name = str(cls._ExpandedName) 402 else: 403 name = str(type(cls)) 404 return name
405
406 -class _DynamicCreate_mixin (pyxb.cscRoot):
407 """Helper to allow overriding the implementation class. 408 409 Generally we'll want to augment the generated bindings by subclassing 410 them, and adding functionality to the subclass. This mix-in provides a 411 way to communicate the existence of the superseding subclass back to the 412 binding infrastructure, so that when it creates an instance it uses the 413 subclass rather than the unaugmented binding class. 414 415 When a raw generated binding is subclassed, L{_SetSupersedingClass} should be 416 invoked on the raw class passing in the superseding subclass. E.g.:: 417 418 class mywsdl (raw.wsdl): 419 pass 420 raw.wsdl._SetSupersedingClass(mywsdl) 421 422 """ 423 424 @classmethod
426 return '_%s__SupersedingClass' % (cls.__name__,)
427 428 @classmethod
430 return '_%s__AlternativeConstructor' % (cls.__name__,)
431 432 @classmethod
433 - def _SupersedingClass (cls):
434 """Return the class stored in the class reference attribute.""" 435 return getattr(cls, cls.__SupersedingClassAttribute(), cls)
436 437 @classmethod
438 - def _AlternativeConstructor (cls):
439 """Return the class stored in the class reference attribute.""" 440 rv = getattr(cls, cls.__AlternativeConstructorAttribute(), None) 441 if isinstance(rv, tuple): 442 rv = rv[0] 443 return rv
444 445 @classmethod
446 - def _SetSupersedingClass (cls, superseding):
447 """Set the class reference attribute. 448 449 @param superseding: A Python class that is a subclass of this class. 450 """ 451 assert (superseding is None) or issubclass(superseding, cls) 452 if superseding is None: 453 cls.__dict__.pop(cls.__SupersedingClassAttribute(), None) 454 else: 455 setattr(cls, cls.__SupersedingClassAttribute(), superseding) 456 return superseding
457 458 @classmethod
459 - def _SetAlternativeConstructor (cls, alternative_constructor):
460 attr = cls.__AlternativeConstructorAttribute() 461 if alternative_constructor is None: 462 cls.__dict__.pop(attr, None) 463 else: 464 # Need to use a tuple as the value: if you use an invokable, this 465 # ends up converting it from a function to an unbound method, 466 # which is not what we want. 467 setattr(cls, attr, (alternative_constructor,)) 468 assert cls._AlternativeConstructor() == alternative_constructor 469 return alternative_constructor
470 471 @classmethod
472 - def _DynamicCreate (cls, *args, **kw):
473 """Invoke the constructor for this class or the one that supersedes it.""" 474 ctor = cls._AlternativeConstructor() 475 if ctor is None: 476 ctor = cls._SupersedingClass() 477 try: 478 return ctor(*args, **kw) 479 except TypeError, e: 480 raise pyxb.BadTypeValueError(e)
481
482 -class simpleTypeDefinition (_TypeBinding_mixin, utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
483 """L{simpleTypeDefinition} is a base class that is part of the 484 hierarchy of any class that represents the Python datatype for a 485 L{SimpleTypeDefinition<pyxb.xmlschema.structures.SimpleTypeDefinition>}. 486 487 @note: This class, or a descendent of it, must be the first class 488 in the method resolution order when a subclass has multiple 489 parents. Otherwise, constructor keyword arguments may not be 490 removed before passing them on to Python classes that do not 491 accept them. 492 """ 493 494 # A map from leaf classes in the facets module to instance of 495 # those classes that constrain or otherwise affect the datatype. 496 # Note that each descendent of simpleTypeDefinition has its own map. 497 __FacetMap = {} 498 499 _ReservedSymbols = _TypeBinding_mixin._ReservedSymbols.union(set([ 'XsdLiteral', 'xsdLiteral', 500 'XsdSuperType', 'XsdPythonType', 'XsdConstraintsOK', 501 'xsdConstraintsOK', 'XsdValueLength', 'xsdValueLength', 502 'PythonLiteral', 'pythonLiteral', 503 'SimpleTypeDefinition' ])) 504 """Symbols that remain the responsibility of this class. Any 505 public symbols in generated binding subclasses are deconflicted 506 by providing an alternative name in the subclass. (There 507 currently are no public symbols in generated SimpleTypeDefinion 508 bindings.""" 509 510 511 @classmethod
512 - def _ConfigureBindingStyle (cls, style):
513 if BINDING_STYLE_PROPERTY == style: 514 pass 515 elif BINDING_STYLE_ACCESSOR == style: 516 pass 517 else: 518 raise pyxb.LogicError('Unrecognized binding style %s' % (style,))
519 520 # Determine the name of the class-private facet map. For the base class 521 # this should produce the same attribute name as Python's privatization 522 # scheme. 523 @classmethod
524 - def __FacetMapAttributeName (cls):
525 if cls == simpleTypeDefinition: 526 return '_%s__FacetMap' % (cls.__name__.strip('_'),) 527 528 # It is not uncommon for a class in one namespace to extend a class of 529 # the same name in a different namespace, so encode the namespace URI 530 # in the attribute name (if it is part of a namespace). 531 ns_uri = '' 532 try: 533 ns_uri = cls._ExpandedName.namespaceURI() 534 except Exception, e: 535 pass 536 nm = '_' + utility.MakeIdentifier('%s_%s_FacetMap' % (ns_uri, cls.__name__.strip('_'))) 537 return nm
538 539 540 @classmethod
541 - def _FacetMap (cls):
542 """Return a reference to the facet map for this datatype. 543 544 The facet map is a map from leaf facet classes to instances of those 545 classes that constrain or otherwise apply to the lexical or value 546 space of the datatype. Classes may inherit their facet map from their 547 superclass, or may create a new class instance if the class adds a new 548 constraint type. 549 550 :raise AttributeError: if the facet map has not been defined""" 551 return getattr(cls, cls.__FacetMapAttributeName())
552 553 @classmethod
554 - def _InitializeFacetMap (cls, *args):
555 """Initialize the facet map for this datatype. 556 557 This must be called exactly once, after all facets belonging to the 558 datatype have been created. 559 560 :raise pyxb.LogicError: if called multiple times (on the same class) 561 :raise pyxb.LogicError: if called when a parent class facet map has not been initialized 562 :return: the facet map""" 563 fm = None 564 try: 565 fm = cls._FacetMap() 566 except AttributeError: 567 pass 568 if fm is not None: 569 raise pyxb.LogicError('%s facet map initialized multiple times: %s' % (cls.__name__,cls.__FacetMapAttributeName())) 570 571 # Search up the type hierarchy to find the nearest ancestor that has a 572 # facet map. This gets a bit tricky: if we hit the ceiling early 573 # because the PSTD hierarchy re-based itself on a new Python type, we 574 # have to jump to the XsdSuperType. 575 source_class = cls 576 while fm is None: 577 # Assume we're staying in this hierarchy. Include source_class in 578 # the candidates, since we might have jumped to it. 579 for super_class in source_class.mro(): 580 #print 'Superclass for %s is %s' % (source_class, super_class) 581 assert super_class is not None 582 if (super_class == simpleTypeDefinition): # and (source_class.XsdSuperType() is not None): 583 break 584 if issubclass(super_class, simpleTypeDefinition): 585 try: 586 fm = super_class._FacetMap() 587 #print 'Selected facet map for %s from %s: %s' % (cls, super_class, fm) 588 break 589 except AttributeError: 590 pass 591 if fm is None: 592 try: 593 source_class = source_class.XsdSuperType() 594 except AttributeError: 595 source_class = None 596 #print 'Nothing acceptable found, jumped to %s' % (source_class,) 597 if source_class is None: 598 fm = { } 599 #print 'Done with set' 600 if fm is None: 601 raise pyxb.LogicError('%s is not a child of simpleTypeDefinition' % (cls.__name__,)) 602 fm = fm.copy() 603 #print 'Augmenting %s map had %d elts with %d from args' % (cls, len(fm), len(args)) 604 for facet in args: 605 fm[type(facet)] = facet 606 #for (fc, fi) in fm.items(): 607 # print ' %s : %s' % (fc, fi) 608 setattr(cls, cls.__FacetMapAttributeName(), fm) 609 return fm
610 611 @classmethod
612 - def _ConvertArguments_vx (cls, args, kw):
613 return args
614 615 @classmethod
616 - def _ConvertArguments (cls, args, kw):
617 """Pre-process the arguments. 618 619 This is used before invoking the parent constructor. One application 620 is to apply the whitespace facet processing; if such a request is in 621 the keywords, it is removed so it does not propagate to the 622 superclass. Another application is to convert the arguments from a 623 string to a list. Binding-specific applications are performed in the 624 overloaded L{_ConvertArguments_vx} method.""" 625 dom_node = kw.pop('_dom_node', None) 626 if dom_node is not None: 627 text_content = domutils.ExtractTextContent(dom_node) 628 if text_content is not None: 629 args = (domutils.ExtractTextContent(dom_node),) + args 630 kw['_apply_whitespace_facet'] = True 631 apply_whitespace_facet = kw.pop('_apply_whitespace_facet', True) 632 if (0 < len(args)) and isinstance(args[0], types.StringTypes): 633 cf_whitespace = getattr(cls, '_CF_whiteSpace', None) 634 if cf_whitespace is not None: 635 #print 'Apply whitespace %s to "%s"' % (cf_whitespace, args[0]) 636 norm_str = unicode(cf_whitespace.normalizeString(args[0])) 637 args = (norm_str,) + args[1:] 638 return cls._ConvertArguments_vx(args, kw)
639 640 # Must override new, because new gets invoked before init, and usually 641 # doesn't accept keywords. In case it does (e.g., datetime.datetime), 642 # only remove the ones that would normally be interpreted by this class. 643 # Do the same argument conversion as is done in init. Trap errors and 644 # convert them to BadTypeValue errors. 645 # 646 # Note: We explicitly do not validate constraints here. That's 647 # done in the normal constructor; here, we might be in the process 648 # of building a value that eventually will be legal, but isn't 649 # yet.
650 - def __new__ (cls, *args, **kw):
651 # PyXBFactoryKeywords 652 kw.pop('_validate_constraints', None) 653 kw.pop('_require_value', None) 654 kw.pop('_element', None) 655 kw.pop('_fallback_namespace', None) 656 kw.pop('_nil', None) 657 # ConvertArguments will remove _element and _apply_whitespace_facet 658 args = cls._ConvertArguments(args, kw) 659 assert issubclass(cls, _TypeBinding_mixin) 660 try: 661 rv = super(simpleTypeDefinition, cls).__new__(cls, *args, **kw) 662 return rv 663 except ValueError, e: 664 raise pyxb.BadTypeValueError(e) 665 except OverflowError, e: 666 raise pyxb.BadTypeValueError(e)
667 668 # Validate the constraints after invoking the parent constructor, 669 # unless told not to.
670 - def __init__ (self, *args, **kw):
671 """Initialize a newly created STD instance. 672 673 Usually there is one positional argument, which is a value that can be 674 converted to the underlying Python type. 675 676 @keyword _validate_constraints: If True (default), the newly 677 constructed value is checked against its constraining facets. 678 @type _validate_constraints: C{bool} 679 """ 680 # PyXBFactoryKeywords 681 validate_constraints = kw.pop('_validate_constraints', self._PerformValidation()) 682 require_value = kw.pop('_require_value', False) 683 # _ConvertArguments handles _dom_node and _apply_whitespace_facet 684 # TypeBinding_mixin handles _nil and _element 685 args = self._ConvertArguments(args, kw) 686 try: 687 super(simpleTypeDefinition, self).__init__(*args, **kw) 688 except OverflowError, e: 689 raise pyxb.BadTypeValueError(e) 690 if require_value and (not self._constructedWithValue()): 691 raise pyxb.MissingContentError('missing value') 692 693 if validate_constraints: 694 self.xsdConstraintsOK()
695 696 697 # The class attribute name used to store the reference to the STD 698 # component instance must be unique to the class, not to this base class. 699 # Otherwise we mistakenly believe we've already associated a STD instance 700 # with a class (e.g., xsd:normalizedString) when in fact it's associated 701 # with the superclass (e.g., xsd:string) 702 @classmethod
703 - def __STDAttrName (cls):
704 return '_%s__SimpleTypeDefinition' % (cls.__name__,)
705 706 @classmethod
707 - def _SimpleTypeDefinition (cls, std):
708 """Set the L{pyxb.xmlschema.structures.SimpleTypeDefinition} instance 709 associated with this binding.""" 710 attr_name = cls.__STDAttrName() 711 if hasattr(cls, attr_name): 712 old_value = getattr(cls, attr_name) 713 if old_value != std: 714 raise pyxb.LogicError('%s: Attempt to override existing STD %s with %s' % (cls, old_value.name(), std.name())) 715 setattr(cls, attr_name, std)
716 717 @classmethod
718 - def SimpleTypeDefinition (cls):
719 """Return the SimpleTypeDefinition instance for the given 720 class. 721 722 This should only be invoked when generating bindings. 723 724 @raise pyxb.IncompleteImplementationError: no STD instance has been 725 associated with the class. 726 727 """ 728 attr_name = cls.__STDAttrName() 729 if hasattr(cls, attr_name): 730 return getattr(cls, attr_name) 731 raise pyxb.IncompleteImplementationError('%s: No STD available' % (cls,))
732 733 @classmethod
734 - def XsdLiteral (cls, value):
735 """Convert from a python value to a string usable in an XML 736 document. 737 738 This should be implemented in the subclass.""" 739 raise pyxb.LogicError('%s does not implement XsdLiteral' % (cls,))
740
741 - def xsdLiteral (self):
742 """Return text suitable for representing the value of this 743 instance in an XML document. 744 745 The base class implementation delegates to the object class's 746 XsdLiteral method.""" 747 if self._isNil(): 748 return '' 749 return self.XsdLiteral(self)
750 751 @classmethod
752 - def XsdSuperType (cls):
753 """Find the nearest parent class in the PST hierarchy. 754 755 The value for anySimpleType is None; for all others, it's a 756 primitive or derived PST descendent (including anySimpleType).""" 757 for sc in cls.mro(): 758 if sc == cls: 759 continue 760 if simpleTypeDefinition == sc: 761 # If we hit the PST base, this is a primitive type or 762 # otherwise directly descends from a Python type; return 763 # the recorded XSD supertype. 764 return cls._XsdBaseType 765 if issubclass(sc, simpleTypeDefinition): 766 return sc 767 raise pyxb.LogicError('No supertype found for %s' % (cls,))
768 769 @classmethod
770 - def _XsdConstraintsPreCheck_vb (cls, value):
771 """Pre-extended class method to verify other things before 772 checking constraints. 773 774 This is used for list types, to verify that the values in the 775 list are acceptable, and for token descendents, to check the 776 lexical/value space conformance of the input. 777 """ 778 super_fn = getattr(super(simpleTypeDefinition, cls), '_XsdConstraintsPreCheck_vb', lambda *a,**kw: value) 779 return super_fn(value)
780 781 @classmethod
782 - def XsdConstraintsOK (cls, value):
783 """Validate the given value against the constraints on this class. 784 785 @raise pyxb.BadTypeValueError: if any constraint is violated. 786 """ 787 788 value = cls._XsdConstraintsPreCheck_vb(value) 789 790 facet_values = None 791 792 # Constraints for simple type definitions are inherited. Check them 793 # from least derived to most derived. 794 classes = [ _x for _x in cls.mro() if issubclass(_x, simpleTypeDefinition) ] 795 classes.reverse() 796 for clazz in classes: 797 # When setting up the datatypes, if we attempt to validate 798 # something before the facets have been initialized (e.g., a 799 # nonNegativeInteger used as a length facet for the parent 800 # integer datatype), just ignore that. 801 try: 802 facet_values = clazz._FacetMap().values() 803 except AttributeError, e: 804 facet_values = [] 805 for f in facet_values: 806 if not f.validateConstraint(value): 807 raise pyxb.BadTypeValueError('%s violation for %s in %s' % (f.Name(), value, cls.__name__)) 808 #print '%s ok for %s' % (f, value) 809 return value
810
811 - def xsdConstraintsOK (self):
812 """Validate the value of this instance against its constraints.""" 813 return self.XsdConstraintsOK(self)
814
815 - def _validateBinding_vx (self):
816 if not self._isNil(): 817 self._checkValidValue() 818 return True
819 820 @classmethod
821 - def XsdValueLength (cls, value):
822 """Return the length of the given value. 823 824 The length is calculated by a subclass implementation of 825 _XsdValueLength_vx in accordance with 826 http://www.w3.org/TR/xmlschema-2/#rf-length. 827 828 The return value is a non-negative integer, or C{None} if length 829 constraints should be considered trivially satisfied (as with 830 QName and NOTATION). 831 832 :raise pyxb.LogicError: the provided value is not an instance of cls. 833 :raise pyxb.LogicError: an attempt is made to calculate a length for 834 an instance of a type that does not support length calculations. 835 """ 836 assert isinstance(value, cls) 837 if not hasattr(cls, '_XsdValueLength_vx'): 838 raise pyxb.LogicError('Class %s does not support length validation' % (cls.__name__,)) 839 return cls._XsdValueLength_vx(value)
840
841 - def xsdValueLength (self):
842 """Return the length of this instance within its value space. 843 844 See XsdValueLength.""" 845 return self.XsdValueLength(self)
846 847 @classmethod
848 - def PythonLiteral (cls, value):
849 """Return a string which can be embedded into Python source to 850 represent the given value as an instance of this class.""" 851 class_name = cls.__name__ 852 return '%s(%s)' % (class_name, repr(value))
853
854 - def pythonLiteral (self):
855 """Return a string which can be embedded into Python source to 856 represent the value of this instance.""" 857 return self.PythonLiteral(self)
858
859 - def _toDOM_csc (self, dom_support, parent):
860 assert parent is not None 861 parent.appendChild(dom_support.document().createTextNode(self.xsdLiteral())) 862 return getattr(super(simpleTypeDefinition, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
863 864 @classmethod
865 - def _IsSimpleTypeContent (cls):
866 """STDs have simple type content.""" 867 return True
868 869 @classmethod
870 - def _IsValidValue (self, value):
871 try: 872 self._CheckValidValue(value) 873 return True 874 except pyxb.PyXBException, e: 875 pass 876 return False
877 878 @classmethod
879 - def _CheckValidValue (cls, value):
880 881 """NB: Invoking this on a value that is a list will, if necessary, 882 replace the members of the list with new values that are of the 883 correct item type. This is permitted because only with lists is it 884 possible to bypass the normal content validation (by invoking 885 append/extend on the list instance).""" 886 if value is None: 887 raise pyxb.BadTypeValueError('None is not a valid instance of %s' % (cls,)) 888 #print 'testing value %s type %s against %s' % (value, type(value), cls) 889 value_class = cls 890 if issubclass(cls, STD_list): 891 #print ' -- checking list of %s' % (cls._ItemType,) 892 try: 893 iter(value) 894 except TypeError, e: 895 raise pyxb.BadTypeValueError('%s cannot have non-iterable value type %s' % (cls, type(value))) 896 for v in value: 897 if not cls._ItemType._IsValidValue(v): 898 raise pyxb.BadTypeValueError('%s cannot have member of type %s (want %s)' % (cls, type(v), cls._ItemType)) 899 else: 900 if issubclass(cls, STD_union): 901 #print ' -- checking union with %d types' % (len(cls._MemberTypes),) 902 value_class = None 903 for mt in cls._MemberTypes: 904 if mt._IsValidValue(value): 905 value_class = mt 906 break 907 if value_class is None: 908 raise pyxb.BadTypeValueError('%s cannot have value type %s' % (cls, type(value))) 909 #if not (isinstance(value, value_class) or issubclass(value_class, type(value))): 910 if not isinstance(value, value_class): 911 raise pyxb.BadTypeValueError('Value type %s is not valid for %s' % (type(value), cls)) 912 value_class.XsdConstraintsOK(value)
913
914 - def _checkValidValue (self):
915 self._CheckValidValue(self)
916
917 - def _isValidValue (self):
918 self._IsValidValue(self)
919 920 @classmethod
921 - def _description (cls, name_only=False, user_documentation=True):
922 name = cls._Name() 923 if name_only: 924 return name 925 desc = [ name, ' restriction of ', cls.XsdSuperType()._description(name_only=True) ] 926 if user_documentation and (cls._Documentation is not None): 927 desc.extend(["\n", cls._Documentation]) 928 return ''.join(desc)
929
930 -class STD_union (simpleTypeDefinition):
931 """Base class for union datatypes. 932 933 This class descends only from simpleTypeDefinition. A pyxb.LogicError is 934 raised if an attempt is made to construct an instance of a subclass of 935 STD_union. Values consistent with the member types are constructed using 936 the Factory class method. Values are validated using the _ValidatedMember 937 class method. 938 939 Subclasses must provide a class variable _MemberTypes which is a 940 tuple of legal members of the union.""" 941 942 _MemberTypes = None 943 """A list of classes which are permitted as values of the union.""" 944 945 # Ick: If we don't declare this here, this class's map doesn't get 946 # initialized. Alternative is to not descend from simpleTypeDefinition. 947 # @todo Ensure that pattern and enumeration are valid constraints 948 __FacetMap = {} 949 950 @classmethod
951 - def Factory (cls, *args, **kw):
952 """Given a value, attempt to create an instance of some member of this 953 union. The first instance which can be legally created is returned. 954 955 @keyword _validate_constraints: If True (default), any constructed 956 value is checked against constraints applied to the union as well as 957 the member type. 958 959 @raise pyxb.BadTypeValueError: no member type will permit creation of 960 an instance from the parameters in C{args} and C{kw}. 961 """ 962 963 used_cls = cls._SupersedingClass() 964 state = used_cls._PreFactory_vx(args, kw) 965 966 rv = None 967 # NB: get, not pop: preserve it for the member type invocations 968 validate_constraints = kw.get('_validate_constraints', cls._PerformValidation()) 969 assert isinstance(validate_constraints, bool) 970 if 0 < len(args): 971 arg = args[0] 972 try: 973 rv = cls._ValidatedMember(arg) 974 except pyxb.BadTypeValueError, e: 975 pass 976 if rv is None: 977 kw['_validate_constraints'] = True 978 for mt in cls._MemberTypes: 979 try: 980 rv = mt.Factory(*args, **kw) 981 break 982 except pyxb.BadTypeValueError: 983 pass 984 except ValueError: 985 pass 986 except: 987 pass 988 if rv is not None: 989 if validate_constraints: 990 cls.XsdConstraintsOK(rv) 991 rv._postFactory_vx(state) 992 return rv 993 raise pyxb.BadTypeValueError('%s cannot construct union member from args %s' % (cls.__name__, args))
994 995 @classmethod
996 - def _ValidatedMember (cls, value):
997 """Validate the given value as a potential union member. 998 999 @raise pyxb.BadTypeValueError: the value is not an instance of a 1000 member type.""" 1001 if not isinstance(value, cls._MemberTypes): 1002 for mt in cls._MemberTypes: 1003 try: 1004 # Force validation so we get the correct type, otherwise 1005 # first member will be accepted. 1006 value = mt.Factory(value, _validate_constraints=True) 1007 return value 1008 except (TypeError, pyxb.BadTypeValueError): 1009 pass 1010 raise pyxb.BadTypeValueError('%s cannot hold a member of type %s' % (cls.__name__, value.__class__.__name__)) 1011 return value
1012
1013 - def __init__ (self, *args, **kw):
1014 raise pyxb.LogicError('%s: cannot construct instances of union' % (self.__class__.__name__,))
1015 1016 @classmethod
1017 - def _description (cls, name_only=False, user_documentation=True):
1018 name = cls._Name() 1019 if name_only: 1020 return name 1021 desc = [ name, ', union of '] 1022 desc.append(', '.join([ _td._description(name_only=True) for _td in cls._MemberTypes ])) 1023 return ''.join(desc)
1024 1025 @classmethod
1026 - def XsdLiteral (cls, value):
1027 """Convert from a binding value to a string usable in an XML document.""" 1028 return cls._ValidatedMember(value).xsdLiteral()
1029
1030 1031 -class STD_list (simpleTypeDefinition, types.ListType):
1032 """Base class for collection datatypes. 1033 1034 This class descends from the Python list type, and incorporates 1035 simpleTypeDefinition. Subclasses must define a class variable _ItemType 1036 which is a reference to the class of which members must be instances.""" 1037 1038 _ItemType = None 1039 """A reference to the binding class for items within this list.""" 1040 1041 # Ick: If we don't declare this here, this class's map doesn't get 1042 # initialized. Alternative is to not descend from simpleTypeDefinition. 1043 __FacetMap = {} 1044 1045 @classmethod
1046 - def _ValidatedItem (cls, value):
1047 """Verify that the given value is permitted as an item of this list. 1048 1049 This may convert the value to the proper type, if it is 1050 compatible but not an instance of the item type. Returns the 1051 value that should be used as the item, or raises an exception 1052 if the value cannot be converted.""" 1053 if isinstance(value, cls._ItemType): 1054 pass 1055 elif issubclass(cls._ItemType, STD_union): 1056 value = cls._ItemType._ValidatedMember(value) 1057 else: 1058 try: 1059 value = cls._ItemType(value) 1060 except (pyxb.BadTypeValueError, TypeError): 1061 raise pyxb.BadTypeValueError('Type %s has member of type %s, must be %s' % (cls.__name__, type(value).__name__, cls._ItemType.__name__)) 1062 return value
1063 1064 @classmethod
1065 - def _ConvertArguments_vx (cls, args, kw):
1066 # If the first argument is a string, split it on spaces and use the 1067 # resulting list of tokens. 1068 if 0 < len(args): 1069 arg1 = args[0] 1070 if isinstance(arg1, types.StringTypes): 1071 args = (arg1.split(),) + args[1:] 1072 arg1 = args[0] 1073 is_iterable = False 1074 try: 1075 iter(arg1) 1076 is_iterable = True 1077 except TypeError: 1078 pass 1079 if is_iterable: 1080 new_arg1 = [] 1081 for i in range(len(arg1)): 1082 new_arg1.append(cls._ValidatedItem(arg1[i])) 1083 args = (new_arg1,) + args[1:] 1084 super_fn = getattr(super(STD_list, cls), '_ConvertArguments_vx', lambda *a,**kw: args) 1085 return super_fn(args, kw)
1086 1087 @classmethod
1088 - def _XsdValueLength_vx (cls, value):
1089 return len(value)
1090 1091 @classmethod
1092 - def XsdLiteral (cls, value):
1093 """Convert from a binding value to a string usable in an XML document.""" 1094 return ' '.join([ cls._ItemType.XsdLiteral(_v) for _v in value ])
1095 1096 @classmethod
1097 - def _description (cls, name_only=False, user_documentation=True):
1098 name = cls._Name() 1099 if name_only: 1100 return name 1101 desc = [ name, ', list of ', cls._ItemType._description(name_only=True) ] 1102 return ''.join(desc)
1103 1104 # Convert a single value to the required type, if not already an instance 1105 @classmethod
1106 - def __ConvertOne (cls, v):
1107 return cls._ValidatedItem(v)
1108 1109 # Convert a sequence of values to the required type, if not already instances
1110 - def __convertMany (self, values):
1111 return [ self._ValidatedItem(_v) for _v in values ]
1112
1113 - def __setitem__ (self, key, value):
1114 if isinstance(key, slice): 1115 super(STD_list, self).__setitem__(key, self.__convertMany(values)) 1116 else: 1117 super(STD_list, self).__setitem__(key, self._ValidatedItem(value))
1118
1119 - def __setslice__ (self, start, end, values):
1120 super(STD_list, self).__setslice__(start, end, self.__convertMany(values))
1121
1122 - def __contains__ (self, item):
1123 return super(STD_list, self).__contains__(self._ValidatedItem(item))
1124 1125 # Standard mutable sequence methods, per Python Library Reference "Mutable Sequence Types" 1126
1127 - def append (self, x):
1128 super(STD_list, self).append(self._ValidatedItem(x))
1129
1130 - def extend (self, x):
1131 super(STD_list, self).extend(self.__convertMany(x))
1132
1133 - def count (self, x):
1134 return super(STD_list, self).count(self._ValidatedItem(x))
1135
1136 - def index (self, x, *args):
1137 return super(STD_list, self).index(self._ValidatedItem(x), *args)
1138
1139 - def insert (self, i, x):
1140 super(STD_list, self).insert(i, self._ValidatedItem(x))
1141
1142 - def remove (self, x):
1143 super(STD_list, self).remove(self._ValidatedItem(x))
1144
1145 -class element (utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
1146 """Class that represents a schema element. 1147 1148 Global and local elements are represented by instances of this class. 1149 """ 1150
1151 - def name (self):
1152 """The expanded name of the element within its scope.""" 1153 return self.__name
1154 __name = None 1155
1156 - def typeDefinition (self):
1157 """The L{_TypeBinding_mixin} subclass for values of this element.""" 1158 return self.__typeDefinition._SupersedingClass()
1159 __typeDefinition = None 1160
1161 - def scope (self):
1162 """The scope of the element. This is either C{None}, representing a 1163 top-level element, or an instance of C{complexTypeDefinition} for 1164 local elements.""" 1165 return self.__scope
1166 __scope = None 1167
1168 - def nillable (self):
1169 """Indicate whether values matching this element can have U{nil 1170 <http://www.w3.org/TR/xmlschema-1/#xsi_nil>} set.""" 1171 return self.__nillable
1172 __nillable = False 1173
1174 - def abstract (self):
1175 """Indicate whether this element is abstract (must use substitution 1176 group members for matches).""" 1177 return self.__abstract
1178 __abstract = False 1179
1180 - def documentation (self):
1181 """Contents of any documentation annotation in the definition.""" 1182 return self.__documentation
1183 __documentation = None 1184
1185 - def defaultValue (self):
1186 return self.__defaultValue
1187 __defaultValue = None 1188
1189 - def substitutionGroup (self):
1190 """The L{element} instance to whose substitution group this element 1191 belongs. C{None} if this element is not part of a substitution 1192 group.""" 1193 return self.__substitutionGroup
1194 - def _setSubstitutionGroup (self, substitution_group):
1195 self.__substitutionGroup = substitution_group 1196 return self
1197 __substitutionGroup = None 1198
1199 - def findSubstituendUse (self, ctd_class):
1200 eu = ctd_class._ElementMap.get(self.name()) 1201 if eu is not None: 1202 return eu 1203 if self.substitutionGroup() is None: 1204 return None 1205 return self.substitutionGroup().findSubstituendUse(ctd_class)
1206
1207 - def substitutesFor (self, other):
1208 """Determine whether an instance of this element can substitute for the other element. 1209 1210 See U{Substitution Group OK<http://www.w3.org/TR/xmlschema-1/#cos-equiv-derived-ok-rec>)}. 1211 1212 @todo: Do something about blocking constraints. This ignores them, as 1213 does everything leading to this point. 1214 """ 1215 if other is None: 1216 return False 1217 assert isinstance(other, element) 1218 # On the first call, other is likely to be the local element. We need 1219 # the global one. 1220 if other.scope() is not None: 1221 other = other.name().elementBinding() 1222 if other is None: 1223 return False 1224 assert other.scope() is None 1225 # Do both these refer to the same (top-level) element? 1226 if self.name().elementBinding() == other: 1227 return True 1228 if self.substitutionGroup() is None: 1229 return False 1230 return (self.substitutionGroup() == other) or self.substitutionGroup().substitutesFor(other)
1231
1232 - def memberElement (self, name):
1233 """Return a reference to the element instance used for the given name 1234 within this element. 1235 1236 The type for this element must be a complex type definition.""" 1237 return self.typeDefinition()._UseForTag(name).elementBinding()
1238
1239 - def __init__ (self, name, type_definition, scope=None, nillable=False, abstract=False, default_value=None, substitution_group=None, documentation=None):
1240 """Create a new element binding. 1241 """ 1242 assert isinstance(name, pyxb.namespace.ExpandedName) 1243 self.__name = name 1244 self.__typeDefinition = type_definition 1245 self.__scope = scope 1246 self.__nillable = nillable 1247 self.__abstract = abstract 1248 self.__defaultValue = default_value 1249 self.__substitutionGroup = substitution_group 1250 self.__documentation = documentation
1251
1252 - def __call__ (self, *args, **kw):
1253 """Invoke the Factory method on the type associated with this element. 1254 1255 @keyword _dom_node: If set, specifies a DOM node that should be used 1256 for initialization. In that case, the L{createFromDOM} method is 1257 invoked instead of the type definition Factory method. 1258 1259 @raise pyxb.AbstractElementError: This element is abstract and no DOM 1260 node was provided. 1261 """ 1262 dom_node = kw.pop('_dom_node', None) 1263 assert dom_node is None, 'Cannot pass DOM node directly to element constructor; use createFromDOM' 1264 if '_element' in kw: 1265 raise pyxb.LogicError('Cannot set _element in element-based instance creation') 1266 kw['_element'] = self 1267 # Can't create instances of abstract elements. 1268 if self.abstract(): 1269 raise pyxb.AbstractElementError(self) 1270 return self.typeDefinition().Factory(*args, **kw)
1271
1272 - def compatibleValue (self, value, **kw):
1273 """Return a variant of the value that is compatible with this element. 1274 1275 This mostly defers to L{_TypeBinding_mixin._CompatibleValue}. 1276 1277 @raise pyxb.BadTypeValueError: if the value is not both 1278 type-consistent and value-consistent with the element's type. 1279 """ 1280 # None is always None 1281 if value is None: 1282 return None 1283 is_plural = kw.get('is_plural', False) 1284 #print 'validating %s against %s, isPlural %s' % (type(value), self.typeDefinition(), is_plural) 1285 if is_plural: 1286 try: 1287 iter(value) 1288 except TypeError: 1289 raise pyxb.BadTypeValueError('Expected plural value, got %s' % (type(value),)) 1290 return [ self.compatibleValue(_v) for _v in value ] 1291 if isinstance(value, _TypeBinding_mixin) and (value._element() is not None) and value._element().substitutesFor(self): 1292 return value 1293 return self.typeDefinition()._CompatibleValue(value, **kw)
1294 1295 # element 1296 @classmethod
1297 - def AnyCreateFromDOM (cls, node, _fallback_namespace):
1298 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1299 node = node.documentElement 1300 expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=_fallback_namespace) 1301 elt = expanded_name.elementBinding() 1302 if elt is None: 1303 raise pyxb.UnrecognizedElementError('No element binding available for %s' % (expanded_name,)) 1304 assert isinstance(elt, pyxb.binding.basis.element) 1305 # Pass on the namespace to use when resolving unqualified qnames as in 1306 # xsi:type 1307 return elt._createFromDOM(node, expanded_name, _fallback_namespace=_fallback_namespace)
1308
1309 - def elementForName (self, name):
1310 """Return the element that should be used if this element binding is 1311 permitted and an element with the given name is encountered. 1312 1313 Normally, the incoming name matches the name of this binding, and 1314 C{self} is returned. If the incoming name is different, it is 1315 expected to be the name of a global element which is within this 1316 element's substitution group. In that case, the binding corresponding 1317 to the named element is return. 1318 1319 @return: An instance of L{element}, or C{None} if no element with the 1320 given name can be found. 1321 """ 1322 1323 # Name match means OK. 1324 if self.name() == name: 1325 return self 1326 # No name match means only hope is a substitution group, for which the 1327 # element must be top-level. 1328 top_elt = self.name().elementBinding() 1329 if top_elt is None: 1330 return None 1331 # Members of the substitution group must also be top-level. NB: If 1332 # named_elt == top_elt, then the adoptName call below improperly 1333 # associated the global namespace with a local element of the same 1334 # name; cf. test-namespace-uu:testBad. 1335 elt_en = top_elt.name().adoptName(name) 1336 assert 'elementBinding' in elt_en.namespace()._categoryMap(), 'No element bindings in %s' % (elt_en.namespace(),) 1337 named_elt = elt_en.elementBinding() 1338 if (named_elt is None) or (named_elt == top_elt): 1339 return None 1340 if named_elt.substitutesFor(top_elt): 1341 return named_elt 1342 return None
1343
1344 - def createFromDOM (self, node, expanded_name=None, fallback_namespace=None, **kw):
1345 """Create a binding instance from the given DOM node. 1346 1347 @keyword expanded_name: Optional name for the DOM node. If not 1348 present, is inferred from C{node}. 1349 1350 @keyword fallback_namespace: Optional namespace to use when resolving 1351 unqualified names. 1352 """ 1353 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1354 node = node.documentElement 1355 if expanded_name is None: 1356 expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=fallback_namespace) 1357 return self._createFromDOM(node, expanded_name, **kw)
1358
1359 - def _createFromDOM (self, node, expanded_name, **kw):
1360 """Create a binding instance from the given DOM node, using the 1361 provided name to identify the correct binding. 1362 1363 The context and information associated with this element is used to 1364 identify the actual element binding to use. By default, C{self} is 1365 used. If this element represents a term in a content model, the name 1366 and namespace of the incoming node may identify a different element. 1367 If that element is a member of this element's substitution group, the 1368 binding associated with the node's name will be used instead. 1369 1370 The type of object returned is determined by the type definition 1371 associated with the element binding and the value of any U{xsi:type 1372 <http://www.w3.org/TR/xmlschema-1/#xsi_type>} attribute found in the 1373 node, modulated by the configuration of L{XSI.ProcessTypeAttribute<pyxb.namespace.builtin._XMLSchema_instance.ProcessTypeAttribute>}. 1374 1375 Keyword parameters are passed to the factory method of the type 1376 associated with the selected element binding. See 1377 L{_TypeBinding_mixin} and any specializations of it. 1378 1379 @param expanded_name: The expanded name of the node. If the value is 1380 C{None}, defaults to the name of this element. (In the case of 1381 substitution groups, the default is wrong, but correct inference 1382 depends on context not available here.) 1383 1384 @keyword _fallback_namespace: Optional namespace to use when resolving 1385 unqualified type names. 1386 1387 @param node: The DOM node specifying the element content. If this is 1388 a (top-level) Document node, its element node is used. 1389 @type node: C{xml.dom.Node} 1390 @return: An instance of L{_TypeBinding_mixin} 1391 @raise pyxb.StructuralBadDocumentError: The node's name does identify an element binding. 1392 @raise pyxb.AbstractElementError: The element binding associated with the node is abstract. 1393 @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 1394 @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. 1395 """ 1396 1397 # Bypass the useless top-level node and start with the element beneath 1398 # it. 1399 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1400 node = node.documentElement 1401 1402 # Identify the element binding to be used for the given node. NB: 1403 # Even if found, this may not be equal to self, since we allow you to 1404 # use an abstract substitution group head to create instances from DOM 1405 # nodes that are in that group. 1406 fallback_namespace = kw.pop('_fallback_namespace', None) 1407 element_binding = self.elementForName(expanded_name) 1408 if element_binding is None: 1409 raise pyxb.StructuralBadDocumentError('Element %s cannot create from node %s' % (self.name(), expanded_name)) 1410 1411 # Can't create instances of abstract elements. @todo: Is there any 1412 # way this could be legal given an xsi:type attribute? I'm pretty 1413 # sure "no"... 1414 if element_binding.abstract(): 1415 raise pyxb.AbstractElementError(element_binding) 1416 1417 # Record the element to be associated with the created binding 1418 # instance. 1419 if '_element' in kw: 1420 raise pyxb.LogicError('Cannot set _element in element-based instance creation') 1421 kw['_element'] = element_binding 1422 1423 # Now determine the type binding for the content. If xsi:type is 1424 # used, it won't be the one built into the element binding. 1425 type_class = element_binding.typeDefinition() 1426 elt_ns = element_binding.name().namespace() 1427 1428 # Get the namespace context for the value being created. If none is 1429 # associated, one will be created. Do not make assumptions about the 1430 # namespace context; if the user cared, she should have assigned a 1431 # context before calling this. 1432 ns_ctx = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(node) 1433 (did_replace, type_class) = XSI._InterpretTypeAttribute(XSI.type.getAttribute(node), ns_ctx, fallback_namespace, type_class) 1434 1435 # Pass xsi:nil on to the constructor regardless of whether the element 1436 # is nillable. Another sop to SOAP-encoding WSDL fans who don't 1437 # bother to provide valid schema for their message content. 1438 is_nil = XSI.nil.getAttribute(node) 1439 if is_nil is not None: 1440 kw['_nil'] = pyxb.binding.datatypes.boolean(is_nil) 1441 1442 rv = type_class.Factory(_dom_node=node, _fallback_namespace=fallback_namespace, **kw) 1443 assert rv._element() == element_binding 1444 rv._setNamespaceContext(ns_ctx) 1445 if pyxb._ParsingRequiresValid: 1446 rv.validateBinding() 1447 return rv
1448
1449 - def __str__ (self):
1450 return 'Element %s' % (self.name(),)
1451
1452 - def _description (self, name_only=False, user_documentation=True):
1453 name = str(self.name()) 1454 if name_only: 1455 return name 1456 desc = [ name, ' (', self.typeDefinition()._description(name_only=True), ')' ] 1457 if self.scope() is not None: 1458 desc.extend([', local to ', self.scope()._description(name_only=True) ]) 1459 if self.nillable(): 1460 desc.append(', nillable') 1461 if self.substitutionGroup() is not None: 1462 desc.extend([', substitutes for ', self.substitutionGroup()._description(name_only=True) ]) 1463 if user_documentation and (self.documentation() is not None): 1464 desc.extend(["\n", self.documentation() ]) 1465 return ''.join(desc)
1466
1467 -class enumeration_mixin (pyxb.cscRoot):
1468 """Marker in case we need to know that a PST has an enumeration constraint facet.""" 1469 pass
1470
1471 -class complexTypeDefinition (_TypeBinding_mixin, utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
1472 """Base for any Python class that serves as the binding for an 1473 XMLSchema complexType. 1474 1475 Subclasses should define a class-level _AttributeMap variable which maps 1476 from the unicode tag of an attribute to the AttributeUse instance that 1477 defines it. Similarly, subclasses should define an _ElementMap variable. 1478 """ 1479 1480 _CT_EMPTY = 'EMPTY' #<<< No content 1481 _CT_SIMPLE = 'SIMPLE' #<<< Simple (character) content 1482 _CT_MIXED = 'MIXED' #<<< Children may be elements or other (e.g., character) content 1483 _CT_ELEMENT_ONLY = 'ELEMENT_ONLY' #<<< Expect only element content. 1484 1485 _ContentTypeTag = None 1486 1487 _TypeDefinition = None 1488 """Subclass of simpleTypeDefinition that corresponds to the type content. 1489 Only valid if _ContentTypeTag is _CT_SIMPLE""" 1490 1491 # If the type supports wildcard attributes, this describes their 1492 # constraints. (If it doesn't, this should remain None.) Supporting 1493 # classes should override this value. 1494 _AttributeWildcard = None 1495 1496 _AttributeMap = { } 1497 """Map from expanded names to AttributeUse instances.""" 1498 1499 # A value that indicates whether the content model for this type supports 1500 # wildcard elements. Supporting classes should override this value. 1501 _HasWildcardElement = False 1502 1503 # Map from expanded names to ElementUse instances 1504 _ElementMap = { } 1505 """Map from expanded names to ElementUse instances.""" 1506 1507 # Per-instance map from tags to attribute values for wildcard attributes. 1508 # Value is C{None} if the type does not support wildcard attributes. 1509 __wildcardAttributeMap = None 1510
1511 - def wildcardAttributeMap (self):
1512 """Obtain access to wildcard attributes. 1513 1514 The return value is C{None} if this type does not support wildcard 1515 attributes. If wildcard attributes are allowed, the return value is a 1516 map from QNames to the unicode string value of the corresponding 1517 attribute. 1518 1519 @todo: The map keys should be namespace extended names rather than 1520 QNames, as the in-scope namespace may not be readily available to the 1521 user. 1522 """ 1523 return self.__wildcardAttributeMap
1524 1525 # Per-instance list of DOM nodes interpreted as wildcard elements. 1526 # Value is None if the type does not support wildcard elements. 1527 __wildcardElements = None 1528
1529 - def wildcardElements (self):
1530 """Obtain access to wildcard elements. 1531 1532 The return value is C{None} if the content model for this type does not 1533 support wildcard elements. If wildcard elements are allowed, the 1534 return value is a list of values corresponding to conformant 1535 unrecognized elements, in the order in which they were encountered. 1536 If the containing binding was created from an XML document and enough 1537 information was present to determine the binding of the member 1538 element, the value is a binding instance. Otherwise, the value is the 1539 original DOM Element node. 1540 """ 1541 return self.__wildcardElements
1542 1543 @classmethod
1544 - def _ConfigureBindingStyle (cls, style):
1545 if BINDING_STYLE_PROPERTY == style: 1546 pass 1547 elif BINDING_STYLE_ACCESSOR == style: 1548 pass 1549 else: 1550 raise pyxb.LogicError('Unrecognized binding style %s' % (style,))
1551
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 = XSI.nil.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, XSI ): 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