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

Source Code for Module pyxb.binding.basis

   1  # -*- coding: utf-8 -*- 
   2  # Copyright 2009-2013, Peter A. Bigot 
   3  # 
   4  # Licensed under the Apache License, Version 2.0 (the "License"); you may 
   5  # not use this file except in compliance with the License. You may obtain a 
   6  # copy of the License at: 
   7  # 
   8  #            http://www.apache.org/licenses/LICENSE-2.0 
   9  # 
  10  # Unless required by applicable law or agreed to in writing, software 
  11  # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
  12  # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
  13  # License for the specific language governing permissions and limitations 
  14  # under the License. 
  15   
  16  """This module contains support classes from which schema-specific bindings 
  17  inherit, and that describe the content models of those schema.""" 
  18   
  19  import logging 
  20  import pyxb 
  21  import xml.dom 
  22  import pyxb.utils.domutils as domutils 
  23  import pyxb.utils.utility as utility 
  24  import types 
  25  import pyxb.namespace 
  26  import collections 
  27  from pyxb.namespace.builtin import XMLSchema_instance as XSI 
  28   
  29  _log = logging.getLogger(__name__) 
30 31 -class _TypeBinding_mixin (utility.Locatable_mixin):
32 # Private member holding the validation configuration that applies to the 33 # class or instance. Can't really make it private with __ prefix because 34 # that would screw up parent classes. You end users---stay away from 35 # this. 36 _validationConfig_ = pyxb.GlobalValidationConfig 37 38 @classmethod
39 - def _SetValidationConfig (cls, validation_config):
40 """Set the validation configuration for this class.""" 41 cls._validationConfig_ = validation_config
42 43 @classmethod
44 - def _GetValidationConfig (cls):
45 """The L{pyxb.ValidationConfig} instance that applies to this class. 46 47 By default this will reference L{pyxb.GlobalValidationConfig}.""" 48 return cls._validationConfig_
49
50 - def _setValidationConfig (self, validation_config):
51 """Set the validation configuration for this instance.""" 52 self._validationConfig_ = validation_config
53
54 - def __getValidationConfig (self):
55 """The L{pyxb.ValidationConfig} instance that applies to this instance. 56 57 By default this will reference the class value from 58 L{_GetValidationConfig}, which defaults to 59 L{pyxb.GlobalValidationConfig}.""" 60 return self._validationConfig_
61 62 # This is how you should be accessing this value. 63 _validationConfig = property(__getValidationConfig) 64 65 @classmethod
66 - def _PerformValidation (cls):
67 """Determine whether the content model should be validated for this class. 68 69 In the absence of context, this returns C{True} iff both binding and 70 document validation are in force. 71 72 @deprecated: use L{_GetValidationConfig} and check specific requirements.""" 73 # Bypass the property since this is a class method 74 vo = cls._validationConfig_ 75 return vo.forBinding and vo.forDocument
76
77 - def _performValidation (self):
78 """Determine whether the content model should be validated for this 79 instance. 80 81 In the absence of context, this returns C{True} iff both binding and 82 document validation are in force. 83 84 @deprecated: use L{_validationConfig} and check specific requirements.""" 85 vo = self._validationConfig 86 return vo.forBinding and vo.forDocument
87 88 _ExpandedName = None 89 """The expanded name of the component.""" 90 91 _XSDLocation = None 92 """Where the definition can be found in the originating schema.""" 93 94 _ReservedSymbols = set([ 'validateBinding', 'toDOM', 'toxml', 'Factory', 'property' ]) 95 96 if pyxb._CorruptionDetectionEnabled:
97 - def __setattr__ (self, name, value):
98 if name in self._ReservedSymbols: 99 raise pyxb.ReservedNameError(self, name) 100 return super(_TypeBinding_mixin, self).__setattr__(name, value)
101 102 _PyXBFactoryKeywords = ( '_dom_node', '_fallback_namespace', '_from_xml', 103 '_apply_whitespace_facet', '_validate_constraints', 104 '_require_value', '_nil', '_element', '_apply_attributes', 105 '_convert_string_values', '_location' ) 106 """Keywords that are interpreted by __new__ or __init__ in one or more 107 classes in the PyXB type hierarchy. All these keywords must be removed 108 before invoking base Python __init__ or __new__.""" 109 110 # While simple type definitions cannot be abstract, they can appear in 111 # many places where complex types can, so we want it to be legal to test 112 # for abstractness without checking whether the object is a complex type. 113 _Abstract = False 114
115 - def _namespaceContext (self):
116 """Return a L{namespace context <pyxb.binding.NamespaceContext>} 117 associated with the binding instance. 118 119 This will return C{None} unless something has provided a context to 120 the instance. Context is provided when instances are generated by the 121 DOM and SAX-based translators.""" 122 return self.__namespaceContext
123 - def _setNamespaceContext (self, namespace_context):
124 """Associate a L{namespace context <pyxb.binding.NamespaceContext>} 125 with the binding instance.""" 126 self.__namespaceContext = namespace_context 127 return self
128 __namespaceContext = None 129
130 - def _setElement (self, elt):
131 """Associate an element binding with the instance. 132 133 Since the value of a binding instance reflects only its content, an 134 associated element is necessary to generate an XML document or DOM 135 tree. 136 137 @param elt: the L{pyxb.binding.basis.element} instance associated with 138 the value. This may be C{None} when disassociating a value from a 139 specific element.""" 140 import pyxb.binding.content 141 assert (elt is None) or isinstance(elt, element) 142 self.__element = elt 143 return self
144 - def _element (self):
145 """Return a L{pyxb.binding.basis.element} associated with the binding 146 instance. 147 148 This will return C{None} unless an element has been associated. 149 Constructing a binding instance using the element instance will add 150 this association. 151 """ 152 return self.__element
153 __element = None 154 155 __xsiNil = None
156 - def _isNil (self):
157 """Indicate whether this instance is U{nil 158 <http://www.w3.org/TR/xmlschema-1/#xsi_nil>}. 159 160 The value is set by the DOM and SAX parsers when building an instance 161 from a DOM element with U{xsi:nil 162 <http://www.w3.org/TR/xmlschema-1/#xsi_nil>} set to C{true}. 163 164 @return: C{None} if the element used to create the instance is not 165 U{nillable<http://www.w3.org/TR/xmlschema-1/#nillable>}. 166 If it is nillable, returns C{True} or C{False} depending on 167 whether the instance itself is U{nil<http://www.w3.org/TR/xmlschema-1/#xsi_nil>}. 168 """ 169 return self.__xsiNil
170 - def _setIsNil (self, nil=True):
171 """Set the xsi:nil property of the instance. 172 173 @param nil: C{True} if the value of xsi:nil should be C{true}, 174 C{False} if the value of xsi:nil should be C{false}. 175 176 @raise pyxb.NoNillableSupportError: the instance is not associated 177 with an element that is L{nillable 178 <pyxb.binding.basis.element.nillable>}. 179 """ 180 if self.__xsiNil is None: 181 raise pyxb.NoNillableSupportError(self) 182 self.__xsiNil = not not nil 183 if self.__xsiNil: 184 # The element must be empty, so also remove all element content. 185 # Attribute values are left unchanged. 186 self._resetContent(reset_elements=True)
187
188 - def _resetContent (self, reset_elements=False):
189 """Reset the content of an element value. 190 191 This is not a public method. 192 193 For simple types, this does nothing. For complex types, this clears the 194 L{content<complexTypeDefinition.content>} array, removing all 195 non-element content from the instance. It optionally also removes all 196 element content. 197 198 @param reset_elements: If C{False} (default) only the content array is 199 cleared, which has the effect of removing any preference for element 200 order when generating a document. If C{True}, the element content 201 stored within the binding is also cleared, leaving it with no content 202 at all. 203 204 @note: This is not the same thing as L{complexTypeDefinition.reset}, 205 which unconditionally resets attributes and element and non-element 206 content. 207 """ 208 pass
209 210 __constructedWithValue = False
211 - def __checkNilCtor (self, args):
212 self.__constructedWithValue = (0 < len(args)) 213 if self.__xsiNil: 214 if self.__constructedWithValue: 215 raise pyxb.ContentInNilInstanceError(self, args[0]) 216 else: 217 # Types that descend from string will, when constructed from an 218 # element with empty content, appear to have no constructor value, 219 # while in fact an empty string should have been passed. 220 if issubclass(type(self), basestring): 221 self.__constructedWithValue = True
222 - def _constructedWithValue (self):
223 return self.__constructedWithValue
224 225 # Flag used to control whether we print a warning when creating a complex 226 # type instance that does not have an associated element. Not sure yet 227 # whether that'll be common practice or common error. 228 __WarnedUnassociatedElement = False 229
230 - def __init__ (self, *args, **kw):
231 # Strip keyword not used above this level. 232 element = kw.pop('_element', None) 233 is_nil = kw.pop('_nil', False) 234 super(_TypeBinding_mixin, self).__init__(*args, **kw) 235 if (element is None) or element.nillable(): 236 self.__xsiNil = is_nil 237 if element is not None: 238 self._setElement(element) 239 self.__checkNilCtor(args)
240 241 @classmethod
242 - def _PreFactory_vx (cls, args, kw):
243 """Method invoked upon entry to the Factory method. 244 245 This method is entitled to modify the keywords array. It can also 246 return a state value which is passed to _postFactory_vx.""" 247 return None
248
249 - def _postFactory_vx (cls, state):
250 """Method invoked prior to leaving the Factory method. 251 252 This is an instance method, and is given the state that was returned 253 by _PreFactory_vx.""" 254 return None
255 256 @classmethod
257 - def Factory (cls, *args, **kw):
258 """Provide a common mechanism to create new instances of this type. 259 260 The class constructor won't do, because you can't create 261 instances of union types. 262 263 This method may be overridden in subclasses (like STD_union). Pre- 264 and post-creation actions can be customized on a per-class instance by 265 overriding the L{_PreFactory_vx} and L{_postFactory_vx} methods. 266 267 @keyword _dom_node: If provided, the value must be a DOM node, the 268 content of which will be used to set the value of the instance. 269 270 @keyword _location: An optional instance of 271 L{pyxb.utils.utility.Location} showing the origin the binding. If 272 C{None}, a value from C{_dom_node} is used if available. 273 274 @keyword _from_xml: If C{True}, the input must be either a DOM node or 275 a unicode string comprising a lexical representation of a value. This 276 is a further control on C{_apply_whitespace_facet} and arises from 277 cases where the lexical and value representations cannot be 278 distinguished by type. The default value is C{True} iff C{_dom_node} 279 is not C{None}. 280 281 @keyword _apply_whitespace_facet: If C{True} and this is a 282 simpleTypeDefinition with a whiteSpace facet, the first argument will 283 be normalized in accordance with that facet prior to invoking the 284 parent constructor. The value is always C{True} if text content is 285 extracted from a C{_dom_node}, and otherwise defaults to the defaulted 286 value of C{_from_xml}. 287 288 @keyword _validate_constraints: If C{True}, any constructed value is 289 checked against constraints applied to the union as well as the member 290 type. 291 292 @keyword _require_value: If C{False} (default), it is permitted to 293 create a value without an initial value. If C{True} and no initial 294 value was provided, causes L{pyxb.SimpleContentAbsentError} to be raised. 295 Only applies to simpleTypeDefinition instances; this is used when 296 creating values from DOM nodes. 297 """ 298 # Invoke _PreFactory_vx for the superseding class, which is where 299 # customizations will be found. 300 dom_node = kw.get('_dom_node') 301 location = kw.get('_location') 302 if (location is None) and isinstance(dom_node, utility.Locatable_mixin): 303 location = dom_node._location() 304 kw.setdefault('_from_xml', dom_node is not None) 305 used_cls = cls._SupersedingClass() 306 state = used_cls._PreFactory_vx(args, kw) 307 rv = cls._DynamicCreate(*args, **kw) 308 rv._postFactory_vx(state) 309 if (rv._location is None) and (location is not None): 310 rv._setLocation(location) 311 return rv
312
313 - def _substitutesFor (self, element):
314 if (element is None) or (self._element() is None): 315 return False 316 return self._element().substitutesFor(element)
317 318 @classmethod
319 - def _IsUrType (cls):
320 """Return C{True} iff this is the ur-type. 321 322 The only ur-type is {http://www.w3.org/2001/XMLSchema}anyType. The 323 implementation of this method is overridden for 324 L{pyxb.binding.datatypes.anyType}.""" 325 return False
326 327 @classmethod
328 - def _RequireXSIType (cls, value_type):
329 if cls._IsUrType(): 330 # Require xsi:type if value refines xs:anyType 331 return value_type != cls 332 return cls._Abstract and value_type != cls._SupersedingClass()
333 334 @classmethod
335 - def _CompatibleValue (cls, value, **kw):
336 """Return a variant of the value that is compatible with this type. 337 338 Compatibility is defined relative to the type definition associated 339 with the element. The value C{None} is always compatible. If 340 C{value} has a Python type (e.g., C{int}) that is a superclass of the 341 required L{_TypeBinding_mixin} class (e.g., C{xs:byte}), C{value} is 342 used as a constructor parameter to return a new instance of the 343 required type. Note that constraining facets are applied here if 344 necessary (e.g., although a Python C{int} with value C{500} is 345 type-compatible with C{xs:byte}, it is outside the value space, and 346 compatibility will fail). 347 348 @keyword _convert_string_values: If C{True} (default) and the incoming value is 349 a string, an attempt will be made to form a compatible value by using 350 the string as a constructor argument to the this class. This flag is 351 set to C{False} when testing automaton transitions. 352 353 @raise pyxb.SimpleTypeValueError: if the value is not both 354 type-consistent and value-consistent with the element's type. 355 """ 356 convert_string_values = kw.get('_convert_string_values', True) 357 # None is always None 358 if value is None: 359 return None 360 # Already an instance? 361 if isinstance(value, cls): 362 # @todo: Consider whether we should change the associated _element 363 # of this value. (**Consider** it, don't just do it.) 364 return value 365 value_type = type(value) 366 # All string-based PyXB binding types use unicode, not str 367 if str == value_type: 368 value_type = unicode 369 370 # See if we got passed a Python value which needs to be "downcasted" 371 # to the _TypeBinding_mixin version. 372 if issubclass(cls, value_type): 373 return cls(value) 374 375 # See if we have a numeric type that needs to be cast across the 376 # numeric hierarchy. int to long is the *only* conversion we accept. 377 if isinstance(value, int) and issubclass(cls, long): 378 return cls(value) 379 380 # Same, but for boolean, which Python won't let us subclass 381 if isinstance(value, bool) and issubclass(cls, pyxb.binding.datatypes.boolean): 382 return cls(value) 383 384 # See if we have convert_string_values on, and have a string type that 385 # somebody understands. 386 if convert_string_values and (unicode == value_type): 387 return cls(value) 388 389 # Maybe this is a union? 390 if issubclass(cls, STD_union): 391 for mt in cls._MemberTypes: 392 try: 393 return mt._CompatibleValue(value, **kw) 394 except: 395 pass 396 397 # Any type is compatible with the corresponding ur-type 398 if (pyxb.binding.datatypes.anySimpleType == cls) and issubclass(value_type, simpleTypeDefinition): 399 return value 400 if pyxb.binding.datatypes.anyType == cls: 401 if not isinstance(value, _TypeBinding_mixin): 402 _log.info('Created %s instance from value of type %s', cls._ExpandedName, type(value)) 403 value = cls(value) 404 return value 405 406 # Is this the wrapper class that indicates we should create a binding 407 # from arguments? 408 if isinstance(value, pyxb.BIND): 409 return value.createInstance(cls.Factory, **kw) 410 411 # Does the class have simple content which we can convert? 412 if cls._IsSimpleTypeContent(): 413 # NB: byte(34.2) will create a value, but it may not be one we 414 # want to accept, so only do this if the output is equal to the 415 # input. 416 rv = cls.Factory(value) 417 if isinstance(rv, simpleTypeDefinition) and (rv == value): 418 return rv 419 if isinstance(rv, complexTypeDefinition) and (rv.value() == value): 420 return rv 421 422 # There may be other things that can be converted to the desired type, 423 # but we can't tell that from the type hierarchy. Too many of those 424 # things result in an undesirable loss of information: for example, 425 # when an all model supports both numeric and string transitions, the 426 # candidate is a number, and the string transition is tested first. 427 raise pyxb.SimpleTypeValueError(cls, value)
428 429 @classmethod
430 - def _IsSimpleTypeContent (cls):
431 """Return True iff the content of this binding object is a simple type. 432 433 This is true only for descendents of simpleTypeDefinition and instances 434 of complexTypeDefinition that have simple type content.""" 435 raise pyxb.LogicError('Failed to override _TypeBinding_mixin._IsSimpleTypeContent')
436 437 # If the type supports wildcard attributes, this describes their 438 # constraints. (If it doesn't, this should remain None.) Supporting 439 # classes should override this value. 440 _AttributeWildcard = None 441 442 _AttributeMap = { } 443 """Map from expanded names to AttributeUse instances. Non-empty only in 444 L{complexTypeDefinition} subclasses.""" 445 446 @classmethod
447 - def __AttributesFromDOM (cls, node):
448 attribute_settings = { } 449 for ai in range(0, node.attributes.length): 450 attr = node.attributes.item(ai) 451 # NB: Specifically do not consider attr's NamespaceContext, since 452 # attributes do not accept a default namespace. 453 attr_en = pyxb.namespace.ExpandedName(attr) 454 455 # Ignore xmlns and xsi attributes; we've already handled those 456 if attr_en.namespace() in ( pyxb.namespace.XMLNamespaces, XSI ): 457 continue 458 459 value = attr.value 460 au = cls._AttributeMap.get(attr_en) 461 if au is None: 462 if cls._AttributeWildcard is None: 463 raise pyxb.UnrecognizedAttributeError(cls, attr_en) 464 attribute_settings[attr_en] = value 465 return attribute_settings
466
467 - def _setAttributesFromKeywordsAndDOM (self, kw, dom_node):
468 """Invoke self._setAttribute based on node attributes and keywords. 469 470 Though attributes can only legally appear in complexTypeDefinition 471 instances, delayed conditional validation requires caching them in 472 simpleTypeDefinition. 473 474 @param kw: keywords passed to the constructor. This map is mutated by 475 the call: keywords corresponding to recognized attributes are removed. 476 477 @param dom_node: an xml.dom Node instance, possibly C{None} 478 """ 479 480 # Extract keywords that match field names 481 attribute_settings = { } 482 if dom_node is not None: 483 attribute_settings.update(self.__AttributesFromDOM(dom_node)) 484 for fu in self._AttributeMap.values(): 485 iv = kw.pop(fu.id(), None) 486 if iv is not None: 487 attribute_settings[fu.name()] = iv 488 for (attr_en, value) in attribute_settings.items(): 489 self._setAttribute(attr_en, value)
490
491 - def toDOM (self, bds=None, parent=None, element_name=None):
492 """Convert this instance to a DOM node. 493 494 The name of the top-level element is either the name of the L{element} 495 instance associated with this instance, or the XML name of the type of 496 this instance. 497 498 @param bds: Support for customizing the generated document 499 @type bds: L{pyxb.utils.domutils.BindingDOMSupport} 500 @param parent: If C{None}, a standalone document is created; 501 otherwise, the created element is a child of the given element. 502 @type parent: C{xml.dom.Element} or C{None} 503 @rtype: C{xml.dom.Document} 504 """ 505 506 if bds is None: 507 bds = domutils.BindingDOMSupport() 508 need_xsi_type = bds.requireXSIType() 509 if isinstance(element_name, (str, unicode)): 510 element_name = pyxb.namespace.ExpandedName(bds.defaultNamespace(), element_name) 511 if (element_name is None) and (self._element() is not None): 512 element_binding = self._element() 513 element_name = element_binding.name() 514 need_xsi_type = need_xsi_type or element_binding.typeDefinition()._RequireXSIType(type(self)) 515 if element_name is None: 516 element_name = self._ExpandedName 517 element = bds.createChildElement(element_name, parent) 518 if need_xsi_type: 519 val_type_qname = self._ExpandedName.localName() 520 tns_prefix = bds.namespacePrefix(self._ExpandedName.namespace()) 521 if tns_prefix is not None: 522 val_type_qname = '%s:%s' % (tns_prefix, val_type_qname) 523 bds.addAttribute(element, XSI.type, val_type_qname) 524 self._toDOM_csc(bds, element) 525 bds.finalize() 526 return bds.document()
527
528 - def toxml (self, encoding=None, bds=None, root_only=False):
529 """Shorthand to get the object as an XML document. 530 531 If you want to set the default namespace, pass in a pre-configured 532 C{bds}. 533 534 @param encoding: The encoding to be used. See 535 @C{xml.dom.Node.toxml()} for a description of why you should always 536 pass @C{'utf-8'} here. Because this method follows the contract of 537 the corresponding C{xml.dom.Node} method, it does not automatically 538 get the default PyXB output encoding. 539 540 @param bds: Optional L{pyxb.utils.domutils.BindingDOMSupport} instance 541 to use for creation. If not provided (default), a new generic one is 542 created. 543 """ 544 dom = self.toDOM(bds) 545 if root_only: 546 dom = dom.documentElement 547 return dom.toxml(encoding)
548
549 - def _toDOM_csc (self, dom_support, parent):
550 assert parent is not None 551 if self.__xsiNil: 552 dom_support.addAttribute(parent, XSI.nil, 'true') 553 return getattr(super(_TypeBinding_mixin, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
554
555 - def _validateBinding_vx (self):
556 """Override in subclasses for type-specific validation of instance 557 content. 558 559 @return: C{True} if the instance validates 560 @raise pyxb.BatchContentValidationError: complex content does not match model 561 @raise pyxb.SimpleTypeValueError: simple content fails to satisfy constraints 562 """ 563 raise NotImplementedError('%s._validateBinding_vx' % (type(self).__name__,))
564
565 - def validateBinding (self):
566 """Check whether the binding content matches its content model. 567 568 @return: C{True} if validation succeeds. 569 @raise pyxb.BatchContentValidationError: complex content does not match model 570 @raise pyxb.SimpleTypeValueError: attribute or simple content fails to satisfy constraints 571 """ 572 if self._performValidation(): 573 self._validateBinding_vx() 574 return True
575
576 - def _finalizeContentModel (self):
577 """Inform content model that all additions have been provided. 578 579 This is used to resolve any pending non-determinism when the content 580 of an element is provided through a DOM assignment or through 581 positional arguments in a constructor.""" 582 return self
583
584 - def _postDOMValidate (self):
585 self.validateBinding() 586 return self
587 588 @classmethod
589 - def _Name (cls):
590 """Return the best descriptive name for the type of the instance. 591 592 This is intended to be a human-readable value used in diagnostics, and 593 is the expanded name if the type has one, or the Python type name if 594 it does not.""" 595 if cls._ExpandedName is not None: 596 return unicode(cls._ExpandedName) 597 return unicode(cls)
598
599 - def _diagnosticName (self):
600 """The best name available for this instance in diagnostics. 601 602 If the instance is associated with an element, it is the element name; 603 otherwise it is the best name for the type of the instance per L{_Name}.""" 604 if self.__element is None: 605 return self._Name() 606 return unicode(self.__element.name())
607
608 -class _DynamicCreate_mixin (pyxb.cscRoot):
609 """Helper to allow overriding the implementation class. 610 611 Generally we'll want to augment the generated bindings by subclassing 612 them, and adding functionality to the subclass. This mix-in provides a 613 way to communicate the existence of the superseding subclass back to the 614 binding infrastructure, so that when it creates an instance it uses the 615 subclass rather than the unaugmented binding class. 616 617 When a raw generated binding is subclassed, L{_SetSupersedingClass} should be 618 invoked on the raw class passing in the superseding subclass. E.g.:: 619 620 class mywsdl (raw.wsdl): 621 pass 622 raw.wsdl._SetSupersedingClass(mywsdl) 623 624 """ 625 626 @classmethod
628 return '_%s__SupersedingClass' % (cls.__name__,)
629 630 @classmethod
632 return '_%s__AlternativeConstructor' % (cls.__name__,)
633 634 @classmethod
635 - def _SupersedingClass (cls):
636 """Return the class stored in the class reference attribute.""" 637 return getattr(cls, cls.__SupersedingClassAttribute(), cls)
638 639 @classmethod
640 - def _AlternativeConstructor (cls):
641 """Return the class stored in the class reference attribute.""" 642 rv = getattr(cls, cls.__AlternativeConstructorAttribute(), None) 643 if isinstance(rv, tuple): 644 rv = rv[0] 645 return rv
646 647 @classmethod
648 - def _SetSupersedingClass (cls, superseding):
649 """Set the class reference attribute. 650 651 @param superseding: A Python class that is a subclass of this class. 652 """ 653 assert (superseding is None) or issubclass(superseding, cls) 654 if superseding is None: 655 cls.__dict__.pop(cls.__SupersedingClassAttribute(), None) 656 else: 657 setattr(cls, cls.__SupersedingClassAttribute(), superseding) 658 return superseding
659 660 @classmethod
661 - def _SetAlternativeConstructor (cls, alternative_constructor):
662 attr = cls.__AlternativeConstructorAttribute() 663 if alternative_constructor is None: 664 cls.__dict__.pop(attr, None) 665 else: 666 # Need to use a tuple as the value: if you use an invokable, this 667 # ends up converting it from a function to an unbound method, 668 # which is not what we want. 669 setattr(cls, attr, (alternative_constructor,)) 670 assert cls._AlternativeConstructor() == alternative_constructor 671 return alternative_constructor
672 673 @classmethod
674 - def _DynamicCreate (cls, *args, **kw):
675 """Invoke the constructor for this class or the one that supersedes it.""" 676 ctor = cls._AlternativeConstructor() 677 if ctor is None: 678 ctor = cls._SupersedingClass() 679 try: 680 return ctor(*args, **kw) 681 except TypeError as e: 682 raise pyxb.SimpleTypeValueError(ctor, args)
683
684 -class simpleTypeDefinition (_TypeBinding_mixin, utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
685 """L{simpleTypeDefinition} is a base class that is part of the 686 hierarchy of any class that represents the Python datatype for a 687 L{SimpleTypeDefinition<pyxb.xmlschema.structures.SimpleTypeDefinition>}. 688 689 @note: This class, or a descendent of it, must be the first class 690 in the method resolution order when a subclass has multiple 691 parents. Otherwise, constructor keyword arguments may not be 692 removed before passing them on to Python classes that do not 693 accept them. 694 """ 695 696 # A map from leaf classes in the facets module to instance of 697 # those classes that constrain or otherwise affect the datatype. 698 # Note that each descendent of simpleTypeDefinition has its own map. 699 __FacetMap = {} 700 701 _ReservedSymbols = _TypeBinding_mixin._ReservedSymbols.union(set([ 'XsdLiteral', 'xsdLiteral', 702 'XsdSuperType', 'XsdPythonType', 'XsdConstraintsOK', 703 'xsdConstraintsOK', 'XsdValueLength', 'xsdValueLength', 704 'PythonLiteral', 'pythonLiteral', 705 'SimpleTypeDefinition' ])) 706 """Symbols that remain the responsibility of this class. Any 707 public symbols in generated binding subclasses are deconflicted 708 by providing an alternative name in the subclass. (There 709 currently are no public symbols in generated SimpleTypeDefinion 710 bindings.""" 711 712 713 # Determine the name of the class-private facet map. For the base class 714 # this should produce the same attribute name as Python's privatization 715 # scheme. 716 __FacetMapAttributeNameMap = { } 717 @classmethod
718 - def __FacetMapAttributeName (cls):
719 """ """ 720 ''' 721 if cls == simpleTypeDefinition: 722 return '_%s__FacetMap' % (cls.__name__.strip('_'),) 723 724 # It is not uncommon for a class in one namespace to extend a class of 725 # the same name in a different namespace, so encode the namespace URI 726 # in the attribute name (if it is part of a namespace). 727 ns_uri = '' 728 try: 729 ns_uri = cls._ExpandedName.namespaceURI() 730 except Exception: 731 pass 732 nm = '_' + utility.MakeIdentifier('%s_%s_FacetMap' % (ns_uri, cls.__name__.strip('_'))) 733 ''' 734 nm = cls.__FacetMapAttributeNameMap.get(cls) 735 if nm is None: 736 nm = cls.__name__ 737 if nm.endswith('_'): 738 nm += '1' 739 if cls == simpleTypeDefinition: 740 nm = '_%s__FacetMap' % (nm,) 741 else: 742 # It is not uncommon for a class in one namespace to extend a class of 743 # the same name in a different namespace, so encode the namespace URI 744 # in the attribute name (if it is part of a namespace). 745 ns_uri = '' 746 try: 747 ns_uri = cls._ExpandedName.namespaceURI() 748 except Exception: 749 pass 750 nm = '_' + utility.MakeIdentifier('%s_%s_FacetMap' % (ns_uri, nm)) 751 cls.__FacetMapAttributeNameMap[cls] = nm 752 return nm
753 754 @classmethod
755 - def _FacetMap (cls):
756 """Return a reference to the facet map for this datatype. 757 758 The facet map is a map from leaf facet classes to instances of those 759 classes that constrain or otherwise apply to the lexical or value 760 space of the datatype. Classes may inherit their facet map from their 761 superclass, or may create a new class instance if the class adds a new 762 constraint type. 763 764 @raise AttributeError: if the facet map has not been defined""" 765 return getattr(cls, cls.__FacetMapAttributeName())
766 767 @classmethod
768 - def _InitializeFacetMap (cls, *args):
769 """Initialize the facet map for this datatype. 770 771 This must be called exactly once, after all facets belonging to the 772 datatype have been created. 773 774 @raise pyxb.LogicError: if called multiple times (on the same class) 775 @raise pyxb.LogicError: if called when a parent class facet map has not been initialized 776 :return: the facet map""" 777 fm = None 778 try: 779 fm = cls._FacetMap() 780 except AttributeError: 781 pass 782 if fm is not None: 783 raise pyxb.LogicError('%s facet map initialized multiple times: %s' % (cls.__name__, cls.__FacetMapAttributeName())) 784 785 # Search up the type hierarchy to find the nearest ancestor that has a 786 # facet map. This gets a bit tricky: if we hit the ceiling early 787 # because the PSTD hierarchy re-based itself on a new Python type, we 788 # have to jump to the XsdSuperType. 789 source_class = cls 790 while fm is None: 791 # Assume we're staying in this hierarchy. Include source_class in 792 # the candidates, since we might have jumped to it. 793 for super_class in source_class.mro(): 794 assert super_class is not None 795 if (super_class == simpleTypeDefinition): # and (source_class.XsdSuperType() is not None): 796 break 797 if issubclass(super_class, simpleTypeDefinition): 798 try: 799 fm = super_class._FacetMap() 800 break 801 except AttributeError: 802 pass 803 if fm is None: 804 try: 805 source_class = source_class.XsdSuperType() 806 except AttributeError: 807 source_class = None 808 if source_class is None: 809 fm = { } 810 if fm is None: 811 raise pyxb.LogicError('%s is not a child of simpleTypeDefinition' % (cls.__name__,)) 812 fm = fm.copy() 813 for facet in args: 814 fm[type(facet)] = facet 815 setattr(cls, cls.__FacetMapAttributeName(), fm) 816 return fm
817 818 @classmethod
819 - def _ConvertArguments_vx (cls, args, kw):
820 return args
821 822 @classmethod
823 - def _ConvertArguments (cls, args, kw):
824 """Pre-process the arguments. 825 826 This is used before invoking the parent constructor. One application 827 is to apply the whitespace facet processing; if such a request is in 828 the keywords, it is removed so it does not propagate to the 829 superclass. Another application is to convert the arguments from a 830 string to a list. Binding-specific applications are performed in the 831 overloaded L{_ConvertArguments_vx} method.""" 832 dom_node = kw.pop('_dom_node', None) 833 from_xml = kw.get('_from_xml', dom_node is not None) 834 if dom_node is not None: 835 text_content = domutils.ExtractTextContent(dom_node) 836 if text_content is not None: 837 args = (domutils.ExtractTextContent(dom_node),) + args 838 kw['_apply_whitespace_facet'] = True 839 apply_whitespace_facet = kw.pop('_apply_whitespace_facet', from_xml) 840 if (0 < len(args)) and isinstance(args[0], types.StringTypes) and apply_whitespace_facet: 841 cf_whitespace = getattr(cls, '_CF_whiteSpace', None) 842 if cf_whitespace is not None: 843 norm_str = unicode(cf_whitespace.normalizeString(args[0])) 844 args = (norm_str,) + args[1:] 845 kw['_from_xml'] = from_xml 846 return cls._ConvertArguments_vx(args, kw)
847 848 # Must override new, because new gets invoked before init, and usually 849 # doesn't accept keywords. In case it does (e.g., datetime.datetime), 850 # only remove the ones that would normally be interpreted by this class. 851 # Do the same argument conversion as is done in init. Trap errors and 852 # convert them to BadTypeValue errors. 853 # 854 # Note: We explicitly do not validate constraints here. That's 855 # done in the normal constructor; here, we might be in the process 856 # of building a value that eventually will be legal, but isn't 857 # yet.
858 - def __new__ (cls, *args, **kw):
859 # PyXBFactoryKeywords 860 kw.pop('_validate_constraints', None) 861 kw.pop('_require_value', None) 862 kw.pop('_element', None) 863 kw.pop('_fallback_namespace', None) 864 kw.pop('_apply_attributes', None) 865 kw.pop('_nil', None) 866 # ConvertArguments will remove _element and _apply_whitespace_facet 867 dom_node = kw.get('_dom_node') 868 args = cls._ConvertArguments(args, kw) 869 kw.pop('_from_xml', dom_node is not None) 870 kw.pop('_location', None) 871 assert issubclass(cls, _TypeBinding_mixin) 872 try: 873 return super(simpleTypeDefinition, cls).__new__(cls, *args, **kw) 874 except ValueError as e: 875 raise pyxb.SimpleTypeValueError(cls, args) 876 except OverflowError as e: 877 raise pyxb.SimpleTypeValueError(cls, args)
878 879 # Validate the constraints after invoking the parent constructor, 880 # unless told not to.
881 - def __init__ (self, *args, **kw):
882 """Initialize a newly created STD instance. 883 884 Usually there is one positional argument, which is a value that can be 885 converted to the underlying Python type. 886 887 @keyword _validate_constraints: If True (default if validation is 888 enabled), the newly constructed value is checked against its 889 constraining facets. 890 @type _validate_constraints: C{bool} 891 892 @keyword _apply_attributes: If C{True} (default), any attributes 893 present in the keywords or DOM node are applied. Normally presence of 894 such an attribute should produce an error; when creating simple 895 content for a complex type we need the DOM node, but do not want to 896 apply the attributes, so we bypass the application. 897 """ 898 # PyXBFactoryKeywords 899 validate_constraints = kw.pop('_validate_constraints', self._validationConfig.forBinding) 900 require_value = kw.pop('_require_value', False) 901 # Save DOM node so we can pull attributes off it 902 dom_node = kw.get('_dom_node') 903 location = kw.get('_location') 904 if (location is None) and isinstance(dom_node, utility.Locatable_mixin): 905 location = dom_node._location() 906 apply_attributes = kw.pop('_apply_attributes', True) 907 # _ConvertArguments handles _dom_node and _apply_whitespace_facet 908 # TypeBinding_mixin handles _nil and _element 909 args = self._ConvertArguments(args, kw) 910 try: 911 super(simpleTypeDefinition, self).__init__(*args, **kw) 912 except OverflowError as e: 913 raise pyxb.SimpleTypeValueError(type(self), args) 914 if apply_attributes and (dom_node is not None): 915 self._setAttributesFromKeywordsAndDOM(kw, dom_node) 916 if require_value and (not self._constructedWithValue()): 917 if location is None: 918 location = self._location() 919 raise pyxb.SimpleContentAbsentError(self, location) 920 if validate_constraints and not kw.pop('_nil', False): 921 self.xsdConstraintsOK(location)
922 923 # The class attribute name used to store the reference to the STD 924 # component instance must be unique to the class, not to this base class. 925 # Otherwise we mistakenly believe we've already associated a STD instance 926 # with a class (e.g., xsd:normalizedString) when in fact it's associated 927 # with the superclass (e.g., xsd:string) 928 @classmethod
929 - def __STDAttrName (cls):
930 return '_%s__SimpleTypeDefinition' % (cls.__name__,)
931 932 @classmethod
933 - def _SimpleTypeDefinition (cls, std):
934 """Set the L{pyxb.xmlschema.structures.SimpleTypeDefinition} instance 935 associated with this binding.""" 936 attr_name = cls.__STDAttrName() 937 if hasattr(cls, attr_name): 938 old_value = getattr(cls, attr_name) 939 if old_value != std: 940 raise pyxb.LogicError('%s: Attempt to override existing STD %s with %s' % (cls, old_value.name(), std.name())) 941 setattr(cls, attr_name, std)
942 943 @classmethod
944 - def SimpleTypeDefinition (cls):
945 """Return the SimpleTypeDefinition instance for the given 946 class. 947 948 This should only be invoked when generating bindings. An STD must 949 have been associated with the class using L{_SimpleTypeDefinition}.""" 950 attr_name = cls.__STDAttrName() 951 assert hasattr(cls, attr_name) 952 return getattr(cls, attr_name)
953 954 @classmethod
955 - def XsdLiteral (cls, value):
956 """Convert from a python value to a string usable in an XML 957 document. 958 959 This should be implemented in the subclass.""" 960 raise pyxb.LogicError('%s does not implement XsdLiteral' % (cls,))
961
962 - def xsdLiteral (self):
963 """Return text suitable for representing the value of this 964 instance in an XML document. 965 966 The base class implementation delegates to the object class's 967 XsdLiteral method.""" 968 if self._isNil(): 969 return '' 970 return self.XsdLiteral(self)
971 972 @classmethod
973 - def XsdSuperType (cls):
974 """Find the nearest parent class in the PST hierarchy. 975 976 The value for anySimpleType is None; for all others, it's a 977 primitive or derived PST descendent (including anySimpleType).""" 978 for sc in cls.mro(): 979 if sc == cls: 980 continue 981 if simpleTypeDefinition == sc: 982 # If we hit the PST base, this is a primitive type or 983 # otherwise directly descends from a Python type; return 984 # the recorded XSD supertype. 985 return cls._XsdBaseType 986 if issubclass(sc, simpleTypeDefinition): 987 return sc 988 raise pyxb.LogicError('No supertype found for %s' % (cls,))
989 990 @classmethod
991 - def _XsdConstraintsPreCheck_vb (cls, value):
992 """Pre-extended class method to verify other things before 993 checking constraints. 994 995 This is used for list types, to verify that the values in the 996 list are acceptable, and for token descendents, to check the 997 lexical/value space conformance of the input. 998 """ 999 super_fn = getattr(super(simpleTypeDefinition, cls), '_XsdConstraintsPreCheck_vb', lambda *a,**kw: value) 1000 return super_fn(value)
1001 1002 # Cache of pre-computed sequences of class facets in the order required 1003 # for constraint validation 1004 __ClassFacetSequence = { } 1005 1006 @classmethod
1007 - def XsdConstraintsOK (cls, value, location=None):
1008 """Validate the given value against the constraints on this class. 1009 1010 @raise pyxb.SimpleTypeValueError: if any constraint is violated. 1011 """ 1012 1013 value = cls._XsdConstraintsPreCheck_vb(value) 1014 1015 facet_values = cls.__ClassFacetSequence.get(cls) 1016 if facet_values is None: 1017 # Constraints for simple type definitions are inherited. Check them 1018 # from least derived to most derived. 1019 classes = [ _x for _x in cls.mro() if issubclass(_x, simpleTypeDefinition) ] 1020 classes.reverse() 1021 cache_result = True 1022 facet_values = [] 1023 for clazz in classes: 1024 # When setting up the datatypes, if we attempt to validate 1025 # something before the facets have been initialized (e.g., a 1026 # nonNegativeInteger used as a length facet for the parent 1027 # integer datatype), just ignore that for now. Don't cache 1028 # the value, though, since a subsequent check after 1029 # initialization should succceed. 1030 try: 1031 clazz_facets = clazz._FacetMap().values() 1032 except AttributeError: 1033 cache_result = False 1034 clazz_facets = [] 1035 for v in clazz_facets: 1036 if not (v in facet_values): 1037 facet_values.append(v) 1038 if cache_result: 1039 cls.__ClassFacetSequence[cls] = facet_values 1040 for f in facet_values: 1041 if not f.validateConstraint(value): 1042 raise pyxb.SimpleFacetValueError(cls, value, f, location) 1043 return value
1044
1045 - def xsdConstraintsOK (self, location=None):
1046 """Validate the value of this instance against its constraints.""" 1047 return self.XsdConstraintsOK(self, location)
1048
1049 - def _validateBinding_vx (self):
1050 if not self._isNil(): 1051 self._checkValidValue() 1052 return True
1053 1054 @classmethod
1055 - def XsdValueLength (cls, value):
1056 """Return the length of the given value. 1057 1058 The length is calculated by a subclass implementation of 1059 _XsdValueLength_vx in accordance with 1060 http://www.w3.org/TR/xmlschema-2/#rf-length. 1061 1062 The return value is a non-negative integer, or C{None} if length 1063 constraints should be considered trivially satisfied (as with 1064 QName and NOTATION). 1065 1066 @raise pyxb.LogicError: the provided value is not an instance of cls. 1067 @raise pyxb.LogicError: an attempt is made to calculate a length for 1068 an instance of a type that does not support length calculations. 1069 """ 1070 assert isinstance(value, cls) 1071 if not hasattr(cls, '_XsdValueLength_vx'): 1072 raise pyxb.LogicError('Class %s does not support length validation' % (cls.__name__,)) 1073 return cls._XsdValueLength_vx(value)
1074
1075 - def xsdValueLength (self):
1076 """Return the length of this instance within its value space. 1077 1078 See XsdValueLength.""" 1079 return self.XsdValueLength(self)
1080 1081 @classmethod
1082 - def PythonLiteral (cls, value):
1083 """Return a string which can be embedded into Python source to 1084 represent the given value as an instance of this class.""" 1085 class_name = cls.__name__ 1086 return '%s(%s)' % (class_name, repr(value))
1087
1088 - def pythonLiteral (self):
1089 """Return a string which can be embedded into Python source to 1090 represent the value of this instance.""" 1091 return self.PythonLiteral(self)
1092
1093 - def _toDOM_csc (self, dom_support, parent):
1094 assert parent is not None 1095 dom_support.appendTextChild(self.xsdLiteral(), parent) 1096 return getattr(super(simpleTypeDefinition, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
1097 1098 @classmethod
1099 - def _IsSimpleTypeContent (cls):
1100 """STDs have simple type content.""" 1101 return True
1102 1103 @classmethod
1104 - def _IsValidValue (self, value):
1105 try: 1106 self._CheckValidValue(value) 1107 return True 1108 except pyxb.PyXBException: 1109 pass 1110 return False
1111 1112 @classmethod
1113 - def _CheckValidValue (cls, value):
1114 1115 """NB: Invoking this on a value that is a list will, if necessary, 1116 replace the members of the list with new values that are of the 1117 correct item type. This is permitted because only with lists is it 1118 possible to bypass the normal content validation (by invoking 1119 append/extend on the list instance).""" 1120 if value is None: 1121 raise pyxb.SimpleTypeValueError(cls, value) 1122 value_class = cls 1123 if issubclass(cls, STD_list): 1124 if not isinstance(value, collections.Iterable): 1125 raise pyxb.SimpleTypeValueError(cls, value) 1126 for v in value: 1127 if not cls._ItemType._IsValidValue(v): 1128 raise pyxb.SimpleListValueError(cls, v) 1129 else: 1130 if issubclass(cls, STD_union): 1131 value_class = None 1132 for mt in cls._MemberTypes: 1133 if mt._IsValidValue(value): 1134 value_class = mt 1135 break 1136 if value_class is None: 1137 raise pyxb.SimpleUnionValueError(cls, value) 1138 #if not (isinstance(value, value_class) or issubclass(value_class, type(value))): 1139 if not isinstance(value, value_class): 1140 raise pyxb.SimpleTypeValueError(cls, value) 1141 value_class.XsdConstraintsOK(value)
1142
1143 - def _checkValidValue (self):
1144 self._CheckValidValue(self)
1145
1146 - def _isValidValue (self):
1147 self._IsValidValue(self)
1148
1149 - def _setAttribute (self, attr_en, value):
1150 # Simple types have no attributes, but the parsing infrastructure 1151 # might invoke this to delegate responsibility for notifying the user 1152 # of the failure. 1153 raise pyxb.AttributeOnSimpleTypeError(self, attr_en, value)
1154 1155 @classmethod
1156 - def _description (cls, name_only=False, user_documentation=True):
1157 name = cls._Name() 1158 if name_only: 1159 return name 1160 desc = [ name, ' restriction of ', cls.XsdSuperType()._description(name_only=True) ] 1161 if user_documentation and (cls._Documentation is not None): 1162 desc.extend(["\n", cls._Documentation]) 1163 return ''.join(desc)
1164
1165 -class STD_union (simpleTypeDefinition):
1166 """Base class for union datatypes. 1167 1168 This class descends only from simpleTypeDefinition. A pyxb.LogicError is 1169 raised if an attempt is made to construct an instance of a subclass of 1170 STD_union. Values consistent with the member types are constructed using 1171 the Factory class method. Values are validated using the _ValidatedMember 1172 class method. 1173 1174 Subclasses must provide a class variable _MemberTypes which is a 1175 tuple of legal members of the union.""" 1176 1177 _MemberTypes = None 1178 """A list of classes which are permitted as values of the union.""" 1179 1180 # Ick: If we don't declare this here, this class's map doesn't get 1181 # initialized. Alternative is to not descend from simpleTypeDefinition. 1182 # @todo Ensure that pattern and enumeration are valid constraints 1183 __FacetMap = {} 1184 1185 @classmethod
1186 - def Factory (cls, *args, **kw):
1187 """Given a value, attempt to create an instance of some member of this 1188 union. The first instance which can be legally created is returned. 1189 1190 @keyword _validate_constraints: If C{True} (default if validation is 1191 enabled), any constructed value is checked against constraints applied 1192 to the union as well as the member type. 1193 1194 @raise pyxb.SimpleTypeValueError: no member type will permit creation of 1195 an instance from the parameters in C{args} and C{kw}. 1196 """ 1197 1198 used_cls = cls._SupersedingClass() 1199 state = used_cls._PreFactory_vx(args, kw) 1200 1201 rv = None 1202 # NB: get, not pop: preserve it for the member type invocations 1203 validate_constraints = kw.get('_validate_constraints', cls._GetValidationConfig().forBinding) 1204 assert isinstance(validate_constraints, bool) 1205 if 0 < len(args): 1206 arg = args[0] 1207 try: 1208 rv = cls._ValidatedMember(arg) 1209 except pyxb.SimpleTypeValueError: 1210 pass 1211 if rv is None: 1212 kw['_validate_constraints'] = True 1213 for mt in cls._MemberTypes: 1214 try: 1215 rv = mt.Factory(*args, **kw) 1216 break 1217 except pyxb.SimpleTypeValueError: 1218 pass 1219 except (ValueError, OverflowError): 1220 pass 1221 except: 1222 pass 1223 location = None 1224 if kw is not None: 1225 location = kw.get('_location') 1226 if rv is not None: 1227 if validate_constraints: 1228 cls.XsdConstraintsOK(rv, location) 1229 rv._postFactory_vx(state) 1230 return rv 1231 # The constructor may take any number of arguments, so pass the whole thing. 1232 # Should we also provide the keywords? 1233 raise pyxb.SimpleUnionValueError(cls, args, location)
1234 1235 @classmethod
1236 - def _ValidatedMember (cls, value):
1237 """Validate the given value as a potential union member. 1238 1239 @raise pyxb.SimpleTypeValueError: the value is not an instance of a 1240 member type.""" 1241 if not isinstance(value, cls._MemberTypes): 1242 for mt in cls._MemberTypes: 1243 try: 1244 # Force validation so we get the correct type, otherwise 1245 # first member will be accepted. 1246 value = mt.Factory(value, _validate_constraints=True) 1247 return value 1248 except (TypeError, pyxb.SimpleTypeValueError): 1249 pass 1250 raise pyxb.SimpleUnionValueError(cls, value) 1251 return value
1252
1253 - def __init__ (self, *args, **kw):
1254 raise pyxb.LogicError('%s: cannot construct instances of union' % (self.__class__.__name__,))
1255 1256 @classmethod
1257 - def _description (cls, name_only=False, user_documentation=True):
1258 name = cls._Name() 1259 if name_only: 1260 return name 1261 desc = [ name, ', union of '] 1262 desc.append(', '.join([ _td._description(name_only=True) for _td in cls._MemberTypes ])) 1263 return ''.join(desc)
1264 1265 @classmethod
1266 - def XsdLiteral (cls, value):
1267 """Convert from a binding value to a string usable in an XML document.""" 1268 return cls._ValidatedMember(value).xsdLiteral()
1269
1270 1271 -class STD_list (simpleTypeDefinition, types.ListType):
1272 """Base class for collection datatypes. 1273 1274 This class descends from the Python list type, and incorporates 1275 simpleTypeDefinition. Subclasses must define a class variable _ItemType 1276 which is a reference to the class of which members must be instances.""" 1277 1278 _ItemType = None 1279 """A reference to the binding class for items within this list.""" 1280 1281 # Ick: If we don't declare this here, this class's map doesn't get 1282 # initialized. Alternative is to not descend from simpleTypeDefinition. 1283 __FacetMap = {} 1284 1285 @classmethod
1286 - def _ValidatedItem (cls, value, kw=None):
1287 """Verify that the given value is permitted as an item of this list. 1288 1289 This may convert the value to the proper type, if it is 1290 compatible but not an instance of the item type. Returns the 1291 value that should be used as the item, or raises an exception 1292 if the value cannot be converted. 1293 1294 @param kw: optional dictionary of standard constructor keywords used 1295 when exceptions must be built. In particular, C{_location} may be 1296 useful. 1297 """ 1298 if isinstance(value, cls._ItemType): 1299 pass 1300 elif issubclass(cls._ItemType, STD_union): 1301 value = cls._ItemType._ValidatedMember(value) 1302 else: 1303 try: 1304 value = cls._ItemType(value) 1305 except (pyxb.SimpleTypeValueError, TypeError): 1306 location = None 1307 if kw is not None: 1308 location = kw.get('_location') 1309 raise pyxb.SimpleListValueError(cls, value, location) 1310 return value
1311 1312 @classmethod
1313 - def _ConvertArguments_vx (cls, args, kw):
1314 # If the first argument is a string, split it on spaces and use the 1315 # resulting list of tokens. 1316 if 0 < len(args): 1317 arg1 = args[0] 1318 if isinstance(arg1, types.StringTypes): 1319 args = (arg1.split(),) + args[1:] 1320 arg1 = args[0] 1321 if isinstance(arg1, collections.Iterable): 1322 new_arg1 = [ cls._ValidatedItem(_v, kw) for _v in arg1 ] 1323 args = (new_arg1,) + args[1:] 1324 super_fn = getattr(super(STD_list, cls), '_ConvertArguments_vx', lambda *a,**kw: args) 1325 return super_fn(args, kw)
1326 1327 @classmethod
1328 - def _XsdValueLength_vx (cls, value):
1329 return len(value)
1330 1331 @classmethod
1332 - def XsdLiteral (cls, value):
1333 """Convert from a binding value to a string usable in an XML document.""" 1334 return ' '.join([ cls._ItemType.XsdLiteral(_v) for _v in value ])
1335 1336 @classmethod
1337 - def _description (cls, name_only=False, user_documentation=True):
1338 name = cls._Name() 1339 if name_only: 1340 return name 1341 desc = [ name, ', list of ', cls._ItemType._description(name_only=True) ] 1342 return ''.join(desc)
1343 1344 # Convert a single value to the required type, if not already an instance 1345 @classmethod
1346 - def __ConvertOne (cls, v):
1347 return cls._ValidatedItem(v)
1348 1349 # Convert a sequence of values to the required type, if not already instances
1350 - def __convertMany (self, values):
1351 return [ self._ValidatedItem(_v) for _v in values ]
1352
1353 - def __setitem__ (self, key, value):
1354 if isinstance(key, slice): 1355 super(STD_list, self).__setitem__(key, self.__convertMany(value)) 1356 else: 1357 super(STD_list, self).__setitem__(key, self._ValidatedItem(value))
1358
1359 - def __setslice__ (self, start, end, values):
1360 super(STD_list, self).__setslice__(start, end, self.__convertMany(values))
1361
1362 - def __contains__ (self, item):
1363 return super(STD_list, self).__contains__(self._ValidatedItem(item))
1364 1365 # Standard mutable sequence methods, per Python Library Reference "Mutable Sequence Types" 1366
1367 - def append (self, x):
1368 super(STD_list, self).append(self._ValidatedItem(x))
1369
1370 - def extend (self, x, _from_xml=False):
1371 super(STD_list, self).extend(self.__convertMany(x))
1372
1373 - def count (self, x):
1374 return super(STD_list, self).count(self._ValidatedItem(x))
1375
1376 - def index (self, x, *args):
1377 return super(STD_list, self).index(self._ValidatedItem(x), *args)
1378
1379 - def insert (self, i, x):
1380 super(STD_list, self).insert(i, self._ValidatedItem(x))
1381
1382 - def remove (self, x):
1383 super(STD_list, self).remove(self._ValidatedItem(x))
1384
1385 -class element (utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
1386 """Class that represents a schema element within a binding. 1387 1388 This gets a little confusing. Within a schema, the 1389 L{pyxb.xmlschema.structures.ElementDeclaration} type represents an 1390 U{element 1391 declaration<http://www.w3.org/TR/xmlschema-1/#cElement_Declarations>}. 1392 Those declarations may be global (have a name that is visible in the 1393 namespace), or local (have a name that is visible only within a complex 1394 type definition). Further, local (but not global) declarations may have a 1395 reference to a global declaration (which might be in a different 1396 namespace). 1397 1398 Within a PyXB binding, the element declarations from the original complex 1399 type definition that have the same 1400 U{QName<http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-qname>} 1401 (after deconflicting the 1402 U{LocalPart<http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-LocalPart>}) 1403 are associated with an attribute in the class for the complex type. Each 1404 of these attributes is defined via a 1405 L{pyxb.binding.content.ElementDeclaration} which provides the mechanism by 1406 which the binding holds values associated with that element. 1407 1408 Furthermore, in the FAC-based content model each schema element 1409 declaration is associated with an 1410 L{ElementUse<pyxb.binding.content.ElementUse>} instance to locate the 1411 point in the schema where content came from. Instances that refer to the 1412 same schema element declaration share the same underlying 1413 L{pyxb.binding.content.ElementDeclaration}. 1414 1415 This element isn't any of those elements. This element is the type used 1416 for an attribute which associates the name of a element with data required 1417 to represent it, all within a particular scope (a module for global scope, 1418 the binding class for a complex type definition for local scope). From 1419 the perspective of a PyXB user they look almost like a class, in that you 1420 can call them to create instances of the underlying complex type. 1421 1422 Global and local elements are represented by instances of this class. 1423 """ 1424
1425 - def name (self):
1426 """The expanded name of the element within its scope.""" 1427 return self.__name
1428 __name = None 1429
1430 - def typeDefinition (self):
1431 """The L{_TypeBinding_mixin} subclass for values of this element.""" 1432 return self.__typeDefinition._SupersedingClass()
1433 __typeDefinition = None 1434
1435 - def xsdLocation (self):
1436 """The L{pyxb.utils.utility.Location} where the element appears in the schema.""" 1437 return self.__xsdLocation
1438 __xsdLocation = None 1439
1440 - def scope (self):
1441 """The scope of the element. This is either C{None}, representing a 1442 top-level element, or an instance of C{complexTypeDefinition} for 1443 local elements.""" 1444 return self.__scope
1445 __scope = None 1446
1447 - def nillable (self):
1448 """Indicate whether values matching this element can have U{nil 1449 <http://www.w3.org/TR/xmlschema-1/#xsi_nil>} set.""" 1450 return self.__nillable
1451 __nillable = False 1452
1453 - def abstract (self):
1454 """Indicate whether this element is abstract (must use substitution 1455 group members for matches).""" 1456 return self.__abstract
1457 __abstract = False 1458
1459 - def documentation (self):
1460 """Contents of any documentation annotation in the definition.""" 1461 return self.__documentation
1462 __documentation = None 1463
1464 - def defaultValue (self):
1465 """The default value of the element. 1466 1467 C{None} if the element has no default value. 1468 1469 @note: A non-C{None} value is always an instance of a simple type, 1470 even if the element has complex content.""" 1471 return self.__defaultValue
1472 __defaultValue = None 1473
1474 - def fixed (self):
1475 """C{True} if the element content cannot be changed""" 1476 return self.__fixed
1477 __fixed = False 1478
1479 - def substitutionGroup (self):
1480 """The L{element} instance to whose substitution group this element 1481 belongs. C{None} if this element is not part of a substitution 1482 group.""" 1483 return self.__substitutionGroup
1484 - def _setSubstitutionGroup (self, substitution_group):
1485 self.__substitutionGroup = substitution_group 1486 if substitution_group is not None: 1487 self.substitutesFor = self._real_substitutesFor 1488 return self
1489 __substitutionGroup = None 1490
1491 - def findSubstituendDecl (self, ctd_class):
1492 ed = ctd_class._ElementMap.get(self.name()) 1493 if ed is not None: 1494 return ed 1495 if self.substitutionGroup() is None: 1496 return None 1497 return self.substitutionGroup().findSubstituendDecl(ctd_class)
1498
1499 - def _real_substitutesFor (self, other):
1500 """Determine whether an instance of this element can substitute for the other element. 1501 1502 See U{Substitution Group OK<http://www.w3.org/TR/xmlschema-1/#cos-equiv-derived-ok-rec>}. 1503 1504 @todo: Do something about blocking constraints. This ignores them, as 1505 does everything leading to this point. 1506 """ 1507 if self.substitutionGroup() is None: 1508 return False 1509 if other is None: 1510 return False 1511 assert isinstance(other, element) 1512 # On the first call, other is likely to be the local element. We need 1513 # the global one. 1514 if other.scope() is not None: 1515 other = other.name().elementBinding() 1516 if other is None: 1517 return False 1518 assert other.scope() is None 1519 # Do both these refer to the same (top-level) element? 1520 if self.name().elementBinding() == other: 1521 return True 1522 return (self.substitutionGroup() == other) or self.substitutionGroup().substitutesFor(other)
1523
1524 - def substitutesFor (self, other):
1525 """Stub replaced by _real_substitutesFor when element supports substitution groups.""" 1526 return False
1527
1528 - def memberElement (self, name):
1529 """Return a reference to the element instance used for the given name 1530 within this element. 1531 1532 The type for this element must be a complex type definition.""" 1533 return self.typeDefinition()._UseForTag(name).elementBinding()
1534
1535 - def __init__ (self, name, type_definition, scope=None, nillable=False, abstract=False, unicode_default=None, fixed=False, substitution_group=None, documentation=None, location=None):
1536 """Create a new element binding. 1537 """ 1538 assert isinstance(name, pyxb.namespace.ExpandedName) 1539 self.__name = name 1540 self.__typeDefinition = type_definition 1541 self.__scope = scope 1542 self.__nillable = nillable 1543 self.__abstract = abstract 1544 if unicode_default is not None: 1545 # Override default None. If this is a complex type with simple 1546 # content, use the underlying simple type value. 1547 self.__defaultValue = self.__typeDefinition.Factory(unicode_default, _from_xml=True) 1548 if isinstance(self.__defaultValue, complexTypeDefinition): 1549 self.__defaultValue = self.__defaultValue.value() 1550 self.__fixed = fixed 1551 self.__substitutionGroup = substitution_group 1552 self.__documentation = documentation 1553 self.__xsdLocation = location 1554 super(element, self).__init__()
1555
1556 - def __call__ (self, *args, **kw):
1557 """Invoke the Factory method on the type associated with this element. 1558 1559 @keyword _dom_node: This keyword is removed. If present, it must be C{None}. 1560 1561 @note: Other keywords are passed to L{_TypeBinding_mixin.Factory}. 1562 1563 @raise pyxb.AbstractElementError: This element is abstract and no DOM 1564 node was provided. 1565 """ 1566 dom_node = kw.pop('_dom_node', None) 1567 assert dom_node is None, 'Cannot pass DOM node directly to element constructor; use createFromDOM' 1568 if '_element' in kw: 1569 raise pyxb.LogicError('Cannot set _element in element-based instance creation') 1570 kw['_element'] = self 1571 # Can't create instances of abstract elements. 1572 if self.abstract(): 1573 location = kw.get('_location') 1574 if (location is None) and isinstance(dom_node, utility.Locatable_mixin): 1575 location = dom_node._location() 1576 raise pyxb.AbstractElementError(self, location, args) 1577 if self.__defaultValue is not None: 1578 if 0 == len(args): 1579 # No initial value; use the default 1580 args = [ self.__defaultValue ] 1581 elif self.__fixed: 1582 # Validate that the value is consistent with the fixed value 1583 if 1 < len(args): 1584 raise ValueError(*args) 1585 args = [ self.compatibleValue(args[0], **kw) ] 1586 rv = self.typeDefinition().Factory(*args, **kw) 1587 rv._setElement(self) 1588 return rv
1589
1590 - def compatibleValue (self, value, **kw):
1591 """Return a variant of the value that is compatible with this element. 1592 1593 This mostly defers to L{_TypeBinding_mixin._CompatibleValue}. 1594 1595 @raise pyxb.SimpleTypeValueError: if the value is not both 1596 type-consistent and value-consistent with the element's type. 1597 """ 1598 # None is always None, unless there's a default. 1599 if value is None: 1600 return self.__defaultValue 1601 is_plural = kw.pop('is_plural', False) 1602 if is_plural: 1603 if not isinstance(value, collections.Iterable): 1604 raise pyxb.SimplePluralValueError(self.typeDefinition(), value) 1605 return [ self.compatibleValue(_v) for _v in value ] 1606 if self.__fixed and (value != self.__defaultValue): 1607 raise pyxb.ElementChangeError(self, value) 1608 if isinstance(value, _TypeBinding_mixin) and (value._element() is not None) and value._element().substitutesFor(self): 1609 return value 1610 if self.abstract(): 1611 location = None 1612 if isinstance(value, utility.Locatable_mixin): 1613 location = value._location() 1614 raise pyxb.AbstractElementError(self, location, value) 1615 return self.typeDefinition()._CompatibleValue(value, **kw)
1616 1617 @classmethod
1618 - def CreateDOMBinding (cls, node, element_binding, **kw):
1619 """Create a binding from a DOM node. 1620 1621 @param node: The DOM node 1622 1623 @param element_binding: An instance of L{element} that would normally 1624 be used to determine the type of the binding. The actual type of 1625 object returned is determined by the type definition associated with 1626 the C{element_binding} and the value of any U{xsi:type 1627 <http://www.w3.org/TR/xmlschema-1/#xsi_type>} attribute found in 1628 C{node}, modulated by 1629 L{XSI._InterpretTypeAttribute<pyxb.namespace.builtin._XMLSchema_instance._InterpretTypeAttribute>}. 1630 1631 @keyword _fallback_namespace: The namespace to use as the namespace for 1632 the node, if the node name is unqualified. This should be an absent 1633 namespace. 1634 1635 @return: A binding for the DOM node. 1636 1637 @raises pyxb.UnrecognizedDOMRootNodeError: if no underlying element or 1638 type for the node can be identified. 1639 """ 1640 1641 if xml.dom.Node.ELEMENT_NODE != node.nodeType: 1642 raise ValueError('node is not an element') 1643 1644 fallback_namespace = kw.get('_fallback_namespace') 1645 1646 # Record the element to be associated with the created binding 1647 # instance. 1648 if '_element' in kw: 1649 raise pyxb.LogicError('Cannot set _element in element-based instance creation') 1650 1651 type_class = None 1652 if element_binding is not None: 1653 # Can't create instances of abstract elements. @todo: Is there any 1654 # way this could be legal given an xsi:type attribute? I'm pretty 1655 # sure "no"... 1656 if element_binding.abstract(): 1657 location = kw.get('location') 1658 if (location is None) and isinstance(node, utility.Locatable_mixin): 1659 location = node._location() 1660 raise pyxb.AbstractElementError(element_binding, location, node) 1661 kw['_element'] = element_binding 1662 type_class = element_binding.typeDefinition() 1663 1664 # Get the namespace context for the value being created. If none is 1665 # associated, one will be created. Do not make assumptions about the 1666 # namespace context; if the user cared, she should have assigned a 1667 # context before calling this. 1668 ns_ctx = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(node) 1669 (did_replace, type_class) = XSI._InterpretTypeAttribute(XSI.type.getAttribute(node), ns_ctx, fallback_namespace, type_class) 1670 1671 if type_class is None: 1672 raise pyxb.UnrecognizedDOMRootNodeError(node) 1673 1674 # Pass xsi:nil on to the constructor regardless of whether the element 1675 # is nillable. Another sop to SOAP-encoding WSDL fans who don't 1676 # bother to provide valid schema for their message content. 1677 is_nil = XSI.nil.getAttribute(node) 1678 if is_nil is not None: 1679 kw['_nil'] = pyxb.binding.datatypes.boolean(is_nil) 1680 1681 rv = type_class.Factory(_dom_node=node, **kw) 1682 assert rv._element() == element_binding 1683 rv._setNamespaceContext(pyxb.namespace.resolution.NamespaceContext.GetNodeContext(node)) 1684 return rv._postDOMValidate()
1685 1686 # element 1687 @classmethod
1688 - def AnyCreateFromDOM (cls, node, fallback_namespace):
1689 """Create an instance of an element from a DOM node. 1690 1691 This method does minimal processing of C{node} and delegates to 1692 L{CreateDOMBinding}. 1693 1694 @param node: An C{xml.dom.Node} representing a root element. If the 1695 node is a document, that document's root node will be substituted. 1696 The name of the node is extracted as the name of the element to be 1697 created, and the node and the name are passed to L{CreateDOMBinding}. 1698 1699 @param fallback_namespace: The value to pass as C{_fallback_namespace} 1700 to L{CreateDOMBinding} 1701 1702 @return: As with L{CreateDOMBinding}""" 1703 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1704 node = node.documentElement 1705 expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=fallback_namespace) 1706 return cls.CreateDOMBinding(node, expanded_name.elementBinding(), _fallback_namespace=fallback_namespace)
1707
1708 - def elementForName (self, name):
1709 """Return the element that should be used if this element binding is 1710 permitted and an element with the given name is encountered. 1711 1712 Normally, the incoming name matches the name of this binding, and 1713 C{self} is returned. If the incoming name is different, it is 1714 expected to be the name of a global element which is within this 1715 element's substitution group. In that case, the binding corresponding 1716 to the named element is return. 1717 1718 @return: An instance of L{element}, or C{None} if no element with the 1719 given name can be found. 1720 """ 1721 1722 # Name match means OK. 1723 if self.name() == name: 1724 return self 1725 # No name match means only hope is a substitution group, for which the 1726 # element must be top-level. 1727 top_elt = self.name().elementBinding() 1728 if top_elt is None: 1729 return None 1730 # Members of the substitution group must also be top-level. NB: If 1731 # named_elt == top_elt, then the adoptName call below improperly 1732 # associated the global namespace with a local element of the same 1733 # name; cf. test-namespace-uu:testBad. 1734 elt_en = top_elt.name().adoptName(name) 1735 assert 'elementBinding' in elt_en.namespace()._categoryMap(), 'No element bindings in %s' % (elt_en.namespace(),) 1736 named_elt = elt_en.elementBinding() 1737 if (named_elt is None) or (named_elt == top_elt): 1738 return None 1739 if named_elt.substitutesFor(top_elt): 1740 return named_elt 1741 return None
1742
1743 - def createFromDOM (self, node, fallback_namespace=None, **kw):
1744 """Create an instance of this element using a DOM node as the source 1745 of its content. 1746 1747 This method does minimal processing of C{node} and delegates to 1748 L{_createFromDOM}. 1749 1750 @param node: An C{xml.dom.Node} representing a root element. If the 1751 node is a document, that document's root node will be substituted. 1752 The name of the node is extracted as the name of the element to be 1753 created, and the node and the name are passed to L{_createFromDOM} 1754 1755 @keyword fallback_namespace: Used as default for 1756 C{_fallback_namespace} in call to L{_createFromDOM} 1757 1758 @note: Keyword parameters are passed to L{CreateDOMBinding}. 1759 1760 @return: As with L{_createFromDOM} 1761 """ 1762 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1763 node = node.documentElement 1764 if fallback_namespace is not None: 1765 kw.setdefault('_fallback_namespace', fallback_namespace) 1766 expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=fallback_namespace) 1767 return self._createFromDOM(node, expanded_name, **kw)
1768
1769 - def _createFromDOM (self, node, expanded_name, **kw):
1770 """Create an instance from a DOM node given the name of an element. 1771 1772 This method does minimal processing of C{node} and C{expanded_name} 1773 and delegates to L{CreateDOMBinding}. 1774 1775 @param node: An C{xml.dom.Node} representing a root element. If the 1776 node is a document, that document's root node will be substituted. 1777 The value is passed to L{CreateDOMBinding}. 1778 1779 @param expanded_name: The expanded name of the element to be used for 1780 content. This is passed to L{elementForName} to obtain the binding 1781 that is passed to L{CreateDOMBinding}, superseding any identification 1782 that might be inferred from C{node}. If no name is available, use 1783 L{createFromDOM}. 1784 1785 @note: Keyword parameters are passed to L{CreateDOMBinding}. 1786 1787 @return: As with L{CreateDOMBinding}. 1788 """ 1789 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1790 node = node.documentElement 1791 return element.CreateDOMBinding(node, self.elementForName(expanded_name), **kw)
1792
1793 - def __str__ (self):
1794 return 'Element %s' % (self.name(),)
1795
1796 - def _description (self, name_only=False, user_documentation=True):
1797 name = unicode(self.name()) 1798 if name_only: 1799 return name 1800 desc = [ name, ' (', self.typeDefinition()._description(name_only=True), ')' ] 1801 if self.scope() is not None: 1802 desc.extend([', local to ', self.scope()._description(name_only=True) ]) 1803 if self.nillable(): 1804 desc.append(', nillable') 1805 if self.substitutionGroup() is not None: 1806 desc.extend([', substitutes for ', self.substitutionGroup()._description(name_only=True) ]) 1807 if user_documentation and (self.documentation() is not None): 1808 desc.extend(["\n", self.documentation() ]) 1809 return u''.join(desc)
1810
1811 -class enumeration_mixin (pyxb.cscRoot):
1812 """Marker in case we need to know that a PST has an enumeration constraint facet.""" 1813 1814 @classmethod
1815 - def values (cls):
1816 """Return a list of values that the enumeration can take.""" 1817 return cls._CF_enumeration.values()
1818 1819 @classmethod
1820 - def itervalues (cls):
1821 """Return a generator for the values that the enumeration can take.""" 1822 return cls._CF_enumeration.itervalues()
1823 1824 @classmethod
1825 - def items (cls):
1826 """Return the associated L{pyxb.binding.facet._EnumerationElement} instances.""" 1827 return cls._CF_enumeration.items()
1828 1829 @classmethod
1830 - def iteritems (cls):
1831 """Generate the associated L{pyxb.binding.facet._EnumerationElement} instances.""" 1832 return cls._CF_enumeration.iteritems()
1833
1834 -class _Content (object):
1835 """Base for any wrapper added to L{complexTypeDefinition.orderedContent}.""" 1836
1837 - def __getValue (self):
1838 """The value of the content. 1839 1840 This is a unicode string for L{NonElementContent}, and (ideally) an 1841 instance of L{_TypeBinding_mixin} for L{ElementContent}.""" 1842 return self.__value
1843 __value = None 1844 value = property(__getValue) 1845
1846 - def __init__ (self, value):
1847 self.__value = value
1848
1849 -class ElementContent (_Content):
1850 """Marking wrapper for element content. 1851 1852 The value should be translated into XML and made a child of its parent.""" 1853
1854 - def __getElementDeclaration (self):
1855 """The L{pyxb.binding.content.ElementDeclaration} associated with the element content. 1856 This may be C{None} if the value is a wildcard.""" 1857 return self.__elementDeclaration
1858 __elementDeclaration = None 1859 1860 elementDeclaration = property(__getElementDeclaration) 1861
1862 - def __init__ (self, value, element_declaration=None, instance=None, tag=None):
1863 """Create a wrapper associating a value with its element declaration. 1864 1865 Normally the element declaration is determined by consulting the 1866 content model when creating a binding instance. When manipulating the 1867 preferred content list, this may be inconvenient to obtain; in that case 1868 provide the C{instance} in which the content appears immediately, 1869 along with the C{tag} that is used for the Python attribute that holds 1870 the element. 1871 1872 @param value: the value of the element. Should be an instance of 1873 L{_TypeBinding_mixin}, but for simple types might be a Python native 1874 type. 1875 1876 @keyword element_declaration: The 1877 L{pyxb.binding.content.ElementDeclaration} associated with the element 1878 value. Should be C{None} if the element matches wildcard content. 1879 1880 @keyword instance: Alternative path to providing C{element_declaration} 1881 @keyword tag: Alternative path to providing C{element_declaration} 1882 """ 1883 1884 import pyxb.binding.content 1885 super(ElementContent, self).__init__(value) 1886 if instance is not None: 1887 if not isinstance(instance, complexTypeDefinition): 1888 raise pyxb.UsageError('Unable to determine element declaration') 1889 element_declaration = instance._UseForTag(tag) 1890 assert (element_declaration is None) or isinstance(element_declaration, pyxb.binding.content.ElementDeclaration) 1891 self.__elementDeclaration = element_declaration
1892
1893 -class NonElementContent (_Content):
1894 """Marking wrapper for non-element content. 1895 1896 The value will be unicode text, and should be appended as character 1897 data."""
1898 - def __init__ (self, value):
1900
1901 -class complexTypeDefinition (_TypeBinding_mixin, utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
1902 """Base for any Python class that serves as the binding for an 1903 XMLSchema complexType. 1904 1905 Subclasses should define a class-level _AttributeMap variable which maps 1906 from the unicode tag of an attribute to the AttributeUse instance that 1907 defines it. Similarly, subclasses should define an _ElementMap variable. 1908 """ 1909 1910 _CT_EMPTY = 'EMPTY' #<<< No content 1911 _CT_SIMPLE = 'SIMPLE' #<<< Simple (character) content 1912 _CT_MIXED = 'MIXED' #<<< Children may be elements or other (e.g., character) content 1913 _CT_ELEMENT_ONLY = 'ELEMENT_ONLY' #<<< Expect only element content. 1914 1915 _ContentTypeTag = None 1916 1917 _TypeDefinition = None 1918 """Subclass of simpleTypeDefinition that corresponds to the type content. 1919 Only valid if _ContentTypeTag is _CT_SIMPLE""" 1920 1921 # A value that indicates whether the content model for this type supports 1922 # wildcard elements. Supporting classes should override this value. 1923 _HasWildcardElement = False 1924 1925 # Map from expanded names to ElementDeclaration instances 1926 _ElementMap = { } 1927 """Map from expanded names to ElementDeclaration instances.""" 1928 1929 # Per-instance map from tags to attribute values for wildcard attributes. 1930 # Value is C{None} if the type does not support wildcard attributes. 1931 __wildcardAttributeMap = None 1932
1933 - def wildcardAttributeMap (self):
1934 """Obtain access to wildcard attributes. 1935 1936 The return value is C{None} if this type does not support wildcard 1937 attributes. If wildcard attributes are allowed, the return value is a 1938 map from QNames to the unicode string value of the corresponding 1939 attribute. 1940 1941 @todo: The map keys should be namespace extended names rather than 1942 QNames, as the in-scope namespace may not be readily available to the 1943 user. 1944 """ 1945 return self.__wildcardAttributeMap
1946 1947 # Per-instance list of DOM nodes interpreted as wildcard elements. 1948 # Value is None if the type does not support wildcard elements. 1949 __wildcardElements = None 1950
1951 - def wildcardElements (self):
1952 """Obtain access to wildcard elements. 1953 1954 The return value is C{None} if the content model for this type does not 1955 support wildcard elements. If wildcard elements are allowed, the 1956 return value is a list of values corresponding to conformant 1957 unrecognized elements, in the order in which they were encountered. 1958 If the containing binding was created from an XML document and enough 1959 information was present to determine the binding of the member 1960 element, the value is a binding instance. Otherwise, the value is the 1961 original DOM Element node. 1962 """ 1963 return self.__wildcardElements
1964
1965 - def __init__ (self, *args, **kw):
1966 """Create a new instance of this binding. 1967 1968 Arguments are used as transition values along the content model. 1969 Keywords are passed to the constructor of any simple content, or used 1970 to initialize attribute and element values whose L{id 1971 <content.ElementDeclaration.id>} (not L{name <content.ElementDeclaration.name>}) 1972 matches the keyword. 1973 1974 @keyword _dom_node: The node to use as the source of binding content. 1975 @type _dom_node: C{xml.dom.Element} 1976 1977 @keyword _location: An optional instance of 1978 L{pyxb.utils.utility.Location} showing the origin the binding. If 1979 C{None}, a value from C{_dom_node} is used if available. 1980 1981 @keyword _from_xml: See L{_TypeBinding_mixin.Factory} 1982 1983 @keyword _finalize_content_model: If C{True} the constructor invokes 1984 L{_TypeBinding_mixin._finalizeContentModel} prior to return. The 1985 value defaults to C{False} when content is assigned through keyword 1986 parameters (bypassing the content model) or neither a C{_dom_node} nor 1987 positional element parameters have been provided, and to C{True} in 1988 all other cases. 1989 """ 1990 1991 fallback_namespace = kw.pop('_fallback_namespace', None) 1992 is_nil = False 1993 dom_node = kw.pop('_dom_node', None) 1994 location = kw.pop('_location', None) 1995 from_xml = kw.pop('_from_xml', dom_node is not None) 1996 do_finalize_content_model = kw.pop('_finalize_content_model', None) 1997 if dom_node is not None: 1998 if (location is None) and isinstance(dom_node, pyxb.utils.utility.Locatable_mixin): 1999 location = dom_node._location() 2000 if xml.dom.Node.DOCUMENT_NODE == dom_node.nodeType: 2001 dom_node = dom_node.documentElement 2002 #kw['_validate_constraints'] = False 2003 is_nil = XSI.nil.getAttribute(dom_node) 2004 if is_nil is not None: 2005 is_nil = kw['_nil'] = pyxb.binding.datatypes.boolean(is_nil) 2006 if location is not None: 2007 self._setLocation(location) 2008 if self._AttributeWildcard is not None: 2009 self.__wildcardAttributeMap = { } 2010 if self._HasWildcardElement: 2011 self.__wildcardElements = [] 2012 if self._Abstract: 2013 raise pyxb.AbstractInstantiationError(type(self), location, dom_node) 2014 super(complexTypeDefinition, self).__init__(**kw) 2015 self.reset() 2016 self._setAttributesFromKeywordsAndDOM(kw, dom_node) 2017 did_set_kw_elt = False 2018 for fu in self._ElementMap.values(): 2019 iv = kw.pop(fu.id(), None) 2020 if iv is not None: 2021 did_set_kw_elt = True 2022 fu.set(self, iv) 2023 if do_finalize_content_model is None: 2024 do_finalize_content_model = not did_set_kw_elt 2025 if kw and kw.pop('_strict_keywords', True): 2026 [ kw.pop(_fkw, None) for _fkw in self._PyXBFactoryKeywords ] 2027 if kw: 2028 raise pyxb.UnprocessedKeywordContentError(self, kw) 2029 if 0 < len(args): 2030 if did_set_kw_elt: 2031 raise pyxb.UsageError('Cannot mix keyword and positional args for element initialization') 2032 self.extend(args, _from_xml=from_xml, _location=location) 2033 elif self._CT_SIMPLE == self._ContentTypeTag: 2034 value = self._TypeDefinition.Factory(_require_value=not self._isNil(), _dom_node=dom_node, _location=location, _nil=self._isNil(), _apply_attributes=False, *args) 2035 if value._constructedWithValue(): 2036 self.append(value) 2037 elif dom_node is not None: 2038 self.extend(dom_node.childNodes[:], fallback_namespace) 2039 else: 2040 do_finalize_content_model = False 2041 if do_finalize_content_model: 2042 self._finalizeContentModel()
2043 2044 # Specify the symbols to be reserved for all CTDs. 2045 _ReservedSymbols = _TypeBinding_mixin._ReservedSymbols.union(set([ 'wildcardElements', 'wildcardAttributeMap', 2046 'xsdConstraintsOK', 'content', 'orderedContent', 'append', 'extend', 'value', 'reset' ])) 2047 2048 # None, or a reference to a pyxb.utils.fac.Automaton instance that defines 2049 # the content model for the type. 2050 _Automaton = None 2051 2052 @classmethod
2053 - def _AddElement (cls, element):
2054 """Method used by generated code to associate the element binding with a use in this type. 2055 2056 This is necessary because all complex type classes appear in the 2057 module prior to any of the element instances (which reference type 2058 classes), so the association must be formed after the element 2059 instances are available.""" 2060 return cls._UseForTag(element.name())._setElementBinding(element)
2061 2062 @classmethod
2063 - def _UseForTag (cls, tag, raise_if_fail=True):
2064 """Return the ElementDeclaration object corresponding to the element name. 2065 2066 @param tag: The L{ExpandedName} of an element in the class.""" 2067 try: 2068 rv = cls._ElementMap[tag] 2069 except KeyError: 2070 if raise_if_fail: 2071 raise 2072 rv = None 2073 return rv
2074
2075 - def __childrenForDOM (self):
2076 """Generate a list of children in the order in which they should be 2077 added to the parent when creating a DOM representation of this 2078 object. 2079 2080 @note: This is only used when L{pyxb.RequireValidWhenGenerating} has 2081 disabled validation. Consequently, it may not generate valid XML. 2082 """ 2083 order = [] 2084 for ed in self._ElementMap.values(): 2085 value = ed.value(self) 2086 if value is None: 2087 continue 2088 if isinstance(value, list) and ed.isPlural(): 2089 order.extend([ ElementContent(_v, ed) for _v in value ]) 2090 continue 2091 order.append(ElementContent(value, ed)) 2092 return order
2093
2094 - def _validatedChildren (self):
2095 """Provide the child elements and non-element content in an order 2096 consistent with the content model. 2097 2098 Returns a sequence of tuples representing a valid path through the 2099 content model where each transition corresponds to one of the member 2100 element instances within this instance. The tuple is a pair 2101 comprising the L{content.ElementDeclaration} instance and the value for the 2102 transition. 2103 2104 If the content of the instance does not validate against the content 2105 model, an exception is raised. 2106 2107 @return: C{None} or a list as described above. 2108 """ 2109 if self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE): 2110 return [] 2111 self._resetAutomaton() 2112 return self.__automatonConfiguration.sequencedChildren()
2113
2114 - def _symbolSet (self):
2115 """Return a map from L{content.ElementDeclaration} instances to a list of 2116 values associated with that use. 2117 2118 This is used as the set of symbols available for transitions when 2119 validating content against a model. Note that the original 2120 L{content.ElementUse} that may have validated the assignment of the 2121 symbol to the content is no longer available, which may result in a 2122 different order being generated by the content model. Preservation of 2123 the original order mitigates this risk. 2124 2125 The value C{None} is used to provide the wildcard members, if any. 2126 2127 If an element use has no associated values, it must not appear in the 2128 returned map. 2129 2130 @raise pyxb.SimpleTypeValueError: when unable tconverting element 2131 content the binding declaration type. 2132 """ 2133 rv = { } 2134 for eu in self._ElementMap.values(): 2135 value = eu.value(self) 2136 if value is None: 2137 continue 2138 converter = eu.elementBinding().compatibleValue 2139 if eu.isPlural(): 2140 if 0 < len(value): 2141 rv[eu] = [ converter(_v) for _v in value ] 2142 else: 2143 rv[eu] = [ converter(value)] 2144 wce = self.__wildcardElements 2145 if (wce is not None) and (0 < len(wce)): 2146 rv[None] = wce[:] 2147 return rv
2148
2149 - def _validateAttributes (self):
2150 for au in self._AttributeMap.values(): 2151 au.validate(self)
2152
2153 - def _validateBinding_vx (self):
2154 if self._isNil(): 2155 if (self._IsSimpleTypeContent() and (self.__content is not None)) or self.__content: 2156 raise pyxb.ContentInNilInstanceError(self, self.__content) 2157 return True 2158 if self._IsSimpleTypeContent() and (self.__content is None): 2159 raise pyxb.SimpleContentAbsentError(self, self._location()) 2160 order = self._validatedChildren() 2161 for content in order: 2162 if isinstance (content, NonElementContent): 2163 continue 2164 if isinstance(content.value, _TypeBinding_mixin): 2165 content.value.validateBinding() 2166 elif content.elementDeclaration is not None: 2167 _log.warning('Cannot validate value %s in field %s', content.value, content.elementDeclaration.id()) 2168 self._validateAttributes() 2169 return True
2170
2171 - def _setAttribute (self, attr_en, value):
2172 au = self._AttributeMap.get(attr_en) 2173 if au is None: 2174 if self._AttributeWildcard is None: 2175 raise pyxb.UnrecognizedAttributeError(type(self), attr_en, self) 2176 self.__wildcardAttributeMap[attr_en] = value 2177 else: 2178 au.set(self, value) 2179 return au
2180
2181 - def xsdConstraintsOK (self, location=None):
2182 """Validate the content against the simple type. 2183 2184 @return: C{True} if the content validates against its type. 2185 @raise pyxb.NotSimpleContentError: this type does not have simple content. 2186 @raise pyxb.SimpleContentAbsentError: the content of this type has not been set 2187 """ 2188 # @todo: type check 2189 if self._CT_SIMPLE != self._ContentTypeTag: 2190 raise pyxb.NotSimpleContentError(self) 2191 if self._isNil(): 2192 return True 2193 if self.__content is None: 2194 if location is None: 2195 location = self._location() 2196 raise pyxb.SimpleContentAbsentError(self, location) 2197 return self.value().xsdConstraintsOK(location)
2198 2199 # __content is used in two ways: when complex content is used, it is as 2200 # documented in L{orderedContent}. When simple content is used, it is as 2201 # documented in L{value}. 2202 __content = None 2203
2204 - def orderedContent (self):
2205 """Return the element and non-element content of the instance in order. 2206 2207 This must be a complex type with complex content. The return value is 2208 a list of the element and non-element content in a preferred order. 2209 2210 The returned list contains L{element<ElementContent>} and 2211 L{non-element<NonElementContent>} content in the order which it was 2212 added to the instance. This may have been through parsing a document, 2213 constructing an instance using positional arguments, invoking the 2214 L{append} or L{extend} methods, or assigning directly to an instance 2215 attribute associated with an element binding. 2216 2217 @note: Be aware that assigning directly to an element attribute does not 2218 remove any previous value for the element from the content list. 2219 2220 @note: Be aware that element values directly appended to an instance 2221 attribute with list type (viz., that corresponds to an element that 2222 allows more than one occurrence) will not appear in the ordered 2223 content list. 2224 2225 The order in the list may influence the generation of documents 2226 depending on L{pyxb.ValidationConfig} values that apply to an 2227 instance. Non-element content is emitted immediately prior to the 2228 following element in this list. Any trailing non-element content is 2229 emitted after the last element in the content. The list should 2230 include all element content. Element content in this list that is not 2231 present within an element member of the binding instance may result in 2232 an error, or may be ignored. 2233 2234 @note: The returned value is mutable, allowing the caller to change 2235 the order to be used. 2236 2237 @raise pyxb.NotComplexContentError: this is not a complex type with mixed or element-only content 2238 """ 2239 if self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE): 2240 raise pyxb.NotComplexContentError(self) 2241 return self.__content
2242 2243 @classmethod
2244 - def __WarnOnContent (cls):
2245 if cls.__NeedWarnOnContent: 2246 import traceback 2247 cls.__NeedWarnOnContent = False 2248 _log.warning('Deprecated complexTypeDefinition method "content" invoked\nPlease use "orderedContent"\n%s', ''.join(traceback.format_stack()[:-2])) 2249 pass
2250 __NeedWarnOnContent = True 2251
2252 - def content (self):
2253 """Legacy interface for ordered content. 2254 2255 This version does not accurately distinguish non-element content from 2256 element content that happens to have unicode type. 2257 2258 @deprecated: use L{orderedContent}.""" 2259 self.__WarnOnContent() 2260 if self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE): 2261 raise pyxb.NotComplexContentError(self) 2262 return [ _v.value for _v in self.__content ]
2263
2264 - def value (self):
2265 """Return the value of the element. 2266 2267 This must be a complex type with simple content. The returned value 2268 is expected to be an instance of some L{simpleTypeDefinition} class. 2269 2270 @raise pyxb.NotSimpleContentError: this is not a complex type with simple content 2271 """ 2272 if self._CT_SIMPLE != self._ContentTypeTag: 2273 raise pyxb.NotSimpleContentError(self) 2274 return self.__content
2275
2276 - def _resetContent (self, reset_elements=False):
2277 if reset_elements: 2278 for eu in self._ElementMap.values(): 2279 eu.reset(self) 2280 nv = None 2281 if self._ContentTypeTag in (self._CT_MIXED, self._CT_ELEMENT_ONLY): 2282 nv = [] 2283 return self.__setContent(nv)
2284 2285 __automatonConfiguration = None
2286 - def _resetAutomaton (self):
2287 if self._Automaton is not None: 2288 if self.__automatonConfiguration is None: 2289 import pyxb.binding.content 2290 self.__automatonConfiguration = pyxb.binding.content.AutomatonConfiguration(self) 2291 self.__automatonConfiguration.reset() 2292 return self.__automatonConfiguration
2293
2294 - def _automatonConfiguration (self):
2295 """For whitebox testing use only""" 2296 return self.__automatonConfiguration
2297
2298 - def reset (self):
2299 """Reset the instance. 2300 2301 This resets all element and attribute fields, and discards any 2302 recorded content. It resets the content model automaton to its 2303 initial state. 2304 2305 @see: Manipulate the return value of L{orderedContent} if your intent is 2306 to influence the generation of documents from the binding instance 2307 without changing its (element) content. 2308 """ 2309 2310 self._resetContent(reset_elements=True) 2311 for au in self._AttributeMap.values(): 2312 au.reset(self) 2313 self._resetAutomaton() 2314 return self
2315 2316 @classmethod
2317 - def _ElementBindingDeclForName (cls, element_name):
2318 """Determine what the given name means as an element in this type. 2319 2320 Normally, C{element_name} identifies an element definition within this 2321 type. If so, the returned C{element_decl} identifies that definition, 2322 and the C{element_binding} is extracted from that use. 2323 2324 It may also be that the C{element_name} does not appear as an element 2325 definition, but that it identifies a global element. In that case, 2326 the returned C{element_binding} identifies the global element. If, 2327 further, that element is a member of a substitution group which does 2328 have an element definition in this class, then the returned 2329 C{element_decl} identifies that definition. 2330 2331 If a non-C{None} C{element_decl} is returned, there will be an 2332 associated C{element_binding}. However, it is possible to return a 2333 non-C{None} C{element_binding}, but C{None} as the C{element_decl}. In 2334 that case, the C{element_binding} can be used to create a binding 2335 instance, but the content model will have to treat it as a wildcard. 2336 2337 @param element_name: The name of the element in this type, either an 2338 expanded name or a local name if the element has an absent namespace. 2339 2340 @return: C{( element_binding, element_decl )} 2341 """ 2342 element_decl = cls._ElementMap.get(element_name) 2343 element_binding = None 2344 if element_decl is None: 2345 try: 2346 element_binding = element_name.elementBinding() 2347 except pyxb.NamespaceError: 2348 pass 2349 if element_binding is not None: 2350 element_decl = element_binding.findSubstituendDecl(cls) 2351 else: 2352 element_binding = element_decl.elementBinding() 2353 return (element_binding, element_decl)
2354
2355 - def append (self, value, **kw):
2356 """Add the value to the instance. 2357 2358 The value should be a DOM node or other value that is or can be 2359 converted to a binding instance, or a string if the instance allows 2360 mixed content. The value must be permitted by the content model. 2361 2362 @raise pyxb.ContentValidationError: the value is not permitted at the current 2363 state of the content model. 2364 """ 2365 2366 # @todo: Allow caller to provide default element use; it's available 2367 # in saxer. 2368 element_decl = kw.get('_element_decl', None) 2369 maybe_element = kw.get('_maybe_element', True) 2370 location = kw.get('_location', None) 2371 if self._isNil(): 2372 raise pyxb.ContentInNilInstanceError(self, value, location) 2373 fallback_namespace = kw.get('_fallback_namespace', None) 2374 require_validation = kw.get('_require_validation', self._validationConfig.forBinding) 2375 from_xml = kw.get('_from_xml', False) 2376 element_binding = None 2377 if element_decl is not None: 2378 from pyxb.binding import content 2379 assert isinstance(element_decl, content.ElementDeclaration) 2380 element_binding = element_decl.elementBinding() 2381 assert element_binding is not None 2382 # Convert the value if it's XML and we recognize it. 2383 if isinstance(value, xml.dom.Node): 2384 from_xml = True 2385 assert maybe_element 2386 assert element_binding is None 2387 node = value 2388 require_validation = pyxb.GlobalValidationConfig.forBinding 2389 if xml.dom.Node.COMMENT_NODE == node.nodeType: 2390 # @todo: Note that we're allowing comments inside the bodies 2391 # of simple content elements, which isn't really Hoyle. 2392 return self 2393 if node.nodeType in (xml.dom.Node.TEXT_NODE, xml.dom.Node.CDATA_SECTION_NODE): 2394 value = node.data 2395 maybe_element = False 2396 else: 2397 # Do type conversion here 2398 assert xml.dom.Node.ELEMENT_NODE == node.nodeType 2399 expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=fallback_namespace) 2400 (element_binding, element_decl) = self._ElementBindingDeclForName(expanded_name) 2401 if element_binding is not None: 2402 # If we have an element binding, we need to use it because 2403 # it knows how to resolve substitution groups. 2404 value = element_binding._createFromDOM(node, expanded_name, _fallback_namespace=fallback_namespace) 2405 else: 2406 # If we don't have an element binding, we might still be 2407 # able to convert this if it has an xsi:type attribute. 2408 try: 2409 value = element.CreateDOMBinding(node, None, _fallback_namespace=fallback_namespace) 2410 except: 2411 _log.warning('Unable to convert DOM node %s at %s to binding', expanded_name, getattr(node, 'location', '[UNAVAILABLE]')) 2412 if (not maybe_element) and isinstance(value, basestring) and (self._ContentTypeTag in (self._CT_EMPTY, self._CT_ELEMENT_ONLY)): 2413 if (0 == len(value.strip())) and not self._isNil(): 2414 return self 2415 if maybe_element and (self.__automatonConfiguration is not None): 2416 # Allows element content. 2417 if not require_validation: 2418 if element_decl is not None: 2419 element_decl.setOrAppend(self, value) 2420 return self 2421 if self.__wildcardElements is not None: 2422 self._appendWildcardElement(value) 2423 return self 2424 raise pyxb.StructuralBadDocumentError(container=self, content=value) 2425 # Attempt to place the value based on the content model 2426 num_cand = self.__automatonConfiguration.step(value, element_decl) 2427 if 1 <= num_cand: 2428 # Resolution was successful (possibly non-deterministic) 2429 return self 2430 # If what we have is element or just complex content, we can't accept 2431 # it, either because the type doesn't accept element content or 2432 # because it does and what we got didn't match the content model. 2433 if (element_binding is not None) or isinstance(value, (xml.dom.Node, complexTypeDefinition, pyxb.BIND)): 2434 raise pyxb.UnrecognizedContentError(self, self.__automatonConfiguration, value, location) 2435 2436 # We have something that doesn't seem to be an element. Are we 2437 # expecting simple content? 2438 if self._IsSimpleTypeContent(): 2439 if self.__content is not None: 2440 raise pyxb.ExtraSimpleContentError(self, value) 2441 if not self._isNil(): 2442 if not isinstance(value, self._TypeDefinition): 2443 value = self._TypeDefinition.Factory(value, _from_xml=from_xml) 2444 self.__setContent(value) 2445 if require_validation: 2446 # NB: This only validates the value, not any associated 2447 # attributes, which is correct to be parallel to complex 2448 # content validation. 2449 self.xsdConstraintsOK(location) 2450 return self 2451 2452 # Do we allow non-element content? 2453 if not self._IsMixed(): 2454 raise pyxb.MixedContentError(self, value, location) 2455 2456 # It's character information. 2457 self._addContent(NonElementContent(value)) 2458 return self
2459
2460 - def _appendWildcardElement (self, value):
2463
2464 - def extend (self, value_list, _fallback_namespace=None, _from_xml=False, _location=None):
2465 """Invoke L{append} for each value in the list, in turn.""" 2466 [ self.append(_v, _fallback_namespace=_fallback_namespace, _from_xml=_from_xml, _location=_location) for _v in value_list ] 2467 return self
2468
2469 - def __setContent (self, value):
2470 self.__content = value 2471 return self.__content
2472
2473 - def _addContent (self, wrapped_value):
2474 # This assert is inadequate in the case of plural/non-plural elements with an STD_list base type. 2475 # Trust that validation elsewhere was done correctly. 2476 #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)) 2477 assert not (self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE)) 2478 assert isinstance(wrapped_value, _Content) 2479 self.__content.append(wrapped_value) 2480 if isinstance(wrapped_value, ElementContent): 2481 value = wrapped_value.value 2482 ed = wrapped_value.elementDeclaration 2483 if isinstance(value, _TypeBinding_mixin) and (ed is not None) and (value._element() is None): 2484 assert isinstance(ed.elementBinding(), element) 2485 value._setElement(ed.elementBinding())
2486 2487 @classmethod
2488 - def _IsMixed (cls):
2489 return (cls._CT_MIXED == cls._ContentTypeTag)
2490
2491 - def _finalizeContentModel (self):
2492 # Override parent implementation. 2493 if self.__automatonConfiguration: 2494 self.__automatonConfiguration.resolveNondeterminism()
2495
2496 - def _postDOMValidate (self):
2497 # It's probably finalized already, but just in case... 2498 self._finalizeContentModel() 2499 if self._validationConfig.forBinding: 2500 # @todo isNil should verify that no content is present. 2501 if (not self._isNil()) and (self.__automatonConfiguration is not None): 2502 if not self.__automatonConfiguration.isAccepting(): 2503 if self._IsSimpleTypeContent(): 2504 raise pyxb.SimpleContentAbsentError(self, self._location()) 2505 self.__automatonConfiguration.diagnoseIncompleteContent() 2506 self._validateAttributes() 2507 return self
2508
2509 - def _setDOMFromAttributes (self, dom_support, element):
2510 """Add any appropriate attributes from this instance into the DOM element.""" 2511 for au in self._AttributeMap.values(): 2512 if pyxb.GlobalValidationConfig.forDocument: 2513 au.validate(self) 2514 au.addDOMAttribute(dom_support, self, element) 2515 return element
2516
2517 - def _toDOM_csc (self, dom_support, parent):
2518 """Create a DOM element with the given tag holding the content of this instance.""" 2519 element = parent 2520 self._setDOMFromAttributes(dom_support, element) 2521 if self._isNil(): 2522 pass 2523 elif self._CT_EMPTY == self._ContentTypeTag: 2524 pass 2525 elif self._CT_SIMPLE == self._ContentTypeTag: 2526 assert self.value() is not None, '%s has no value' % (self,) 2527 dom_support.appendTextChild(self.value().xsdLiteral(), element) 2528 else: 2529 if pyxb.GlobalValidationConfig.forDocument: 2530 order = self._validatedChildren() 2531 else: 2532 order = self.__childrenForDOM() 2533 for content in order: 2534 assert content.value != self 2535 if isinstance(content, NonElementContent): 2536 dom_support.appendTextChild(content.value, element) 2537 continue 2538 if content.elementDeclaration is None: 2539 if isinstance(content.value, xml.dom.Node): 2540 dom_support.appendChild(content.value, element) 2541 else: 2542 content.value.toDOM(dom_support, parent) 2543 else: 2544 content.elementDeclaration.toDOM(dom_support, parent, content.value) 2545 mixed_content = self.orderedContent() 2546 for mc in mixed_content: 2547 pass 2548 return getattr(super(complexTypeDefinition, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
2549 2550 @classmethod
2551 - def _IsSimpleTypeContent (cls):
2552 """CTDs with simple content are simple; other CTDs are not.""" 2553 return cls._CT_SIMPLE == cls._ContentTypeTag
2554 2555 @classmethod
2556 - def _description (cls, name_only=False, user_documentation=True):
2557 name = cls._Name() 2558 if name_only: 2559 return name 2560 desc = [ name ] 2561 if cls._CT_EMPTY == cls._ContentTypeTag: 2562 desc.append(', empty content') 2563 elif cls._CT_SIMPLE == cls._ContentTypeTag: 2564 desc.extend([', simple content type ', cls._TypeDefinition._description(name_only=True)]) 2565 else: 2566 if cls._CT_MIXED == cls._ContentTypeTag: 2567 desc.append(', mixed content') 2568 else: 2569 assert cls._CT_ELEMENT_ONLY == cls._ContentTypeTag 2570 desc.append(', element-only content') 2571 if (0 < len(cls._AttributeMap)) or (cls._AttributeWildcard is not None): 2572 desc.append("\nAttributes:\n ") 2573 desc.append("\n ".join([ _au._description(user_documentation=False) for _au in cls._AttributeMap.values() ])) 2574 if cls._AttributeWildcard is not None: 2575 desc.append("\n Wildcard attribute(s)") 2576 if (0 < len(cls._ElementMap)) or cls._HasWildcardElement: 2577 desc.append("\nElements:\n ") 2578 desc.append("\n ".join([ _eu._description(user_documentation=False) for _eu in cls._ElementMap.values() ])) 2579 if cls._HasWildcardElement: 2580 desc.append("\n Wildcard element(s)") 2581 return ''.join(desc)
2582 2583 ## Local Variables: 2584 ## fill-column:78 2585 ## End: 2586