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