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