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

Source Code for Module pyxb.binding.basis

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