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-2012, 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 str(cls._ExpandedName) 597 return str(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 str(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: 921 self.xsdConstraintsOK(location)
922 923 924 # The class attribute name used to store the reference to the STD 925 # component instance must be unique to the class, not to this base class. 926 # Otherwise we mistakenly believe we've already associated a STD instance 927 # with a class (e.g., xsd:normalizedString) when in fact it's associated 928 # with the superclass (e.g., xsd:string) 929 @classmethod
930 - def __STDAttrName (cls):
931 return '_%s__SimpleTypeDefinition' % (cls.__name__,)
932 933 @classmethod
934 - def _SimpleTypeDefinition (cls, std):
935 """Set the L{pyxb.xmlschema.structures.SimpleTypeDefinition} instance 936 associated with this binding.""" 937 attr_name = cls.__STDAttrName() 938 if hasattr(cls, attr_name): 939 old_value = getattr(cls, attr_name) 940 if old_value != std: 941 raise pyxb.LogicError('%s: Attempt to override existing STD %s with %s' % (cls, old_value.name(), std.name())) 942 setattr(cls, attr_name, std)
943 944 @classmethod
945 - def SimpleTypeDefinition (cls):
946 """Return the SimpleTypeDefinition instance for the given 947 class. 948 949 This should only be invoked when generating bindings. An STD must 950 have been associated with the class using L{_SimpleTypeDefinition}.""" 951 attr_name = cls.__STDAttrName() 952 assert hasattr(cls, attr_name) 953 return getattr(cls, attr_name)
954 955 @classmethod
956 - def XsdLiteral (cls, value):
957 """Convert from a python value to a string usable in an XML 958 document. 959 960 This should be implemented in the subclass.""" 961 raise pyxb.LogicError('%s does not implement XsdLiteral' % (cls,))
962
963 - def xsdLiteral (self):
964 """Return text suitable for representing the value of this 965 instance in an XML document. 966 967 The base class implementation delegates to the object class's 968 XsdLiteral method.""" 969 if self._isNil(): 970 return '' 971 return self.XsdLiteral(self)
972 973 @classmethod
974 - def XsdSuperType (cls):
975 """Find the nearest parent class in the PST hierarchy. 976 977 The value for anySimpleType is None; for all others, it's a 978 primitive or derived PST descendent (including anySimpleType).""" 979 for sc in cls.mro(): 980 if sc == cls: 981 continue 982 if simpleTypeDefinition == sc: 983 # If we hit the PST base, this is a primitive type or 984 # otherwise directly descends from a Python type; return 985 # the recorded XSD supertype. 986 return cls._XsdBaseType 987 if issubclass(sc, simpleTypeDefinition): 988 return sc 989 raise pyxb.LogicError('No supertype found for %s' % (cls,))
990 991 @classmethod
992 - def _XsdConstraintsPreCheck_vb (cls, value):
993 """Pre-extended class method to verify other things before 994 checking constraints. 995 996 This is used for list types, to verify that the values in the 997 list are acceptable, and for token descendents, to check the 998 lexical/value space conformance of the input. 999 """ 1000 super_fn = getattr(super(simpleTypeDefinition, cls), '_XsdConstraintsPreCheck_vb', lambda *a,**kw: value) 1001 return super_fn(value)
1002 1003 # Cache of pre-computed sequences of class facets in the order required 1004 # for constraint validation 1005 __ClassFacetSequence = { } 1006 1007 @classmethod
1008 - def XsdConstraintsOK (cls, value, location=None):
1009 """Validate the given value against the constraints on this class. 1010 1011 @raise pyxb.SimpleTypeValueError: if any constraint is violated. 1012 """ 1013 1014 value = cls._XsdConstraintsPreCheck_vb(value) 1015 1016 facet_values = cls.__ClassFacetSequence.get(cls) 1017 if facet_values is None: 1018 # Constraints for simple type definitions are inherited. Check them 1019 # from least derived to most derived. 1020 classes = [ _x for _x in cls.mro() if issubclass(_x, simpleTypeDefinition) ] 1021 classes.reverse() 1022 cache_result = True 1023 facet_values = [] 1024 for clazz in classes: 1025 # When setting up the datatypes, if we attempt to validate 1026 # something before the facets have been initialized (e.g., a 1027 # nonNegativeInteger used as a length facet for the parent 1028 # integer datatype), just ignore that for now. Don't cache 1029 # the value, though, since a subsequent check after 1030 # initialization should succceed. 1031 try: 1032 clazz_facets = clazz._FacetMap().values() 1033 except AttributeError: 1034 cache_result = False 1035 clazz_facets = [] 1036 for v in clazz_facets: 1037 if not (v in facet_values): 1038 facet_values.append(v) 1039 if cache_result: 1040 cls.__ClassFacetSequence[cls] = facet_values 1041 for f in facet_values: 1042 if not f.validateConstraint(value): 1043 raise pyxb.SimpleFacetValueError(cls, value, f, location) 1044 return value
1045
1046 - def xsdConstraintsOK (self, location=None):
1047 """Validate the value of this instance against its constraints.""" 1048 return self.XsdConstraintsOK(self, location)
1049
1050 - def _validateBinding_vx (self):
1051 if not self._isNil(): 1052 self._checkValidValue() 1053 return True
1054 1055 @classmethod
1056 - def XsdValueLength (cls, value):
1057 """Return the length of the given value. 1058 1059 The length is calculated by a subclass implementation of 1060 _XsdValueLength_vx in accordance with 1061 http://www.w3.org/TR/xmlschema-2/#rf-length. 1062 1063 The return value is a non-negative integer, or C{None} if length 1064 constraints should be considered trivially satisfied (as with 1065 QName and NOTATION). 1066 1067 @raise pyxb.LogicError: the provided value is not an instance of cls. 1068 @raise pyxb.LogicError: an attempt is made to calculate a length for 1069 an instance of a type that does not support length calculations. 1070 """ 1071 assert isinstance(value, cls) 1072 if not hasattr(cls, '_XsdValueLength_vx'): 1073 raise pyxb.LogicError('Class %s does not support length validation' % (cls.__name__,)) 1074 return cls._XsdValueLength_vx(value)
1075
1076 - def xsdValueLength (self):
1077 """Return the length of this instance within its value space. 1078 1079 See XsdValueLength.""" 1080 return self.XsdValueLength(self)
1081 1082 @classmethod
1083 - def PythonLiteral (cls, value):
1084 """Return a string which can be embedded into Python source to 1085 represent the given value as an instance of this class.""" 1086 class_name = cls.__name__ 1087 return '%s(%s)' % (class_name, repr(value))
1088
1089 - def pythonLiteral (self):
1090 """Return a string which can be embedded into Python source to 1091 represent the value of this instance.""" 1092 return self.PythonLiteral(self)
1093
1094 - def _toDOM_csc (self, dom_support, parent):
1095 assert parent is not None 1096 dom_support.appendTextChild(self.xsdLiteral(), parent) 1097 return getattr(super(simpleTypeDefinition, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
1098 1099 @classmethod
1100 - def _IsSimpleTypeContent (cls):
1101 """STDs have simple type content.""" 1102 return True
1103 1104 @classmethod
1105 - def _IsValidValue (self, value):
1106 try: 1107 self._CheckValidValue(value) 1108 return True 1109 except pyxb.PyXBException: 1110 pass 1111 return False
1112 1113 @classmethod
1114 - def _CheckValidValue (cls, value):
1115 1116 """NB: Invoking this on a value that is a list will, if necessary, 1117 replace the members of the list with new values that are of the 1118 correct item type. This is permitted because only with lists is it 1119 possible to bypass the normal content validation (by invoking 1120 append/extend on the list instance).""" 1121 if value is None: 1122 raise pyxb.SimpleTypeValueError(cls, value) 1123 value_class = cls 1124 if issubclass(cls, STD_list): 1125 if not isinstance(value, collections.Iterable): 1126 raise pyxb.SimpleTypeValueError(cls, value) 1127 for v in value: 1128 if not cls._ItemType._IsValidValue(v): 1129 raise pyxb.SimpleListValueError(cls, v) 1130 else: 1131 if issubclass(cls, STD_union): 1132 value_class = None 1133 for mt in cls._MemberTypes: 1134 if mt._IsValidValue(value): 1135 value_class = mt 1136 break 1137 if value_class is None: 1138 raise pyxb.SimpleUnionValueError(cls, value) 1139 #if not (isinstance(value, value_class) or issubclass(value_class, type(value))): 1140 if not isinstance(value, value_class): 1141 raise pyxb.SimpleTypeValueError(cls, value) 1142 value_class.XsdConstraintsOK(value)
1143
1144 - def _checkValidValue (self):
1145 self._CheckValidValue(self)
1146
1147 - def _isValidValue (self):
1148 self._IsValidValue(self)
1149
1150 - def _setAttribute (self, attr_en, value):
1151 # Simple types have no attributes, but the parsing infrastructure 1152 # might invoke this to delegate responsibility for notifying the user 1153 # of the failure. 1154 raise pyxb.AttributeOnSimpleTypeError(self, attr_en, value)
1155 1156 @classmethod
1157 - def _description (cls, name_only=False, user_documentation=True):
1158 name = cls._Name() 1159 if name_only: 1160 return name 1161 desc = [ name, ' restriction of ', cls.XsdSuperType()._description(name_only=True) ] 1162 if user_documentation and (cls._Documentation is not None): 1163 desc.extend(["\n", cls._Documentation]) 1164 return ''.join(desc)
1165
1166 -class STD_union (simpleTypeDefinition):
1167 """Base class for union datatypes. 1168 1169 This class descends only from simpleTypeDefinition. A pyxb.LogicError is 1170 raised if an attempt is made to construct an instance of a subclass of 1171 STD_union. Values consistent with the member types are constructed using 1172 the Factory class method. Values are validated using the _ValidatedMember 1173 class method. 1174 1175 Subclasses must provide a class variable _MemberTypes which is a 1176 tuple of legal members of the union.""" 1177 1178 _MemberTypes = None 1179 """A list of classes which are permitted as values of the union.""" 1180 1181 # Ick: If we don't declare this here, this class's map doesn't get 1182 # initialized. Alternative is to not descend from simpleTypeDefinition. 1183 # @todo Ensure that pattern and enumeration are valid constraints 1184 __FacetMap = {} 1185 1186 @classmethod
1187 - def Factory (cls, *args, **kw):
1188 """Given a value, attempt to create an instance of some member of this 1189 union. The first instance which can be legally created is returned. 1190 1191 @keyword _validate_constraints: If C{True} (default if validation is 1192 enabled), any constructed value is checked against constraints applied 1193 to the union as well as the member type. 1194 1195 @raise pyxb.SimpleTypeValueError: no member type will permit creation of 1196 an instance from the parameters in C{args} and C{kw}. 1197 """ 1198 1199 used_cls = cls._SupersedingClass() 1200 state = used_cls._PreFactory_vx(args, kw) 1201 1202 rv = None 1203 # NB: get, not pop: preserve it for the member type invocations 1204 validate_constraints = kw.get('_validate_constraints', cls._GetValidationConfig().forBinding) 1205 assert isinstance(validate_constraints, bool) 1206 if 0 < len(args): 1207 arg = args[0] 1208 try: 1209 rv = cls._ValidatedMember(arg) 1210 except pyxb.SimpleTypeValueError: 1211 pass 1212 if rv is None: 1213 kw['_validate_constraints'] = True 1214 for mt in cls._MemberTypes: 1215 try: 1216 rv = mt.Factory(*args, **kw) 1217 break 1218 except pyxb.SimpleTypeValueError: 1219 pass 1220 except (ValueError, OverflowError): 1221 pass 1222 except: 1223 pass 1224 location = None 1225 if kw is not None: 1226 location = kw.get('_location') 1227 if rv is not None: 1228 if validate_constraints: 1229 cls.XsdConstraintsOK(rv, location) 1230 rv._postFactory_vx(state) 1231 return rv 1232 # The constructor may take any number of arguments, so pass the whole thing. 1233 # Should we also provide the keywords? 1234 raise pyxb.SimpleUnionValueError(cls, args, location)
1235 1236 @classmethod
1237 - def _ValidatedMember (cls, value):
1238 """Validate the given value as a potential union member. 1239 1240 @raise pyxb.SimpleTypeValueError: the value is not an instance of a 1241 member type.""" 1242 if not isinstance(value, cls._MemberTypes): 1243 for mt in cls._MemberTypes: 1244 try: 1245 # Force validation so we get the correct type, otherwise 1246 # first member will be accepted. 1247 value = mt.Factory(value, _validate_constraints=True) 1248 return value 1249 except (TypeError, pyxb.SimpleTypeValueError): 1250 pass 1251 raise pyxb.SimpleUnionValueError(cls, value) 1252 return value
1253
1254 - def __init__ (self, *args, **kw):
1255 raise pyxb.LogicError('%s: cannot construct instances of union' % (self.__class__.__name__,))
1256 1257 @classmethod
1258 - def _description (cls, name_only=False, user_documentation=True):
1259 name = cls._Name() 1260 if name_only: 1261 return name 1262 desc = [ name, ', union of '] 1263 desc.append(', '.join([ _td._description(name_only=True) for _td in cls._MemberTypes ])) 1264 return ''.join(desc)
1265 1266 @classmethod
1267 - def XsdLiteral (cls, value):
1268 """Convert from a binding value to a string usable in an XML document.""" 1269 return cls._ValidatedMember(value).xsdLiteral()
1270
1271 1272 -class STD_list (simpleTypeDefinition, types.ListType):
1273 """Base class for collection datatypes. 1274 1275 This class descends from the Python list type, and incorporates 1276 simpleTypeDefinition. Subclasses must define a class variable _ItemType 1277 which is a reference to the class of which members must be instances.""" 1278 1279 _ItemType = None 1280 """A reference to the binding class for items within this list.""" 1281 1282 # Ick: If we don't declare this here, this class's map doesn't get 1283 # initialized. Alternative is to not descend from simpleTypeDefinition. 1284 __FacetMap = {} 1285 1286 @classmethod
1287 - def _ValidatedItem (cls, value, kw=None):
1288 """Verify that the given value is permitted as an item of this list. 1289 1290 This may convert the value to the proper type, if it is 1291 compatible but not an instance of the item type. Returns the 1292 value that should be used as the item, or raises an exception 1293 if the value cannot be converted. 1294 1295 @param kw: optional dictionary of standard constructor keywords used 1296 when exceptions must be built. In particular, C{_location} may be 1297 useful. 1298 """ 1299 if isinstance(value, cls._ItemType): 1300 pass 1301 elif issubclass(cls._ItemType, STD_union): 1302 value = cls._ItemType._ValidatedMember(value) 1303 else: 1304 try: 1305 value = cls._ItemType(value) 1306 except (pyxb.SimpleTypeValueError, TypeError): 1307 location = None 1308 if kw is not None: 1309 location = kw.get('_location') 1310 raise pyxb.SimpleListValueError(cls, value, location) 1311 return value
1312 1313 @classmethod
1314 - def _ConvertArguments_vx (cls, args, kw):
1315 # If the first argument is a string, split it on spaces and use the 1316 # resulting list of tokens. 1317 if 0 < len(args): 1318 arg1 = args[0] 1319 if isinstance(arg1, types.StringTypes): 1320 args = (arg1.split(),) + args[1:] 1321 arg1 = args[0] 1322 if isinstance(arg1, collections.Iterable): 1323 new_arg1 = [ cls._ValidatedItem(_v, kw) for _v in arg1 ] 1324 args = (new_arg1,) + args[1:] 1325 super_fn = getattr(super(STD_list, cls), '_ConvertArguments_vx', lambda *a,**kw: args) 1326 return super_fn(args, kw)
1327 1328 @classmethod
1329 - def _XsdValueLength_vx (cls, value):
1330 return len(value)
1331 1332 @classmethod
1333 - def XsdLiteral (cls, value):
1334 """Convert from a binding value to a string usable in an XML document.""" 1335 return ' '.join([ cls._ItemType.XsdLiteral(_v) for _v in value ])
1336 1337 @classmethod
1338 - def _description (cls, name_only=False, user_documentation=True):
1339 name = cls._Name() 1340 if name_only: 1341 return name 1342 desc = [ name, ', list of ', cls._ItemType._description(name_only=True) ] 1343 return ''.join(desc)
1344 1345 # Convert a single value to the required type, if not already an instance 1346 @classmethod
1347 - def __ConvertOne (cls, v):
1348 return cls._ValidatedItem(v)
1349 1350 # Convert a sequence of values to the required type, if not already instances
1351 - def __convertMany (self, values):
1352 return [ self._ValidatedItem(_v) for _v in values ]
1353
1354 - def __setitem__ (self, key, value):
1355 if isinstance(key, slice): 1356 super(STD_list, self).__setitem__(key, self.__convertMany(value)) 1357 else: 1358 super(STD_list, self).__setitem__(key, self._ValidatedItem(value))
1359
1360 - def __setslice__ (self, start, end, values):
1361 super(STD_list, self).__setslice__(start, end, self.__convertMany(values))
1362
1363 - def __contains__ (self, item):
1364 return super(STD_list, self).__contains__(self._ValidatedItem(item))
1365 1366 # Standard mutable sequence methods, per Python Library Reference "Mutable Sequence Types" 1367
1368 - def append (self, x):
1369 super(STD_list, self).append(self._ValidatedItem(x))
1370
1371 - def extend (self, x, _from_xml=False):
1372 super(STD_list, self).extend(self.__convertMany(x))
1373
1374 - def count (self, x):
1375 return super(STD_list, self).count(self._ValidatedItem(x))
1376
1377 - def index (self, x, *args):
1378 return super(STD_list, self).index(self._ValidatedItem(x), *args)
1379
1380 - def insert (self, i, x):
1381 super(STD_list, self).insert(i, self._ValidatedItem(x))
1382
1383 - def remove (self, x):
1384 super(STD_list, self).remove(self._ValidatedItem(x))
1385
1386 -class element (utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
1387 """Class that represents a schema element within a binding. 1388 1389 This gets a little confusing. Within a schema, the 1390 L{pyxb.xmlschema.structures.ElementDeclaration} type represents an 1391 U{element 1392 declaration<http://www.w3.org/TR/xmlschema-1/#cElement_Declarations>}. 1393 Those declarations may be global (have a name that is visible in the 1394 namespace), or local (have a name that is visible only within a complex 1395 type definition). Further, local (but not global) declarations may have a 1396 reference to a global declaration (which might be in a different 1397 namespace). 1398 1399 Within a PyXB binding, the element declarations from the original complex 1400 type definition that have the same 1401 U{QName<http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-qname>} 1402 (after deconflicting the 1403 U{LocalPart<http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-LocalPart>}) 1404 are associated with an attribute in the class for the complex type. Each 1405 of these attributes is defined via a 1406 L{pyxb.binding.content.ElementDeclaration} which provides the mechanism by 1407 which the binding holds values associated with that element. 1408 1409 Furthermore, in the FAC-based content model each schema element 1410 declaration is associated with an 1411 L{ElementUse<pyxb.binding.content.ElementUse>} instance to locate the 1412 point in the schema where content came from. Instances that refer to the 1413 same schema element declaration share the same underlying 1414 L{pyxb.binding.content.ElementDeclaration}. 1415 1416 This element isn't any of those elements. This element is the type used 1417 for an attribute which associates the name of a element with data required 1418 to represent it, all within a particular scope (a module for global scope, 1419 the binding class for a complex type definition for local scope). From 1420 the perspective of a PyXB user they look almost like a class, in that you 1421 can call them to create instances of the underlying complex type. 1422 1423 Global and local elements are represented by instances of this class. 1424 """ 1425
1426 - def name (self):
1427 """The expanded name of the element within its scope.""" 1428 return self.__name
1429 __name = None 1430
1431 - def typeDefinition (self):
1432 """The L{_TypeBinding_mixin} subclass for values of this element.""" 1433 return self.__typeDefinition._SupersedingClass()
1434 __typeDefinition = None 1435
1436 - def xsdLocation (self):
1437 """The L{pyxb.utils.utility.Location} where the element appears in the schema.""" 1438 return self.__xsdLocation
1439 __xsdLocation = None 1440
1441 - def scope (self):
1442 """The scope of the element. This is either C{None}, representing a 1443 top-level element, or an instance of C{complexTypeDefinition} for 1444 local elements.""" 1445 return self.__scope
1446 __scope = None 1447
1448 - def nillable (self):
1449 """Indicate whether values matching this element can have U{nil 1450 <http://www.w3.org/TR/xmlschema-1/#xsi_nil>} set.""" 1451 return self.__nillable
1452 __nillable = False 1453
1454 - def abstract (self):
1455 """Indicate whether this element is abstract (must use substitution 1456 group members for matches).""" 1457 return self.__abstract
1458 __abstract = False 1459
1460 - def documentation (self):
1461 """Contents of any documentation annotation in the definition.""" 1462 return self.__documentation
1463 __documentation = None 1464
1465 - def defaultValue (self):
1466 """The default value of the element. 1467 1468 C{None} if the element has no default value. 1469 1470 @note: A non-C{None} value is always an instance of a simple type, 1471 even if the element has complex content.""" 1472 return self.__defaultValue
1473 __defaultValue = None 1474
1475 - def fixed (self):
1476 """C{True} if the element content cannot be changed""" 1477 return self.__fixed
1478 __fixed = False 1479
1480 - def substitutionGroup (self):
1481 """The L{element} instance to whose substitution group this element 1482 belongs. C{None} if this element is not part of a substitution 1483 group.""" 1484 return self.__substitutionGroup
1485 - def _setSubstitutionGroup (self, substitution_group):
1486 self.__substitutionGroup = substitution_group 1487 if substitution_group is not None: 1488 self.substitutesFor = self._real_substitutesFor 1489 return self
1490 __substitutionGroup = None 1491
1492 - def findSubstituendDecl (self, ctd_class):
1493 ed = ctd_class._ElementMap.get(self.name()) 1494 if ed is not None: 1495 return ed 1496 if self.substitutionGroup() is None: 1497 return None 1498 return self.substitutionGroup().findSubstituendDecl(ctd_class)
1499
1500 - def _real_substitutesFor (self, other):
1501 """Determine whether an instance of this element can substitute for the other element. 1502 1503 See U{Substitution Group OK<http://www.w3.org/TR/xmlschema-1/#cos-equiv-derived-ok-rec>}. 1504 1505 @todo: Do something about blocking constraints. This ignores them, as 1506 does everything leading to this point. 1507 """ 1508 if self.substitutionGroup() is None: 1509 return False 1510 if other is None: 1511 return False 1512 assert isinstance(other, element) 1513 # On the first call, other is likely to be the local element. We need 1514 # the global one. 1515 if other.scope() is not None: 1516 other = other.name().elementBinding() 1517 if other is None: 1518 return False 1519 assert other.scope() is None 1520 # Do both these refer to the same (top-level) element? 1521 if self.name().elementBinding() == other: 1522 return True 1523 return (self.substitutionGroup() == other) or self.substitutionGroup().substitutesFor(other)
1524
1525 - def substitutesFor (self, other):
1526 """Stub replaced by _real_substitutesFor when element supports substitution groups.""" 1527 return False
1528
1529 - def memberElement (self, name):
1530 """Return a reference to the element instance used for the given name 1531 within this element. 1532 1533 The type for this element must be a complex type definition.""" 1534 return self.typeDefinition()._UseForTag(name).elementBinding()
1535
1536 - def __init__ (self, name, type_definition, scope=None, nillable=False, abstract=False, unicode_default=None, fixed=False, substitution_group=None, documentation=None, location=None):
1537 """Create a new element binding. 1538 """ 1539 assert isinstance(name, pyxb.namespace.ExpandedName) 1540 self.__name = name 1541 self.__typeDefinition = type_definition 1542 self.__scope = scope 1543 self.__nillable = nillable 1544 self.__abstract = abstract 1545 if unicode_default is not None: 1546 # Override default None. If this is a complex type with simple 1547 # content, use the underlying simple type value. 1548 self.__defaultValue = self.__typeDefinition.Factory(unicode_default, _from_xml=True) 1549 if isinstance(self.__defaultValue, complexTypeDefinition): 1550 self.__defaultValue = self.__defaultValue.value() 1551 self.__fixed = fixed 1552 self.__substitutionGroup = substitution_group 1553 self.__documentation = documentation 1554 self.__xsdLocation = location 1555 super(element, self).__init__()
1556
1557 - def __call__ (self, *args, **kw):
1558 """Invoke the Factory method on the type associated with this element. 1559 1560 @keyword _dom_node: This keyword is removed. If present, it must be C{None}. 1561 1562 @note: Other keywords are passed to L{_TypeBinding_mixin.Factory}. 1563 1564 @raise pyxb.AbstractElementError: This element is abstract and no DOM 1565 node was provided. 1566 """ 1567 dom_node = kw.pop('_dom_node', None) 1568 assert dom_node is None, 'Cannot pass DOM node directly to element constructor; use createFromDOM' 1569 if '_element' in kw: 1570 raise pyxb.LogicError('Cannot set _element in element-based instance creation') 1571 kw['_element'] = self 1572 # Can't create instances of abstract elements. 1573 if self.abstract(): 1574 location = kw.get('_location') 1575 if (location is None) and isinstance(dom_node, utility.Locatable_mixin): 1576 location = dom_node._location() 1577 raise pyxb.AbstractElementError(self, location, args) 1578 if self.__defaultValue is not None: 1579 if 0 == len(args): 1580 # No initial value; use the default 1581 args = [ self.__defaultValue ] 1582 elif self.__fixed: 1583 # Validate that the value is consistent with the fixed value 1584 if 1 < len(args): 1585 raise ValueError(*args) 1586 args = [ self.compatibleValue(args[0], **kw) ] 1587 rv = self.typeDefinition().Factory(*args, **kw) 1588 rv._setElement(self) 1589 return rv
1590
1591 - def compatibleValue (self, value, **kw):
1592 """Return a variant of the value that is compatible with this element. 1593 1594 This mostly defers to L{_TypeBinding_mixin._CompatibleValue}. 1595 1596 @raise pyxb.SimpleTypeValueError: if the value is not both 1597 type-consistent and value-consistent with the element's type. 1598 """ 1599 # None is always None, unless there's a default. 1600 if value is None: 1601 return self.__defaultValue 1602 is_plural = kw.pop('is_plural', False) 1603 if is_plural: 1604 if not isinstance(value, collections.Iterable): 1605 raise pyxb.SimplePluralValueError(self.typeDefinition(), value) 1606 return [ self.compatibleValue(_v) for _v in value ] 1607 if self.__fixed and (value != self.__defaultValue): 1608 raise pyxb.ElementChangeError(self, value) 1609 if isinstance(value, _TypeBinding_mixin) and (value._element() is not None) and value._element().substitutesFor(self): 1610 return value 1611 if self.abstract(): 1612 location = None 1613 if isinstance(value, utility.Locatable_mixin): 1614 location = value._location() 1615 raise pyxb.AbstractElementError(self, location, value) 1616 return self.typeDefinition()._CompatibleValue(value, **kw)
1617 1618 @classmethod
1619 - def CreateDOMBinding (cls, node, element_binding, **kw):
1620 """Create a binding from a DOM node. 1621 1622 @param node: The DOM node 1623 1624 @param element_binding: An instance of L{element} that would normally 1625 be used to determine the type of the binding. The actual type of 1626 object returned is determined by the type definition associated with 1627 the C{element_binding} and the value of any U{xsi:type 1628 <http://www.w3.org/TR/xmlschema-1/#xsi_type>} attribute found in 1629 C{node}, modulated by 1630 L{XSI._InterpretTypeAttribute<pyxb.namespace.builtin._XMLSchema_instance._InterpretTypeAttribute>}. 1631 1632 @keyword _fallback_namespace: The namespace to use as the namespace for 1633 the node, if the node name is unqualified. This should be an absent 1634 namespace. 1635 1636 @return: A binding for the DOM node. 1637 1638 @raises pyxb.UnrecognizedDOMRootNodeError: if no underlying element or 1639 type for the node can be identified. 1640 """ 1641 1642 if xml.dom.Node.ELEMENT_NODE != node.nodeType: 1643 raise ValueError('node is not an element') 1644 1645 fallback_namespace = kw.get('_fallback_namespace') 1646 1647 # Record the element to be associated with the created binding 1648 # instance. 1649 if '_element' in kw: 1650 raise pyxb.LogicError('Cannot set _element in element-based instance creation') 1651 1652 type_class = None 1653 if element_binding is not None: 1654 # Can't create instances of abstract elements. @todo: Is there any 1655 # way this could be legal given an xsi:type attribute? I'm pretty 1656 # sure "no"... 1657 if element_binding.abstract(): 1658 location = kw.get('location') 1659 if (location is None) and isinstance(node, utility.Locatable_mixin): 1660 location = node._location() 1661 raise pyxb.AbstractElementError(element_binding, location, node) 1662 kw['_element'] = element_binding 1663 type_class = element_binding.typeDefinition() 1664 1665 # Get the namespace context for the value being created. If none is 1666 # associated, one will be created. Do not make assumptions about the 1667 # namespace context; if the user cared, she should have assigned a 1668 # context before calling this. 1669 ns_ctx = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(node) 1670 (did_replace, type_class) = XSI._InterpretTypeAttribute(XSI.type.getAttribute(node), ns_ctx, fallback_namespace, type_class) 1671 1672 if type_class is None: 1673 raise pyxb.UnrecognizedDOMRootNodeError(node) 1674 1675 # Pass xsi:nil on to the constructor regardless of whether the element 1676 # is nillable. Another sop to SOAP-encoding WSDL fans who don't 1677 # bother to provide valid schema for their message content. 1678 is_nil = XSI.nil.getAttribute(node) 1679 if is_nil is not None: 1680 kw['_nil'] = pyxb.binding.datatypes.boolean(is_nil) 1681 1682 rv = type_class.Factory(_dom_node=node, **kw) 1683 assert rv._element() == element_binding 1684 rv._setNamespaceContext(pyxb.namespace.resolution.NamespaceContext.GetNodeContext(node)) 1685 return rv._postDOMValidate()
1686 1687 # element 1688 @classmethod
1689 - def AnyCreateFromDOM (cls, node, fallback_namespace):
1690 """Create an instance of an element from a DOM node. 1691 1692 This method does minimal processing of C{node} and delegates to 1693 L{CreateDOMBinding}. 1694 1695 @param node: An C{xml.dom.Node} representing a root element. If the 1696 node is a document, that document's root node will be substituted. 1697 The name of the node is extracted as the name of the element to be 1698 created, and the node and the name are passed to L{CreateDOMBinding}. 1699 1700 @param fallback_namespace: The value to pass as C{_fallback_namespace} 1701 to L{CreateDOMBinding} 1702 1703 @return: As with L{CreateDOMBinding}""" 1704 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1705 node = node.documentElement 1706 expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=fallback_namespace) 1707 return cls.CreateDOMBinding(node, expanded_name.elementBinding(), _fallback_namespace=fallback_namespace)
1708
1709 - def elementForName (self, name):
1710 """Return the element that should be used if this element binding is 1711 permitted and an element with the given name is encountered. 1712 1713 Normally, the incoming name matches the name of this binding, and 1714 C{self} is returned. If the incoming name is different, it is 1715 expected to be the name of a global element which is within this 1716 element's substitution group. In that case, the binding corresponding 1717 to the named element is return. 1718 1719 @return: An instance of L{element}, or C{None} if no element with the 1720 given name can be found. 1721 """ 1722 1723 # Name match means OK. 1724 if self.name() == name: 1725 return self 1726 # No name match means only hope is a substitution group, for which the 1727 # element must be top-level. 1728 top_elt = self.name().elementBinding() 1729 if top_elt is None: 1730 return None 1731 # Members of the substitution group must also be top-level. NB: If 1732 # named_elt == top_elt, then the adoptName call below improperly 1733 # associated the global namespace with a local element of the same 1734 # name; cf. test-namespace-uu:testBad. 1735 elt_en = top_elt.name().adoptName(name) 1736 assert 'elementBinding' in elt_en.namespace()._categoryMap(), 'No element bindings in %s' % (elt_en.namespace(),) 1737 named_elt = elt_en.elementBinding() 1738 if (named_elt is None) or (named_elt == top_elt): 1739 return None 1740 if named_elt.substitutesFor(top_elt): 1741 return named_elt 1742 return None
1743
1744 - def createFromDOM (self, node, fallback_namespace=None, **kw):
1745 """Create an instance of this element using a DOM node as the source 1746 of its content. 1747 1748 This method does minimal processing of C{node} and delegates to 1749 L{_createFromDOM}. 1750 1751 @param node: An C{xml.dom.Node} representing a root element. If the 1752 node is a document, that document's root node will be substituted. 1753 The name of the node is extracted as the name of the element to be 1754 created, and the node and the name are passed to L{_createFromDOM} 1755 1756 @keyword fallback_namespace: Used as default for 1757 C{_fallback_namespace} in call to L{_createFromDOM} 1758 1759 @note: Keyword parameters are passed to L{CreateDOMBinding}. 1760 1761 @return: As with L{_createFromDOM} 1762 """ 1763 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1764 node = node.documentElement 1765 if fallback_namespace is not None: 1766 kw.setdefault('_fallback_namespace', fallback_namespace) 1767 expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=fallback_namespace) 1768 return self._createFromDOM(node, expanded_name, **kw)
1769
1770 - def _createFromDOM (self, node, expanded_name, **kw):
1771 """Create an instance from a DOM node given the name of an element. 1772 1773 This method does minimal processing of C{node} and C{expanded_name} 1774 and delegates to L{CreateDOMBinding}. 1775 1776 @param node: An C{xml.dom.Node} representing a root element. If the 1777 node is a document, that document's root node will be substituted. 1778 The value is passed to L{CreateDOMBinding}. 1779 1780 @param expanded_name: The expanded name of the element to be used for 1781 content. This is passed to L{elementForName} to obtain the binding 1782 that is passed to L{CreateDOMBinding}, superseding any identification 1783 that might be inferred from C{node}. If no name is available, use 1784 L{createFromDOM}. 1785 1786 @note: Keyword parameters are passed to L{CreateDOMBinding}. 1787 1788 @return: As with L{CreateDOMBinding}. 1789 """ 1790 if xml.dom.Node.DOCUMENT_NODE == node.nodeType: 1791 node = node.documentElement 1792 return element.CreateDOMBinding(node, self.elementForName(expanded_name), **kw)
1793
1794 - def __str__ (self):
1795 return 'Element %s' % (self.name(),)
1796
1797 - def _description (self, name_only=False, user_documentation=True):
1798 name = str(self.name()) 1799 if name_only: 1800 return name 1801 desc = [ name, ' (', self.typeDefinition()._description(name_only=True), ')' ] 1802 if self.scope() is not None: 1803 desc.extend([', local to ', self.scope()._description(name_only=True) ]) 1804 if self.nillable(): 1805 desc.append(', nillable') 1806 if self.substitutionGroup() is not None: 1807 desc.extend([', substitutes for ', self.substitutionGroup()._description(name_only=True) ]) 1808 if user_documentation and (self.documentation() is not None): 1809 desc.extend(["\n", self.documentation() ]) 1810 return ''.join(desc)
1811
1812 -class enumeration_mixin (pyxb.cscRoot):
1813 """Marker in case we need to know that a PST has an enumeration constraint facet.""" 1814 1815 @classmethod
1816 - def values (cls):
1817 """Return a list of values that the enumeration can take.""" 1818 return cls._CF_enumeration.values()
1819 1820 @classmethod
1821 - def itervalues (cls):
1822 """Return a generator for the values that the enumeration can take.""" 1823 return cls._CF_enumeration.itervalues()
1824 1825 @classmethod
1826 - def items (cls):
1827 """Return the associated L{pyxb.binding.facet._EnumerationElement} instances.""" 1828 return cls._CF_enumeration.items()
1829 1830 @classmethod
1831 - def iteritems (cls):
1832 """Generate the associated L{pyxb.binding.facet._EnumerationElement} instances.""" 1833 return cls._CF_enumeration.iteritems()
1834
1835 -class _Content (object):
1836 """Base for any wrapper added to L{complexTypeDefinition.orderedContent}.""" 1837
1838 - def __getValue (self):
1839 """The value of the content. 1840 1841 This is a unicode string for L{NonElementContent}, and (ideally) an 1842 instance of L{_TypeBinding_mixin} for L{ElementContent}.""" 1843 return self.__value
1844 __value = None 1845 value = property(__getValue) 1846
1847 - def __init__ (self, value):
1848 self.__value = value
1849
1850 -class ElementContent (_Content):
1851 """Marking wrapper for element content. 1852 1853 The value should be translated into XML and made a child of its parent.""" 1854
1855 - def __getElementDeclaration (self):
1856 """The L{pyxb.binding.content.ElementDeclaration} associated with the element content. 1857 This may be C{None} if the value is a wildcard.""" 1858 return self.__elementDeclaration
1859 __elementDeclaration = None 1860 1861 elementDeclaration = property(__getElementDeclaration) 1862
1863 - def __init__ (self, value, element_declaration=None, instance=None, tag=None):
1864 """Create a wrapper associating a value with its element declaration. 1865 1866 Normally the element declaration is determined by consulting the 1867 content model when creating a binding instance. When manipulating the 1868 preferred content list, this may be inconvenient to obtain; in that case 1869 provide the C{instance} in which the content appears immediately, 1870 along with the C{tag} that is used for the Python attribute that holds 1871 the element. 1872 1873 @param value: the value of the element. Should be an instance of 1874 L{_TypeBinding_mixin}, but for simple types might be a Python native 1875 type. 1876 1877 @keyword element_declaration: The 1878 L{pyxb.binding.content.ElementDeclaration} associated with the element 1879 value. Should be C{None} if the element matches wildcard content. 1880 1881 @keyword instance: Alternative path to providing C{element_declaration} 1882 @keyword tag: Alternative path to providing C{element_declaration} 1883 """ 1884 1885 import pyxb.binding.content 1886 super(ElementContent, self).__init__(value) 1887 if instance is not None: 1888 if not isinstance(instance, complexTypeDefinition): 1889 raise pyxb.UsageError('Unable to determine element declaration') 1890 element_declaration = instance._UseForTag(tag) 1891 assert (element_declaration is None) or isinstance(element_declaration, pyxb.binding.content.ElementDeclaration) 1892 self.__elementDeclaration = element_declaration
1893
1894 -class NonElementContent (_Content):
1895 """Marking wrapper for non-element content. 1896 1897 The value will be unicode text, and should be appended as character 1898 data."""
1899 - def __init__ (self, value):
1901
1902 -class complexTypeDefinition (_TypeBinding_mixin, utility._DeconflictSymbols_mixin, _DynamicCreate_mixin):
1903 """Base for any Python class that serves as the binding for an 1904 XMLSchema complexType. 1905 1906 Subclasses should define a class-level _AttributeMap variable which maps 1907 from the unicode tag of an attribute to the AttributeUse instance that 1908 defines it. Similarly, subclasses should define an _ElementMap variable. 1909 """ 1910 1911 _CT_EMPTY = 'EMPTY' #<<< No content 1912 _CT_SIMPLE = 'SIMPLE' #<<< Simple (character) content 1913 _CT_MIXED = 'MIXED' #<<< Children may be elements or other (e.g., character) content 1914 _CT_ELEMENT_ONLY = 'ELEMENT_ONLY' #<<< Expect only element content. 1915 1916 _ContentTypeTag = None 1917 1918 _TypeDefinition = None 1919 """Subclass of simpleTypeDefinition that corresponds to the type content. 1920 Only valid if _ContentTypeTag is _CT_SIMPLE""" 1921 1922 # A value that indicates whether the content model for this type supports 1923 # wildcard elements. Supporting classes should override this value. 1924 _HasWildcardElement = False 1925 1926 # Map from expanded names to ElementDeclaration instances 1927 _ElementMap = { } 1928 """Map from expanded names to ElementDeclaration instances.""" 1929 1930 # Per-instance map from tags to attribute values for wildcard attributes. 1931 # Value is C{None} if the type does not support wildcard attributes. 1932 __wildcardAttributeMap = None 1933
1934 - def wildcardAttributeMap (self):
1935 """Obtain access to wildcard attributes. 1936 1937 The return value is C{None} if this type does not support wildcard 1938 attributes. If wildcard attributes are allowed, the return value is a 1939 map from QNames to the unicode string value of the corresponding 1940 attribute. 1941 1942 @todo: The map keys should be namespace extended names rather than 1943 QNames, as the in-scope namespace may not be readily available to the 1944 user. 1945 """ 1946 return self.__wildcardAttributeMap
1947 1948 # Per-instance list of DOM nodes interpreted as wildcard elements. 1949 # Value is None if the type does not support wildcard elements. 1950 __wildcardElements = None 1951
1952 - def wildcardElements (self):
1953 """Obtain access to wildcard elements. 1954 1955 The return value is C{None} if the content model for this type does not 1956 support wildcard elements. If wildcard elements are allowed, the 1957 return value is a list of values corresponding to conformant 1958 unrecognized elements, in the order in which they were encountered. 1959 If the containing binding was created from an XML document and enough 1960 information was present to determine the binding of the member 1961 element, the value is a binding instance. Otherwise, the value is the 1962 original DOM Element node. 1963 """ 1964 return self.__wildcardElements
1965
1966 - def __init__ (self, *args, **kw):
1967 """Create a new instance of this binding. 1968 1969 Arguments are used as transition values along the content model. 1970 Keywords are passed to the constructor of any simple content, or used 1971 to initialize attribute and element values whose L{id 1972 <content.ElementDeclaration.id>} (not L{name <content.ElementDeclaration.name>}) 1973 matches the keyword. 1974 1975 @keyword _dom_node: The node to use as the source of binding content. 1976 @type _dom_node: C{xml.dom.Element} 1977 1978 @keyword _location: An optional instance of 1979 L{pyxb.utils.utility.Location} showing the origin the binding. If 1980 C{None}, a value from C{_dom_node} is used if available. 1981 1982 @keyword _from_xml: See L{_TypeBinding_mixin.Factory} 1983 1984 @keyword _finalize_content_model: If C{True} the constructor invokes 1985 L{_TypeBinding_mixin._finalizeContentModel} prior to return. The 1986 value defaults to C{False} when content is assigned through keyword 1987 parameters (bypassing the content model) or neither a C{_dom_node} nor 1988 positional element parameters have been provided, and to C{True} in 1989 all other cases. 1990 """ 1991 1992 fallback_namespace = kw.pop('_fallback_namespace', None) 1993 is_nil = False 1994 dom_node = kw.pop('_dom_node', None) 1995 location = kw.pop('_location', None) 1996 from_xml = kw.pop('_from_xml', dom_node is not None) 1997 do_finalize_content_model = kw.pop('_finalize_content_model', None) 1998 if dom_node is not None: 1999 if (location is None) and isinstance(dom_node, pyxb.utils.utility.Locatable_mixin): 2000 location = dom_node._location() 2001 if xml.dom.Node.DOCUMENT_NODE == dom_node.nodeType: 2002 dom_node = dom_node.documentElement 2003 #kw['_validate_constraints'] = False 2004 is_nil = XSI.nil.getAttribute(dom_node) 2005 if is_nil is not None: 2006 is_nil = kw['_nil'] = pyxb.binding.datatypes.boolean(is_nil) 2007 if location is not None: 2008 self._setLocation(location) 2009 if self._AttributeWildcard is not None: 2010 self.__wildcardAttributeMap = { } 2011 if self._HasWildcardElement: 2012 self.__wildcardElements = [] 2013 if self._Abstract: 2014 raise pyxb.AbstractInstantiationError(type(self), location, dom_node) 2015 super(complexTypeDefinition, self).__init__(**kw) 2016 self.reset() 2017 self._setAttributesFromKeywordsAndDOM(kw, dom_node) 2018 did_set_kw_elt = False 2019 for fu in self._ElementMap.values(): 2020 iv = kw.pop(fu.id(), None) 2021 if iv is not None: 2022 did_set_kw_elt = True 2023 fu.set(self, iv) 2024 if do_finalize_content_model is None: 2025 do_finalize_content_model = not did_set_kw_elt 2026 if kw and kw.pop('_strict_keywords', True): 2027 [ kw.pop(_fkw, None) for _fkw in self._PyXBFactoryKeywords ] 2028 if kw: 2029 raise pyxb.UnprocessedKeywordContentError(self, kw) 2030 if 0 < len(args): 2031 if did_set_kw_elt: 2032 raise pyxb.UsageError('Cannot mix keyword and positional args for element initialization') 2033 self.extend(args, _from_xml=from_xml, _location=location) 2034 elif self._CT_SIMPLE == self._ContentTypeTag: 2035 value = self._TypeDefinition.Factory(_require_value=not self._isNil(), _dom_node=dom_node, _location=location, _nil=self._isNil(), _apply_attributes=False, *args) 2036 if value._constructedWithValue(): 2037 self.append(value) 2038 elif dom_node is not None: 2039 self.extend(dom_node.childNodes[:], fallback_namespace) 2040 else: 2041 do_finalize_content_model = False 2042 if do_finalize_content_model: 2043 self._finalizeContentModel()
2044 2045 # Specify the symbols to be reserved for all CTDs. 2046 _ReservedSymbols = _TypeBinding_mixin._ReservedSymbols.union(set([ 'wildcardElements', 'wildcardAttributeMap', 2047 'xsdConstraintsOK', 'content', 'orderedContent', 'append', 'extend', 'value', 'reset' ])) 2048 2049 # None, or a reference to a pyxb.utils.fac.Automaton instance that defines 2050 # the content model for the type. 2051 _Automaton = None 2052 2053 @classmethod
2054 - def _AddElement (cls, element):
2055 """Method used by generated code to associate the element binding with a use in this type. 2056 2057 This is necessary because all complex type classes appear in the 2058 module prior to any of the element instances (which reference type 2059 classes), so the association must be formed after the element 2060 instances are available.""" 2061 return cls._UseForTag(element.name())._setElementBinding(element)
2062 2063 @classmethod
2064 - def _UseForTag (cls, tag, raise_if_fail=True):
2065 """Return the ElementDeclaration object corresponding to the element name. 2066 2067 @param tag: The L{ExpandedName} of an element in the class.""" 2068 try: 2069 rv = cls._ElementMap[tag] 2070 except KeyError: 2071 if raise_if_fail: 2072 raise 2073 rv = None 2074 return rv
2075
2076 - def __childrenForDOM (self):
2077 """Generate a list of children in the order in which they should be 2078 added to the parent when creating a DOM representation of this 2079 object. 2080 2081 @note: This is only used when L{pyxb.RequireValidWhenGenerating} has 2082 disabled validation. Consequently, it may not generate valid XML. 2083 """ 2084 order = [] 2085 for ed in self._ElementMap.values(): 2086 value = ed.value(self) 2087 if value is None: 2088 continue 2089 if isinstance(value, list) and ed.isPlural(): 2090 order.extend([ ElementContent(_v, ed) for _v in value ]) 2091 continue 2092 order.append(ElementContent(value, ed)) 2093 return order
2094
2095 - def _validatedChildren (self):
2096 """Provide the child elements and non-element content in an order 2097 consistent with the content model. 2098 2099 Returns a sequence of tuples representing a valid path through the 2100 content model where each transition corresponds to one of the member 2101 element instances within this instance. The tuple is a pair 2102 comprising the L{content.ElementDeclaration} instance and the value for the 2103 transition. 2104 2105 If the content of the instance does not validate against the content 2106 model, an exception is raised. 2107 2108 @return: C{None} or a list as described above. 2109 """ 2110 if self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE): 2111 return [] 2112 self._resetAutomaton() 2113 return self.__automatonConfiguration.sequencedChildren()
2114
2115 - def _symbolSet (self):
2116 """Return a map from L{content.ElementDeclaration} instances to a list of 2117 values associated with that use. 2118 2119 This is used as the set of symbols available for transitions when 2120 validating content against a model. Note that the original 2121 L{content.ElementUse} that may have validated the assignment of the 2122 symbol to the content is no longer available, which may result in a 2123 different order being generated by the content model. Preservation of 2124 the original order mitigates this risk. 2125 2126 The value C{None} is used to provide the wildcard members, if any. 2127 2128 If an element use has no associated values, it must not appear in the 2129 returned map. 2130 2131 @raise pyxb.SimpleTypeValueError: when unable tconverting element 2132 content the binding declaration type. 2133 """ 2134 rv = { } 2135 for eu in self._ElementMap.values(): 2136 value = eu.value(self) 2137 if value is None: 2138 continue 2139 converter = eu.elementBinding().compatibleValue 2140 if eu.isPlural(): 2141 if 0 < len(value): 2142 rv[eu] = [ converter(_v) for _v in value ] 2143 else: 2144 rv[eu] = [ converter(value)] 2145 wce = self.__wildcardElements 2146 if (wce is not None) and (0 < len(wce)): 2147 rv[None] = wce[:] 2148 return rv
2149
2150 - def _validateAttributes (self):
2151 for au in self._AttributeMap.values(): 2152 au.validate(self)
2153
2154 - def _validateBinding_vx (self):
2155 if self._isNil(): 2156 if (self._IsSimpleTypeContent() and (self.__content is not None)) or self.__content: 2157 raise pyxb.ContentInNilInstanceError(self, self.__content) 2158 return True 2159 if self._IsSimpleTypeContent() and (self.__content is None): 2160 raise pyxb.SimpleContentAbsentError(self, self._location()) 2161 order = self._validatedChildren() 2162 for content in order: 2163 if isinstance (content, NonElementContent): 2164 continue 2165 if isinstance(content.value, _TypeBinding_mixin): 2166 content.value.validateBinding() 2167 elif content.elementDeclaration is not None: 2168 _log.warning('Cannot validate value %s in field %s', content.value, content.elementDeclaration.id()) 2169 self._validateAttributes() 2170 return True
2171
2172 - def _setAttribute (self, attr_en, value):
2173 au = self._AttributeMap.get(attr_en) 2174 if au is None: 2175 if self._AttributeWildcard is None: 2176 raise pyxb.UnrecognizedAttributeError(type(self), attr_en, self) 2177 self.__wildcardAttributeMap[attr_en] = value 2178 else: 2179 au.set(self, value) 2180 return au
2181
2182 - def xsdConstraintsOK (self, location=None):
2183 """Validate the content against the simple type. 2184 2185 @return: C{True} if the content validates against its type. 2186 @raise pyxb.NotSimpleContentError: this type does not have simple content. 2187 @raise pyxb.SimpleContentAbsentError: the content of this type has not been set 2188 """ 2189 # @todo: type check 2190 if self._CT_SIMPLE != self._ContentTypeTag: 2191 raise pyxb.NotSimpleContentError(self) 2192 if self._isNil(): 2193 return True 2194 if self.__content is None: 2195 if location is None: 2196 location = self._location() 2197 raise pyxb.SimpleContentAbsentError(self, location) 2198 return self.value().xsdConstraintsOK(location)
2199 2200 # __content is used in two ways: when complex content is used, it is as 2201 # documented in L{orderedContent}. When simple content is used, it is as 2202 # documented in L{value}. 2203 __content = None 2204
2205 - def orderedContent (self):
2206 """Return the element and non-element content of the instance in order. 2207 2208 This must be a complex type with complex content. The return value is 2209 a list of the element and non-element content in a preferred order. 2210 2211 The returned list contains L{element<ElementContent>} and 2212 L{non-element<NonElementContent>} content in the order which it was 2213 added to the instance. This may have been through parsing a document, 2214 constructing an instance using positional arguments, invoking the 2215 L{append} or L{extend} methods, or assigning directly to an instance 2216 attribute associated with an element binding. 2217 2218 @note: Be aware that assigning directly to an element attribute does not 2219 remove any previous value for the element from the content list. 2220 2221 @note: Be aware that element values directly appended to an instance 2222 attribute with list type (viz., that corresponds to an element that 2223 allows more than one occurrence) will not appear in the ordered 2224 content list. 2225 2226 The order in the list may influence the generation of documents 2227 depending on L{pyxb.ValidationConfig} values that apply to an 2228 instance. Non-element content is emitted immediately prior to the 2229 following element in this list. Any trailing non-element content is 2230 emitted after the last element in the content. The list should 2231 include all element content. Element content in this list that is not 2232 present within an element member of the binding instance may result in 2233 an error, or may be ignored. 2234 2235 @note: The returned value is mutable, allowing the caller to change 2236 the order to be used. 2237 2238 @raise pyxb.NotComplexContentError: this is not a complex type with mixed or element-only content 2239 """ 2240 if self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE): 2241 raise pyxb.NotComplexContentError(self) 2242 return self.__content
2243 2244 @classmethod
2245 - def __WarnOnContent (cls):
2246 if cls.__NeedWarnOnContent: 2247 import traceback 2248 cls.__NeedWarnOnContent = False 2249 _log.warning('Deprecated complexTypeDefinition method "content" invoked\nPlease use "orderedContent"\n%s', ''.join(traceback.format_stack()[:-2])) 2250 pass
2251 __NeedWarnOnContent = True 2252
2253 - def content (self):
2254 """Legacy interface for ordered content. 2255 2256 This version does not accurately distinguish non-element content from 2257 element content that happens to have unicode type. 2258 2259 @deprecated: use L{orderedContent}.""" 2260 self.__WarnOnContent() 2261 if self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE): 2262 raise pyxb.NotComplexContentError(self) 2263 return [ _v.value for _v in self.__content ]
2264
2265 - def value (self):
2266 """Return the value of the element. 2267 2268 This must be a complex type with simple content. The returned value 2269 is expected to be an instance of some L{simpleTypeDefinition} class. 2270 2271 @raise pyxb.NotSimpleContentError: this is not a complex type with simple content 2272 """ 2273 if self._CT_SIMPLE != self._ContentTypeTag: 2274 raise pyxb.NotSimpleContentError(self) 2275 return self.__content
2276
2277 - def _resetContent (self, reset_elements=False):
2278 if reset_elements: 2279 for eu in self._ElementMap.values(): 2280 eu.reset(self) 2281 nv = None 2282 if self._ContentTypeTag in (self._CT_MIXED, self._CT_ELEMENT_ONLY): 2283 nv = [] 2284 return self.__setContent(nv)
2285 2286 __automatonConfiguration = None
2287 - def _resetAutomaton (self):
2288 if self._Automaton is not None: 2289 if self.__automatonConfiguration is None: 2290 import pyxb.binding.content 2291 self.__automatonConfiguration = pyxb.binding.content.AutomatonConfiguration(self) 2292 self.__automatonConfiguration.reset() 2293 return self.__automatonConfiguration
2294
2295 - def _automatonConfiguration (self):
2296 """For whitebox testing use only""" 2297 return self.__automatonConfiguration
2298
2299 - def reset (self):
2300 """Reset the instance. 2301 2302 This resets all element and attribute fields, and discards any 2303 recorded content. It resets the content model automaton to its 2304 initial state. 2305 2306 @see: Manipulate the return value of L{orderedContent} if your intent is 2307 to influence the generation of documents from the binding instance 2308 without changing its (element) content. 2309 """ 2310 2311 self._resetContent(reset_elements=True) 2312 for au in self._AttributeMap.values(): 2313 au.reset(self) 2314 self._resetAutomaton() 2315 return self
2316 2317 @classmethod
2318 - def _ElementBindingDeclForName (cls, element_name):
2319 """Determine what the given name means as an element in this type. 2320 2321 Normally, C{element_name} identifies an element definition within this 2322 type. If so, the returned C{element_decl} identifies that definition, 2323 and the C{element_binding} is extracted from that use. 2324 2325 It may also be that the C{element_name} does not appear as an element 2326 definition, but that it identifies a global element. In that case, 2327 the returned C{element_binding} identifies the global element. If, 2328 further, that element is a member of a substitution group which does 2329 have an element definition in this class, then the returned 2330 C{element_decl} identifies that definition. 2331 2332 If a non-C{None} C{element_decl} is returned, there will be an 2333 associated C{element_binding}. However, it is possible to return a 2334 non-C{None} C{element_binding}, but C{None} as the C{element_decl}. In 2335 that case, the C{element_binding} can be used to create a binding 2336 instance, but the content model will have to treat it as a wildcard. 2337 2338 @param element_name: The name of the element in this type, either an 2339 expanded name or a local name if the element has an absent namespace. 2340 2341 @return: C{( element_binding, element_decl )} 2342 """ 2343 element_decl = cls._ElementMap.get(element_name) 2344 element_binding = None 2345 if element_decl is None: 2346 try: 2347 element_binding = element_name.elementBinding() 2348 except pyxb.NamespaceError: 2349 pass 2350 if element_binding is not None: 2351 element_decl = element_binding.findSubstituendDecl(cls) 2352 else: 2353 element_binding = element_decl.elementBinding() 2354 return (element_binding, element_decl)
2355
2356 - def append (self, value, **kw):
2357 """Add the value to the instance. 2358 2359 The value should be a DOM node or other value that is or can be 2360 converted to a binding instance, or a string if the instance allows 2361 mixed content. The value must be permitted by the content model. 2362 2363 @raise pyxb.ContentValidationError: the value is not permitted at the current 2364 state of the content model. 2365 """ 2366 2367 # @todo: Allow caller to provide default element use; it's available 2368 # in saxer. 2369 element_decl = kw.get('_element_decl', None) 2370 maybe_element = kw.get('_maybe_element', True) 2371 location = kw.get('_location', None) 2372 if self._isNil(): 2373 raise pyxb.ContentInNilInstanceError(self, value, location) 2374 fallback_namespace = kw.get('_fallback_namespace', None) 2375 require_validation = kw.get('_require_validation', self._validationConfig.forBinding) 2376 from_xml = kw.get('_from_xml', False) 2377 element_binding = None 2378 if element_decl is not None: 2379 from pyxb.binding import content 2380 assert isinstance(element_decl, content.ElementDeclaration) 2381 element_binding = element_decl.elementBinding() 2382 assert element_binding is not None 2383 # Convert the value if it's XML and we recognize it. 2384 if isinstance(value, xml.dom.Node): 2385 from_xml = True 2386 assert maybe_element 2387 assert element_binding is None 2388 node = value 2389 require_validation = pyxb.GlobalValidationConfig.forBinding 2390 if xml.dom.Node.COMMENT_NODE == node.nodeType: 2391 # @todo: Note that we're allowing comments inside the bodies 2392 # of simple content elements, which isn't really Hoyle. 2393 return self 2394 if node.nodeType in (xml.dom.Node.TEXT_NODE, xml.dom.Node.CDATA_SECTION_NODE): 2395 value = node.data 2396 maybe_element = False 2397 else: 2398 # Do type conversion here 2399 assert xml.dom.Node.ELEMENT_NODE == node.nodeType 2400 expanded_name = pyxb.namespace.ExpandedName(node, fallback_namespace=fallback_namespace) 2401 (element_binding, element_decl) = self._ElementBindingDeclForName(expanded_name) 2402 if element_binding is not None: 2403 # If we have an element binding, we need to use it because 2404 # it knows how to resolve substitution groups. 2405 value = element_binding._createFromDOM(node, expanded_name, _fallback_namespace=fallback_namespace) 2406 else: 2407 # If we don't have an element binding, we might still be 2408 # able to convert this if it has an xsi:type attribute. 2409 try: 2410 value = element.CreateDOMBinding(node, None, _fallback_namespace=fallback_namespace) 2411 except: 2412 _log.warning('Unable to convert DOM node %s at %s to binding', expanded_name, getattr(node, 'location', '[UNAVAILABLE]')) 2413 if (not maybe_element) and isinstance(value, basestring) and (self._ContentTypeTag in (self._CT_EMPTY, self._CT_ELEMENT_ONLY)): 2414 if (0 == len(value.strip())) and not self._isNil(): 2415 return self 2416 if maybe_element and (self.__automatonConfiguration is not None): 2417 # Allows element content. 2418 if not require_validation: 2419 if element_decl is not None: 2420 element_decl.setOrAppend(self, value) 2421 return self 2422 if self.__wildcardElements is not None: 2423 self._appendWildcardElement(value) 2424 return self 2425 raise pyxb.StructuralBadDocumentError('Validation is required when no element_decl can be found') 2426 # Attempt to place the value based on the content model 2427 num_cand = self.__automatonConfiguration.step(value, element_decl) 2428 if 1 <= num_cand: 2429 # Resolution was successful (possibly non-deterministic) 2430 return self 2431 # If what we have is element or just complex content, we can't accept 2432 # it, either because the type doesn't accept element content or 2433 # because it does and what we got didn't match the content model. 2434 if (element_binding is not None) or isinstance(value, (xml.dom.Node, complexTypeDefinition, pyxb.BIND)): 2435 raise pyxb.UnrecognizedContentError(self, self.__automatonConfiguration, value, location) 2436 2437 # We have something that doesn't seem to be an element. Are we 2438 # expecting simple content? 2439 if self._IsSimpleTypeContent(): 2440 if self.__content is not None: 2441 raise pyxb.ExtraSimpleContentError(self, value) 2442 if not self._isNil(): 2443 if not isinstance(value, self._TypeDefinition): 2444 value = self._TypeDefinition.Factory(value, _from_xml=from_xml) 2445 self.__setContent(value) 2446 if require_validation: 2447 # NB: This only validates the value, not any associated 2448 # attributes, which is correct to be parallel to complex 2449 # content validation. 2450 self.xsdConstraintsOK(location) 2451 return self 2452 2453 # Do we allow non-element content? 2454 if not self._IsMixed(): 2455 raise pyxb.MixedContentError(self, value, location) 2456 2457 # It's character information. 2458 self._addContent(NonElementContent(value)) 2459 return self
2460
2461 - def _appendWildcardElement (self, value):
2464
2465 - def extend (self, value_list, _fallback_namespace=None, _from_xml=False, _location=None):
2466 """Invoke L{append} for each value in the list, in turn.""" 2467 [ self.append(_v, _fallback_namespace=_fallback_namespace, _from_xml=_from_xml, _location=_location) for _v in value_list ] 2468 return self
2469
2470 - def __setContent (self, value):
2471 self.__content = value 2472 return self.__content
2473
2474 - def _addContent (self, wrapped_value):
2475 # This assert is inadequate in the case of plural/non-plural elements with an STD_list base type. 2476 # Trust that validation elsewhere was done correctly. 2477 #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)) 2478 assert not (self._ContentTypeTag in (self._CT_EMPTY, self._CT_SIMPLE)) 2479 assert isinstance(wrapped_value, _Content) 2480 self.__content.append(wrapped_value) 2481 if isinstance(wrapped_value, ElementContent): 2482 value = wrapped_value.value 2483 ed = wrapped_value.elementDeclaration 2484 if isinstance(value, _TypeBinding_mixin) and (ed is not None) and (value._element() is None): 2485 assert isinstance(ed.elementBinding(), element) 2486 value._setElement(ed.elementBinding())
2487 2488 @classmethod
2489 - def _IsMixed (cls):
2490 return (cls._CT_MIXED == cls._ContentTypeTag)
2491
2492 - def _finalizeContentModel (self):
2493 # Override parent implementation. 2494 if self.__automatonConfiguration: 2495 self.__automatonConfiguration.resolveNondeterminism()
2496
2497 - def _postDOMValidate (self):
2498 # It's probably finalized already, but just in case... 2499 self._finalizeContentModel() 2500 if self._validationConfig.forBinding: 2501 # @todo isNil should verify that no content is present. 2502 if (not self._isNil()) and (self.__automatonConfiguration is not None): 2503 if not self.__automatonConfiguration.isAccepting(): 2504 if self._IsSimpleTypeContent(): 2505 raise pyxb.SimpleContentAbsentError(self, self._location()) 2506 self.__automatonConfiguration.diagnoseIncompleteContent() 2507 self._validateAttributes() 2508 return self
2509
2510 - def _setDOMFromAttributes (self, dom_support, element):
2511 """Add any appropriate attributes from this instance into the DOM element.""" 2512 for au in self._AttributeMap.values(): 2513 if pyxb.GlobalValidationConfig.forDocument: 2514 au.validate(self) 2515 au.addDOMAttribute(dom_support, self, element) 2516 return element
2517
2518 - def _toDOM_csc (self, dom_support, parent):
2519 """Create a DOM element with the given tag holding the content of this instance.""" 2520 element = parent 2521 self._setDOMFromAttributes(dom_support, element) 2522 if self._isNil(): 2523 pass 2524 elif self._CT_EMPTY == self._ContentTypeTag: 2525 pass 2526 elif self._CT_SIMPLE == self._ContentTypeTag: 2527 assert self.value() is not None, '%s has no value' % (self,) 2528 dom_support.appendTextChild(self.value().xsdLiteral(), element) 2529 else: 2530 if pyxb.GlobalValidationConfig.forDocument: 2531 order = self._validatedChildren() 2532 else: 2533 order = self.__childrenForDOM() 2534 for content in order: 2535 assert content.value != self 2536 if isinstance(content, NonElementContent): 2537 dom_support.appendTextChild(content.value, element) 2538 continue 2539 if content.elementDeclaration is None: 2540 if isinstance(content.value, xml.dom.Node): 2541 dom_support.appendChild(content.value, element) 2542 else: 2543 content.value.toDOM(dom_support, parent) 2544 else: 2545 content.elementDeclaration.toDOM(dom_support, parent, content.value) 2546 mixed_content = self.orderedContent() 2547 for mc in mixed_content: 2548 pass 2549 return getattr(super(complexTypeDefinition, self), '_toDOM_csc', lambda *_args,**_kw: dom_support)(dom_support, parent)
2550 2551 @classmethod
2552 - def _IsSimpleTypeContent (cls):
2553 """CTDs with simple content are simple; other CTDs are not.""" 2554 return cls._CT_SIMPLE == cls._ContentTypeTag
2555 2556 @classmethod
2557 - def _description (cls, name_only=False, user_documentation=True):
2558 name = cls._Name() 2559 if name_only: 2560 return name 2561 desc = [ name ] 2562 if cls._CT_EMPTY == cls._ContentTypeTag: 2563 desc.append(', empty content') 2564 elif cls._CT_SIMPLE == cls._ContentTypeTag: 2565 desc.extend([', simple content type ', cls._TypeDefinition._description(name_only=True)]) 2566 else: 2567 if cls._CT_MIXED == cls._ContentTypeTag: 2568 desc.append(', mixed content') 2569 else: 2570 assert cls._CT_ELEMENT_ONLY == cls._ContentTypeTag 2571 desc.append(', element-only content') 2572 if (0 < len(cls._AttributeMap)) or (cls._AttributeWildcard is not None): 2573 desc.append("\nAttributes:\n ") 2574 desc.append("\n ".join([ _au._description(user_documentation=False) for _au in cls._AttributeMap.values() ])) 2575 if cls._AttributeWildcard is not None: 2576 desc.append("\n Wildcard attribute(s)") 2577 if (0 < len(cls._ElementMap)) or cls._HasWildcardElement: 2578 desc.append("\nElements:\n ") 2579 desc.append("\n ".join([ _eu._description(user_documentation=False) for _eu in cls._ElementMap.values() ])) 2580 if cls._HasWildcardElement: 2581 desc.append("\n Wildcard element(s)") 2582 return ''.join(desc)
2583 2584 ## Local Variables: 2585 ## fill-column:78 2586 ## End: 2587