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

Source Code for Module pyxb.binding.basis

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