Package pyxb :: Package xmlschema :: Module structures
[hide private]
[frames] | no frames]

Source Code for Module pyxb.xmlschema.structures

   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  """Classes corresponding to W3C XML Schema components. 
  17   
  18  Class names and behavior should conform to the schema components described in 
  19  U{XML Schema Part 1: Structures<http://www.w3.org/TR/xmlschema-1/>}. 
  20  References to sections in the documentation of this module generally refers to 
  21  that document. 
  22   
  23  Each class has a C{CreateFromDOM} class method that creates an instance and 
  24  initializes it from a DOM node.  Only the L{Wildcard}, L{Particle}, and 
  25  L{ModelGroup} components are created from non-DOM sources.  However, the 
  26  requirements on DOM interface are restricted to attributes, child nodes, and 
  27  basic fields, though all these must support namespaces. 
  28   
  29  @group Mixins: *_mixin 
  30  @group Ur Type Specializations: *UrType* 
  31  @group Utilities: _PluralityData, _ImportElementInformationItem 
  32   
  33  """ 
  34   
  35  import pyxb 
  36  import pyxb.xmlschema 
  37  from xml.dom import Node 
  38  import types 
  39  import re 
  40  import logging 
  41   
  42  import pyxb.namespace.archive 
  43  import pyxb.namespace.resolution 
  44   
  45  from pyxb.binding import basis 
  46  from pyxb.binding import datatypes 
  47  from pyxb.binding import facets 
  48  from pyxb.utils import domutils 
  49  import pyxb.utils.utility 
  50  import copy 
  51  import urlparse 
  52  import os.path 
  53   
  54  _log = logging.getLogger(__name__) 
  55   
  56  # Flag indicating that the built in types have been registered 
  57  _PastAddBuiltInTypes = False 
  58   
  59  # Make it easier to check node names in the XMLSchema namespace 
  60  from pyxb.namespace import XMLSchema as xsd 
61 62 -class _SchemaComponent_mixin (pyxb.namespace._ComponentDependency_mixin, 63 pyxb.namespace.archive._ArchivableObject_mixin, 64 pyxb.utils.utility.PrivateTransient_mixin, 65 pyxb.utils.utility.Locatable_mixin):
66 """A mix-in that marks the class as representing a schema component. 67 68 This exists so that we can determine the owning schema for any 69 component we encounter. This is normally done at construction 70 time by passing a C{schema=val} parameter to the constructor. 71 """ 72 73 # This class suppports transient instance variables. These variables are 74 # added to the set of transients at the point of declaration in the class. 75 __PrivateTransient = set() 76
77 - def _namespaceContext (self):
78 """The namespace context for this schema. 79 80 This defines where it looks things up, where it puts things it 81 createas, the in-scope namespace declarations, etc. Must be defined 82 for anything that does any sort of QName interpretation. The value is 83 generally a reference to a namespace context associated with the DOM 84 element node corresponding to this component.""" 85 if self.__namespaceContext is None: 86 raise pyxb.LogicError('Attempt to access missing namespace context for %s' % (self,)) 87 return self.__namespaceContext
88 - def _clearNamespaceContext (self):
89 self.__namespaceContext = None 90 return self
91 __namespaceContext = None 92 __PrivateTransient.add('namespaceContext') 93 94 # The name by which this component is known within the binding module. 95 # This is in component rather than _NamedComponent_mixin because some 96 # unnamed components (like ModelGroup and Wildcard) have Python objects to 97 # represent them, so need a binding-level name. 98 __nameInBinding = None 99 100 # The schema component that owns this. If C{None}, the component is owned 101 # directly by the schema. 102 __owner = None 103 __PrivateTransient.add('owner') 104 105 # The schema components owned by this component. 106 __ownedComponents = None 107 __PrivateTransient.add('ownedComponent') 108
109 - def _scope (self):
110 """The context into which declarations in or subordinate to this nodeare placed.""" 111 return self.__scope
112 __scope = None 113
114 - def _scopeIsIndeterminate (self):
115 """Return True iff nobody has defined a scope for this node.""" 116 return _ScopedDeclaration_mixin.ScopeIsIndeterminate(self._scope())
117
118 - def _scopeIsGlobal (self):
119 """Return True iff this component has global scope.""" 120 return _ScopedDeclaration_mixin.ScopeIsGlobal(self._scope())
121
122 - def _setScope (self, ctd):
123 """Set the scope of this instance after construction. 124 125 This should only be invoked on cloned declarations being incorporated 126 into a complex type definition. Note that the source of the clone may 127 be any scope: indeterminate if from a model (attribute) group 128 definition; global if a reference to a global component; or ctd if 129 inherited from a complex base type.""" 130 assert self.__cloneSource is not None 131 assert isinstance(self, _ScopedDeclaration_mixin) 132 assert isinstance(ctd, ComplexTypeDefinition) 133 self.__scope = ctd 134 return self
135
136 - def __init__ (self, *args, **kw):
137 """Initialize portions of a component. 138 139 @keyword scope: The scope in which the component is defined 140 141 @keyword namespace_context: The NamespaceContext to use within this component 142 143 @keyword node: If no C{namespace_context} is provided, a DOM node must 144 be provided from which a namespace context can be identified. 145 146 @keyword owner: Reference to the component that owns this one (the 147 immediately enclosing component). Is C{None} in the case of top-level 148 components. 149 150 @keyword schema: Reference to the L{Schema} component to which the 151 component belongs. Required for every component except L{Schema}, 152 L{Annotation}, and L{Wildcard}. 153 """ 154 155 self.__ownedComponents = set() 156 self.__scope = kw.get('scope') 157 self.__namespaceContext = kw.get('namespace_context') 158 node = kw.get('node') 159 if self.__namespaceContext is None: 160 if node is None: 161 raise pyxb.LogicError('Schema component constructor must be given namespace_context or node') 162 self.__namespaceContext = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(node) 163 if self.__namespaceContext is None: 164 raise pyxb.LogicError('No namespace_context for schema component') 165 166 super(_SchemaComponent_mixin, self).__init__(*args, **kw) 167 168 if isinstance(node, pyxb.utils.utility.Locatable_mixin): 169 self._setLocation(node._location()) 170 171 self._namespaceContext().targetNamespace()._associateComponent(self) 172 173 self._setOwner(kw.get('owner')) 174 175 schema = kw.get('schema') 176 if schema is not None: 177 self._setObjectOrigin(schema.originRecord()) 178 else: 179 assert isinstance(self, (Schema, Annotation, Wildcard)), 'No origin available for type %s' % (type(self),) 180 181 if isinstance(self, ComplexTypeDefinition): 182 assert 1 < len(self.__namespaceContext.inScopeNamespaces())
183 184
185 - def _dissociateFromNamespace (self):
186 """Dissociate this component from its owning namespace. 187 188 This should only be done whwen there are no other references to the 189 component, and you want to ensure it does not appear in the model.""" 190 self._namespaceContext().targetNamespace()._replaceComponent(self, None) 191 return self
192
193 - def _setOwner (self, owner):
194 """Set the owner of this component. 195 196 If C{owner} is C{None}, this has no effect. Otherwise, the 197 component's current owner must be either C{None} or the same as the 198 input C{owner}.""" 199 200 if owner is not None: 201 assert (self.__owner is None) or (self.__owner == owner), 'Owner was %s set to %s' % (self.__owner, owner) 202 self.__owner = owner 203 owner.__ownedComponents.add(self) 204 return self
205
206 - def owner (self):
207 return self.__owner
208 209 # A reference to the instance from which this instance was cloned. 210 __cloneSource = None 211 __PrivateTransient.add('cloneSource') 212
213 - def _cloneSource (self):
214 """The source component from which this is a clone. 215 216 Returns C{None} if this is not a clone.""" 217 return self.__cloneSource
218 219 # A set of references to all instances that are clones of this one. 220 __clones = None 221 __PrivateTransient.add('clones') 222
223 - def _clones (self):
224 """The set of instances cloned from this component. 225 226 Returns None if no instances have been cloned from this.""" 227 return self.__clones
228
229 - def _resetClone_csc (self, **kw):
230 """Virtual method to clear whatever attributes should be reset in a 231 cloned component. 232 233 This instance should be an instance created by copy.copy(). 234 235 The implementation in this class clears the owner and dependency 236 relations. 237 238 Returns C{self}. 239 """ 240 assert self.__cloneSource is not None 241 owner = kw['owner'] 242 self.__nameInBinding = None 243 self.__owner = owner 244 assert not (isinstance(self, ComplexTypeDefinition) and isinstance(owner, Schema)) 245 self.__ownedComponents = set() 246 self.__clones = None 247 owner._namespaceContext().targetNamespace()._associateComponent(self) 248 if self.__namespaceContext is None: 249 # When cloning imported components, loan them the owner's 250 # namespace context, only so that their cloned children can be 251 # associated with the same namespace. 252 self.__namespaceContext = owner._namespaceContext() 253 self_fn = lambda *_args, **_kw: self 254 return getattr(super(_SchemaComponent_mixin, self), '_resetClone_csc', self_fn)(**kw)
255
256 - def _clone (self, owner, origin):
257 """Create a copy of this instance suitable for adoption by some other 258 component. 259 260 This is used for creating a locally-scoped declaration from a 261 declaration in a named model or attribute group.""" 262 263 # We only care about cloning declarations, and they should 264 # have an unassigned scope. However, we do clone 265 # non-declarations that contain cloned declarations. 266 #assert (not isinstance(self, _ScopedDeclaration_mixin)) or self._scopeIsIndeterminate() 267 if isinstance(self, pyxb.namespace.resolution._Resolvable_mixin): 268 assert self.isResolved() 269 270 assert owner is not None 271 that = copy.copy(self) 272 that.__cloneSource = self 273 if self.__clones is None: 274 self.__clones = set() 275 self.__clones.add(that) 276 that._resetClone_csc(owner=owner, origin=origin) 277 if isinstance(that, pyxb.namespace.resolution._Resolvable_mixin): 278 assert that.isResolved() 279 return that
280
281 - def isTypeDefinition (self):
282 """Return True iff this component is a simple or complex type 283 definition.""" 284 return isinstance(self, (SimpleTypeDefinition, ComplexTypeDefinition))
285
286 - def isUrTypeDefinition (self):
287 """Return True iff this component is a simple or complex type 288 definition.""" 289 return isinstance(self, (_SimpleUrTypeDefinition, _UrTypeDefinition))
290
291 - def bestNCName (self):
292 """Return the name of this component, as best it can be determined. 293 294 For example, ModelGroup instances will be named by their 295 ModelGroupDefinition, if available. Returns None if no name can be 296 inferred.""" 297 if isinstance(self, _NamedComponent_mixin): 298 return self.name() 299 if isinstance(self, ModelGroup): 300 agd = self.modelGroupDefinition() 301 if agd is not None: 302 return agd.name() 303 return None
304
305 - def nameInBinding (self):
306 """Return the name by which this component is known in the generated 307 binding. 308 309 @note: To support builtin datatypes, type definitions with an 310 associated L{pythonSupport<SimpleTypeDefinition.pythonSupport>} class 311 initialize their binding name from the class name when the support 312 association is created. As long as no built-in datatype conflicts 313 with a language keyword, this should be fine.""" 314 return self.__nameInBinding
315
316 - def hasBinding (self):
317 """Return C{True} iff this is a component which has a user-visible 318 Python construct which serves as its binding. 319 320 Type definitions have classes as their bindings. Global element 321 declarations have instances of L{pyxb.binding.basis.element} as their 322 bindings.""" 323 return self.isTypeDefinition() or (isinstance(self, ElementDeclaration) and self._scopeIsGlobal())
324
325 - def setNameInBinding (self, name_in_binding):
326 """Set the name by which this component shall be known in the XSD binding.""" 327 self.__nameInBinding = name_in_binding 328 return self
329
330 - def _updateFromOther_csc (self, other):
331 """Override fields in this instance with those from the other. 332 333 Post-extended; description in leaf implementation in 334 ComplexTypeDefinition and SimpleTypeDefinition.""" 335 assert self != other 336 self_fn = lambda *_args, **_kw: self 337 getattr(super(_SchemaComponent_mixin, self), '_updateFromOther_csc', self_fn)(other) 338 # The only thing we update is the binding name, and that only if it's new. 339 if self.__nameInBinding is None: 340 self.__nameInBinding = other.__nameInBinding 341 return self
342
343 -class _Singleton_mixin (pyxb.cscRoot):
344 """This class is a mix-in which guarantees that only one instance 345 of the class will be created. It is used to ensure that the 346 ur-type instances are pointer-equivalent even when unpickling. 347 See ComplexTypeDefinition.UrTypeDefinition()."""
348 - def __new__ (cls, *args, **kw):
349 singleton_property = '_%s__singleton' % (cls.__name__,) 350 if not (singleton_property in cls.__dict__): 351 setattr(cls, singleton_property, super(_Singleton_mixin, cls).__new__(cls, *args, **kw)) 352 return cls.__dict__[singleton_property]
353
354 -class _Annotated_mixin (pyxb.cscRoot):
355 """Mix-in that supports an optional single annotation that describes the component. 356 357 Most schema components have annotations. The ones that don't are 358 L{AttributeUse}, L{Particle}, and L{Annotation}. L{ComplexTypeDefinition} 359 and L{Schema} support multiple annotations, so do not mix-in this 360 class.""" 361 362 # Optional Annotation instance 363 __annotation = None 364
365 - def __init__ (self, *args, **kw):
366 super(_Annotated_mixin, self).__init__(*args, **kw) 367 self.__annotation = kw.get('annotation')
368
369 - def _annotationFromDOM (self, node):
370 cn = domutils.LocateUniqueChild(node, 'annotation') 371 if cn is not None: 372 kw = { } 373 if isinstance(self, _SchemaComponent_mixin): 374 kw['owner'] = self 375 self.__annotation = Annotation.CreateFromDOM(cn, **kw)
376
377 - def _updateFromOther_csc (self, other):
378 """Override fields in this instance with those from the other. 379 380 Post-extended; description in leaf implementation in 381 ComplexTypeDefinition and SimpleTypeDefinition.""" 382 assert self != other 383 self_fn = lambda *_args, **_kw: self 384 getattr(super(_Annotated_mixin, self), '_updateFromOther_csc', self_fn)(other) 385 # @todo: make this a copy? 386 self.__annotation = other.__annotation 387 return self
388
389 - def annotation (self):
390 return self.__annotation
391
392 -class _PickledAnonymousReference (object):
393 """A helper that encapsulates a reference to an anonymous type in a different namespace. 394 395 Normally references to components in other namespaces can be made using 396 the component's name. This is not the case when a namespace derives from 397 a base type in another namespace and needs to reference the attribute or 398 element declarations held in that type. If these declarations are local 399 to the base complex type, they cannot be identified by name. This class 400 provides a pickleable representation for them that behaves rather like an 401 L{pyxb.namespace.ExpandedName} instance in that it can be used to 402 dereference various component types.""" 403 404 __AnonymousCategory = pyxb.namespace.archive.NamespaceArchive._AnonymousCategory() 405 406 __namespace = None 407 __anonymousName = None
408 - def __init__ (self, namespace, anonymous_name):
409 """Create a new anonymous reference. 410 411 @param namespace: The namespace in which the component is declared. 412 @type namespace: L{pyxb.namespace.Namespace} 413 @param anonymous_name: A generated name guaranteed to be unique within 414 the namespace. See L{_NamedComponent_mixin._anonymousName}. 415 @type anonymous_name: C{basestring}. 416 """ 417 self.__namespace = namespace 418 self.__anonymousName = anonymous_name 419 assert self.__anonymousName is not None
420 421 @classmethod
422 - def FromPickled (cls, object_reference):
423 """Return the component referred to by the provided reference, 424 regardless of whether it is a normal or anonymous reference.""" 425 if not isinstance(object_reference, _PickledAnonymousReference): 426 assert isinstance(object_reference, tuple) 427 object_reference = pyxb.namespace.ExpandedName(object_reference) 428 return object_reference
429
430 - def namespace (self):
431 return self.__namespace
432
433 - def anonymousName (self):
434 return self.__anonymousName
435
436 - def validateComponentModel (self):
437 """Forward to the associated namespace.""" 438 return self.__namespace.validateComponentModel()
439
440 - def __lookupObject (self):
442 443 typeDefinition = __lookupObject 444 attributeGroupDefinition = __lookupObject 445 modelGroupDefinition = __lookupObject 446 attributeDeclaration = __lookupObject 447 elementDeclaration = __lookupObject 448 identityConstraintDefinition = __lookupObject 449 notationDeclaration = __lookupObject 450
451 - def __str__ (self):
452 """Represent the anonymous reference in a form recognizable by a developer.""" 453 return 'ANONYMOUS:%s' % (pyxb.namespace.ExpandedName(self.__namespace, self.__anonymousName),)
454
455 -class _NamedComponent_mixin (pyxb.utils.utility.PrivateTransient_mixin, pyxb.cscRoot):
456 """Mix-in to hold the name and targetNamespace of a component. 457 458 The name may be None, indicating an anonymous component. The 459 targetNamespace is never None, though it could be an empty namespace. The 460 name and targetNamespace values are immutable after creation. 461 462 This class overrides the pickling behavior: when pickling a Namespace, 463 objects that do not belong to that namespace are pickled as references, 464 not as values. This ensures the uniqueness of objects when multiple 465 namespace definitions are pre-loaded. 466 467 This class must follow L{_SchemaComponent_mixin} in the MRO. 468 """ 469 470 __PrivateTransient = set() 471
472 - def name (self):
473 """Name of the component within its scope or namespace. 474 475 This is an NCName. The value isNone if the component is 476 anonymous. The attribute is immutable after the component is 477 created creation.""" 478 return self.__name
479 __name = None 480
481 - def isAnonymous (self):
482 """Return true iff this instance is locally scoped (has no name).""" 483 return self.__name is None
484
485 - def _setAnonymousName (self, namespace, unique_id=None, anon_name=None):
486 # If this already has a name, keep using it. 487 if self.__anonymousName is not None: 488 return 489 assert self.__needAnonymousSupport() 490 assert namespace is not None 491 if self.bindingNamespace() is not None: 492 assert self.bindingNamespace() == namespace 493 if self.targetNamespace() is not None: 494 assert self.targetNamespace() == namespace 495 if anon_name is None: 496 anon_name = self.nameInBinding() 497 if anon_name is None: 498 anon_name = self.name() 499 if anon_name is None: 500 anon_name = 'ANON_IN_GROUP' 501 if unique_id is not None: 502 anon_name = '%s_%s' % (anon_name, unique_id) 503 anon_name = pyxb.utils.utility.MakeUnique(anon_name, set(namespace.categoryMap(self.__AnonymousCategory).keys())) 504 self.__anonymousName = anon_name 505 namespace.addCategoryObject(self.__AnonymousCategory, anon_name, self)
506 - def _anonymousName (self, namespace=None):
507 assert self.__anonymousName is not None, '%x %s %s in %s missing anonymous name' % (id(self), type(self), self.name(), self.targetNamespace()) 508 return self.__anonymousName
509 __anonymousName = None 510
511 - def targetNamespace (self):
512 """The targetNamespace of a component. 513 514 This is None, or a reference to a Namespace in which the 515 component is declared (either as a global or local to one of 516 the namespace's complex type definitions). This is immutable 517 after creation. 518 """ 519 return self.__targetNamespace
520 __targetNamespace = None 521
522 - def bindingNamespace (self):
523 """The namespace in which this component's binding is placed.""" 524 return self.__bindingNamespace
525 - def _setBindingNamespace (self, namespace):
527 __bindingNamespace = None 528
529 - def _templateMap (self):
530 """A map from template keys to component-specific values. 531 532 This is used in code generation to maintain unique names for accessor 533 methods, identifiers, keys, and other characteristics associated with 534 the code generated in support of the binding for this component.""" 535 return self.__templateMap
536 __templateMap = None 537 538 __AnonymousCategory = pyxb.namespace.archive.NamespaceArchive._AnonymousCategory() 539
540 - def __needAnonymousSupport (self):
541 # If this component doesn't have a name, or if it's in some scope in 542 # which it cannot be located in a category map, we'll need a unique 543 # name for it. 544 return self.isAnonymous() or (self._scopeIsIndeterminate() and not isinstance(self, (AttributeGroupDefinition, ModelGroupDefinition)))
545
546 - def _schema (self):
547 """Return the schema component from which this component was defined. 548 549 Needed so we can distinguish components that came from different 550 locations, since that imposes an external order dependency on them and 551 on cross-namespace inclusions. 552 553 @note: This characteristic is removed when the component is stored in 554 a namespace archive.""" 555 return self.__schema
556 __schema = None 557 __PrivateTransient.add('schema') 558
559 - def _prepareForArchive_csc (self, module_record):
560 if self.__needAnonymousSupport(): 561 self._setAnonymousName(module_record.namespace(), unique_id=module_record.generationUID()) 562 self_fn = lambda *_args, **_kw: self 563 return getattr(super(_NamedComponent_mixin, self), '_prepareForArchive_csc', self_fn)(module_record)
564
565 - def _picklesInArchive (self, archive):
566 """Return C{True} if this component should be pickled by value in the 567 given namespace. 568 569 When pickling, a declaration component is considered to belong to the 570 namespace if it has a local scope which belongs to the namespace. In 571 that case, the declaration is a clone of something that does not 572 belong to the namespace; but the clone does. 573 574 @see: L{_bindsInNamespace} 575 576 @return: C{False} if the component should be pickled by reference. 577 """ 578 if isinstance(self._scope(), ComplexTypeDefinition): 579 return self._scope()._picklesInArchive(archive) 580 assert not (self.targetNamespace() is None), '%s has no tns, scope %s, location %s, schema %s' % (self, self._scope(), self._location(), self._schema().targetNamespace()) 581 assert not (self._objectOrigin() is None) 582 new_flag = (self._objectOrigin().generationUID() == archive.generationUID()) 583 return new_flag
584
585 - def _bindsInNamespace (self, ns):
586 """Return C{True} if the binding for this component should be 587 generated in the given namespace. 588 589 This is the case when the component is in the given namespace. It's 590 also the case when the component has no associated namespace (but not 591 an absent namespace). Be aware that cross-namespace inheritance means 592 you will get references to elements in another namespace when 593 generating code for a subclass; that's fine, and those references 594 should not be generated locally. 595 """ 596 return self.targetNamespace() in (ns, None)
597
598 - def expandedName (self):
599 """Return the L{pyxb.namespace.ExpandedName} of this object.""" 600 if self.name() is None: 601 return None 602 return pyxb.namespace.ExpandedName(self.targetNamespace(), self.name())
603
604 - def __new__ (cls, *args, **kw):
605 """Pickling support. 606 607 Normally, we just create a new instance of this class. 608 However, if we're unpickling a reference in a loadable schema, 609 we need to return the existing component instance by looking 610 up the name in the component map of the desired namespace. We 611 can tell the difference because no normal constructors that 612 inherit from this have positional arguments; only invocations 613 by unpickling with a value returned in __getnewargs__ do. 614 615 This does require that the dependent namespace already have 616 been validated (or that it be validated here). That shouldn't 617 be a problem, except for the dependency loop resulting from 618 use of xml:lang in the XMLSchema namespace. For that issue, 619 see pyxb.namespace._XMLSchema. 620 """ 621 622 if 0 == len(args): 623 rv = super(_NamedComponent_mixin, cls).__new__(cls) 624 return rv 625 ( object_reference, scope, icls ) = args 626 627 object_reference = _PickledAnonymousReference.FromPickled(object_reference) 628 629 # Explicitly validate here: the lookup operations won't do so, 630 # but will abort if the namespace hasn't been validated yet. 631 object_reference.validateComponentModel() 632 if isinstance(scope, (tuple, _PickledAnonymousReference)): 633 # Scope is the expanded name of the complex type in which the 634 # named value can be located. 635 scope_ref = _PickledAnonymousReference.FromPickled(scope) 636 if object_reference.namespace() != scope_ref.namespace(): 637 scope_ref.validateComponentModel() 638 assert 'typeDefinition' in scope_ref.namespace().categories() 639 scope_ctd = scope_ref.typeDefinition() 640 if scope_ctd is None: 641 raise pyxb.SchemaValidationError('Unable to resolve local scope %s' % (scope_ref,)) 642 if issubclass(icls, AttributeDeclaration): 643 rv = scope_ctd.lookupScopedAttributeDeclaration(object_reference) 644 elif issubclass(icls, ElementDeclaration): 645 rv = scope_ctd.lookupScopedElementDeclaration(object_reference) 646 else: 647 raise pyxb.IncompleteImplementationError('Scope %s reference lookup of %s not implemented for type %s' % (scope_ref, object_reference, icls)) 648 if rv is None: 649 raise pyxb.SchemaValidationError('Unable to resolve %s as %s in scope %s' % (object_reference, icls, scope_ref)) 650 elif _ScopedDeclaration_mixin.ScopeIsGlobal(scope) or _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope): 651 if (issubclass(icls, SimpleTypeDefinition) or issubclass(icls, ComplexTypeDefinition)): 652 rv = object_reference.typeDefinition() 653 elif issubclass(icls, AttributeGroupDefinition): 654 rv = object_reference.attributeGroupDefinition() 655 elif issubclass(icls, ModelGroupDefinition): 656 rv = object_reference.modelGroupDefinition() 657 elif issubclass(icls, AttributeDeclaration): 658 rv = object_reference.attributeDeclaration() 659 elif issubclass(icls, ElementDeclaration): 660 rv = object_reference.elementDeclaration() 661 elif issubclass(icls, IdentityConstraintDefinition): 662 rv = object_reference.identityConstraintDefinition() 663 else: 664 raise pyxb.IncompleteImplementationError('Reference lookup of %s not implemented for type %s' % (object_reference, icls)) 665 if rv is None: 666 raise pyxb.SchemaValidationError('Unable to resolve %s as %s' % (object_reference, icls)) 667 else: 668 raise pyxb.IncompleteImplementationError('Unable to resolve reference %s, scope %s ns %s type %s, class %s' % (object_reference, scope, scope.targetNamespace(), type(scope), icls)) 669 return rv
670
671 - def __init__ (self, *args, **kw):
672 assert 0 == len(args) 673 name = kw.get('name') 674 # Must be None or a valid NCName 675 assert (name is None) or (0 > name.find(':')), 'name %s' % (name,) 676 self.__name = name 677 678 # Target namespace is taken from the context, unless somebody 679 # overrides it (as is done for local declarations if the form is 680 # unqualified). 681 self.__targetNamespace = kw.get('target_namespace', self._namespaceContext().targetNamespace()) 682 self.__bindingNamespace = kw.get('binding_namespace') 683 684 self.__templateMap = {} 685 686 self.__schema = kw.get('schema') 687 assert self._schema() is not None 688 689 # Do parent invocations after we've set the name: they might need it. 690 super(_NamedComponent_mixin, self).__init__(*args, **kw)
691
692 - def isNameEquivalent (self, other):
693 """Return true iff this and the other component share the same name and target namespace. 694 695 Anonymous components are inherently name inequivalent, except to 696 themselves. This relies on equivalence as defined for 697 pyxb.namespace.ExpandedName, for which None is not equivalent to any 698 non-anonymous name.""" 699 # Note that unpickled objects 700 return (self == other) or ((not self.isAnonymous()) and (self.expandedName() == other.expandedName()))
701
702 - def isTypeEquivalent (self, other):
703 """Return True iff this and the other component have matching types. 704 705 It appears that name equivalence is used; two complex type definitions 706 with identical structures are not considered equivalent (at least, per 707 XMLSpy). 708 """ 709 return (type(self) == type(other)) and self.isNameEquivalent(other)
710
711 - def isDerivationConsistent (self, other):
712 """Return True iff this type can serve as a restriction of the other 713 type for the purposes of U{element consistency<http://www.w3.org/TR/xmlschema-1/#cos-element-consistent>}. 714 715 It appears that name equivalence is normally used; two complex type 716 definitions with identical structures are not considered equivalent 717 (at least, per XMLSpy). However, some OpenGIS standards demonstrate 718 that derivation by restriction from the other type is also acceptable. 719 That opens a whole can of worms; see 720 L{ElementDeclaration.isAdaptable}. 721 """ 722 this = self 723 # can this succeed if component types are not equivalent? 724 while this is not None: 725 if this.isTypeEquivalent(other): 726 return True 727 if not (this.isResolved() and other.isResolved()): 728 raise pyxb.IncompleteImplementationError('Oh fudge. Somebody violated the assumptions in ElementDeclaration.isAdaptable.') 729 if isinstance(self, ComplexTypeDefinition): 730 if self.DM_restriction != this.derivationMethod(): 731 return False 732 elif isinstance(self, SimpleTypeDefinition): 733 if self._DA_restriction != this._derivationAlternative(): 734 return False 735 else: 736 raise pyxb.IncompleteImplementationError('Need derivation consistency check for type %s' % (type(this),)) 737 this = this.baseTypeDefinition() 738 if this.isUrTypeDefinition(): 739 # Well, this certainly can't be a valid restriction of 740 # anything else. 741 break 742 return False
743
744 - def _picklingReference (self):
745 if self.__needAnonymousSupport(): 746 assert self._anonymousName() is not None 747 return _PickledAnonymousReference(self.targetNamespace(), self._anonymousName()) 748 return self.expandedName().uriTuple()
749
750 - def __pickleAsReference (self):
751 if self.targetNamespace() is None: 752 return False 753 # Get the namespace we're pickling. If the namespace is None, 754 # we're not pickling; we're probably cloning, and in that case 755 # we don't want to use the reference state encoding. 756 pickling_archive = pyxb.namespace.archive.NamespaceArchive.PicklingArchive() 757 if pickling_archive is None: 758 return False 759 # If this thing is scoped in a complex type that belongs to the 760 # namespace being pickled, then it gets pickled as an object even if 761 # its target namespace isn't this one. 762 assert self._objectOrigin() is not None 763 if self._picklesInArchive(pickling_archive): 764 return False 765 # Note that anonymous objects must use their fallback 766 return True
767
768 - def __getstate__ (self):
769 if self.__pickleAsReference(): 770 # NB: This instance may be a scoped declaration, but in 771 # this case (unlike getnewargs) we don't care about trying 772 # to look up a previous instance, so we don't need to 773 # encode the scope in the reference tuple. 774 return self._picklingReference() 775 if self.targetNamespace() is None: 776 # The only internal named objects that should exist are 777 # ones that have a non-global scope (including those with 778 # absent scope). 779 # @todo: this is wrong for schema that are not bound to a 780 # namespace, unless we use an unbound Namespace instance 781 #assert isinstance(self, _ScopedDeclaration_mixin) 782 #assert self.SCOPE_global != self.scope() 783 # NOTE: The name of the scope may be None. This is not a 784 # problem unless somebody tries to extend or restrict the 785 # scope type, which at the moment I'm thinking is 786 # impossible for anonymous types. If it isn't, we're 787 # gonna need some other sort of ID, like a UUID associated 788 # with the anonymous class at the time it's written to the 789 # preprocessed schema file. 790 pass 791 return super(_NamedComponent_mixin, self).__getstate__()
792
793 - def __getnewargs__ (self):
794 """Pickling support. 795 796 If this instance is being pickled as a reference, provide the 797 arguments that are necessary so that the unpickler can locate 798 the appropriate component rather than create a duplicate 799 instance.""" 800 801 if self.__pickleAsReference(): 802 scope = self._scope() 803 if isinstance(self, _ScopedDeclaration_mixin): 804 # If scope is global, we can look it up in the namespace. 805 # If scope is indeterminate, this must be within a group in 806 # another namespace. Why are we serializing it? 807 # If scope is local, provide the namespace and name of 808 # the type that holds it 809 if self.SCOPE_global == self.scope(): 810 pass 811 elif isinstance(self.scope(), ComplexTypeDefinition): 812 scope = self.scope()._picklingReference() 813 assert isinstance(scope, (tuple, _PickledAnonymousReference)), self 814 elif self._scopeIsIndeterminate(): 815 # This is actually OK: we made sure both the scope and 816 # this instance can be looked up by a unique identifier. 817 pass 818 else: 819 raise pyxb.IncompleteImplementationError('pickling unrecognized scope %s type %s' % (self.scope(), type(self.scope()))) 820 else: 821 assert isinstance(self, _NamedComponent_mixin), 'Pickling unnamed component %s in indeterminate scope by reference' % (self,) 822 assert not isinstance(scope, ComplexTypeDefinition), '%s %s %s %s' % (self, self.name(), scope, self._objectOrigin()) 823 824 rv = ( self._picklingReference(), scope, self.__class__ ) 825 return rv 826 return ()
827
828 - def __setstate__ (self, state):
829 if isinstance(state, tuple): 830 # We don't actually have to set any state here; we just 831 # make sure that we resolved to an already-configured 832 # instance. 833 assert self.targetNamespace() is not None 834 assert self.targetNamespace().uri() == state[0] 835 assert self.name() == state[1] 836 return 837 if isinstance(state, _PickledAnonymousReference): 838 assert self.targetNamespace() is not None 839 assert self.targetNamespace() == state.namespace() 840 assert self.__needAnonymousSupport() 841 assert self._anonymousName() == state.anonymousName() 842 return 843 self.__dict__.update(state)
844
845 - def _resetClone_csc (self, **kw):
846 self.__schema = None 847 self_fn = lambda *_args, **_kw: self 848 rv = getattr(super(_NamedComponent_mixin, self), '_resetClone_csc', self_fn)(**kw) 849 self.__templateMap = { } 850 origin = kw.get('origin') 851 self.__anonymousName = None 852 self._setObjectOrigin(origin, override=True) 853 return rv
854
855 -class _ValueConstraint_mixin (pyxb.cscRoot):
856 """Mix-in indicating that the component contains a simple-type 857 value that may be constrained.""" 858 859 VC_na = 0 #<<< No value constraint applies 860 VC_default = 1 #<<< Provided value constraint is default value 861 VC_fixed = 2 #<<< Provided value constraint is fixed value 862 863 # None, or a tuple containing a string followed by one of the VC_* 864 # values above. 865 __valueConstraint = None
866 - def valueConstraint (self):
867 """A constraint on the value of the attribute or element. 868 869 Either None, or a pair consisting of a string in the lexical 870 space of the typeDefinition and one of VC_default and 871 VC_fixed.""" 872 return self.__valueConstraint
873
874 - def default (self):
875 """If this instance constraints a default value, return that 876 value; otherwise return None.""" 877 if not isinstance(self.__valueConstraint, tuple): 878 return None 879 if self.VC_default != self.__valueConstraint[1]: 880 return None 881 return self.__valueConstraint[0]
882
883 - def fixed (self):
884 """If this instance constraints a fixed value, return that 885 value; otherwise return None.""" 886 if not isinstance(self.__valueConstraint, tuple): 887 return None 888 if self.VC_fixed != self.__valueConstraint[1]: 889 return None 890 return self.__valueConstraint[0]
891
892 - def _valueConstraintFromDOM (self, node):
893 aval = domutils.NodeAttribute(node, 'default') 894 if aval is not None: 895 self.__valueConstraint = (aval, self.VC_default) 896 return self 897 aval = domutils.NodeAttribute(node, 'fixed') 898 if aval is not None: 899 self.__valueConstraint = (aval, self.VC_fixed) 900 return self 901 self.__valueConstraint = None 902 return self
903
904 -class _ScopedDeclaration_mixin (pyxb.cscRoot):
905 """Mix-in class for named components that have a scope. 906 907 Scope is important when doing cross-namespace inheritance, 908 e.g. extending or restricting a complex type definition that is 909 from a different namespace. In this case, we will need to retain 910 a reference to the external component when the schema is 911 serialized. 912 913 This is done in the pickling process by including the scope when 914 pickling a component as a reference. The scope is the 915 SCOPE_global if global; otherwise, it is a tuple containing the 916 external namespace URI and the NCName of the complex type 917 definition in that namespace. We assume that the complex type 918 definition has global scope; otherwise, it should not have been 919 possible to extend or restrict it. (Should this be untrue, there 920 are comments in the code about a possible solution.) 921 922 @warning: This mix-in must follow L{_NamedComponent_mixin} in the C{mro}. 923 """ 924 925 SCOPE_global = 'global' #<<< Marker to indicate global scope 926 XSCOPE_indeterminate = 'indeterminate' #<<< Marker to indicate scope has not been assigned 927 928 @classmethod
929 - def IsValidScope (cls, value):
930 return (cls.SCOPE_global == value) or isinstance(value, ComplexTypeDefinition)
931 932 @classmethod
933 - def ScopeIsIndeterminate (cls, value):
934 return (cls.XSCOPE_indeterminate == value)
935 936 @classmethod
937 - def ScopeIsGlobal (cls, value):
938 return (cls.SCOPE_global == value)
939
940 - def _scopeIsCompatible (self, scope):
941 """Return True if this scope currently assigned to this instance is compatible with the given scope. 942 943 If either scope is indeterminate, presume they will ultimately be 944 compatible. Scopes that are equal are compatible, as is a local scope 945 if this already has a global scope.""" 946 if self.ScopeIsIndeterminate(scope) or self.ScopeIsIndeterminate(self.scope()): 947 return True 948 if self.scope() == scope: 949 return True 950 return (self.SCOPE_global == self.scope()) and isinstance(scope, ComplexTypeDefinition)
951 952 # The scope for the element. Valid values are SCOPE_global or a 953 # complex type definition. None is an invalid value, but may 954 # appear if scope is determined by an ancestor component.
955 - def scope (self):
956 """The scope for the declaration. 957 958 Valid values are SCOPE_global, or a complex type definition. 959 A value of None means a non-global declaration that is not 960 owned by a complex type definition. These can only appear in 961 attribute group definitions or model group definitions. 962 963 @todo: For declarations in named model groups (viz., local 964 elements that aren't references), the scope needs to be set by 965 the owning complex type. 966 """ 967 return self._scope()
968 969 # The base declaration is the original _ScopedDeclaration_mixin which 970 # introduced the element into its scope. This is used to retain a 971 # particular defining declaration when each extension type gets its own 972 # clone adapted for its scope. 973 __baseDeclaration = None
974 - def baseDeclaration (self):
975 return self.__baseDeclaration or self
976 - def _baseDeclaration (self, referenced_declaration):
977 self.__baseDeclaration = referenced_declaration.baseDeclaration() 978 return self.__baseDeclaration
979
980 -class _PluralityData (types.ListType):
981 """This class represents an abstraction of the set of documents conformant 982 to a particle or particle term. 983 984 The abstraction of a given document is a map from element declarations 985 that can appear at the top level of the document to a boolean that is true 986 iff there could be multiple instances of that element declaration at the 987 top level of a valid document. The abstraction of the set is a list of 988 document abstractions. 989 990 This information is used in binding generation to determine whether a 991 field associated with a tag might need to hold multiple instances. 992 """ 993 994 @classmethod
995 - def _MapUnion (cls, map1, map2):
996 """Given two maps, return an updated map indicating the unified 997 plurality.""" 998 umap = { } 999 for k in set(map1.keys()).union(map2.keys()): 1000 if k in map1: 1001 umap[k] = (k in map2) or map1[k] 1002 else: 1003 umap[k] = map2[k] 1004 return umap
1005
1006 - def combinedPlurality (self):
1007 """Combine all the document abstractions into a single one that covers 1008 all possible documents. 1009 1010 The combined plurality is simply the elemental maximum over all 1011 document abstractions. 1012 """ 1013 1014 combined_plurality = { } 1015 for pdm in self: 1016 for (ed, v) in pdm.items(): 1017 if isinstance(ed, ElementDeclaration): 1018 assert ed.baseDeclaration() == ed 1019 combined_plurality[ed] = combined_plurality.get(ed, False) or v 1020 elif isinstance(ed, Wildcard): 1021 pass 1022 else: 1023 raise pyxb.LogicError('Unexpected plurality index %s' % (ed,)) 1024 return combined_plurality
1025
1026 - def __fromModelGroup (self, model_group):
1027 # Start by collecting the data for each of the particles. 1028 pdll = [ _PluralityData(_p) for _p in model_group.particles() ] 1029 #dumpmap = lambda _pdm: ', '.join( [ '%s: %s' % (_ed.expandedName(), _pl) for (_ed, _pl) in _pdm.items() ]) 1030 #dumpmapset = lambda _pd: '(' + ') | ('.join([ dumpmap(_pdm) for _pdm in _pd ]) + ')' 1031 if (ModelGroup.C_CHOICE == model_group.compositor()): 1032 # Plurality for choice is simply any of the pluralities of the particles 1033 [ self.extend(_pd) for _pd in pdll ] 1034 elif ((ModelGroup.C_SEQUENCE == model_group.compositor()) or (ModelGroup.C_ALL == model_group.compositor())): 1035 # Sequence means all of them, in all their glory. All is treated 1036 # the same way. Essentially this is a pointwise OR of the 1037 # pluralities of the particles. 1038 if 0 < len(pdll): 1039 new_pd = pdll.pop() 1040 for pd in pdll: 1041 assert 0 < len(pd) 1042 assert 0 < len(new_pd) 1043 stage_pd = [ ] 1044 for pdm1 in new_pd: 1045 for pdm2 in pd: 1046 stage_pd.append(self._MapUnion(pdm1, pdm2)) 1047 new_pd = stage_pd 1048 self.extend(new_pd) 1049 else: 1050 raise pyxb.LogicError('Unrecognized compositor value %s' % (model_group.compositor(),))
1051
1052 - def __fromParticle (self, particle):
1053 assert particle.isResolved() 1054 pd = particle.term().pluralityData() 1055 1056 # If the particle can't appear at all, there are no results. 1057 if 0 == particle.maxOccurs(): 1058 return 1059 1060 # If the particle can only occur once, it has no effect on the 1061 # pluralities; use the term to identify them 1062 if 1 == particle.maxOccurs(): 1063 self.__setFromComponent(particle.term()) 1064 return 1065 1066 # If there are multiple alternatives, assume they are all 1067 # taken. Do this by creating a map that treats every possible 1068 # element as appearing multiple times. 1069 true_map = {} 1070 pd = _PluralityData(particle.term()) 1071 while 0 < len(pd): 1072 pdm = pd.pop() 1073 [ true_map.setdefault(_k, True) for _k in pdm.keys() ] 1074 self.append(true_map)
1075
1076 - def __setFromComponent (self, component=None):
1077 del self[:] 1078 if isinstance(component, ElementDeclaration): 1079 assert component.isResolved() 1080 assert isinstance(component.baseDeclaration(), ElementDeclaration) 1081 self.append( { component.baseDeclaration(): False } ) 1082 #self.append( { component: False } ) 1083 elif isinstance(component, ModelGroup): 1084 self.__fromModelGroup(component) 1085 elif isinstance(component, Particle): 1086 self.__fromParticle(component) 1087 elif isinstance(component, Wildcard): 1088 pass 1089 elif component is not None: 1090 raise pyxb.IncompleteImplementationError("No support for plurality of component type %s" % (type(component),)) 1091 # Elements get lost if there's a result set that doesn't have any 1092 # documents in it. 1093 if 0 == len(self): 1094 self.append({})
1095
1096 - def __init__ (self, component=None):
1097 super(_PluralityData, self).__init__() 1098 self.__setFromComponent(component)
1099
1100 -class _AttributeWildcard_mixin (pyxb.cscRoot):
1101 """Support for components that accept attribute wildcards. 1102 1103 That is L{AttributeGroupDefinition} and L{ComplexTypeDefinition}. The 1104 calculations of the appropriate wildcard are sufficiently complex that 1105 they need to be abstracted out to a mix-in class.""" 1106 1107 # Optional wildcard that constrains attributes 1108 __attributeWildcard = None 1109
1110 - def attributeWildcard (self):
1111 """Return the L{Wildcard} component associated with attributes of this 1112 instance, or C{None} if attribute wildcards are not present in the 1113 instance.""" 1114 return self.__attributeWildcard
1115
1116 - def _setAttributeWildcard (self, attribute_wildcard):
1117 """Set the attribute wildcard property for this instance.""" 1118 assert (attribute_wildcard is None) or isinstance(attribute_wildcard, Wildcard) 1119 self.__attributeWildcard = attribute_wildcard 1120 return self
1121
1122 - def _attributeRelevantChildren (self, node_list):
1123 """Return the nodes that are relevant for attribute processing. 1124 1125 @param node_list: A sequence of nodes found in a definition content 1126 information item. 1127 1128 @return: A tuple C{( attributes, attributeGroups, attributeWildcard)} 1129 where C{attributes} is the subsequence of C{node_list} that are 1130 XMLSchema C{attribute} nodes; C{attributeGroups} is analogous; and 1131 C{attributeWildcard} is a single DOM node with XMLSchema name 1132 C{anyAttribute} (or C{None}, if no such node is present in the list). 1133 1134 @raise pyxb.SchemaValidationError: An C{attributeGroup} node is 1135 present but does not have the required C{ref} attribute. 1136 @raise pyxb.SchemaValidationError: Multiple C{anyAttribute} nodes are 1137 identified. 1138 """ 1139 1140 attributes = [] 1141 attribute_groups = [] 1142 any_attribute = None 1143 # Handle clauses 1 and 2 (common between simple and complex types) 1144 for node in node_list: 1145 if Node.ELEMENT_NODE != node.nodeType: 1146 continue 1147 if xsd.nodeIsNamed(node, 'attribute'): 1148 # Note: This attribute use instance may have use=prohibited 1149 attributes.append(node) 1150 elif xsd.nodeIsNamed(node, 'attributeGroup'): 1151 # This must be an attributeGroupRef 1152 agd_attr = domutils.NodeAttribute(node, 'ref') 1153 if agd_attr is None: 1154 raise pyxb.SchemaValidationError('Require ref attribute on internal attributeGroup elements') 1155 attribute_groups.append(agd_attr) 1156 elif xsd.nodeIsNamed(node, 'anyAttribute'): 1157 if any_attribute is not None: 1158 raise pyxb.SchemaValidationError('Multiple anyAttribute children are not allowed') 1159 any_attribute = node 1160 1161 return (attributes, attribute_groups, any_attribute)
1162 1163 @classmethod
1164 - def CompleteWildcard (cls, namespace_context, attribute_groups, local_wildcard):
1165 """Implement the algorithm as described the 1166 U{specification<http://www.w3.org/TR/xmlschema-1/#declare-type>}. 1167 1168 @param namespace_context: The L{pyxb.namespace.NamespaceContext} to be 1169 associated with any created L{Wildcard} instance 1170 @param attribute_groups: A list of L{AttributeGroupDefinition} instances 1171 @param local_wildcard: A L{Wildcard} instance computed from a relevant 1172 XMLSchema C{anyAttribute} element, or C{None} if no attribute wildcard 1173 is relevant 1174 """ 1175 1176 # Non-absent wildcard properties of attribute groups 1177 agd_wildcards = [] 1178 for agd in attribute_groups: 1179 assert isinstance(agd, AttributeGroupDefinition) 1180 if agd.attributeWildcard() is not None: 1181 agd_wildcards.append(agd.attributeWildcard()) 1182 agd_constraints = [ _agd.namespaceConstraint() for _agd in agd_wildcards ] 1183 1184 # Clause 2.1 1185 if 0 == len(agd_wildcards): 1186 return local_wildcard 1187 1188 if local_wildcard is not None: 1189 # Clause 2.2.1 1190 return Wildcard(process_contents=local_wildcard.processContents(), 1191 namespace_constraint=Wildcard.IntensionalIntersection(agd_constraints + [local_wildcard.namespaecConstraint()]), 1192 annotation=local_wildcard.annotation(), 1193 namespace_context=namespace_context) 1194 # Clause 2.2.2 1195 return Wildcard(process_contents=agd_wildcards[0].processContents(), 1196 namespace_constraint=Wildcard.IntensionalIntersection(agd_constraints), 1197 namespace_context=namespace_context)
1198
1199 -class AttributeDeclaration (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _ValueConstraint_mixin, _ScopedDeclaration_mixin):
1200 """An XMLSchema U{Attribute Declaration<http://www.w3.org/TR/xmlschema-1/#cAttribute_Declarations>} component. 1201 """ 1202 1203 # The STD to which attribute values must conform 1204 __typeDefinition = None
1205 - def typeDefinition (self):
1206 """The simple type definition to which an attribute value must 1207 conform.""" 1208 return self.__typeDefinition
1209 1210 # The string value of the XSD type attribute 1211 __typeAttribute = None 1212
1213 - def __init__ (self, *args, **kw):
1214 super(AttributeDeclaration, self).__init__(*args, **kw) 1215 assert 'scope' in kw
1216
1217 - def __str__ (self):
1218 if self.typeDefinition(): 1219 return 'AD[%s:%s]' % (self.name(), self.typeDefinition().expandedName()) 1220 return 'AD[%s:?]' % (self.expandedName(),)
1221 1222 @classmethod
1223 - def CreateBaseInstance (cls, name, schema, std=None):
1224 """Create an attribute declaration component for a specified namespace.""" 1225 kw = { 'name' : name, 1226 'schema' : schema, 1227 'namespace_context' : schema.targetNamespace().initialNamespaceContext(), 1228 'scope' : _ScopedDeclaration_mixin.SCOPE_global } 1229 assert schema is not None 1230 bi = cls(**kw) 1231 if std is not None: 1232 bi.__typeDefinition = std 1233 bi.__typeAttribute = None 1234 return bi
1235 1236 # CFD:AD CFD:AttributeDeclaration 1237 @classmethod
1238 - def CreateFromDOM (cls, node, **kw):
1239 """Create an attribute declaration from the given DOM node. 1240 1241 wxs is a Schema instance within which the attribute is being 1242 declared. 1243 1244 node is a DOM element. The name must be one of ( 'all', 1245 'choice', 'sequence' ), and the node must be in the XMLSchema 1246 namespace. 1247 1248 scope is the _ScopeDeclaration_mxin context into which the 1249 attribute declaration is placed. It can be SCOPE_global, a 1250 complex type definition, or XSCOPE_indeterminate if this is an 1251 anonymous declaration within an attribute group. It is a 1252 required parameter for this function. 1253 """ 1254 1255 scope = kw['scope'] 1256 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or _ScopedDeclaration_mixin.IsValidScope(scope) 1257 1258 # Node should be an XMLSchema attribute node 1259 assert xsd.nodeIsNamed(node, 'attribute') 1260 1261 name = domutils.NodeAttribute(node, 'name') 1262 1263 # Implement per section 3.2.2 1264 if xsd.nodeIsNamed(node.parentNode, 'schema'): 1265 assert cls.SCOPE_global == scope 1266 elif domutils.NodeAttribute(node, 'ref') is None: 1267 # This is an anonymous declaration within an attribute use 1268 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition) 1269 else: 1270 raise pyxb.SchemaValidationError('Internal attribute declaration by reference') 1271 1272 rv = cls(name=name, node=node, **kw) 1273 rv._annotationFromDOM(node) 1274 rv._valueConstraintFromDOM(node) 1275 1276 rv.__typeAttribute = domutils.NodeAttribute(node, 'type') 1277 1278 kw.pop('node', None) 1279 kw['owner'] = rv 1280 1281 st_node = domutils.LocateUniqueChild(node, 'simpleType') 1282 if st_node is not None: 1283 rv.__typeDefinition = SimpleTypeDefinition.CreateFromDOM(st_node, **kw) 1284 elif rv.__typeAttribute is None: 1285 rv.__typeDefinition = SimpleTypeDefinition.SimpleUrTypeDefinition() 1286 1287 if rv.__typeDefinition is None: 1288 rv._queueForResolution('creation') 1289 return rv
1290
1291 - def isResolved (self):
1292 return self.__typeDefinition is not None
1293 1294 # res:AD res:AttributeDeclaration
1295 - def _resolve (self):
1296 if self.isResolved(): 1297 return self 1298 1299 # Although the type definition may not be resolved, *this* component 1300 # is resolved, since we don't look into the type definition for anything. 1301 assert self.__typeAttribute is not None, 'AD %s is unresolved but has no typeAttribute field' % (self.expandedName(),) 1302 type_en = self._namespaceContext().interpretQName(self.__typeAttribute) 1303 self.__typeDefinition = type_en.typeDefinition() 1304 if self.__typeDefinition is None: 1305 raise pyxb.SchemaValidationError('Type reference %s cannot be found' % (type_en,)) 1306 if not isinstance(self.__typeDefinition, SimpleTypeDefinition): 1307 raise pyxb.SchemaValidationError('Need %s to be a simple type' % (type_en,)) 1308 1309 return self
1310
1311 - def _updateFromOther_csc (self, other):
1312 """Override fields in this instance with those from the other. 1313 1314 This method is invoked only by Schema._addNamedComponent, and 1315 then only when a built-in type collides with a schema-defined 1316 type. Material like facets is not (currently) held in the 1317 built-in copy, so the DOM information is copied over to the 1318 built-in STD, which is subsequently re-resolved. 1319 1320 Returns self. 1321 """ 1322 assert self != other 1323 assert self.name() is not None 1324 assert self.isNameEquivalent(other) 1325 super(AttributeDeclaration, self)._updateFromOther_csc(other) 1326 1327 # The other STD should be an unresolved schema-defined type. 1328 # Mark this instance as unresolved so it is re-examined 1329 if not other.isResolved(): 1330 if pyxb.namespace.BuiltInObjectUID == self._objectOrigin().generationUID(): 1331 #assert self.isResolved(), 'Built-in %s is not resolved' % (self.expandedName(),) 1332 _log.warning('Not destroying builtin %s: %s', self.expandedName(), self.__typeDefinition) 1333 else: 1334 self.__typeDefinition = None 1335 return self
1336 1337 # bR:AD
1338 - def _bindingRequires_vx (self, include_lax):
1339 """Attribute declarations require their type.""" 1340 return frozenset([ self.__typeDefinition ])
1341
1342 -class AttributeUse (_SchemaComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _ValueConstraint_mixin):
1343 """An XMLSchema U{Attribute Use<http://www.w3.org/TR/xmlschema-1/#cAttribute_Use>} component.""" 1344 1345 # How this attribute can be used. The component property 1346 # "required" is true iff the value is USE_required. 1347 __use = None 1348 1349 USE_required = 0x01 #<<< The attribute is required 1350 USE_optional = 0x02 #<<< The attribute may or may not appear 1351 USE_prohibited = 0x04 #<<< The attribute must not appear 1352
1353 - def required (self):
1354 return self.USE_required == self.__use
1355
1356 - def prohibited (self):
1357 return self.USE_prohibited == self.__use
1358 1359 # The string value of the XSD ref attribute 1360 __refAttribute = None 1361 1362 __restrictionOf = None
1363 - def restrictionOf (self):
1364 return self.__restrictionOf
1365 - def _setRestrictionOf (self, au):
1366 assert isinstance(au, AttributeUse) 1367 # Might re-assign if had to suspend resolution 1368 assert (self.__restrictionOf is None) or (self.__restrictionOf == au) 1369 self.__restrictionOf = au
1370 1371 # A reference to an AttributeDeclaration
1372 - def attributeDeclaration (self):
1373 """The attribute declaration for this use. 1374 1375 When the use scope is assigned, the declaration is cloned (if 1376 necessary) so that each declaration corresponds to only one use. We 1377 rely on this in code generation, because the template map for the use 1378 is stored in its declaration.""" 1379 return self.__attributeDeclaration
1380 __attributeDeclaration = None 1381 1382 # Define so superclasses can take keywords
1383 - def __init__ (self, **kw):
1384 super(AttributeUse, self).__init__(**kw)
1385
1386 - def matchingQNameMembers (self, au_set):
1387 """Return the subset of au_set for which the use names match this use.""" 1388 1389 if not self.isResolved(): 1390 return None 1391 this_ad = self.attributeDeclaration() 1392 rv = set() 1393 for au in au_set: 1394 if not au.isResolved(): 1395 return None 1396 that_ad = au.attributeDeclaration() 1397 if this_ad.isNameEquivalent(that_ad): 1398 rv.add(au) 1399 return rv
1400 1401 @classmethod
1402 - def CreateBaseInstance (cls, schema, attribute_declaration, use=USE_optional):
1403 kw = { 'schema' : schema, 1404 'namespace_context' : schema.targetNamespace().initialNamespaceContext() } 1405 bi = cls(**kw) 1406 assert isinstance(attribute_declaration, AttributeDeclaration) 1407 bi.__attributeDeclaration = attribute_declaration 1408 bi.__use = use 1409 return bi
1410 1411 # CFD:AU CFD:AttributeUse 1412 @classmethod
1413 - def CreateFromDOM (cls, node, **kw):
1414 """Create an Attribute Use from the given DOM node. 1415 1416 wxs is a Schema instance within which the attribute use is 1417 being defined. 1418 1419 node is a DOM element. The name must be 'attribute', and the 1420 node must be in the XMLSchema namespace. 1421 1422 scope is the _ScopeDeclaration_mixin context into which any 1423 required anonymous attribute declaration is put. This must be 1424 a complex type definition, or None if this use is in an 1425 attribute group. 1426 """ 1427 1428 scope = kw['scope'] 1429 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition) 1430 assert xsd.nodeIsNamed(node, 'attribute') 1431 schema = kw['schema'] 1432 rv = cls(node=node, **kw) 1433 1434 rv.__use = cls.USE_optional 1435 use = domutils.NodeAttribute(node, 'use') 1436 if use is not None: 1437 if 'required' == use: 1438 rv.__use = cls.USE_required 1439 elif 'optional' == use: 1440 rv.__use = cls.USE_optional 1441 elif 'prohibited' == use: 1442 rv.__use = cls.USE_prohibited 1443 else: 1444 raise pyxb.SchemaValidationError('Unexpected value %s for attribute use attribute' % (use,)) 1445 1446 rv._valueConstraintFromDOM(node) 1447 1448 rv.__refAttribute = domutils.NodeAttribute(node, 'ref') 1449 if rv.__refAttribute is None: 1450 # Create an anonymous declaration 1451 kw.pop('node', None) 1452 kw['owner'] = rv 1453 kw['target_namespace'] = schema.targetNamespaceForNode(node, AttributeDeclaration) 1454 rv.__attributeDeclaration = AttributeDeclaration.CreateFromDOM(node, **kw) 1455 1456 if not rv.isResolved(): 1457 rv._queueForResolution('creation') 1458 1459 return rv
1460
1461 - def isResolved (self):
1462 return self.__attributeDeclaration is not None
1463
1464 - def _resolve (self):
1465 if self.isResolved(): 1466 return self 1467 ad_en = self._namespaceContext().interpretQName(self.__refAttribute) 1468 self.__attributeDeclaration = ad_en.attributeDeclaration() 1469 if self.__attributeDeclaration is None: 1470 raise pyxb.SchemaValidationError('Attribute declaration %s cannot be found' % (ad_en,)) 1471 1472 assert isinstance(self.__attributeDeclaration, AttributeDeclaration) 1473 1474 return self
1475 1476 # bR:AU
1477 - def _bindingRequires_vx (self, include_lax):
1478 """Attribute uses require their declarations, but only if lax.""" 1479 if not include_lax: 1480 return frozenset() 1481 return frozenset([ self.attributeDeclaration() ])
1482 1483 # aFS:AU
1484 - def _adaptForScope (self, ctd):
1485 """Adapt this instance for the given complex type. 1486 1487 If the attribute declaration for this use is not associated with a 1488 complex type definition, then associate a clone of it with this CTD, 1489 and clone a new attribute use that uses the associated declaration. 1490 This attribute use is then inherited by extensions and restrictions, 1491 while retaining its original scope.""" 1492 rv = self 1493 assert self.isResolved() 1494 ad = self.__attributeDeclaration 1495 assert ad.scope() is not None 1496 assert isinstance(ctd, ComplexTypeDefinition) 1497 if not isinstance(ad.scope(), ComplexTypeDefinition): 1498 rv = self._clone(ctd, ctd._objectOrigin()) 1499 rv.__attributeDeclaration = ad._clone(rv, ctd._objectOrigin()) 1500 rv.__attributeDeclaration._setScope(ctd) 1501 ctd._recordLocalDeclaration(rv.__attributeDeclaration) 1502 return rv
1503
1504 - def __str__ (self):
1505 return 'AU[%s]' % (self.attributeDeclaration(),)
1506
1507 1508 -class ElementDeclaration (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _ValueConstraint_mixin, _ScopedDeclaration_mixin):
1509 """An XMLSchema U{Element Declaration<http://www.w3.org/TR/xmlschema-1/#cElement_Declarations>} component.""" 1510 1511 # Simple or complex type definition 1512 __typeDefinition = None
1513 - def typeDefinition (self):
1514 """The simple or complex type to which the element value conforms.""" 1515 return self.__typeDefinition
1516 - def _typeDefinition (self, type_definition):
1517 self.__typeDefinition = type_definition 1518 return self
1519 1520 __substitutionGroupAttribute = None 1521 1522 __typeAttribute = None 1523 1524 __nillable = False
1525 - def nillable (self):
1526 return self.__nillable
1527 1528 __identityConstraintDefinitions = None
1530 """A list of IdentityConstraintDefinition instances.""" 1531 return self.__identityConstraintDefinitions
1532 1533 __substitutionGroupAffiliation = None
1535 """None, or a reference to an ElementDeclaration.""" 1536 return self.__substitutionGroupAffiliation
1537 1538 SGE_none = 0 #<<< No substitution group exclusion specified 1539 SGE_extension = 0x01 #<<< Substitution by an extension of the base type 1540 SGE_restriction = 0x02 #<<< Substitution by a restriction of the base type 1541 SGE_substitution = 0x04 #<<< Substitution by replacement (?) 1542 1543 _SGE_Map = { 'extension' : SGE_extension 1544 , 'restriction' : SGE_restriction } 1545 _DS_Map = _SGE_Map.copy() 1546 _DS_Map.update( { 'substitution' : SGE_substitution } ) 1547 1548 # Subset of SGE marks formed by bitmask. SGE_substitution is disallowed. 1549 __substitutionGroupExclusions = SGE_none 1550 1551 # Subset of SGE marks formed by bitmask 1552 __disallowedSubstitutions = SGE_none 1553 1554 __abstract = False
1555 - def abstract (self):
1556 return self.__abstract
1557
1558 - def pluralityData (self):
1559 """Return the plurality information for this component. 1560 1561 An ElementDeclaration produces one instance of a single element.""" 1562 return _PluralityData(self)
1563
1564 - def hasWildcardElement (self):
1565 """Return False, since element declarations are not wildcards.""" 1566 return False
1567 1568 # bR:ED
1569 - def _bindingRequires_vx (self, include_lax):
1570 """Element declarations depend on the type definition of their 1571 content.""" 1572 return frozenset([self.__typeDefinition])
1573
1574 - def __init__ (self, *args, **kw):
1575 super(ElementDeclaration, self).__init__(*args, **kw)
1576 1577 # CFD:ED CFD:ElementDeclaration 1578 @classmethod
1579 - def CreateFromDOM (cls, node, **kw):
1580 """Create an element declaration from the given DOM node. 1581 1582 wxs is a Schema instance within which the element is being 1583 declared. 1584 1585 scope is the _ScopeDeclaration_mixin context into which the 1586 element declaration is recorded. It can be SCOPE_global, a 1587 complex type definition, or None in the case of elements 1588 declared in a named model group. 1589 1590 node is a DOM element. The name must be 'element', and the 1591 node must be in the XMLSchema namespace.""" 1592 1593 scope = kw['scope'] 1594 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or _ScopedDeclaration_mixin.IsValidScope(scope) 1595 1596 # Node should be an XMLSchema element node 1597 assert xsd.nodeIsNamed(node, 'element') 1598 1599 # Might be top-level, might be local 1600 name = domutils.NodeAttribute(node, 'name') 1601 if xsd.nodeIsNamed(node.parentNode, 'schema'): 1602 assert _ScopedDeclaration_mixin.SCOPE_global == scope 1603 elif domutils.NodeAttribute(node, 'ref') is None: 1604 # Scope may be None or a CTD. 1605 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition) 1606 else: 1607 raise pyxb.SchemaValidationError('Created reference as element declaration') 1608 1609 rv = cls(name=name, node=node, **kw) 1610 rv._annotationFromDOM(node) 1611 rv._valueConstraintFromDOM(node) 1612 1613 rv.__substitutionGroupAttribute = domutils.NodeAttribute(node, 'substitutionGroup') 1614 1615 kw.pop('node', None) 1616 kw['owner'] = rv 1617 1618 identity_constraints = [] 1619 for cn in node.childNodes: 1620 if (Node.ELEMENT_NODE == cn.nodeType) and xsd.nodeIsNamed(cn, 'key', 'unique', 'keyref'): 1621 identity_constraints.append(IdentityConstraintDefinition.CreateFromDOM(cn, **kw)) 1622 rv.__identityConstraintDefinitions = identity_constraints 1623 1624 rv.__typeDefinition = None 1625 rv.__typeAttribute = domutils.NodeAttribute(node, 'type') 1626 simpleType_node = domutils.LocateUniqueChild(node, 'simpleType') 1627 complexType_node = domutils.LocateUniqueChild(node, 'complexType') 1628 if rv.__typeAttribute is not None: 1629 if (simpleType_node is not None) and (complexType_node is not None): 1630 raise pyxb.SchemaValidationError('Cannot combine type attribute with simpleType or complexType child') 1631 if (rv.__typeDefinition is None) and (simpleType_node is not None): 1632 rv.__typeDefinition = SimpleTypeDefinition.CreateFromDOM(simpleType_node, **kw) 1633 if (rv.__typeDefinition is None) and (complexType_node is not None): 1634 rv.__typeDefinition = ComplexTypeDefinition.CreateFromDOM(complexType_node, **kw) 1635 if rv.__typeDefinition is None: 1636 if rv.__typeAttribute is None: 1637 # Scan for particle types which were supposed to be enclosed in a complexType 1638 for cn in node.childNodes: 1639 if Particle.IsParticleNode(cn): 1640 raise pyxb.SchemaValidationError('Node %s in element must be wrapped by complexType.' % (cn.localName,)) 1641 rv.__typeDefinition = ComplexTypeDefinition.UrTypeDefinition() 1642 rv.__isResolved = (rv.__typeDefinition is not None) and (rv.__substitutionGroupAttribute is None) 1643 if not rv.__isResolved: 1644 rv._queueForResolution('creation') 1645 1646 attr_val = domutils.NodeAttribute(node, 'nillable') 1647 if attr_val is not None: 1648 rv.__nillable = datatypes.boolean(attr_val) 1649 1650 attr_val = domutils.NodeAttribute(node, 'abstract') 1651 if attr_val is not None: 1652 rv.__abstract = datatypes.boolean(attr_val) 1653 1654 schema = kw['schema'] 1655 rv.__disallowedSubstitutions = schema.blockForNode(node, cls._DS_Map) 1656 rv.__substitutionGroupExclusions = schema.finalForNode(node, cls._SGE_Map) 1657 1658 return rv
1659
1660 - def isAdaptable (self, ctd):
1661 """Determine whether this element declaration is adaptable. 1662 1663 OK, this gets ugly. First, if this declaration isn't resolved, it's 1664 clearly not adaptable. 1665 1666 Now: For it to be adaptable, we must know enough about its type to 1667 verify that it is derivation-consistent with any other uses of the 1668 same name in the same complex type. If the element's type is 1669 resolved, that's good enough. 1670 1671 If the element's type isn't resolved, we're golden as long as 1672 type-equivalent types were used. But it's also allowed for the 1673 derived ctd to use the element name constraining it to a derivation of 1674 the element base type. (Go see namespace 1675 http://www.opengis.net/ows/1.1 types PositionType, PositionType2D, 1676 BoundingBox, and WGS84BoundingBox for an example). So, we really do 1677 have to have the element's type resolved. 1678 1679 Except that if a CTD's content incorporates an element with the same 1680 type as the CTD (i.e., nested), this will never happen, because the 1681 CTD can't get resolved until after it has been resolved. 1682 (Go see {http://www.opengis.net/ows/1.1}ContentsBaseType and 1683 {http://www.opengis.net/ows/1.1}DatasetDescriptionSummaryBaseType for 1684 an example). 1685 1686 So, we give the world a break and assume that if the type we're trying 1687 to resolve is the same as the type of an element in that type, then 1688 the element type will be resolved by the point it's needed. In point 1689 of fact, it won't, but we'll only notice that if a CTD contains an 1690 element whose type is a restriction of the CTD. In that case, 1691 isDerivationConsistent will blow chunks and somebody'll have to come 1692 back and finish up this mess. 1693 """ 1694 1695 if not self.isResolved(): 1696 return False 1697 if self.typeDefinition().isResolved(): 1698 return True 1699 # Aw, dammit. See if we're gonna need the type resolved before we can 1700 # adapt this thing. 1701 existing_decl = ctd.lookupScopedElementDeclaration(self.expandedName()) 1702 if existing_decl is None: 1703 # Nobody else has this name, so we don't have to check for 1704 # consistency. 1705 return True 1706 # OK, we've got a name clash. Are the two types trivially equivalent? 1707 if self.typeDefinition().isTypeEquivalent(existing_decl.typeDefinition()): 1708 # Yes! Go for it. 1709 return True 1710 # No. Can't proceed until the type definition is resolved. Hope it 1711 # can be.... 1712 _log.warning('Require %s to be resolved; might be a loop.', self.typeDefinition()) 1713 return False
1714 1715 # aFS:ED
1716 - def _adaptForScope (self, owner, ctd):
1717 rv = self 1718 assert isinstance(ctd, ComplexTypeDefinition), '%s is not a CTD' % (ctd,) 1719 if not isinstance(self.scope(), ComplexTypeDefinition): 1720 assert owner is not None 1721 rv = self._clone(owner, ctd._objectOrigin()) 1722 rv._setScope(ctd) 1723 ctd._recordLocalDeclaration(rv) 1724 return rv
1725 1726 __isResolved = False
1727 - def isResolved (self):
1728 return self.__isResolved
1729 1730 # res:ED res:ElementDeclaration
1731 - def _resolve (self):
1732 if self.isResolved(): 1733 return self 1734 1735 #if self._scopeIsIndeterminate(): 1736 # _log.debug('WARNING: Resolving ED %s with indeterminate scope (is this a problem?)', self.expandedName()) 1737 if self.__substitutionGroupAttribute is not None: 1738 sg_en = self._namespaceContext().interpretQName(self.__substitutionGroupAttribute) 1739 sga = sg_en.elementDeclaration() 1740 if sga is None: 1741 raise pyxb.SchemaValidationError('Element declaration refers to unrecognized substitution group %s' % (sg_en,)) 1742 self.__substitutionGroupAffiliation = sga 1743 1744 if self.__typeDefinition is None: 1745 assert self.__typeAttribute is not None 1746 type_en = self._namespaceContext().interpretQName(self.__typeAttribute) 1747 self.__typeDefinition = type_en.typeDefinition() 1748 if self.__typeDefinition is None: 1749 raise pyxb.SchemaValidationError('Type declaration %s cannot be found' % (type_en,)) 1750 1751 self.__isResolved = True 1752 return self
1753
1754 - def __str__ (self):
1755 if self.typeDefinition() is not None: 1756 return 'ED[%s:%s]' % (self.name(), self.typeDefinition().name()) 1757 return 'ED[%s:?]' % (self.name(),)
1758
1759 1760 -class ComplexTypeDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _AttributeWildcard_mixin):
1761 __PrivateTransient = set() 1762 1763 # The type resolved from the base attribute. 1764 __baseTypeDefinition = None
1765 - def baseTypeDefinition (self):
1766 "The type resolved from the base attribute.""" 1767 return self.__baseTypeDefinition
1768 1769 DM_empty = 0 #<<< No derivation method specified 1770 DM_extension = 0x01 #<<< Derivation by extension 1771 DM_restriction = 0x02 #<<< Derivation by restriction 1772 1773 _DM_Map = { 'extension' : DM_extension 1774 , 'restriction' : DM_restriction } 1775 1776 # How the type was derived (a DM_* value) 1777 # (This field is used to identify unresolved definitions.) 1778 __derivationMethod = None
1779 - def derivationMethod (self):
1780 """How the type was derived.""" 1781 return self.__derivationMethod
1782 1783 # Derived from the final and finalDefault attributes 1784 __final = DM_empty 1785 1786 # Derived from the abstract attribute 1787 __abstract = False
1788 - def abstract (self):
1789 return self.__abstract
1790 1791 # A frozenset() of AttributeUse instances. 1792 __attributeUses = None
1793 - def attributeUses (self):
1794 """A frozenset() of AttributeUse instances.""" 1795 return self.__attributeUses
1796 1797 # A map from NCNames to AttributeDeclaration instances that are 1798 # local to this type. 1799 __scopedAttributeDeclarations = None
1800 - def lookupScopedAttributeDeclaration (self, expanded_name):
1801 """Find an attribute declaration with the given name that is local to this type. 1802 1803 Returns None if there is no such local attribute declaration.""" 1804 if self.__scopedAttributeDeclarations is None: 1805 return None 1806 return self.__scopedAttributeDeclarations.get(expanded_name)
1807 1808 # A map from NCNames to ElementDeclaration instances that are 1809 # local to this type. 1810 __scopedElementDeclarations = None
1811 - def lookupScopedElementDeclaration (self, expanded_name):
1812 """Find an element declaration with the given name that is local to this type. 1813 1814 Returns None if there is no such local element declaration.""" 1815 if self.__scopedElementDeclarations is None: 1816 return None 1817 return self.__scopedElementDeclarations.get(expanded_name)
1818 1819 __localScopedDeclarations = None
1820 - def localScopedDeclarations (self, reset=False):
1821 """Return a list of element and attribute declarations that were 1822 introduced in this definition (i.e., their scope is this CTD). 1823 1824 @note: This specifically returns a list, with element declarations 1825 first, because name binding should privilege the elements over the 1826 attributes. Within elements and attributes, the components are sorted 1827 by expanded name, to ensure consistency across a series of binding 1828 generations. 1829 1830 @keyword reset: If C{False} (default), a cached previous value (if it 1831 exists) will be returned. 1832 """ 1833 if reset or (self.__localScopedDeclarations is None): 1834 rve = [ _ed for _ed in self.__scopedElementDeclarations.values() if (self == _ed.scope()) ] 1835 rve.sort(lambda _a, _b: cmp(_a.expandedName(), _b.expandedName())) 1836 rva = [ _ad for _ad in self.__scopedAttributeDeclarations.values() if (self == _ad.scope()) ] 1837 rva.sort(lambda _a, _b: cmp(_a.expandedName(), _b.expandedName())) 1838 self.__localScopedDeclarations = rve 1839 self.__localScopedDeclarations.extend(rva) 1840 return self.__localScopedDeclarations
1841
1842 - def _recordLocalDeclaration (self, decl):
1843 """Record the given declaration as being locally scoped in 1844 this type.""" 1845 assert isinstance(decl, _ScopedDeclaration_mixin) 1846 if isinstance(decl, ElementDeclaration): 1847 scope_map = self.__scopedElementDeclarations 1848 elif isinstance(decl, AttributeDeclaration): 1849 scope_map = self.__scopedAttributeDeclarations 1850 else: 1851 raise pyxb.LogicError('Unexpected instance of %s recording as local declaration' % (type(decl),)) 1852 decl_en = decl.expandedName() 1853 existing_decl = scope_map.setdefault(decl_en, decl) 1854 if decl != existing_decl: 1855 if isinstance(decl, ElementDeclaration): 1856 # Test cos-element-consistent 1857 existing_type = existing_decl.typeDefinition() 1858 pending_type = decl.typeDefinition() 1859 if not pending_type.isDerivationConsistent(existing_type): 1860 raise pyxb.SchemaValidationError('Conflicting element declarations for %s: existing %s versus new %s' % (decl.expandedName(), existing_type, pending_type)) 1861 elif isinstance(decl, AttributeDeclaration): 1862 raise pyxb.SchemaValidationError('Multiple attribute declarations for %s' % (decl.expandedName(),)) 1863 else: 1864 assert False, 'Unrecognized type %s' % (type(decl),) 1865 decl._baseDeclaration(existing_decl) 1866 return self
1867
1868 - def _isHierarchyRoot (self):
1869 """Return C{True} iff this is the root of a complex type definition hierarchy. 1870 """ 1871 base = self.__baseTypeDefinition 1872 return isinstance(base, SimpleTypeDefinition) or base.isUrTypeDefinition()
1873 1874 CT_EMPTY = 'EMPTY' #<<< No content 1875 CT_SIMPLE = 'SIMPLE' #<<< Simple (character) content 1876 CT_MIXED = 'MIXED' #<<< Children may be elements or other (e.g., character) content 1877 CT_ELEMENT_ONLY = 'ELEMENT_ONLY' #<<< Expect only element content. 1878
1879 - def _contentTypeTag (self):
1880 """Return the value of the content type identifier, i.e. one of the 1881 CT_ constants. Return value is None if no content type has been 1882 defined.""" 1883 if isinstance(self.__contentType, tuple): 1884 return self.__contentType[0] 1885 return self.__contentType
1886
1887 - def _contentTypeComponent (self):
1888 if isinstance(self.__contentType, tuple): 1889 return self.__contentType[1] 1890 return None
1891 1892 # Identify the sort of content in this type. 1893 __contentType = None
1894 - def contentType (self):
1895 """Identify the sort of content in this type. 1896 1897 Valid values are: 1898 - C{CT_EMPTY} 1899 - ( C{CT_SIMPLE}, a L{SimpleTypeDefinition} instance ) 1900 - ( C{CT_MIXED}, a L{Particle} instance ) 1901 - ( C{CT_ELEMENT_ONLY}, a L{Particle} instance ) 1902 """ 1903 return self.__contentType
1904
1905 - def contentTypeAsString (self):
1906 if self.CT_EMPTY == self.contentType(): 1907 return 'EMPTY' 1908 ( tag, particle ) = self.contentType() 1909 if self.CT_SIMPLE == tag: 1910 return 'Simple [%s]' % (particle,) 1911 if self.CT_MIXED == tag: 1912 return 'Mixed [%s]' % (particle,) 1913 if self.CT_ELEMENT_ONLY == tag: 1914 return 'Element [%s]' % (particle,) 1915 raise pyxb.LogicError('Unhandled content type')
1916 1917 # Derived from the block and blockDefault attributes 1918 __prohibitedSubstitutions = DM_empty 1919 1920 # @todo: Extracted from children of various types 1921 __annotations = None 1922
1923 - def __init__ (self, *args, **kw):
1924 super(ComplexTypeDefinition, self).__init__(*args, **kw) 1925 self.__derivationMethod = kw.get('derivation_method') 1926 self.__scopedElementDeclarations = { } 1927 self.__scopedAttributeDeclarations = { }
1928
1929 - def hasWildcardElement (self):
1930 """Return True iff this type includes a wildcard element in 1931 its content model.""" 1932 if self.CT_EMPTY == self.contentType(): 1933 return False 1934 ( tag, particle ) = self.contentType() 1935 if self.CT_SIMPLE == tag: 1936 return False 1937 return particle.hasWildcardElement()
1938
1939 - def _updateFromOther_csc (self, other):
1940 """Override fields in this instance with those from the other. 1941 1942 This method is invoked only by Schema._addNamedComponent, and 1943 then only when a built-in type collides with a schema-defined 1944 type. Material like facets is not (currently) held in the 1945 built-in copy, so the DOM information is copied over to the 1946 built-in STD, which is subsequently re-resolved. 1947 1948 Returns self. 1949 """ 1950 assert self != other 1951 assert self.isNameEquivalent(other) 1952 super(ComplexTypeDefinition, self)._updateFromOther_csc(other) 1953 1954 if not other.isResolved(): 1955 if pyxb.namespace.BuiltInObjectUID != self._objectOrigin().generationUID(): 1956 self.__derivationMethod = None 1957 1958 return self
1959 1960 __UrTypeDefinition = None 1961 @classmethod
1962 - def UrTypeDefinition (cls, schema=None, in_builtin_definition=False):
1963 """Create the ComplexTypeDefinition instance that approximates 1964 the ur-type. 1965 1966 See section 3.4.7. 1967 """ 1968 1969 # The first time, and only the first time, this is called, a 1970 # namespace should be provided which is the XMLSchema 1971 # namespace for this run of the system. Please, do not try to 1972 # allow this by clearing the type definition. 1973 #if in_builtin_definition and (cls.__UrTypeDefinition is not None): 1974 # raise pyxb.LogicError('Multiple definitions of UrType') 1975 if cls.__UrTypeDefinition is None: 1976 # NOTE: We use a singleton subclass of this class 1977 assert schema is not None 1978 1979 ns_ctx = schema.targetNamespace().initialNamespaceContext() 1980 1981 kw = { 'name' : 'anyType', 1982 'schema' : schema, 1983 'namespace_context' : ns_ctx, 1984 'binding_namespace' : schema.targetNamespace(), 1985 'derivation_method' : cls.DM_restriction, 1986 'scope' : _ScopedDeclaration_mixin.SCOPE_global } 1987 bi = _UrTypeDefinition(**kw) 1988 1989 # The ur-type is its own baseTypeDefinition 1990 bi.__baseTypeDefinition = bi 1991 1992 # No constraints on attributes 1993 bi._setAttributeWildcard(Wildcard(namespace_constraint=Wildcard.NC_any, process_contents=Wildcard.PC_lax, **kw)) 1994 1995 # There isn't anything to look up, but context is still global. 1996 # No declarations will be created, so use indeterminate scope to 1997 # be consistent with validity checks in Particle constructor. 1998 # Content is mixed, with elements completely unconstrained. @todo: 1999 # not associated with a schema (it should be) 2000 kw = { 'namespace_context' : ns_ctx 2001 , 'schema' : schema 2002 , 'scope': _ScopedDeclaration_mixin.XSCOPE_indeterminate } 2003 w = Wildcard(namespace_constraint=Wildcard.NC_any, process_contents=Wildcard.PC_lax, **kw) 2004 p = Particle(w, min_occurs=0, max_occurs=None, **kw) 2005 m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[ p ], **kw) 2006 bi.__contentType = ( cls.CT_MIXED, Particle(m, **kw) ) 2007 2008 # No attribute uses 2009 bi.__attributeUses = set() 2010 2011 # No constraints on extension or substitution 2012 bi.__final = cls.DM_empty 2013 bi.__prohibitedSubstitutions = cls.DM_empty 2014 2015 bi.__abstract = False 2016 2017 # Refer to it by name 2018 bi.setNameInBinding(bi.name()) 2019 2020 # The ur-type is always resolved 2021 bi.__derivationMethod = cls.DM_restriction 2022 2023 cls.__UrTypeDefinition = bi 2024 return cls.__UrTypeDefinition
2025
2026 - def isBuiltin (self):
2027 """Indicate whether this simple type is a built-in type.""" 2028 return (self.UrTypeDefinition() == self)
2029 2030 # bR:CTD
2031 - def _bindingRequires_vx (self, include_lax):
2032 """Complex type definitions depend on their base type definition, the 2033 type definitions of any local attribute declarations, and if strict 2034 the type definitions of any local element declarations.""" 2035 rv = set() 2036 assert self.__baseTypeDefinition is not None 2037 rv.add(self.__baseTypeDefinition) 2038 for decl in self.localScopedDeclarations(): 2039 if include_lax or isinstance(decl, AttributeDeclaration): 2040 rv.add(decl.typeDefinition()) 2041 if include_lax: 2042 ct = self._contentTypeComponent() 2043 if ct is not None: 2044 rv.add(ct) 2045 return frozenset(rv)
2046 2047 # CFD:CTD CFD:ComplexTypeDefinition 2048 @classmethod
2049 - def CreateFromDOM (cls, node, **kw):
2050 # Node should be an XMLSchema complexType node 2051 assert xsd.nodeIsNamed(node, 'complexType') 2052 2053 name = domutils.NodeAttribute(node, 'name') 2054 2055 rv = cls(name=name, node=node, derivation_method=None, **kw) 2056 2057 if name is None: 2058 assert not isinstance(rv.owner(), Schema) 2059 2060 # Most of the time, the scope will be global. It can be something 2061 # else only if this is an anonymous CTD (created within an element 2062 # declaration which itself may be global, in a containing CTD, or in a 2063 # model group). 2064 if not (rv._scopeIsGlobal() or rv.isAnonymous()): 2065 raise pyxb.LogicError('Attempt to create non-global complex type definition') 2066 2067 kw.pop('node', None) 2068 kw['owner'] = rv 2069 kw['scope'] = rv 2070 2071 return rv.__setContentFromDOM(node, **kw)
2072 2073 __baseAttribute = None 2074 2075 2076 __ckw = None 2077 __anyAttribute = None 2078 __attributeGroupAttributes = None 2079 __usesC1 = None 2080 __usesC1C2 = None 2081 __attributeGroups = None 2082 __PrivateTransient.update(['ckw', 'anyAttribute', 'attributeGroupAttributes', 'usesC1', 'usesC1C2', 'attributeGroups' ]) 2083 2084 # Handle attributeUses, attributeWildcard, contentType
2085 - def __completeProcessing (self, method, content_style):
2086 2087 if self.__usesC1C2 is None: 2088 # Handle clauses 1 and 2 (common between simple and complex types) 2089 uses_c1 = self.__usesC1 # attribute children 2090 uses_c2 = set() # attribute group children 2091 self.__attributeGroups = [] 2092 for ag_attr in self.__attributeGroupAttributes: 2093 ag_en = self._namespaceContext().interpretQName(ag_attr) 2094 agd = ag_en.attributeGroupDefinition() 2095 if agd is None: 2096 raise pyxb.SchemaValidationError('Attribute group %s cannot be found' % (ag_en,)) 2097 if not agd.isResolved(): 2098 self._queueForResolution('unresolved attribute group', depends_on=agd) 2099 return self 2100 self.__attributeGroups.append(agd) 2101 uses_c2.update(agd.attributeUses()) 2102 2103 uses_c1c2 = uses_c1.union(uses_c2) 2104 for au in uses_c1c2: 2105 if not au.isResolved(): 2106 self._queueForResolution('attribute use not resolved') 2107 return self 2108 ad = au.attributeDeclaration() 2109 if not ad.isResolved(): 2110 ad_en = ad.expandedName() 2111 self._queueForResolution('unresolved attribute declaration %s from base type' % (ad_en,), depends_on=ad) 2112 return self 2113 2114 self.__usesC1C2 = frozenset([ _u._adaptForScope(self) for _u in uses_c1c2 ]) 2115 2116 # Handle clause 3. Note the slight difference in description between 2117 # simple and complex content is just that the complex content doesn't 2118 # bother to check that the base type definition is a complex type 2119 # definition. So the same code should work for both, and we don't 2120 # bother to check content_style. 2121 uses_c3 = set() # base attributes 2122 if isinstance(self.__baseTypeDefinition, ComplexTypeDefinition): 2123 # NB: The base type definition should be resolved, which means 2124 # that all its attribute uses have been adapted for scope already 2125 uses_c3 = set(self.__baseTypeDefinition.__attributeUses) 2126 assert self.__baseTypeDefinition.isResolved() 2127 for au in uses_c3: 2128 if not au.isResolved(): 2129 self._queueForResolution('unresolved attribute use from base type', depends_on=au) 2130 return self 2131 ad = au.attributeDeclaration() 2132 if not ad.isResolved(): 2133 ad_en = ad.expandedName() 2134 self._queueForResolution('unresolved attribute declaration %s from base type' % (ad_en,), depends_on=ad) 2135 return self 2136 assert not au.attributeDeclaration()._scopeIsIndeterminate() 2137 2138 if self.DM_restriction == method: 2139 # Exclude attributes per clause 3. Note that this process 2140 # handles both 3.1 and 3.2, since we have not yet filtered 2141 # uses_c1 for prohibited attributes. 2142 for au in self.__usesC1C2: 2143 matching_uses = au.matchingQNameMembers(uses_c3) 2144 assert matching_uses is not None 2145 assert 1 >= len(matching_uses), 'Multiple inherited attribute uses with name %s' 2146 for au2 in matching_uses: 2147 assert au2.isResolved() 2148 uses_c3.remove(au2) 2149 au._setRestrictionOf(au2) 2150 else: 2151 # In theory, the same attribute name can't appear in the base 2152 # and sub types because that would violate the local 2153 # declaration constraint. 2154 assert self.DM_extension == method 2155 2156 use_map = { } 2157 for au in self.__usesC1C2.union(uses_c3): 2158 assert au.isResolved() 2159 ad_en = au.attributeDeclaration().expandedName() 2160 if ad_en in use_map: 2161 raise pyxb.SchemaValidationError('Multiple definitions for %s in CTD %s' % (ad_en, self.expandedName())) 2162 use_map[ad_en] = au 2163 2164 # Past the last point where we might not resolve this instance. Store 2165 # the attribute uses, also recording local attribute declarations. 2166 self.__attributeUses = frozenset(use_map.values()) 2167 if not self._scopeIsIndeterminate(): 2168 for au in self.__attributeUses: 2169 assert not au.attributeDeclaration()._scopeIsIndeterminate(), 'indeterminate scope for %s' % (au,) 2170 2171 # @todo: Handle attributeWildcard 2172 # Clause 1 2173 local_wildcard = None 2174 if self.__anyAttribute is not None: 2175 local_wildcard = Wildcard.CreateFromDOM(self.__anyAttribute) 2176 2177 # Clause 2 2178 complete_wildcard = _AttributeWildcard_mixin.CompleteWildcard(self._namespaceContext(), self.__attributeGroups, local_wildcard) 2179 2180 # Clause 3 2181 if self.DM_restriction == method: 2182 # Clause 3.1 2183 self._setAttributeWildcard(complete_wildcard) 2184 else: 2185 assert (self.DM_extension == method) 2186 assert self.baseTypeDefinition().isResolved() 2187 # 3.2.1 2188 base_wildcard = None 2189 if isinstance(self.baseTypeDefinition(), ComplexTypeDefinition): 2190 base_wildcard = self.baseTypeDefinition().attributeWildcard() 2191 # 3.2.2 2192 if base_wildcard is not None: 2193 if complete_wildcard is None: 2194 # 3.2.2.1.1 2195 self._setAttributeWildcard(base_wildcard) 2196 else: 2197 # 3.2.2.1.2 2198 self._setAttributeWildcard(Wildcard (process_contents=complete_wildcard.processContents(), 2199 namespace_constraint = Wildcard.IntensionalUnion([complete_wildcard.namespaceConstraint(), 2200 base_wildcard.namespaceConstraint()]), 2201 annotation=complete_wildcard.annotation(), 2202 namespace_context=self._namespaceContext())) 2203 else: 2204 # 3.2.2.2 2205 self._setAttributeWildcard(complete_wildcard) 2206 2207 # @todo: Make sure we didn't miss any child nodes 2208 2209 # Remove local attributes we will never use again 2210 del self.__usesC1 2211 del self.__usesC1C2 2212 del self.__attributeGroups 2213 self.__ckw = None 2214 2215 # Only now that we've succeeded do we store the method, which 2216 # marks this component resolved. 2217 2218 self.__derivationMethod = method 2219 return self
2220
2221 - def __simpleContent (self, method, **kw):
2222 # Do content type 2223 if isinstance(self.__baseTypeDefinition, ComplexTypeDefinition): 2224 # Clauses 1, 2, and 3 might apply 2225 parent_content_type = self.__baseTypeDefinition.__contentType 2226 if ((type(parent_content_type) == tuple) \ 2227 and (self.CT_SIMPLE == parent_content_type[0]) \ 2228 and (self.DM_restriction == method)): 2229 # Clause 1 2230 assert self.__ctscRestrictionNode is not None 2231 std = self.__ctscClause2STD 2232 if std is None: 2233 std = parent_content_type[1] 2234 assert isinstance(std, SimpleTypeDefinition) 2235 if not std.isResolved(): 2236 return None 2237 restriction_node = self.__ctscRestrictionNode 2238 self.__ctscClause2STD = None 2239 self.__ctscRestrictionNode = None 2240 return ( self.CT_SIMPLE, std._createRestriction(self, restriction_node) ) 2241 if ((type(parent_content_type) == tuple) \ 2242 and (self.CT_MIXED == parent_content_type[0]) \ 2243 and parent_content_type[1].isEmptiable()): 2244 # Clause 2 2245 assert isinstance(self.__ctscClause2STD, SimpleTypeDefinition) 2246 return ( self.CT_SIMPLE, self.__ctscClause2STD ) 2247 # Clause 3 2248 return parent_content_type 2249 # Clause 4 2250 return ( self.CT_SIMPLE, self.__baseTypeDefinition )
2251 2252 __ctscClause2STD = None 2253 __ctscRestrictionNode = None 2254 __effectiveMixed = None 2255 __effectiveContent = None 2256 __pendingDerivationMethod = None 2257 __isComplexContent = None 2258 __ctscRestrictionMode = None 2259 __contentStyle = None 2260
2261 - def __setComplexContentFromDOM (self, type_node, content_node, definition_node_list, method, **kw):
2262 # Do content type. Cache the keywords that need to be used 2263 # for newly created schema components. 2264 ckw = kw.copy() 2265 ckw['namespace_context'] = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(type_node) 2266 2267 # Definition 1: effective mixed 2268 mixed_attr = None 2269 if content_node is not None: 2270 mixed_attr = domutils.NodeAttribute(content_node, 'mixed') 2271 if mixed_attr is None: 2272 mixed_attr = domutils.NodeAttribute(type_node, 'mixed') 2273 if mixed_attr is not None: 2274 effective_mixed = datatypes.boolean(mixed_attr) 2275 else: 2276 effective_mixed = False 2277 2278 # Definition 2: effective content 2279 test_2_1_1 = True 2280 test_2_1_2 = False 2281 test_2_1_3 = False 2282 typedef_node = None 2283 for cn in definition_node_list: 2284 if Node.ELEMENT_NODE != cn.nodeType: 2285 continue 2286 if xsd.nodeIsNamed(cn, 'simpleContent', 'complexContent'): 2287 # Should have found the content node earlier. 2288 raise pyxb.LogicError('Missed explicit wrapper in complexType content') 2289 if Particle.IsTypedefNode(cn): 2290 typedef_node = cn 2291 test_2_1_1 = False 2292 if xsd.nodeIsNamed(cn, 'all', 'sequence') \ 2293 and (not domutils.HasNonAnnotationChild(cn)): 2294 test_2_1_2 = True 2295 if xsd.nodeIsNamed(cn, 'choice') \ 2296 and (not domutils.HasNonAnnotationChild(cn)): 2297 mo_attr = domutils.NodeAttribute(cn, 'minOccurs') 2298 if ((mo_attr is not None) \ 2299 and (0 == datatypes.integer(mo_attr))): 2300 test_2_1_3 = True 2301 satisfied_predicates = 0 2302 if test_2_1_1: 2303 satisfied_predicates += 1 2304 if test_2_1_2: 2305 satisfied_predicates += 1 2306 if test_2_1_3: 2307 satisfied_predicates += 1 2308 if 1 == satisfied_predicates: 2309 if effective_mixed: 2310 # Clause 2.1.4 2311 assert (typedef_node is None) or test_2_1_2 2312 m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[], **ckw) 2313 effective_content = Particle(m, **ckw) 2314 else: 2315 # Clause 2.1.5 2316 effective_content = self.CT_EMPTY 2317 else: 2318 # Clause 2.2 2319 assert typedef_node is not None 2320 effective_content = Particle.CreateFromDOM(typedef_node, **kw) 2321 2322 # For issues related to soapenc:Array and the fact that PyXB 2323 # determines the content of types derived from it is empty, see 2324 # http://tech.groups.yahoo.com/group/soapbuilders/message/5879 and 2325 # lament the fact that the WSDL spec is not compatible with XSD. It 2326 # is *not* an error in PyXB. 2327 2328 self.__effectiveMixed = effective_mixed 2329 self.__effectiveContent = effective_content 2330 self.__ckw = ckw
2331
2332 - def __complexContent (self, method):
2333 ckw = self.__ckw 2334 2335 # Shared from clause 3.1.2 2336 if self.__effectiveMixed: 2337 ct = self.CT_MIXED 2338 else: 2339 ct = self.CT_ELEMENT_ONLY 2340 # Clause 3 2341 if self.DM_restriction == method: 2342 # Clause 3.1 2343 if self.CT_EMPTY == self.__effectiveContent: 2344 # Clause 3.1.1 2345 content_type = self.CT_EMPTY # ASSIGN CT_EMPTY 2346 else: 2347 # Clause 3.1.2(.2) 2348 content_type = ( ct, self.__effectiveContent ) # ASSIGN RESTRICTION 2349 assert 0 == len(self.__scopedElementDeclarations) 2350 # Reference the parent element declarations; normally this 2351 # would happen naturally as a consequence of appending this 2352 # type's content model to the parent's, but with restriction 2353 # there is no such re-use unless we do this. 2354 self.__scopedElementDeclarations.update(self.__baseTypeDefinition.__scopedElementDeclarations) 2355 else: 2356 # Clause 3.2 2357 assert self.DM_extension == method 2358 assert self.__baseTypeDefinition.isResolved() 2359 parent_content_type = self.__baseTypeDefinition.contentType() 2360 if self.CT_EMPTY == self.__effectiveContent: 2361 content_type = parent_content_type # ASSIGN EXTENSION PARENT ONLY 2362 elif self.CT_EMPTY == parent_content_type: 2363 # Clause 3.2.2 2364 content_type = ( ct, self.__effectiveContent ) # ASSIGN EXTENSION LOCAL ONLY 2365 else: 2366 assert type(parent_content_type) == tuple 2367 m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[ parent_content_type[1], self.__effectiveContent ], **ckw) 2368 content_type = ( ct, Particle(m, **ckw) ) # ASSIGN EXTENSION PARENT AND LOCAL 2369 2370 assert (self.CT_EMPTY == content_type) or ((type(content_type) == tuple) and (content_type[1] is not None)) 2371 return content_type
2372
2373 - def isResolved (self):
2374 """Indicate whether this complex type is fully defined. 2375 2376 All built-in type definitions are resolved upon creation. 2377 Schema-defined type definitionss are held unresolved until the 2378 schema has been completely read, so that references to later 2379 schema-defined types can be resolved. Resolution is performed 2380 after the entire schema has been scanned and type-definition 2381 instances created for all topLevel{Simple,Complex}Types. 2382 2383 If a built-in type definition is also defined in a schema 2384 (which it should be), the built-in definition is kept, with 2385 the schema-related information copied over from the matching 2386 schema-defined type definition. The former then replaces the 2387 latter in the list of type definitions to be resolved. See 2388 Schema._addNamedComponent. 2389 """ 2390 # Only unresolved nodes have an unset derivationMethod 2391 return (self.__derivationMethod is not None)
2392 2393 # Back door to allow the ur-type to re-resolve itself. Only needed when 2394 # we're generating bindings for XMLSchema itself.
2395 - def _setDerivationMethod (self, derivation_method):
2396 self.__derivationMethod = derivation_method 2397 return self
2398
2399 - def __setContentFromDOM (self, node, **kw):
2400 schema = kw.get('schema') 2401 assert schema is not None 2402 self.__prohibitedSubstitutions = schema.blockForNode(node, self._DM_Map) 2403 self.__final = schema.finalForNode(node, self._DM_Map) 2404 2405 attr_val = domutils.NodeAttribute(node, 'abstract') 2406 if attr_val is not None: 2407 self.__abstract = datatypes.boolean(attr_val) 2408 2409 # Assume we're in the short-hand case: the entire content is 2410 # implicitly wrapped in a complex restriction of the ur-type. 2411 definition_node_list = node.childNodes 2412 is_complex_content = True 2413 self.__baseTypeDefinition = ComplexTypeDefinition.UrTypeDefinition() 2414 method = self.DM_restriction 2415 2416 # Determine whether above assumption is correct by looking for 2417 # element content and seeing if it's one of the wrapper 2418 # elements. 2419 first_elt = domutils.LocateFirstChildElement(node) 2420 content_node = None 2421 clause2_std = None 2422 ctsc_restriction_node = None 2423 if first_elt: 2424 have_content = False 2425 if xsd.nodeIsNamed(first_elt, 'simpleContent'): 2426 have_content = True 2427 is_complex_content = False 2428 elif xsd.nodeIsNamed(first_elt, 'complexContent'): 2429 have_content = True 2430 else: 2431 # Not one of the wrappers; use implicit wrapper around 2432 # the children 2433 if not Particle.IsParticleNode(first_elt, 'attributeGroup', 'attribute', 'anyAttribute'): 2434 raise pyxb.SchemaValidationError('Unexpected element %s at root of complexType' % (first_elt.nodeName,)) 2435 if have_content: 2436 # Repeat the search to verify that only the one child is present. 2437 content_node = domutils.LocateFirstChildElement(node, require_unique=True) 2438 assert content_node == first_elt 2439 2440 # Identify the contained restriction or extension 2441 # element, and extract the base type. 2442 ions = domutils.LocateFirstChildElement(content_node, absent_ok=False) 2443 if xsd.nodeIsNamed(ions, 'restriction'): 2444 method = self.DM_restriction 2445 if not is_complex_content: 2446 # Clause 2 of complex type with simple content 2447 ctsc_restriction_node = ions 2448 ions_st = domutils.LocateUniqueChild(ions,'simpleType') 2449 if ions_st is not None: 2450 clause2_std = SimpleTypeDefinition.CreateFromDOM(ions_st, **kw) 2451 elif xsd.nodeIsNamed(ions, 'extension'): 2452 method = self.DM_extension 2453 else: 2454 raise pyxb.SchemaValidationError('Expected restriction or extension as sole child of %s in %s' % (content_node.nodeName, self.name())) 2455 self.__baseAttribute = domutils.NodeAttribute(ions, 'base') 2456 if self.__baseAttribute is None: 2457 raise pyxb.SchemaValidationError('Element %s missing base attribute' % (ions.nodeName,)) 2458 self.__baseTypeDefinition = None 2459 # The content is defined by the restriction/extension element 2460 definition_node_list = ions.childNodes 2461 # deriviationMethod is assigned after resolution completes 2462 self.__pendingDerivationMethod = method 2463 self.__isComplexContent = is_complex_content 2464 self.__ctscRestrictionNode = ctsc_restriction_node 2465 self.__ctscClause2STD = clause2_std 2466 2467 (attributes, attribute_group_attrs, any_attribute) = self._attributeRelevantChildren(definition_node_list) 2468 self.__usesC1 = set() 2469 for cn in attributes: 2470 au = AttributeUse.CreateFromDOM(cn, **kw) 2471 self.__usesC1.add(au) 2472 self.__attributeGroupAttributes = attribute_group_attrs 2473 self.__anyAttribute = any_attribute 2474 2475 if self.__isComplexContent: 2476 self.__setComplexContentFromDOM(node, content_node, definition_node_list, self.__pendingDerivationMethod, **kw) 2477 2478 # Creation does not attempt to do resolution. Queue up the newly created 2479 # whatsis so we can resolve it after everything's been read in. 2480 self._annotationFromDOM(node) 2481 2482 if not self.isResolved(): 2483 self._queueForResolution('creation') 2484 2485 return self
2486 2487 # Resolution of a CTD can be delayed for the following reasons: 2488 # 2489 # * It extends or restricts a base type that has not been resolved 2490 # [_resolve] 2491 # 2492 # * It refers to an attribute or attribute group that has not been 2493 # resolved [__completeProcessing] 2494 # 2495 # * It includes an attribute that matches in NCName and namespace 2496 # an unresolved attribute from the base type 2497 # [__completeProcessing] 2498 # 2499 # * The content model includes a particle which cannot be resolved 2500 # (so has not contributed any local element declarations). 2501 # res:CTD
2502 - def _resolve (self):
2503 if self.isResolved(): 2504 return self 2505 2506 # @todo: implement prohibitedSubstitutions, final, annotations 2507 2508 # See whether we've resolved through to the base type 2509 if self.__baseTypeDefinition is None: 2510 base_en = self._namespaceContext().interpretQName(self.__baseAttribute) 2511 base_type = base_en.typeDefinition() 2512 if base_type is None: 2513 raise pyxb.SchemaValidationError('Cannot locate %s: need import?' % (base_en,)) 2514 if not base_type.isResolved(): 2515 # Have to delay resolution until the type this 2516 # depends on is available. 2517 self._queueForResolution('unresolved base type %s' % (base_en,), depends_on=base_type) 2518 return self 2519 self.__baseTypeDefinition = base_type 2520 2521 # Only build the content once. This will not complete if the content 2522 # is a restriction of an unresolved simple type; otherwise, it only 2523 # depends on the base type which we know is good. 2524 if self.__contentType is None: 2525 if self.__isComplexContent: 2526 content_type = self.__complexContent(self.__pendingDerivationMethod) 2527 self.__contentStyle = 'complex' 2528 else: 2529 # The definition node list is not relevant to simple content 2530 content_type = self.__simpleContent(self.__pendingDerivationMethod) 2531 if content_type is None: 2532 self._queueForResolution('restriction of unresolved simple type') 2533 return self 2534 self.__contentStyle = 'simple' 2535 assert content_type is not None 2536 self.__contentType = content_type 2537 2538 # Last chance for failure is if we haven't been able to 2539 # extract all the element declarations that might appear in 2540 # this complex type. That technically wouldn't stop this from 2541 # being resolved, but it does prevent us from using it as a 2542 # context. 2543 if isinstance(self.__contentType, tuple) and isinstance(self.__contentType[1], Particle): 2544 prt = self.__contentType[1] 2545 if not prt.isAdaptable(self): 2546 self._queueForResolution('content particle %s is not deep-resolved' % (prt,)) 2547 return self 2548 self.__contentType = (self.__contentType[0], prt._adaptForScope(self, self)) 2549 2550 return self.__completeProcessing(self.__pendingDerivationMethod, self.__contentStyle)
2551
2552 - def pythonSupport (self):
2553 """Complex type definitions have no built-in type support.""" 2554 return None
2555
2556 - def __str__ (self):
2557 if self.isAnonymous(): 2558 return 'CTD{Anonymous}[%x]' % (id(self),) 2559 return 'CTD[%s]' % (self.expandedName(),)
2560
2561 -class _UrTypeDefinition (ComplexTypeDefinition, _Singleton_mixin):
2562 """Subclass ensures there is only one ur-type."""
2563 - def pythonSupport (self):
2564 """The ur-type does have a Python class backing it up.""" 2565 return datatypes.anyType
2566
2567 - def _resolve (self):
2568 # The ur type is always resolved, except when it gets unresolved 2569 # through being updated from an instance read from the schema. 2570 return self._setDerivationMethod(self.DM_restriction)
2571
2572 2573 -class AttributeGroupDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _AttributeWildcard_mixin):
2574 """An XMLSchema U{Attribute Group Definition<http://www.w3.org/TR/xmlschema-1/#cAttribute_Group_Definitions>} component.""" 2575 __PrivateTransient = set() 2576 2577 # A frozenset of AttributeUse instances 2578 __attributeUses = None 2579
2580 - def __init__ (self, *args, **kw):
2581 super(AttributeGroupDefinition, self).__init__(*args, **kw)
2582 #assert 'scope' in kw 2583 #assert self._scopeIsIndeterminate() 2584
2585 - def __str__ (self):
2586 return 'AGD[%s]' % (self.expandedName(),)
2587 2588 @classmethod
2589 - def CreateBaseInstance (cls, name, schema, attribute_uses):
2590 """Create an attribute declaration component for a specified namespace.""" 2591 kw = { 'name' : name, 2592 'schema' : schema, 2593 'namespace_context' : schema.targetNamespace().initialNamespaceContext(), 2594 'scope' : _ScopedDeclaration_mixin.SCOPE_global } 2595 bi = cls(**kw) 2596 bi.__attributeUses = frozenset(attribute_uses) 2597 bi.__isResolved = True 2598 return bi
2599 2600 __anyAttribute = None 2601 __attributeGroupAttributes = None 2602 __refAttribute = None 2603 __PrivateTransient.update(['anyAttribute', 'attributeGroupAttributes']) 2604 2605 2606 # CFD:AGD CFD:AttributeGroupDefinition 2607 @classmethod
2608 - def CreateFromDOM (cls, node, **kw):
2609 """Create an attribute group definition from the given DOM node. 2610 2611 """ 2612 2613 assert xsd.nodeIsNamed(node, 'attributeGroup') 2614 name = domutils.NodeAttribute(node, 'name') 2615 2616 # Attribute group definitions can only appear at the top level of the 2617 # schema, and any definitions in them are scope indeterminate until 2618 # they're referenced in a complex type. 2619 kw.update({ 'scope' : _ScopedDeclaration_mixin.XSCOPE_indeterminate }) 2620 rv = cls(name=name, node=node, **kw) 2621 2622 rv._annotationFromDOM(node) 2623 2624 # Attribute group definitions must not be references 2625 rv.__refAttribute = domutils.NodeAttribute(node, 'ref') 2626 if rv.__refAttribute is not None: 2627 raise pyxb.SchemaValidationError('Attribute reference at top level') 2628 2629 kw.pop('node', None) 2630 kw['owner'] = rv 2631 2632 (attributes, attribute_group_attrs, any_attribute) = rv._attributeRelevantChildren(node.childNodes) 2633 rv.__attributeUses = set() 2634 for cn in attributes: 2635 rv.__attributeUses.add(AttributeUse.CreateFromDOM(cn, **kw)) 2636 rv.__attributeGroupAttributes = attribute_group_attrs 2637 rv.__anyAttribute = any_attribute 2638 2639 # Unconditionally queue for resolution, to avoid repeating the 2640 # wildcard code. 2641 rv._queueForResolution('creation') 2642 2643 return rv
2644 2645 # Indicates whether we have resolved any references 2646 __isResolved = False
2647 - def isResolved (self):
2648 return self.__isResolved
2649
2650 - def _resolve (self):
2651 if self.__isResolved: 2652 return self 2653 2654 uses = self.__attributeUses 2655 attribute_groups = [] 2656 for ag_attr in self.__attributeGroupAttributes: 2657 ag_en = self._namespaceContext().interpretQName(ag_attr) 2658 agd = ag_en.attributeGroupDefinition() 2659 if agd is None: 2660 raise pyxb.SchemaValidationError('Attribute group %s cannot be found' % (ag_en,)) 2661 attribute_groups.append(agd) 2662 uses = uses.union(agd.attributeUses()) 2663 2664 self.__attributeUses = frozenset(uses) 2665 2666 # "Complete wildcard" per CTD 2667 local_wildcard = None 2668 if self.__anyAttribute is not None: 2669 local_wildcard = Wildcard.CreateFromDOM(self.__anyAttribute) 2670 self._setAttributeWildcard(_AttributeWildcard_mixin.CompleteWildcard(self._namespaceContext(), attribute_groups, local_wildcard)) 2671 2672 self.__isResolved = True 2673 return self
2674 2675 # bR:AGD
2676 - def _bindingRequires_vx (self, include_lax):
2677 """Attribute group declarations require their uses, but only if lax.""" 2678 if not include_lax: 2679 return frozenset() 2680 return frozenset(self.attributeUses())
2681
2682 - def attributeUses (self):
2683 return self.__attributeUses
2684
2685 -class ModelGroupDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, _Annotated_mixin):
2686 """An XMLSchema U{Model Group Definition<http://www.w3.org/TR/xmlschema-1/#cModel_Group_Definitions>} component.""" 2687 # Reference to a _ModelGroup 2688 __modelGroup = None 2689
2690 - def modelGroup (self):
2691 """The model group for which this definition provides a name.""" 2692 return self.__modelGroup
2693 2694 # CFD:MGD CFD:ModelGroupDefinition 2695 @classmethod
2696 - def CreateFromDOM (cls, node, **kw):
2697 """Create a Model Group Definition from a DOM element node. 2698 2699 wxs is a Schema instance within which the model group is being 2700 defined. 2701 2702 node is a DOM element. The name must be 'group', and the node 2703 must be in the XMLSchema namespace. The node must have a 2704 'name' attribute, and must not have a 'ref' attribute. 2705 """ 2706 assert xsd.nodeIsNamed(node, 'group') 2707 2708 assert domutils.NodeAttribute(node, 'ref') is None 2709 2710 name = domutils.NodeAttribute(node, 'name') 2711 kw['scope'] = _ScopedDeclaration_mixin.XSCOPE_indeterminate 2712 rv = cls(name=name, node=node, **kw) 2713 rv._annotationFromDOM(node) 2714 2715 kw.pop('node', None) 2716 kw['owner'] = rv 2717 2718 for cn in node.childNodes: 2719 if Node.ELEMENT_NODE != cn.nodeType: 2720 continue 2721 if ModelGroup.IsGroupMemberNode(cn): 2722 assert not rv.__modelGroup 2723 # Model group definitions always occur at the top level of the 2724 # schema, so the elements declared in them are not bound to a 2725 # scope until they are referenced in a complex type. 2726 rv.__modelGroup = ModelGroup.CreateFromDOM(cn, model_group_definition=rv, **kw) 2727 assert rv.__modelGroup is not None 2728 return rv
2729 2730 # bR:MGD
2731 - def _bindingRequires_vx (self, include_lax):
2732 """Model group definitions depend on the contained model group.""" 2733 if not include_lax: 2734 return frozenset() 2735 return frozenset([self.__modelGroup])
2736
2737 - def __str__ (self):
2738 return 'MGD[%s: %s]' % (self.name(), self.modelGroup())
2739
2740 2741 -class ModelGroup (_SchemaComponent_mixin, _Annotated_mixin):
2742 """An XMLSchema U{Model Group<http://www.w3.org/TR/xmlschema-1/#cModel_Group>} component.""" 2743 C_INVALID = 0 2744 C_ALL = 0x01 2745 C_CHOICE = 0x02 2746 C_SEQUENCE = 0x03 2747 2748 # One of the C_* values above. Set at construction time from the 2749 # keyword parameter "compositor". 2750 __compositor = C_INVALID
2751 - def compositor (self):
2752 return self.__compositor
2753 2754 @classmethod
2755 - def CompositorToString (cls, compositor):
2756 """Map a compositor value to a string.""" 2757 if cls.C_ALL == compositor: 2758 return 'all' 2759 if cls.C_CHOICE == compositor: 2760 return 'choice' 2761 if cls.C_SEQUENCE == compositor: 2762 return 'sequence' 2763 return 'invalid'
2764
2765 - def compositorToString (self):
2766 """Return a string representing the compositor value.""" 2767 return self.CompositorToString(self.__compositor)
2768 2769 # A list of Particle instances. Set at construction time from 2770 # the keyword parameter "particles". 2771 __particles = None
2772 - def particles (self):
2773 return self.__particles
2774
2775 - def isAdaptable (self, ctd):
2776 """A model group has an unresolvable particle if any of its 2777 particles is unresolvable. Duh.""" 2778 for p in self.particles(): 2779 if not p.isAdaptable(ctd): 2780 return False 2781 return True
2782
2783 - def effectiveTotalRange (self, particle):
2784 """Return the minimum and maximum of the number of elements that can 2785 appear in a sequence matched by this particle. 2786 2787 See U{http://www.w3.org/TR/xmlschema-1/#cos-seq-range} 2788 """ 2789 if self.__compositor in (self.C_ALL, self.C_SEQUENCE): 2790 sum_minoccurs = 0 2791 sum_maxoccurs = 0 2792 for prt in self.__particles: 2793 (prt_min, prt_max) = prt.effectiveTotalRange() 2794 sum_minoccurs += prt_min 2795 if sum_maxoccurs is not None: 2796 if prt_max is None: 2797 sum_maxoccurs = None 2798 else: 2799 sum_maxoccurs += prt_max 2800 prod_maxoccurs = particle.maxOccurs() 2801 if prod_maxoccurs is not None: 2802 if sum_maxoccurs is None: 2803 prod_maxoccurs = None 2804 else: 2805 prod_maxoccurs *= sum_maxoccurs 2806 return (sum_minoccurs * particle.minOccurs(), prod_maxoccurs) 2807 assert self.__compositor == self.C_CHOICE 2808 if 0 == len(self.__particles): 2809 min_minoccurs = 0 2810 max_maxoccurs = 0 2811 else: 2812 (min_minoccurs, max_maxoccurs) = self.__particles[0].effectiveTotalRange() 2813 for prt in self.__particles[1:]: 2814 (prt_min, prt_max) = prt.effectiveTotalRange() 2815 if prt_min < min_minoccurs: 2816 min_minoccurs = prt_min 2817 if prt_max is None: 2818 max_maxoccurs = None 2819 elif (max_maxoccurs is not None) and (prt_max > max_maxoccurs): 2820 max_maxoccurs = prt_max 2821 min_minoccurs *= particle.minOccurs() 2822 if (max_maxoccurs is not None) and (particle.maxOccurs() is not None): 2823 max_maxoccurs *= particle.maxOccurs() 2824 return (min_minoccurs, max_maxoccurs)
2825 2826 # The ModelGroupDefinition that names this ModelGroup, or None if 2827 # the ModelGroup is anonymous. This is set at construction time 2828 # from the keyword parameter "model_group_definition". 2829 __modelGroupDefinition = None
2830 - def modelGroupDefinition (self):
2831 """The ModelGroupDefinition that names this group, or None if it is unnamed.""" 2832 return self.__modelGroupDefinition
2833
2834 - def __init__ (self, compositor, particles, *args, **kw):
2835 """Create a new model group. 2836 2837 compositor must be a legal compositor value (one of C_ALL, C_CHOICE, C_SEQUENCE). 2838 2839 particles must be a list of zero or more Particle instances. 2840 2841 scope is the _ScopeDeclaration_mixin context into which new 2842 declarations are recorded. It can be SCOPE_global, a complex 2843 type definition, or None if this is (or is within) a named 2844 model group. 2845 2846 model_group_definition is an instance of ModelGroupDefinition 2847 if this is a named model group. It defaults to None 2848 indicating a local group. 2849 """ 2850 2851 super(ModelGroup, self).__init__(*args, **kw) 2852 assert 'scope' in kw 2853 self.__compositor = compositor 2854 self.__particles = particles 2855 self.__modelGroupDefinition = kw.get('model_group_definition')
2856
2857 - def pluralityData (self):
2858 """Get the plurality data for this model group. 2859 """ 2860 return _PluralityData(self)
2861
2862 - def hasWildcardElement (self):
2863 """Return True if the model includes a wildcard amongst its particles.""" 2864 for p in self.particles(): 2865 if p.hasWildcardElement(): 2866 return True 2867 return False
2868 2869 # bR:MG
2870 - def _bindingRequires_vx (self, include_lax):
2871 if not include_lax: 2872 return frozenset() 2873 return frozenset(self.__particles)
2874 2875 # CFD:MG CFD:ModelGroup 2876 @classmethod
2877 - def CreateFromDOM (cls, node, **kw):
2878 """Create a model group from the given DOM node. 2879 2880 wxs is a Schema instance within which the model group is being 2881 defined. 2882 2883 node is a DOM element. The name must be one of ( 'all', 2884 'choice', 'sequence' ), and the node must be in the XMLSchema 2885 namespace. 2886 2887 scope is the _ScopeDeclaration_mxin context that is assigned 2888 to declarations that appear within the model group. It can be 2889 None, indicating no scope defined, or a complex type 2890 definition. 2891 """ 2892 2893 scope = kw['scope'] 2894 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition) 2895 2896 if xsd.nodeIsNamed(node, 'all'): 2897 compositor = cls.C_ALL 2898 elif xsd.nodeIsNamed(node, 'choice'): 2899 compositor = cls.C_CHOICE 2900 elif xsd.nodeIsNamed(node, 'sequence'): 2901 compositor = cls.C_SEQUENCE 2902 else: 2903 raise pyxb.IncompleteImplementationError('ModelGroup: Got unexpected %s' % (node.nodeName,)) 2904 particles = [] 2905 # Remove the owner from particle constructor arguments: we need to set it later 2906 kw.pop('owner', None) 2907 for cn in node.childNodes: 2908 if Node.ELEMENT_NODE != cn.nodeType: 2909 continue 2910 if Particle.IsParticleNode(cn): 2911 # NB: Ancestor of particle is set in the ModelGroup constructor 2912 particles.append(Particle.CreateFromDOM(node=cn, **kw)) 2913 elif not xsd.nodeIsNamed(cn, 'annotation'): 2914 raise pyxb.SchemaValidationError('Unexpected element %s in model group' % (cn.nodeName,)) 2915 rv = cls(compositor, particles, node=node, **kw) 2916 for p in particles: 2917 p._setOwner(rv) 2918 rv._annotationFromDOM(node) 2919 return rv
2920 2921 @classmethod
2922 - def IsGroupMemberNode (cls, node):
2923 return xsd.nodeIsNamed(node, 'all', 'choice', 'sequence')
2924
2925 - def elementDeclarations (self):
2926 """Return a list of all ElementDeclarations that are at the 2927 top level of this model group, in the order in which they can 2928 occur.""" 2929 element_decls = [] 2930 model_groups = [ self ] 2931 while model_groups: 2932 mg = model_groups.pop(0) 2933 for p in mg.particles(): 2934 if isinstance(p.term(), ModelGroup): 2935 model_groups.append(p.term()) 2936 elif isinstance(p.term(), ElementDeclaration): 2937 element_decls.extend(p.elementDeclarations()) 2938 else: 2939 assert p.term() is not None 2940 return element_decls
2941 2942 # aFS:MG
2943 - def _adaptForScope (self, owner, ctd):
2944 rv = self 2945 assert isinstance(ctd, ComplexTypeDefinition) 2946 maybe_rv = self._clone(owner, ctd._objectOrigin()) 2947 scoped_particles = [ _p._adaptForScope(maybe_rv, ctd) for _p in self.particles() ] 2948 do_clone = (self._scope() != ctd) or (self.particles() != scoped_particles) 2949 if do_clone: 2950 rv = maybe_rv 2951 rv.__particles = scoped_particles 2952 return rv
2953
2954 - def __str__ (self):
2955 comp = None 2956 if self.C_ALL == self.compositor(): 2957 comp = 'ALL' 2958 elif self.C_CHOICE == self.compositor(): 2959 comp = 'CHOICE' 2960 elif self.C_SEQUENCE == self.compositor(): 2961 comp = 'SEQUENCE' 2962 return '%s:(%s)' % (comp, ",".join( [ str(_p) for _p in self.particles() ] ) )
2963
2964 -class Particle (_SchemaComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin):
2965 """An XMLSchema U{Particle<http://www.w3.org/TR/xmlschema-1/#cParticle>} component.""" 2966 2967 # The minimum number of times the term may appear. 2968 __minOccurs = 1
2969 - def minOccurs (self):
2970 """The minimum number of times the term may appear. 2971 2972 Defaults to 1.""" 2973 return self.__minOccurs
2974 2975 # Upper limit on number of times the term may appear. 2976 __maxOccurs = 1
2977 - def maxOccurs (self):
2978 """Upper limit on number of times the term may appear. 2979 2980 If None, the term may appear any number of times; otherwise, 2981 this is an integral value indicating the maximum number of times 2982 the term may appear. The default value is 1; the value, unless 2983 None, must always be at least minOccurs(). 2984 """ 2985 return self.__maxOccurs
2986 2987 # A reference to a ModelGroup, WildCard, or ElementDeclaration 2988 __term = None
2989 - def term (self):
2990 """A reference to a ModelGroup, Wildcard, or ElementDeclaration.""" 2991 return self.__term
2992 __pendingTerm = None 2993 2994 __refAttribute = None 2995 __resolvableType = None 2996
2997 - def elementDeclarations (self):
2998 assert self.__term is not None 2999 if isinstance(self.__term, ModelGroup): 3000 return self.__term.elementDeclarations() 3001 if isinstance(self.__term, ElementDeclaration): 3002 return [ self.__term ] 3003 if isinstance(self.__term, Wildcard): 3004 return [ ] 3005 raise pyxb.LogicError('Unexpected term type %s' % (self.__term,))
3006
3007 - def pluralityData (self):
3008 """Return the plurality data for this component. 3009 3010 The plurality data for a particle is the plurality data for 3011 its term, with the counts scaled by the effect of 3012 maxOccurs.""" 3013 return _PluralityData(self)
3014
3015 - def effectiveTotalRange (self):
3016 """Extend the concept of effective total range to all particles. 3017 3018 See U{http://www.w3.org/TR/xmlschema-1/#cos-seq-range} and 3019 U{http://www.w3.org/TR/xmlschema-1/#cos-choice-range} 3020 """ 3021 if isinstance(self.__term, ModelGroup): 3022 return self.__term.effectiveTotalRange(self) 3023 return (self.minOccurs(), self.maxOccurs())
3024
3025 - def isEmptiable (self):
3026 """Return C{True} iff this particle can legitimately match an empty 3027 sequence (no content). 3028 3029 See U{http://www.w3.org/TR/xmlschema-1/#cos-group-emptiable} 3030 """ 3031 return 0 == self.effectiveTotalRange()[0]
3032
3033 - def hasWildcardElement (self):
3034 """Return True iff this particle has a wildcard in its term. 3035 3036 Note that the wildcard may be in a nested model group.""" 3037 return self.term().hasWildcardElement()
3038
3039 - def __init__ (self, term, *args, **kw):
3040 """Create a particle from the given DOM node. 3041 3042 term is a XML Schema Component: one of ModelGroup, 3043 ElementDeclaration, and Wildcard. 3044 3045 The following keyword arguments are processed: 3046 3047 min_occurs is a non-negative integer value with default 1, 3048 denoting the minimum number of terms required by the content 3049 model. 3050 3051 max_occurs is a positive integer value with default 1, or None 3052 indicating unbounded, denoting the maximum number of terms 3053 allowed by the content model. 3054 3055 scope is the _ScopeDeclaration_mxin context that is assigned 3056 to declarations that appear within the particle. It can be 3057 None, indicating no scope defined, or a complex type 3058 definition. 3059 """ 3060 3061 super(Particle, self).__init__(*args, **kw) 3062 3063 min_occurs = kw.get('min_occurs', 1) 3064 max_occurs = kw.get('max_occurs', 1) 3065 3066 assert 'scope' in kw 3067 assert (self._scopeIsIndeterminate()) or isinstance(self._scope(), ComplexTypeDefinition) 3068 3069 if term is not None: 3070 self.__term = term 3071 3072 assert isinstance(min_occurs, (types.IntType, types.LongType)) 3073 self.__minOccurs = min_occurs 3074 assert (max_occurs is None) or isinstance(max_occurs, (types.IntType, types.LongType)) 3075 self.__maxOccurs = max_occurs 3076 if self.__maxOccurs is not None: 3077 if self.__minOccurs > self.__maxOccurs: 3078 raise pyxb.LogicError('Particle minOccurs %s is greater than maxOccurs %s on creation' % (min_occurs, max_occurs))
3079 3080 # res:Particle
3081 - def _resolve (self):
3082 if self.isResolved(): 3083 return self 3084 3085 # @RESOLUTION@ 3086 if ModelGroup == self.__resolvableType: 3087 ref_en = self._namespaceContext().interpretQName(self.__refAttribute) 3088 group_decl = ref_en.modelGroupDefinition() 3089 if group_decl is None: 3090 raise pyxb.SchemaValidationError('Model group reference %s cannot be found' % (ref_en,)) 3091 3092 self.__pendingTerm = group_decl.modelGroup() 3093 assert self.__pendingTerm is not None 3094 elif ElementDeclaration == self.__resolvableType: 3095 # 3.9.2 says use 3.3.2, which is Element. The element inside a 3096 # particle is a localElement, so we either get the one it refers 3097 # to (which is top-level), or create a local one here. 3098 if self.__refAttribute is not None: 3099 assert self.__pendingTerm is None 3100 ref_en = self._namespaceContext().interpretQName(self.__refAttribute) 3101 self.__pendingTerm = ref_en.elementDeclaration() 3102 if self.__pendingTerm is None: 3103 raise pyxb.SchemaValidationError('Unable to locate element referenced by %s' % (ref_en,)) 3104 assert self.__pendingTerm is not None 3105 3106 # Whether this is a local declaration or one pulled in from the 3107 # global type definition symbol space, its name is now reserved in 3108 # this type. 3109 assert self.__pendingTerm is not None 3110 else: 3111 assert False 3112 3113 self.__term = self.__pendingTerm 3114 assert self.__term is not None 3115 return self
3116
3117 - def isResolved (self):
3118 return self.__term is not None
3119 3120 # CFD:Particle 3121 @classmethod
3122 - def CreateFromDOM (cls, node, **kw):
3123 """Create a particle from the given DOM node. 3124 3125 wxs is a Schema instance within which the model group is being 3126 defined. 3127 3128 node is a DOM element. The name must be one of ( 'group', 3129 'element', 'any', 'all', 'choice', 'sequence' ), and the node 3130 must be in the XMLSchema namespace. 3131 3132 scope is the _ScopeDeclaration_mxin context that is assigned 3133 to declarations that appear within the model group. It can be 3134 None, indicating no scope defined, or a complex type 3135 definition. 3136 """ 3137 scope = kw['scope'] 3138 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition) 3139 3140 kw.update({ 'min_occurs' : 1 3141 , 'max_occurs' : 1 3142 , 'node' : node }) 3143 3144 if not Particle.IsParticleNode(node): 3145 raise pyxb.LogicError('Attempted to create particle from illegal element %s' % (node.nodeName,)) 3146 attr_val = domutils.NodeAttribute(node, 'minOccurs') 3147 if attr_val is not None: 3148 kw['min_occurs'] = datatypes.nonNegativeInteger(attr_val) 3149 attr_val = domutils.NodeAttribute(node, 'maxOccurs') 3150 if attr_val is not None: 3151 if 'unbounded' == attr_val: 3152 kw['max_occurs'] = None 3153 else: 3154 kw['max_occurs'] = datatypes.nonNegativeInteger(attr_val) 3155 3156 rv = cls(None, **kw) 3157 3158 kw.pop('node', None) 3159 kw['owner'] = rv 3160 3161 rv.__refAttribute = domutils.NodeAttribute(node, 'ref') 3162 rv.__pendingTerm = None 3163 rv.__resolvableType = None 3164 if xsd.nodeIsNamed(node, 'group'): 3165 # 3.9.2 says use 3.8.2, which is ModelGroup. The group 3166 # inside a particle is a groupRef. If there is no group 3167 # with that name, this throws an exception as expected. 3168 if rv.__refAttribute is None: 3169 raise pyxb.SchemaValidationError('group particle without reference') 3170 rv.__resolvableType = ModelGroup 3171 elif xsd.nodeIsNamed(node, 'element'): 3172 if rv.__refAttribute is None: 3173 schema = kw.get('schema') 3174 assert schema is not None 3175 target_namespace = schema.targetNamespaceForNode(node, ElementDeclaration) 3176 incoming_tns = kw.get('target_namespace') 3177 if incoming_tns is not None: 3178 assert incoming_tns == target_namespace 3179 else: 3180 kw['target_namespace'] = target_namespace 3181 rv.__term = ElementDeclaration.CreateFromDOM(node=node, **kw) 3182 else: 3183 # NOTE: 3.3.3 clause 2.2 specifies that if ref is used, all 3184 # the other configuration attributes like nillable and default 3185 # must be absent. We don't even bother looking for them. 3186 rv.__resolvableType = ElementDeclaration 3187 assert not xsd.nodeIsNamed(node.parentNode, 'schema') 3188 elif xsd.nodeIsNamed(node, 'any'): 3189 # 3.9.2 says use 3.10.2, which is Wildcard. 3190 rv.__term = Wildcard.CreateFromDOM(node=node) 3191 elif ModelGroup.IsGroupMemberNode(node): 3192 # Choice, sequence, and all inside a particle are explicit 3193 # groups (or a restriction of explicit group, in the case 3194 # of all) 3195 rv.__term = ModelGroup.CreateFromDOM(node, **kw) 3196 else: 3197 raise pyxb.LogicError('Unhandled node in Particle.CreateFromDOM: %s' % (node.toxml("utf-8"),)) 3198 3199 if not rv.isResolved(): 3200 rv._queueForResolution('creation') 3201 return rv
3202 3203 # bR:PRT
3204 - def _bindingRequires_vx (self, include_lax):
3205 if not include_lax: 3206 return frozenset() 3207 return frozenset([ self.__term ])
3208 3209 # aFS:PRT
3210 - def _adaptForScope (self, owner, ctd):
3211 rv = self 3212 assert isinstance(ctd, ComplexTypeDefinition) 3213 maybe_rv = self._clone(owner, ctd._objectOrigin()) 3214 term = rv.__term._adaptForScope(maybe_rv, ctd) 3215 do_clone = (self._scope() != ctd) or (rv.__term != term) 3216 if do_clone: 3217 rv = maybe_rv 3218 rv.__term = term 3219 return rv
3220
3221 - def isAdaptable (self, ctd):
3222 """A particle has an unresolvable particle if it cannot be 3223 resolved, or if it has resolved to a term which is a model 3224 group that has an unresolvable particle. 3225 """ 3226 if not self.isResolved(): 3227 return False 3228 return self.term().isAdaptable(ctd)
3229 3230 @classmethod
3231 - def IsTypedefNode (cls, node):
3232 return xsd.nodeIsNamed(node, 'group', 'all', 'choice', 'sequence')
3233 3234 @classmethod
3235 - def IsParticleNode (cls, node, *others):
3236 return xsd.nodeIsNamed(node, 'group', 'all', 'choice', 'sequence', 'element', 'any', *others)
3237
3238 - def __str__ (self):
3239 #return 'PART{%s:%d,%s}' % (self.term(), self.minOccurs(), self.maxOccurs()) 3240 return 'PART{%s:%d,%s}[%x]' % ('TERM', self.minOccurs(), self.maxOccurs(), id(self))
3241
3242 3243 # 3.10.1 3244 -class Wildcard (_SchemaComponent_mixin, _Annotated_mixin):
3245 """An XMLSchema U{Wildcard<http://www.w3.org/TR/xmlschema-1/#cParticle>} component.""" 3246 3247 NC_any = '##any' #<<< The namespace constraint "##any" 3248 NC_not = '##other' #<<< A flag indicating constraint "##other" 3249 NC_targetNamespace = '##targetNamespace' 3250 NC_local = '##local' 3251 3252 __namespaceConstraint = None
3253 - def namespaceConstraint (self):
3254 """A constraint on the namespace for the wildcard. 3255 3256 Valid values are: 3257 - L{Wildcard.NC_any} 3258 - A tuple ( L{Wildcard.NC_not}, a_namespace ) 3259 - set(of_namespaces) 3260 3261 Note that namespace are represented by 3262 L{Namespace<pyxb.namespace.Namespace>} instances, not the URIs that 3263 actually define a namespace. Absence of a namespace is represented by 3264 C{None}, both in the "not" pair and in the set. 3265 """ 3266 return self.__namespaceConstraint
3267 3268 @classmethod
3269 - def IntensionalUnion (cls, constraints):
3270 """http://www.w3.org/TR/xmlschema-1/#cos-aw-union""" 3271 assert 0 < len(constraints) 3272 o1 = constraints.pop(0) 3273 while 0 < len(constraints): 3274 o2 = constraints.pop(0) 3275 # 1 3276 if (o1 == o2): 3277 continue 3278 # 2 3279 if (cls.NC_any == o1) or (cls.NC_any == o2): 3280 o1 = cls.NC_any 3281 continue 3282 # 3 3283 if isinstance(o1, set) and isinstance(o2, set): 3284 o1 = o1.union(o2) 3285 continue 3286 # 4 3287 if (isinstance(o1, tuple) and isinstance(o2, tuple)) and (o1[1] != o2[1]): 3288 o1 = ( cls.NC_not, None ) 3289 continue 3290 # At this point, one must be a negated namespace and the 3291 # other a set. Identify them. 3292 c_tuple = None 3293 c_set = None 3294 if isinstance(o1, tuple): 3295 assert isinstance(o2, set) 3296 c_tuple = o1 3297 c_set = o2 3298 else: 3299 assert isinstance(o1, set) 3300 assert isinstance(o2, tuple) 3301 c_tuple = o2 3302 c_set = o1 3303 negated_ns = c_tuple[1] 3304 if negated_ns is not None: 3305 # 5.1 3306 if (negated_ns in c_set) and (None in c_set): 3307 o1 = cls.NC_any 3308 continue 3309 # 5.2 3310 if negated_ns in c_set: 3311 o1 = ( cls.NC_not, None ) 3312 continue 3313 # 5.3 3314 if None in c_set: 3315 raise pyxb.SchemaValidationError('Union of wildcard namespace constraints not expressible') 3316 o1 = c_tuple 3317 continue 3318 # 6 3319 if None in c_set: 3320 o1 = cls.NC_any 3321 else: 3322 o1 = ( cls.NC_not, None ) 3323 return o1
3324 3325 @classmethod
3326 - def IntensionalIntersection (cls, constraints):
3327 """http://www.w3.org/TR/xmlschema-1/#cos-aw-intersect""" 3328 assert 0 < len(constraints) 3329 o1 = constraints.pop(0) 3330 while 0 < len(constraints): 3331 o2 = constraints.pop(0) 3332 # 1 3333 if (o1 == o2): 3334 continue 3335 # 2 3336 if (cls.NC_any == o1) or (cls.NC_any == o2): 3337 if cls.NC_any == o1: 3338 o1 = o2 3339 continue 3340 # 4 3341 if isinstance(o1, set) and isinstance(o2, set): 3342 o1 = o1.intersection(o2) 3343 continue 3344 if isinstance(o1, tuple) and isinstance(o2, tuple): 3345 ns1 = o1[1] 3346 ns2 = o2[1] 3347 # 5 3348 if (ns1 is not None) and (ns2 is not None) and (ns1 != ns2): 3349 raise pyxb.SchemaValidationError('Intersection of wildcard namespace constraints not expressible') 3350 # 6 3351 assert (ns1 is None) or (ns2 is None) 3352 if ns1 is None: 3353 assert ns2 is not None 3354 o1 = ( cls.NC_not, ns2 ) 3355 else: 3356 assert ns1 is not None 3357 o1 = ( cls.NC_not, ns1 ) 3358 continue 3359 # 3 3360 # At this point, one must be a negated namespace and the 3361 # other a set. Identify them. 3362 c_tuple = None 3363 c_set = None 3364 if isinstance(o1, tuple): 3365 assert isinstance(o2, set) 3366 c_tuple = o1 3367 c_set = o2 3368 else: 3369 assert isinstance(o1, set) 3370 assert isinstance(o2, tuple) 3371 c_tuple = o2 3372 c_set = o1 3373 negated_ns = c_tuple[1] 3374 if negated_ns in c_set: 3375 c_set.remove(negated_ns) 3376 if None in c_set: 3377 c_set.remove(None) 3378 o1 = c_set 3379 return o1
3380 3381 PC_skip = 'skip' #<<< No constraint is applied 3382 PC_lax = 'lax' #<<< Validate against available uniquely determined declaration 3383 PC_strict = 'strict' #<<< Validate against declaration or xsi:type which must be available 3384 3385 # One of PC_* 3386 __processContents = None
3387 - def processContents (self):
3388 return self.__processContents
3389
3390 - def pluralityData (self):
3391 """Get the plurality data for this wildcard 3392 """ 3393 return _PluralityData(self)
3394
3395 - def hasWildcardElement (self):
3396 """Return True, since Wildcard components are wildcards.""" 3397 return True
3398
3399 - def __init__ (self, *args, **kw):
3400 assert 0 == len(args) 3401 super(Wildcard, self).__init__(*args, **kw) 3402 self.__namespaceConstraint = kw['namespace_constraint'] 3403 self.__processContents = kw['process_contents']
3404
3405 - def isAdaptable (self, ctd):
3406 return True
3407 3408 # aFS:WC
3409 - def _adaptForScope (self, owner, ctd):
3410 """Wildcards are scope-independent; return self""" 3411 return self
3412 3413 # CFD:Wildcard 3414 @classmethod
3415 - def CreateFromDOM (cls, node, **kw):
3416 namespace_context = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(node) 3417 assert xsd.nodeIsNamed(node, 'any', 'anyAttribute') 3418 nc = domutils.NodeAttribute(node, 'namespace') 3419 if nc is None: 3420 namespace_constraint = cls.NC_any 3421 else: 3422 if cls.NC_any == nc: 3423 namespace_constraint = cls.NC_any 3424 elif cls.NC_not == nc: 3425 namespace_constraint = ( cls.NC_not, namespace_context.targetNamespace() ) 3426 else: 3427 ncs = set() 3428 for ns_uri in nc.split(): 3429 if cls.NC_local == ns_uri: 3430 ncs.add(None) 3431 elif cls.NC_targetNamespace == ns_uri: 3432 ncs.add(namespace_context.targetNamespace()) 3433 else: 3434 ncs.add(pyxb.namespace.NamespaceForURI(ns_uri, create_if_missing=True)) 3435 namespace_constraint = frozenset(ncs) 3436 3437 pc = domutils.NodeAttribute(node, 'processContents') 3438 if pc is None: 3439 process_contents = cls.PC_strict 3440 else: 3441 if pc in [ cls.PC_skip, cls.PC_lax, cls.PC_strict ]: 3442 process_contents = pc 3443 else: 3444 raise pyxb.SchemaValidationError('illegal value "%s" for any processContents attribute' % (pc,)) 3445 3446 rv = cls(node=node, namespace_constraint=namespace_constraint, process_contents=process_contents, **kw) 3447 rv._annotationFromDOM(node) 3448 return rv
3449
3450 # 3.11.1 3451 -class IdentityConstraintDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, _Annotated_mixin, pyxb.namespace.resolution._Resolvable_mixin):
3452 """An XMLSchema U{Identity Constraint Definition<http://www.w3.org/TR/xmlschema-1/#cIdentity-constraint_Definitions>} component.""" 3453 3454 ICC_KEY = 0x01 3455 ICC_KEYREF = 0x02 3456 ICC_UNIQUE = 0x04 3457 3458 __identityConstraintCategory = None
3459 - def identityConstraintCategory (self):
3461 3462 __selector = None
3463 - def selector (self):
3464 return self.__selector
3465 3466 __fields = None
3467 - def fields (self):
3468 return self.__fields
3469 3470 __referencedKey = None 3471 __referAttribute = None 3472 __icc = None 3473 3474 __annotations = None
3475 - def annotations (self):
3476 return self.__annotations
3477 3478 # CFD:ICD CFD:IdentityConstraintDefinition 3479 @classmethod
3480 - def CreateFromDOM (cls, node, **kw):
3481 name = domutils.NodeAttribute(node, 'name') 3482 scope = kw['scope'] 3483 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or _ScopedDeclaration_mixin.IsValidScope(scope) 3484 rv = cls(name=name, node=node, **kw) 3485 3486 kw.pop('node', None) 3487 kw['owner'] = rv 3488 3489 #self._annotationFromDOM(node); 3490 rv.__isResolved = True 3491 icc = None 3492 if xsd.nodeIsNamed(node, 'key'): 3493 icc = rv.ICC_KEY 3494 elif xsd.nodeIsNamed(node, 'keyref'): 3495 icc = rv.ICC_KEYREF 3496 rv.__referAttribute = domutils.NodeAttribute(node, 'refer') 3497 if rv.__referAttribute is None: 3498 raise pyxb.SchemaValidationError('Require refer attribute on keyref elements') 3499 rv.__isResolved = False 3500 elif xsd.nodeIsNamed(node, 'unique'): 3501 icc = rv.ICC_UNIQUE 3502 else: 3503 raise pyxb.LogicError('Unexpected identity constraint node %s' % (node.toxml("utf-8"),)) 3504 rv.__icc = icc 3505 3506 cn = domutils.LocateUniqueChild(node, 'selector') 3507 rv.__selector = domutils.NodeAttribute(cn, 'xpath') 3508 if rv.__selector is None: 3509 raise pyxb.SchemaValidationError('selector element missing xpath attribute') 3510 3511 rv.__fields = [] 3512 for cn in domutils.LocateMatchingChildren(node, 'field'): 3513 xp_attr = domutils.NodeAttribute(cn, 'xpath') 3514 if xp_attr is None: 3515 raise pyxb.SchemaValidationError('field element missing xpath attribute') 3516 rv.__fields.append(xp_attr) 3517 3518 rv._annotationFromDOM(node) 3519 rv.__annotations = [] 3520 if rv.annotation() is not None: 3521 rv.__annotations.append(rv) 3522 3523 for cn in node.childNodes: 3524 if (Node.ELEMENT_NODE != cn.nodeType): 3525 continue 3526 an = None 3527 if xsd.nodeIsNamed(cn, 'selector', 'field'): 3528 an = domutils.LocateUniqueChild(cn, 'annotation') 3529 elif xsd.nodeIsNamed(cn, 'annotation'): 3530 an = cn 3531 if an is not None: 3532 rv.__annotations.append(Annotation.CreateFromDOM(an, **kw)) 3533 3534 rv.__identityConstraintCategory = icc 3535 if rv.ICC_KEYREF != rv.__identityConstraintCategory: 3536 rv._namespaceContext().targetNamespace().addCategoryObject('identityConstraintDefinition', rv.name(), rv) 3537 3538 if not rv.isResolved(): 3539 rv._queueForResolution('creation') 3540 return rv
3541 3542 __isResolved = False
3543 - def isResolved (self):
3544 return self.__isResolved
3545 3546 # res:ICD res:IdentityConstraintDefinition
3547 - def _resolve (self):
3548 if self.isResolved(): 3549 return self 3550 3551 icc = self.__icc 3552 if self.ICC_KEYREF == icc: 3553 refer_en = self._namespaceContext().interpretQName(self.__referAttribute) 3554 refer = refer_en.identityConstraintDefinition() 3555 if refer is None: 3556 self._queueForResolution('Identity constraint definition %s cannot be found' % (refer_en,), depends_on=refer) 3557 return self 3558 self.__referencedKey = refer 3559 self.__isResolved = True 3560 return self
3561 3562 # bR:ICD
3563 - def _bindingRequires_vx (self, include_lax):
3564 """Constraint definitions that are by reference require the referenced constraint.""" 3565 rv = set() 3566 if include_lax and (self.__referencedKey is not None): 3567 rv.add(self.__referencedKey) 3568 return frozenset(rv)
3569
3570 3571 3572 # 3.12.1 3573 -class NotationDeclaration (_SchemaComponent_mixin, _NamedComponent_mixin, _Annotated_mixin):
3574 """An XMLSchema U{Notation Declaration<http://www.w3.org/TR/xmlschema-1/#cNotation_Declarations>} component.""" 3575 __systemIdentifier = None
3576 - def systemIdentifier (self):
3577 return self.__systemIdentifier
3578 3579 __publicIdentifier = None
3580 - def publicIdentifier (self):
3581 return self.__publicIdentifier
3582 3583 # CFD:ND CFD:NotationDeclaration 3584 @classmethod
3585 - def CreateFromDOM (cls, node, **kw):
3586 name = domutils.NodeAttribute(node, 'name') 3587 rv = cls(name=name, node=node, **kw) 3588 3589 rv.__systemIdentifier = domutils.NodeAttribute(node, 'system') 3590 rv.__publicIdentifier = domutils.NodeAttribute(node, 'public') 3591 3592 rv._annotationFromDOM(node) 3593 return rv
3594
3595 # 3.13.1 3596 -class Annotation (_SchemaComponent_mixin):
3597 """An XMLSchema U{Annotation<http://www.w3.org/TR/xmlschema-1/#cAnnotation>} component.""" 3598 3599 __applicationInformation = None
3600 - def applicationInformation (self):
3601 return self.__applicationInformation
3602 3603 __userInformation = None
3604 - def userInformation (self):
3605 return self.__userInformation
3606 3607 # Define so superclasses can take keywords
3608 - def __init__ (self, **kw):
3609 application_information = kw.pop('application_information', None) 3610 user_information = kw.pop('user_information', None) 3611 super(Annotation, self).__init__(**kw) 3612 if (user_information is not None) and (not isinstance(user_information, list)): 3613 user_information = [ unicode(user_information) ] 3614 if (application_information is not None) and (not isinstance(application_information, list)): 3615 application_information = [ unicode(application_information) ] 3616 self.__userInformation = user_information 3617 self.__applicationInformation = application_information
3618 3619 # @todo: what the hell is this? From 3.13.2, I think it's a place 3620 # to stuff attributes from the annotation element, which makes 3621 # sense, as well as from the annotation's parent element, which 3622 # doesn't. Apparently it's for attributes that don't belong to 3623 # the XMLSchema namespace; so maybe we're not supposed to add 3624 # those to the other components. Note that these are attribute 3625 # information items, not attribute uses. 3626 __attributes = None 3627 3628 # CFD:Annotation 3629 @classmethod
3630 - def CreateFromDOM (cls, node, **kw):
3631 rv = cls(node=node, **kw) 3632 3633 # @todo:: Scan for attributes in the node itself that do not 3634 # belong to the XMLSchema namespace. 3635 3636 # Node should be an XMLSchema annotation node 3637 assert xsd.nodeIsNamed(node, 'annotation') 3638 app_info = [] 3639 user_info = [] 3640 for cn in node.childNodes: 3641 if xsd.nodeIsNamed(cn, 'appinfo'): 3642 app_info.append(cn) 3643 elif xsd.nodeIsNamed(cn, 'documentation'): 3644 user_info.append(cn) 3645 else: 3646 pass 3647 if 0 < len(app_info): 3648 rv.__applicationInformation = app_info 3649 if 0 < len(user_info): 3650 rv.__userInformation = user_info 3651 3652 return rv
3653 3654 __RemoveMultiQuote_re = re.compile('""+')
3655 - def asDocString (self):
3656 """Return the text in a form suitable for embedding in a 3657 triple-double-quoted docstring. 3658 3659 Any sequence of two or more double quotes is replaced by a sequence of 3660 single quotes that is the same length. Following this, spaces are 3661 added at the start and the end as necessary to ensure a double quote 3662 does not appear in those positions.""" 3663 rv = self.text() 3664 rv = self.__RemoveMultiQuote_re.sub(lambda _mo: "'" * (_mo.end(0) - _mo.start(0)), rv) 3665 if rv.startswith('"'): 3666 rv = ' ' + rv 3667 if rv.endswith('"'): 3668 rv = rv + ' ' 3669 return rv
3670
3671 - def text (self):
3672 if self.__userInformation is None: 3673 return '' 3674 text = [] 3675 # Values in userInformation are DOM "documentation" elements. 3676 # We want their combined content. 3677 for dn in self.__userInformation: 3678 for cn in dn.childNodes: 3679 if Node.TEXT_NODE == cn.nodeType: 3680 text.append(cn.data) 3681 return ''.join(text)
3682
3683 - def __str__ (self):
3684 """Return the catenation of all user information elements in the 3685 annotation as a single unicode string. Returns the empty string if 3686 there are no user information elements.""" 3687 return self.text()
3688
3689 # Section 3.14. 3690 -class SimpleTypeDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin):
3691 """An XMLSchema U{Simple Type Definition<http://www.w3.org/TR/xmlschema-1/#Simple_Type_Definitions>} component.""" 3692 3693 # Reference to the SimpleTypeDefinition on which this is based. 3694 # The value must be non-None except for the simple ur-type 3695 # definition. 3696 __baseTypeDefinition = None
3697 - def baseTypeDefinition (self):
3698 return self.__baseTypeDefinition
3699 3700 __memberTypes = None 3701 __itemTypeAttribute = None 3702 __baseAttribute = None 3703 __memberTypesAttribute = None 3704 __localFacets = None 3705 3706 # A map from a subclass of facets.Facet to an instance of that class. 3707 # Presence of a facet class as a key in this map is the indicator that the 3708 # type definition and its subtypes are permitted to use the corresponding 3709 # facet. All facets in force for this type are present in the map, 3710 # including those constraints inherited parent types. 3711 __facets = None
3712 - def facets (self):
3713 assert (self.__facets is None) or (type(self.__facets) == types.DictType) 3714 return self.__facets
3715 3716 # The facets.FundamentalFacet instances that describe this type 3717 __fundamentalFacets = None
3718 - def fundamentalFacets (self):
3719 """A frozenset of instances of facets.FundamentallFacet.""" 3720 return self.__fundamentalFacets
3721 3722 STD_empty = 0 #<<< Marker indicating an empty set of STD forms 3723 STD_extension = 0x01 #<<< Representation for extension in a set of STD forms 3724 STD_list = 0x02 #<<< Representation for list in a set of STD forms 3725 STD_restriction = 0x04 #<<< Representation of restriction in a set of STD forms 3726 STD_union = 0x08 #<<< Representation of union in a set of STD forms 3727 3728 _STD_Map = { 'extension' : STD_extension 3729 , 'list' : STD_list 3730 , 'restriction' : STD_restriction 3731 , 'union' : STD_union } 3732 3733 # Bitmask defining the subset that comprises the final property 3734 __final = STD_empty 3735 @classmethod
3736 - def _FinalToString (cls, final_value):
3737 """Convert a final value to a string.""" 3738 tags = [] 3739 if final_value & cls.STD_extension: 3740 tags.append('extension') 3741 if final_value & cls.STD_list: 3742 tags.append('list') 3743 if final_value & cls.STD_restriction: 3744 tags.append('restriction') 3745 if final_value & cls.STD_union: 3746 tags.append('union') 3747 return ' '.join(tags)
3748 3749 VARIETY_absent = 0x01 #<<< Only used for the ur-type 3750 VARIETY_atomic = 0x02 #<<< Use for types based on a primitive type 3751 VARIETY_list = 0x03 #<<< Use for lists of atomic-variety types 3752 VARIETY_union = 0x04 #<<< Use for types that aggregate other types 3753 3754 # Derivation alternative 3755 _DA_empty = 'none specified' 3756 _DA_restriction = 'restriction' 3757 _DA_list = 'list' 3758 _DA_union = 'union' 3759
3760 - def _derivationAlternative (self):
3761 return self.__derivationAlternative
3762 __derivationAlternative = None 3763 3764 # Identify the sort of value collection this holds. This field is 3765 # used to identify unresolved definitions. 3766 __variety = None
3767 - def variety (self):
3768 return self.__variety
3769 @classmethod
3770 - def VarietyToString (cls, variety):
3771 """Convert a variety value to a string.""" 3772 if cls.VARIETY_absent == variety: 3773 return 'absent' 3774 if cls.VARIETY_atomic == variety: 3775 return 'atomic' 3776 if cls.VARIETY_list == variety: 3777 return 'list' 3778 if cls.VARIETY_union == variety: 3779 return 'union' 3780 return '?NoVariety?'
3781 3782 # For atomic variety only, the root (excepting ur-type) type. 3783 __primitiveTypeDefinition = None
3784 - def primitiveTypeDefinition (self, throw_if_absent=True):
3785 if throw_if_absent: 3786 if self.variety() != self.VARIETY_atomic: 3787 raise pyxb.BadPropertyError('[%s] primitiveTypeDefinition only defined for atomic types' % (self.name(), self.variety())) 3788 if self.__primitiveTypeDefinition is None: 3789 raise pyxb.LogicError('Expected primitive type for %s in %s', self, self.targetNamespace()) 3790 return self.__primitiveTypeDefinition
3791 3792 # For list variety only, the type of items in the list 3793 __itemTypeDefinition = None
3794 - def itemTypeDefinition (self):
3795 if self.VARIETY_list != self.variety(): 3796 raise pyxb.BadPropertyError('itemTypeDefinition only defined for list types') 3797 if self.__itemTypeDefinition is None: 3798 raise pyxb.LogicError('Expected item type') 3799 return self.__itemTypeDefinition
3800 3801 # For union variety only, the sequence of candidate members 3802 __memberTypeDefinitions = None
3803 - def memberTypeDefinitions (self):
3804 if self.VARIETY_union != self.variety(): 3805 raise pyxb.BadPropertyError('memberTypeDefinitions only defined for union types') 3806 if self.__memberTypeDefinitions is None: 3807 raise pyxb.LogicError('Expected member types') 3808 return self.__memberTypeDefinitions
3809 3810 # bR:STD
3811 - def _bindingRequires_vx (self, include_lax):
3812 """Implement base class method. 3813 3814 This STD depends on its baseTypeDefinition, unless its variety 3815 is absent. Other dependencies are on item, primitive, or 3816 member type definitions.""" 3817 type_definitions = set() 3818 if self != self.baseTypeDefinition(): 3819 type_definitions.add(self.baseTypeDefinition()) 3820 if self.VARIETY_absent == self.variety(): 3821 type_definitions = set() 3822 elif self.VARIETY_atomic == self.variety(): 3823 if self != self.primitiveTypeDefinition(): 3824 type_definitions.add(self.primitiveTypeDefinition()) 3825 elif self.VARIETY_list == self.variety(): 3826 assert self != self.itemTypeDefinition() 3827 type_definitions.add(self.itemTypeDefinition()) 3828 elif self.VARIETY_union == self.variety(): 3829 assert self not in self.memberTypeDefinitions() 3830 type_definitions.update(self.memberTypeDefinitions()) 3831 else: 3832 raise pyxb.LogicError('Unable to identify dependent types: variety %s' % (self.variety(),)) 3833 # NB: This type also depends on the value type definitions for 3834 # any facets that apply to it. This fact only matters when 3835 # generating the datatypes_facets source. That, and the fact 3836 # that there are dependency loops (e.g., integer requires a 3837 # nonNegativeInteger for its length facet) means we don't 3838 # bother adding in those. 3839 return frozenset(type_definitions)
3840 3841 # A non-property field that holds a reference to the DOM node from 3842 # which the type is defined. The value is held only between the 3843 # point where the simple type definition instance is created until 3844 # the point it is resolved. 3845 __domNode = None 3846 3847 # Indicate that this instance was defined as a built-in rather 3848 # than from a DOM instance. 3849 __isBuiltin = False 3850 3851 # Allocate one of these. Users should use one of the Create* 3852 # factory methods instead. 3853
3854 - def __init__ (self, *args, **kw):
3855 super(SimpleTypeDefinition, self).__init__(*args, **kw) 3856 self.__variety = kw['variety']
3857
3858 - def __setstate__ (self, state):
3859 """Extend base class unpickle support to retain link between 3860 this instance and the Python class that it describes. 3861 3862 This is because the pythonSupport value is a class reference, 3863 not an instance reference, so it wasn't deserialized, and its 3864 class member link was never set. 3865 """ 3866 super_fn = getattr(super(SimpleTypeDefinition, self), '__setstate__', lambda _state: self.__dict__.update(_state)) 3867 super_fn(state) 3868 if self.__pythonSupport is not None: 3869 self.__pythonSupport._SimpleTypeDefinition(self)
3870
3871 - def __str__ (self):
3872 if self.name() is not None: 3873 elts = [ self.name(), ':' ] 3874 else: 3875 elts = [ '<anonymous>:' ] 3876 if self.VARIETY_absent == self.variety(): 3877 elts.append('the ur-type') 3878 elif self.VARIETY_atomic == self.variety(): 3879 elts.append('restriction of %s' % (self.baseTypeDefinition().name(),)) 3880 elif self.VARIETY_list == self.variety(): 3881 elts.append('list of %s' % (self.itemTypeDefinition().name(),)) 3882 elif self.VARIETY_union == self.variety(): 3883 elts.append('union of %s' % (" ".join([str(_mtd.name()) for _mtd in self.memberTypeDefinitions()],))) 3884 else: 3885 # Gets here if the type has not been resolved. 3886 elts.append('?') 3887 #raise pyxb.LogicError('Unexpected variety %s' % (self.variety(),)) 3888 if self.__facets: 3889 felts = [] 3890 for (k, v) in self.__facets.items(): 3891 if v is not None: 3892 felts.append(str(v)) 3893 elts.append("\n %s" % (','.join(felts),)) 3894 if self.__fundamentalFacets: 3895 elts.append("\n ") 3896 elts.append(','.join( [str(_f) for _f in self.__fundamentalFacets ])) 3897 return 'STD[%s]' % (''.join(elts),)
3898
3899 - def _updateFromOther_csc (self, other):
3900 """Override fields in this instance with those from the other. 3901 3902 This method is invoked only by Schema._addNamedComponent, and 3903 then only when a built-in type collides with a schema-defined 3904 type. Material like facets is not (currently) held in the 3905 built-in copy, so the DOM information is copied over to the 3906 built-in STD, which is subsequently re-resolved. 3907 3908 Returns self. 3909 """ 3910 assert self != other 3911 assert self.isNameEquivalent(other) 3912 super(SimpleTypeDefinition, self)._updateFromOther_csc(other) 3913 3914 # The other STD should be an unresolved schema-defined type. 3915 assert other.__baseTypeDefinition is None, 'Update from resolved STD %s' % (other,) 3916 assert other.__domNode is not None 3917 self.__domNode = other.__domNode 3918 3919 # Preserve the python support 3920 if other.__pythonSupport is not None: 3921 # @todo: ERROR multiple references 3922 self.__pythonSupport = other.__pythonSupport 3923 3924 # Mark this instance as unresolved so it is re-examined 3925 self.__variety = None 3926 return self
3927
3928 - def isBuiltin (self):
3929 """Indicate whether this simple type is a built-in type.""" 3930 return self.__isBuiltin
3931 3932 __SimpleUrTypeDefinition = None 3933 @classmethod
3934 - def SimpleUrTypeDefinition (cls, schema=None, in_builtin_definition=False):
3935 """Create the SimpleTypeDefinition instance that approximates the simple ur-type. 3936 3937 See section 3.14.7.""" 3938 3939 #if in_builtin_definition and (cls.__SimpleUrTypeDefinition is not None): 3940 # raise pyxb.LogicError('Multiple definitions of SimpleUrType') 3941 if cls.__SimpleUrTypeDefinition is None: 3942 # Note: We use a singleton subclass 3943 assert schema is not None 3944 3945 ns_ctx = schema.targetNamespace().initialNamespaceContext() 3946 3947 kw = { 'name' : 'anySimpleType', 3948 'schema' : schema, 3949 'namespace_context' : ns_ctx, 3950 'binding_namespace' : schema.targetNamespace(), 3951 'variety' : cls.VARIETY_absent, 3952 'scope' : _ScopedDeclaration_mixin.SCOPE_global } 3953 bi = _SimpleUrTypeDefinition(**kw) 3954 bi._setPythonSupport(datatypes.anySimpleType) 3955 3956 # The baseTypeDefinition is the ur-type. 3957 bi.__baseTypeDefinition = ComplexTypeDefinition.UrTypeDefinition() 3958 # The simple ur-type has an absent variety, not an atomic 3959 # variety, so does not have a primitiveTypeDefinition 3960 3961 # No facets on the ur type 3962 bi.__facets = {} 3963 bi.__fundamentalFacets = frozenset() 3964 3965 bi.__resolveBuiltin() 3966 3967 cls.__SimpleUrTypeDefinition = bi 3968 return cls.__SimpleUrTypeDefinition
3969 3970 @classmethod
3971 - def _CreateXMLInstance (cls, name, schema):
3972 """Create STD instances for built-in types. 3973 3974 For example, xml:space is a restriction of NCName; xml:lang is a union. 3975 3976 """ 3977 from pyxb.binding import xml_ 3978 kw = { 'schema' : schema, 3979 'binding_namespace' : schema.targetNamespace(), 3980 'namespace_context' : schema.targetNamespace().initialNamespaceContext(), 3981 'scope' : _ScopedDeclaration_mixin.SCOPE_global, 3982 'variety' : cls.VARIETY_atomic } 3983 if 'space' == name: 3984 bi = cls(**kw) 3985 bi.__derivationAlternative = cls._DA_restriction 3986 bi.__baseTypeDefinition = datatypes.NCName.SimpleTypeDefinition() 3987 bi.__primitiveTypeDefinition = bi.__baseTypeDefinition.__primitiveTypeDefinition 3988 bi._setPythonSupport(xml_.STD_ANON_space) 3989 bi.setNameInBinding('STD_ANON_space') 3990 elif 'lang' == name: 3991 bi = cls(**kw) 3992 bi.__baseTypeDefinition = cls.SimpleUrTypeDefinition() 3993 bi.__memberTypes = [ datatypes.language.SimpleTypeDefinition() ] 3994 bi.__derivationAlternative = cls._DA_union 3995 bi.__primitiveTypeDefinition = bi 3996 bi._setPythonSupport(xml_.STD_ANON_lang) 3997 bi.setNameInBinding('STD_ANON_lang') 3998 else: 3999 raise pyxb.IncompleteImplementationError('No implementation for %s' % (name,)) 4000 bi.__facets = { } 4001 for v in bi.pythonSupport().__dict__.values(): 4002 if isinstance(v, facets.ConstrainingFacet): 4003 bi.__facets[v.__class__] = v 4004 return bi
4005 4006 @classmethod
4007 - def CreatePrimitiveInstance (cls, name, schema, python_support):
4008 """Create a primitive simple type in the target namespace. 4009 4010 This is mainly used to pre-load standard built-in primitive 4011 types, such as those defined by XMLSchema Datatypes. You can 4012 use it for your own schemas as well, if you have special types 4013 that require explicit support to for Pythonic conversion. 4014 4015 All parameters are required and must be non-None. 4016 """ 4017 4018 kw = { 'name' : name, 4019 'schema' : schema, 4020 'binding_namespace' : schema.targetNamespace(), 4021 'namespace_context' : schema.targetNamespace().initialNamespaceContext(), 4022 'scope' : _ScopedDeclaration_mixin.SCOPE_global, 4023 'variety' : cls.VARIETY_atomic } 4024 4025 bi = cls(**kw) 4026 bi._setPythonSupport(python_support) 4027 4028 # Primitive types are based on the ur-type, and have 4029 # themselves as their primitive type definition. 4030 bi.__baseTypeDefinition = cls.SimpleUrTypeDefinition() 4031 bi.__primitiveTypeDefinition = bi 4032 4033 # Primitive types are built-in 4034 bi.__resolveBuiltin() 4035 assert bi.isResolved() 4036 return bi
4037 4038 @classmethod
4039 - def CreateDerivedInstance (cls, name, schema, parent_std, python_support):
4040 """Create a derived simple type in the target namespace. 4041 4042 This is used to pre-load standard built-in derived types. You 4043 can use it for your own schemas as well, if you have special 4044 types that require explicit support to for Pythonic 4045 conversion. 4046 """ 4047 assert parent_std 4048 assert parent_std.__variety in (cls.VARIETY_absent, cls.VARIETY_atomic) 4049 kw = { 'name' : name, 4050 'schema' : schema, 4051 'binding_namespace' : schema.targetNamespace(), 4052 'namespace_context' : schema.targetNamespace().initialNamespaceContext(), 4053 'scope' : _ScopedDeclaration_mixin.SCOPE_global, 4054 'variety' : parent_std.__variety } 4055 4056 bi = cls(**kw) 4057 bi._setPythonSupport(python_support) 4058 4059 # We were told the base type. If this is atomic, we re-use 4060 # its primitive type. Note that these all may be in different 4061 # namespaces. 4062 bi.__baseTypeDefinition = parent_std 4063 if cls.VARIETY_atomic == bi.__variety: 4064 bi.__primitiveTypeDefinition = bi.__baseTypeDefinition.__primitiveTypeDefinition 4065 4066 # Derived types are built-in 4067 bi.__resolveBuiltin() 4068 return bi
4069 4070 @classmethod
4071 - def CreateListInstance (cls, name, schema, item_std, python_support):
4072 """Create a list simple type in the target namespace. 4073 4074 This is used to preload standard built-in list types. You can 4075 use it for your own schemas as well, if you have special types 4076 that require explicit support to for Pythonic conversion; but 4077 note that such support is identified by the item_std. 4078 """ 4079 4080 kw = { 'name' : name, 4081 'schema' : schema, 4082 'binding_namespace' : schema.targetNamespace(), 4083 'namespace_context' : schema.targetNamespace().initialNamespaceContext(), 4084 'scope' : _ScopedDeclaration_mixin.SCOPE_global, 4085 'variety' : cls.VARIETY_list } 4086 bi = cls(**kw) 4087 bi._setPythonSupport(python_support) 4088 4089 # The base type is the ur-type. We were given the item type. 4090 bi.__baseTypeDefinition = cls.SimpleUrTypeDefinition() 4091 assert item_std 4092 bi.__itemTypeDefinition = item_std 4093 4094 # List types are built-in 4095 bi.__resolveBuiltin() 4096 return bi
4097 4098 @classmethod
4099 - def CreateUnionInstance (cls, name, schema, member_stds):
4100 """(Placeholder) Create a union simple type in the target namespace. 4101 4102 This function has not been implemented.""" 4103 raise pyxb.IncompleteImplementationError('No support for built-in union types')
4104
4105 - def __singleSimpleTypeChild (self, body, other_elts_ok=False):
4106 simple_type_child = None 4107 for cn in body.childNodes: 4108 if (Node.ELEMENT_NODE == cn.nodeType): 4109 if not xsd.nodeIsNamed(cn, 'simpleType'): 4110 if other_elts_ok: 4111 continue 4112 raise pyxb.SchemaValidationError('Context requires element to be xs:simpleType') 4113 assert not simple_type_child 4114 simple_type_child = cn 4115 if simple_type_child is None: 4116 raise pyxb.SchemaValidationError('Content requires an xs:simpleType member (or a base attribute)') 4117 return simple_type_child
4118 4119 # The __initializeFrom* methods are responsible for identifying 4120 # the variety and the baseTypeDefinition. The remainder of the 4121 # resolution is performed by the __completeResolution method. 4122 # Note that in some cases resolution might yet be premature, so 4123 # variety is not saved until it is complete. All this stuff is 4124 # from section 3.14.2. 4125
4126 - def __initializeFromList (self, body, **kw):
4127 self.__baseTypeDefinition = self.SimpleUrTypeDefinition() 4128 self.__itemTypeAttribute = domutils.NodeAttribute(body, 'itemType') 4129 if self.__itemTypeAttribute is None: 4130 # NOTE: The newly created anonymous item type will 4131 # not be resolved; the caller needs to handle 4132 # that. 4133 self.__itemTypeDefinition = self.CreateFromDOM(self.__singleSimpleTypeChild(body), **kw) 4134 return self.__completeResolution(body, self.VARIETY_list, self._DA_list)
4135
4136 - def __initializeFromRestriction (self, body, **kw):
4137 if self.__baseTypeDefinition is None: 4138 self.__baseAttribute = domutils.NodeAttribute(body, 'base') 4139 if self.__baseAttribute is None: 4140 self.__baseTypeDefinition = self.CreateFromDOM(self.__singleSimpleTypeChild(body, other_elts_ok=True), **kw) 4141 return self.__completeResolution(body, None, self._DA_restriction)
4142 4143 __localMemberTypes = None
4144 - def __initializeFromUnion (self, body, **kw):
4145 self.__baseTypeDefinition = self.SimpleUrTypeDefinition() 4146 self.__memberTypesAttribute = domutils.NodeAttribute(body, 'memberTypes') 4147 if self.__localMemberTypes is None: 4148 self.__localMemberTypes = [] 4149 for cn in body.childNodes: 4150 if (Node.ELEMENT_NODE == cn.nodeType) and xsd.nodeIsNamed(cn, 'simpleType'): 4151 self.__localMemberTypes.append(self.CreateFromDOM(cn, **kw)) 4152 return self.__completeResolution(body, self.VARIETY_union, self._DA_union)
4153
4154 - def __resolveBuiltin (self):
4155 if self.hasPythonSupport(): 4156 self.__facets = { } 4157 for v in self.pythonSupport().__dict__.values(): 4158 if isinstance(v, facets.ConstrainingFacet): 4159 self.__facets[v.__class__] = v 4160 if v.ownerTypeDefinition() is None: 4161 v.setFromKeywords(_constructor=True, owner_type_definition=self) 4162 self.__isBuiltin = True 4163 return self
4164
4165 - def __defineDefaultFacets (self, variety):
4166 """Create facets for varieties that can take facets that are undeclared. 4167 4168 This means unions, which per section 4.1.2.3 of 4169 http://www.w3.org/TR/xmlschema-2/ can have enumeration or 4170 pattern restrictions.""" 4171 if self.VARIETY_union != variety: 4172 return self 4173 self.__facets.setdefault(facets.CF_pattern) 4174 self.__facets.setdefault(facets.CF_enumeration) 4175 return self
4176
4177 - def __processHasFacetAndProperty (self, variety):
4178 """Identify the facets and properties for this stype. 4179 4180 This method simply identifies the facets that apply to this 4181 specific type, and records property values. Only 4182 explicitly-associated facets and properties are stored; others 4183 from base types will also affect this type. The information 4184 is taken from the applicationInformation children of the 4185 definition's annotation node, if any. If there is no support 4186 for the XMLSchema_hasFacetAndProperty namespace, this is a 4187 no-op. 4188 4189 Upon return, self.__facets is a map from the class for an 4190 associated fact to None, and self.__fundamentalFacets is a 4191 frozenset of instances of FundamentalFacet. 4192 4193 The return value is self. 4194 """ 4195 self.__facets = { } 4196 self.__fundamentalFacets = frozenset() 4197 if self.annotation() is None: 4198 return self.__defineDefaultFacets(variety) 4199 app_info = self.annotation().applicationInformation() 4200 if app_info is None: 4201 return self.__defineDefaultFacets(variety) 4202 facet_map = { } 4203 fundamental_facets = set() 4204 seen_facets = set() 4205 for ai in app_info: 4206 for cn in ai.childNodes: 4207 if Node.ELEMENT_NODE != cn.nodeType: 4208 continue 4209 if pyxb.namespace.XMLSchema_hfp.nodeIsNamed(cn, 'hasFacet'): 4210 facet_name = domutils.NodeAttribute(cn, 'name')# , pyxb.namespace.XMLSchema_hfp) 4211 if facet_name is None: 4212 raise pyxb.SchemaValidationError('hasFacet missing name attribute in %s' % (cn,)) 4213 if facet_name in seen_facets: 4214 raise pyxb.SchemaValidationError('Multiple hasFacet specifications for %s' % (facet_name,)) 4215 seen_facets.add(facet_name) 4216 facet_class = facets.ConstrainingFacet.ClassForFacet(facet_name) 4217 #facet_map[facet_class] = facet_class(base_type_definition=self) 4218 facet_map[facet_class] = None 4219 if pyxb.namespace.XMLSchema_hfp.nodeIsNamed(cn, 'hasProperty'): 4220 fundamental_facets.add(facets.FundamentalFacet.CreateFromDOM(cn, self)) 4221 if 0 < len(facet_map): 4222 assert self.__baseTypeDefinition == self.SimpleUrTypeDefinition() 4223 self.__facets = facet_map 4224 assert type(self.__facets) == types.DictType 4225 if 0 < len(fundamental_facets): 4226 self.__fundamentalFacets = frozenset(fundamental_facets) 4227 return self
4228 4229 # NB: Must be done after resolution of the base type
4230 - def __updateFacets (self, body):
4231 4232 # Create local list consisting of facet classes matched in children 4233 # and the map of keywords used to initialize the local instance. 4234 4235 local_facets = {} 4236 for fc in facets.Facet.Facets: 4237 children = domutils.LocateMatchingChildren(body, fc.Name()) 4238 if 0 < len(children): 4239 fi = fc(base_type_definition=self.__baseTypeDefinition, 4240 owner_type_definition=self) 4241 if isinstance(fi, facets._LateDatatype_mixin): 4242 fi.bindValueDatatype(self) 4243 for cn in children: 4244 kw = { 'annotation': domutils.LocateUniqueChild(cn, 'annotation') } 4245 for ai in range(0, cn.attributes.length): 4246 attr = cn.attributes.item(ai) 4247 # Convert name from unicode to string 4248 kw[str(attr.localName)] = attr.value 4249 try: 4250 fi.setFromKeywords(**kw) 4251 except pyxb.PyXBException, e: 4252 raise pyxb.SchemaValidationError('Error assigning facet %s in %s: %s' % (fc.Name(), self.expandedName(), e)) 4253 local_facets[fc] = fi 4254 self.__localFacets = local_facets 4255 4256 # We want a map from the union of the facet classes from this STD up 4257 # through its baseTypeDefinition (if present). Map elements should be 4258 # to None if the facet has not been constrained, or to the nearest 4259 # ConstrainingFacet instance if it is. ConstrainingFacet instances 4260 # created for local constraints also need a pointer to the 4261 # corresponding facet from the ancestor type definition, because those 4262 # constraints also affect this type. 4263 base_facets = {} 4264 4265 # Built-ins didn't get their facets() setting configured, so use the 4266 # _FacetMap() instead. 4267 if self.__baseTypeDefinition.isBuiltin(): 4268 pstd = self.__baseTypeDefinition.pythonSupport() 4269 if pstd != datatypes.anySimpleType: 4270 base_facets.update(pstd._FacetMap()) 4271 elif self.__baseTypeDefinition.facets(): 4272 assert type(self.__baseTypeDefinition.facets()) == types.DictType 4273 base_facets.update(self.__baseTypeDefinition.facets()) 4274 base_facets.update(self.facets()) 4275 4276 self.__facets = self.__localFacets 4277 for fc in base_facets.keys(): 4278 self.__facets.setdefault(fc, base_facets[fc]) 4279 assert type(self.__facets) == types.DictType
4280
4281 - def _createRestriction (self, owner, body):
4282 """Create a new simple type with this as its base. 4283 4284 The type is owned by the provided owner, and may have facet 4285 restrictions defined by the body. 4286 @param owner: the owner for the newly created type 4287 @type owner: L{ComplexTypeDefinition} 4288 @param body: the DOM node from which facet information will be extracted 4289 @type body: C{xml.dom.Node} 4290 @rtype: L{SimpleTypeDefinition} 4291 """ 4292 std = SimpleTypeDefinition(owner=owner, namespace_context=owner._namespaceContext(), variety=None, scope=self._scope(), schema=owner._schema()) 4293 std.__baseTypeDefinition = self 4294 return std.__completeResolution(body, None, self._DA_restriction)
4295 4296 # Complete the resolution of some variety of STD. Note that the 4297 # variety is compounded by an alternative, since there is no 4298 # 'restriction' variety.
4299 - def __completeResolution (self, body, variety, alternative):
4300 assert self.__variety is None 4301 if self.__baseTypeDefinition is None: 4302 assert self.__baseAttribute is not None 4303 base_en = self._namespaceContext().interpretQName(self.__baseAttribute) 4304 base_type = base_en.typeDefinition() 4305 if not isinstance(base_type, SimpleTypeDefinition): 4306 raise pyxb.SchemaValidationError('Unable to locate base type %s' % (base_en,)) 4307 self.__baseTypeDefinition = base_type 4308 # If the base type exists but has not yet been resolved, 4309 # delay processing this type until the one it depends on 4310 # has been completed. 4311 assert self.__baseTypeDefinition != self 4312 if not self.__baseTypeDefinition.isResolved(): 4313 self._queueForResolution('base type %s is not resolved' % (self.__baseTypeDefinition,), depends_on=self.__baseTypeDefinition) 4314 return self 4315 if variety is None: 4316 # 3.14.1 specifies that the variety is the variety of the base 4317 # type definition which, by the way, can't be the ur type. 4318 variety = self.__baseTypeDefinition.__variety 4319 assert variety is not None 4320 4321 if self.VARIETY_absent == variety: 4322 # The ur-type is always resolved. So are restrictions of it, 4323 # which is how we might get here. 4324 pass 4325 elif self.VARIETY_atomic == variety: 4326 # Atomic types (and their restrictions) use the primitive 4327 # type, which is the highest type that is below the 4328 # ur-type (which is not atomic). 4329 ptd = self 4330 while isinstance(ptd, SimpleTypeDefinition) and (self.VARIETY_atomic == ptd.__baseTypeDefinition.variety()): 4331 ptd = ptd.__baseTypeDefinition 4332 4333 self.__primitiveTypeDefinition = ptd 4334 elif self.VARIETY_list == variety: 4335 if self._DA_list == alternative: 4336 if self.__itemTypeAttribute is not None: 4337 it_en = self._namespaceContext().interpretQName(self.__itemTypeAttribute) 4338 self.__itemTypeDefinition = it_en.typeDefinition() 4339 if not isinstance(self.__itemTypeDefinition, SimpleTypeDefinition): 4340 raise pyxb.SchemaValidationError('Unable to locate STD %s for items' % (it_en,)) 4341 elif self._DA_restriction == alternative: 4342 self.__itemTypeDefinition = self.__baseTypeDefinition.__itemTypeDefinition 4343 else: 4344 raise pyxb.LogicError('completeResolution list variety with alternative %s' % (alternative,)) 4345 elif self.VARIETY_union == variety: 4346 if self._DA_union == alternative: 4347 # First time we try to resolve, create the member type 4348 # definitions. If something later prevents us from resolving 4349 # this type, we don't want to create them again, because we 4350 # might already have references to them. 4351 if self.__memberTypeDefinitions is None: 4352 mtd = [] 4353 # If present, first extract names from memberTypes, 4354 # and add each one to the list 4355 if self.__memberTypesAttribute is not None: 4356 for mn in self.__memberTypesAttribute.split(): 4357 # THROW if type has not been defined 4358 mn_en = self._namespaceContext().interpretQName(mn) 4359 std = mn_en.typeDefinition() 4360 if std is None: 4361 raise pyxb.SchemaValidationError('Unable to locate member type %s' % (mn_en,)) 4362 # Note: We do not need these to be resolved (here) 4363 assert isinstance(std, SimpleTypeDefinition) 4364 mtd.append(std) 4365 # Now look for local type definitions 4366 mtd.extend(self.__localMemberTypes) 4367 self.__memberTypeDefinitions = mtd 4368 assert None not in self.__memberTypeDefinitions 4369 4370 # Replace any member types that are themselves unions with the 4371 # members of those unions, in order. Note that doing this 4372 # might indicate we can't resolve this type yet, which is why 4373 # we separated the member list creation and the substitution 4374 # phases 4375 mtd = [] 4376 for mt in self.__memberTypeDefinitions: 4377 assert isinstance(mt, SimpleTypeDefinition) 4378 if not mt.isResolved(): 4379 self._queueForResolution('member type not resolved', depends_on=mt) 4380 return self 4381 if self.VARIETY_union == mt.variety(): 4382 mtd.extend(mt.memberTypeDefinitions()) 4383 else: 4384 mtd.append(mt) 4385 elif self._DA_restriction == alternative: 4386 assert self.__baseTypeDefinition 4387 # Base type should have been resolved before we got here 4388 assert self.__baseTypeDefinition.isResolved() 4389 mtd = self.__baseTypeDefinition.__memberTypeDefinitions 4390 assert mtd is not None 4391 else: 4392 raise pyxb.LogicError('completeResolution union variety with alternative %s' % (alternative,)) 4393 # Save a unique copy 4394 self.__memberTypeDefinitions = mtd[:] 4395 else: 4396 raise pyxb.LogicError('completeResolution with variety 0x%02x' % (variety,)) 4397 4398 # Determine what facets, if any, apply to this type. This 4399 # should only do something if this is a primitive type. 4400 self.__processHasFacetAndProperty(variety) 4401 self.__updateFacets(body) 4402 4403 self.__derivationAlternative = alternative 4404 self.__variety = variety 4405 self.__domNode = None 4406 return self
4407
4408 - def isResolved (self):
4409 """Indicate whether this simple type is fully defined. 4410 4411 Type resolution for simple types means that the corresponding 4412 schema component fields have been set. Specifically, that 4413 means variety, baseTypeDefinition, and the appropriate 4414 additional fields depending on variety. See _resolve() for 4415 more information. 4416 """ 4417 # Only unresolved nodes have an unset variety 4418 return (self.__variety is not None)
4419 4420 # STD:res
4421 - def _resolve (self):
4422 """Attempt to resolve the type. 4423 4424 Type resolution for simple types means that the corresponding 4425 schema component fields have been set. Specifically, that 4426 means variety, baseTypeDefinition, and the appropriate 4427 additional fields depending on variety. 4428 4429 All built-in STDs are resolved upon creation. Schema-defined 4430 STDs are held unresolved until the schema has been completely 4431 read, so that references to later schema-defined STDs can be 4432 resolved. Resolution is performed after the entire schema has 4433 been scanned and STD instances created for all 4434 topLevelSimpleTypes. 4435 4436 If a built-in STD is also defined in a schema (which it should 4437 be for XMLSchema), the built-in STD is kept, with the 4438 schema-related information copied over from the matching 4439 schema-defined STD. The former then replaces the latter in 4440 the list of STDs to be resolved. 4441 4442 Types defined by restriction have the same variety as the type 4443 they restrict. If a simple type restriction depends on an 4444 unresolved type, this method simply queues it for resolution 4445 in a later pass and returns. 4446 """ 4447 if self.__variety is not None: 4448 return self 4449 assert self.__domNode 4450 node = self.__domNode 4451 4452 kw = { 'owner' : self 4453 , 'schema' : self._schema() } 4454 4455 bad_instance = False 4456 # The guts of the node should be exactly one instance of 4457 # exactly one of these three types. 4458 candidate = domutils.LocateUniqueChild(node, 'list') 4459 if candidate: 4460 self.__initializeFromList(candidate, **kw) 4461 4462 candidate = domutils.LocateUniqueChild(node, 'restriction') 4463 if candidate: 4464 if self.__variety is None: 4465 self.__initializeFromRestriction(candidate, **kw) 4466 else: 4467 bad_instance = True 4468 4469 candidate = domutils.LocateUniqueChild(node, 'union') 4470 if candidate: 4471 if self.__variety is None: 4472 self.__initializeFromUnion(candidate, **kw) 4473 else: 4474 bad_instance = True 4475 4476 if self.__baseTypeDefinition is None: 4477 raise pyxb.SchemaValidationError('xs:simpleType must have list, union, or restriction as child') 4478 4479 if self._schema() is not None: 4480 self.__final = self._schema().finalForNode(node, self._STD_Map) 4481 4482 # It is NOT an error to fail to resolve the type. 4483 if bad_instance: 4484 raise pyxb.SchemaValidationError('Expected exactly one of list, restriction, union as child of simpleType') 4485 4486 return self
4487 4488 # CFD:STD CFD:SimpleTypeDefinition 4489 @classmethod
4490 - def CreateFromDOM (cls, node, **kw):
4491 # Node should be an XMLSchema simpleType node 4492 assert xsd.nodeIsNamed(node, 'simpleType') 4493 4494 name = domutils.NodeAttribute(node, 'name') 4495 4496 rv = cls(name=name, node=node, variety=None, **kw) 4497 rv._annotationFromDOM(node) 4498 4499 # Creation does not attempt to do resolution. Queue up the newly created 4500 # whatsis so we can resolve it after everything's been read in. 4501 rv.__domNode = node 4502 rv._queueForResolution('creation') 4503 4504 return rv
4505 4506 # pythonSupport is None, or a subclass of datatypes.simpleTypeDefinition. 4507 # When set, this simple type definition instance must be uniquely 4508 # associated with the python support type. 4509 __pythonSupport = None 4510
4511 - def _setPythonSupport (self, python_support):
4512 # Includes check that python_support is not None 4513 assert issubclass(python_support, basis.simpleTypeDefinition) 4514 # Can't share support instances 4515 self.__pythonSupport = python_support 4516 self.__pythonSupport._SimpleTypeDefinition(self) 4517 if self.nameInBinding() is None: 4518 self.setNameInBinding(self.__pythonSupport.__name__) 4519 return self.__pythonSupport
4520
4521 - def hasPythonSupport (self):
4522 return self.__pythonSupport is not None
4523
4524 - def pythonSupport (self):
4525 if self.__pythonSupport is None: 4526 raise pyxb.LogicError('%s: No support defined' % (self.name(),)) 4527 return self.__pythonSupport
4528
4529 - def stringToPython (self, string):
4530 return self.pythonSupport().stringToPython(string)
4531
4532 - def pythonToString (self, value):
4533 return self.pythonSupport().pythonToString(value)
4534
4535 -class _SimpleUrTypeDefinition (SimpleTypeDefinition, _Singleton_mixin):
4536 """Subclass ensures there is only one simple ur-type.""" 4537 pass
4538
4539 -class _ImportElementInformationItem (_Annotated_mixin):
4540 """Data associated with an 4541 U{import<http://www.w3.org/TR/xmlschema-1/#composition-schemaImport>} 4542 statement within a schema.""" 4543
4544 - def id (self):
4545 """The value of the C{id} attribute from the import statement.""" 4546 return self.__id
4547 __id = None 4548
4549 - def namespace (self):
4550 """The L{pyxb.namespace.Namespace} instance corresponding to the value 4551 of the C{namespace} attribute from the import statement.""" 4552 return self.__namespace
4553 __namespace = None 4554
4555 - def schemaLocation (self):
4556 """The value of the C{schemaLocation} attribute from the import 4557 statement, normalized relative to the location of the importing 4558 schema.""" 4559 return self.__schemaLocation
4560 __schemaLocation = None 4561
4562 - def prefix (self):
4563 """The prefix from a namespace declaration for L{namespace} that was 4564 active in the context of the import element, or C{None} if there was 4565 no relevant namespace declaration in scope at that point. 4566 4567 This is propagated to be used as the default prefix for the 4568 corresponding namespace if no prefix had been assigned. 4569 """ 4570 return self.__prefix
4571 __prefix = None 4572
4573 - def schema (self):
4574 """The L{Schema} instance corresponding to the imported schema, if 4575 available. 4576 4577 Normally C{import} statements will be fulfilled by loading components 4578 from a L{namespace archive<pyxb.namespace.NamespaceArchive>} in which 4579 the corresponding namespace is marked as public. Where there are 4580 cycles in the namespace dependency graph, or the schema for a 4581 namespace are associated with a restricted profile of another 4582 namespace, there may be no such archive and instead the components are 4583 obtained using this schema.""" 4584 return self.__schema
4585 __schema = None 4586
4587 - def __init__ (self, importing_schema, node, **kw):
4588 """Gather the information relative to an C{import} statement. 4589 4590 If the imported namespace can be loaded from an archive, the 4591 C{schemaLocation} attribute is ignored. Otherwise, it attempts to 4592 retrieve and parse the corresponding schema (if this has not already 4593 been done). 4594 4595 @param importing_schema: The L{Schema} instance in which the import 4596 was found. 4597 @param node: The C{xml.dom.DOM} node incorporating the schema 4598 information. 4599 4600 @raise Exception: Any exception raised when attempting to retrieve and 4601 parse data from the schema location. 4602 """ 4603 4604 super(_ImportElementInformationItem, self).__init__(**kw) 4605 uri = domutils.NodeAttribute(node, 'namespace') 4606 if uri is None: 4607 raise pyxb.IncompleteImplementationError('import statements without namespace not supported') 4608 schema_location = pyxb.utils.utility.NormalizeLocation(domutils.NodeAttribute(node, 'schemaLocation'), importing_schema.location()) 4609 self.__schemaLocation = schema_location 4610 ns = self.__namespace = pyxb.namespace.NamespaceForURI(uri, create_if_missing=True) 4611 need_schema = not (ns.isLoadable() or ns.isBuiltinNamespace()) 4612 if not need_schema: 4613 # Discard location if we expect to be able to learn about this 4614 # namespace from an archive or a built-in description 4615 self.__schemaLocation = None 4616 4617 ns_ctx = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(node) 4618 if self.schemaLocation() is not None: 4619 # @todo: NOTICE 4620 (has_schema, schema_instance) = self.__namespace.lookupSchemaByLocation(schema_location) 4621 if not has_schema: 4622 ckw = { 'absolute_schema_location' : schema_location, 4623 'generation_uid' : importing_schema.generationUID(), 4624 'uri_content_archive_directory' : importing_schema._uriContentArchiveDirectory(), 4625 } 4626 try: 4627 schema_instance = Schema.CreateFromLocation(**ckw) 4628 except Exception, e: 4629 _log.exception('Import %s cannot read schema location %s (%s)', ns, self.__schemaLocation, schema_location) 4630 raise 4631 self.__schema = schema_instance 4632 elif need_schema: 4633 _log.warning('No information available on imported namespace %s', uri) 4634 4635 # If we think we found a schema, make sure it's in the right 4636 # namespace. 4637 if self.__schema is not None: 4638 if ns != self.__schema.targetNamespace(): 4639 raise pyxb.SchemaValidationError('Import expected namespace %s but got %s' % (ns, self.__schema.targetNamespace())) 4640 4641 self.__prefix = ns_ctx.prefixForNamespace(self.namespace()) 4642 4643 self._annotationFromDOM(node)
4644
4645 -class Schema (_SchemaComponent_mixin):
4646 """An XMLSchema U{Schema<http://www.w3.org/TR/xmlschema-1/#Schemas>}.""" 4647
4648 - def __getstate__ (self):
4649 raise pyxb.LogicError('Attempt to serialize Schema instance')
4650 4651 # List of annotations 4652 __annotations = None 4653 4654 # True when we have started seeing elements, attributes, or 4655 # notations. 4656 __pastProlog = False 4657
4658 - def location (self):
4659 """URI or path to where the schema can be found. 4660 4661 For schema created by a user, the location should be provided to the 4662 constructor using the C{schema_location} keyword. In the case of 4663 imported or included schema, the including schema's location is used 4664 as the base URI for determining the absolute URI of the included 4665 schema from its (possibly relative) location value. For files, 4666 the scheme and authority portions are generally absent, as is often 4667 the abs_path part.""" 4668 return self.__location
4669 __location = None 4670
4671 - def locationTag (self):
4672 return self.__locationTag
4673 __locationTag = None 4674
4675 - def signature (self):
4676 return self.__signature
4677 __signature = None 4678
4679 - def generationUID (self):
4680 return self.__generationUID
4681 __generationUID = None 4682
4683 - def originRecord (self):
4684 return self.__originRecord
4685 __originRecord = None 4686
4687 - def targetNamespace (self):
4688 """The targetNamespace of a componen. 4689 4690 This is None, or a reference to a Namespace in which the 4691 component is declared (either as a global or local to one of 4692 the namespace's complex type definitions). This is immutable 4693 after creation. 4694 """ 4695 return self.__targetNamespace
4696 __targetNamespace = None 4697
4698 - def defaultNamespace (self):
4699 """Default namespace of the schema. 4700 4701 Will be None unless the schema has an 'xmlns' attribute. The 4702 value must currently be provided as a keyword parameter to the 4703 constructor. """ 4704 return self.__defaultNamespace
4705 __defaultNamespace = None 4706
4707 - def referencedNamespaces (self):
4708 return self.__referencedNamespaces
4709 __referencedNamespaces = None 4710 4711 __namespaceData = None 4712
4713 - def importEIIs (self):
4714 return self.__importEIIs
4715 __importEIIs = None 4716
4717 - def importedSchema (self):
4718 return self.__importedSchema
4719 __importedSchema = None
4720 - def includedSchema (self):
4721 return self.__includedSchema
4722 __includedSchema = None 4723 4724 _QUALIFIED = "qualified" 4725 _UNQUALIFIED = "unqualified" 4726 4727 # Default values for standard recognized schema attributes 4728 __attributeMap = { pyxb.namespace.ExpandedName(None, 'attributeFormDefault') : _UNQUALIFIED 4729 , pyxb.namespace.ExpandedName(None, 'elementFormDefault') : _UNQUALIFIED 4730 , pyxb.namespace.ExpandedName(None, 'blockDefault') : '' 4731 , pyxb.namespace.ExpandedName(None, 'finalDefault') : '' 4732 , pyxb.namespace.ExpandedName(None, 'id') : None 4733 , pyxb.namespace.ExpandedName(None, 'targetNamespace') : None 4734 , pyxb.namespace.ExpandedName(None, 'version') : None 4735 , pyxb.namespace.XML.createExpandedName('lang') : None 4736 } 4737
4738 - def _setAttributeFromDOM (self, attr):
4739 """Override the schema attribute with the given DOM value.""" 4740 self.__attributeMap[pyxb.namespace.ExpandedName(attr.name)] = attr.nodeValue 4741 return self
4742
4743 - def _setAttributesFromMap (self, attr_map):
4744 """Override the schema attributes with values from the given map.""" 4745 self.__attributeMap.update(attr_map) 4746 return self
4747
4748 - def schemaHasAttribute (self, attr_name):
4749 """Return True iff the schema has an attribute with the given (nc)name.""" 4750 if isinstance(attr_name, basestring): 4751 attr_name = pyxb.namespace.ExpandedName(None, attr_name) 4752 return self.__attributeMap.has_key(attr_name)
4753
4754 - def schemaAttribute (self, attr_name):
4755 """Return the schema attribute value associated with the given (nc)name. 4756 4757 @param attr_name: local name for the attribute in the schema element. 4758 @return: the value of the corresponding attribute, or C{None} if it 4759 has not been defined and has no default. 4760 @raise KeyError: C{attr_name} is not a valid attribute for a C{schema} element. 4761 """ 4762 if isinstance(attr_name, basestring): 4763 attr_name = pyxb.namespace.ExpandedName(None, attr_name) 4764 return self.__attributeMap[attr_name]
4765 4766 __SchemaCategories = ( 'typeDefinition', 'attributeGroupDefinition', 'modelGroupDefinition', 4767 'attributeDeclaration', 'elementDeclaration', 'notationDeclaration', 4768 'identityConstraintDefinition' ) 4769
4770 - def _uriContentArchiveDirectory (self):
4772 __uriContentArchiveDirectory = None 4773
4774 - def __init__ (self, *args, **kw):
4775 # Force resolution of available namespaces if not already done 4776 if not kw.get('_bypass_preload', False): 4777 pyxb.namespace.archive.NamespaceArchive.PreLoadArchives() 4778 4779 assert 'schema' not in kw 4780 self.__uriContentArchiveDirectory = kw.get('uri_content_archive_directory') 4781 self.__location = kw.get('schema_location') 4782 if self.__location is not None: 4783 schema_path = self.__location 4784 if 0 <= schema_path.find(':'): 4785 schema_path = urlparse.urlparse(schema_path)[2] # .path 4786 self.__locationTag = os.path.split(schema_path)[1].split('.')[0] 4787 4788 self.__generationUID = kw.get('generation_uid') 4789 if self.__generationUID is None: 4790 _log.warning('No generationUID provided') 4791 self.__generationUID = pyxb.utils.utility.UniqueIdentifier() 4792 4793 self.__signature = kw.get('schema_signature') 4794 4795 super(Schema, self).__init__(*args, **kw) 4796 self.__importEIIs = set() 4797 self.__includedSchema = set() 4798 self.__importedSchema = set() 4799 self.__targetNamespace = self._namespaceContext().targetNamespace() 4800 if not isinstance(self.__targetNamespace, pyxb.namespace.Namespace): 4801 raise pyxb.LogicError('Schema constructor requires valid Namespace instance as target_namespace') 4802 4803 # NB: This will raise pyxb.SchemaUniquenessError if it appears this 4804 # schema has already been incorporated into the target namespace. 4805 self.__originRecord = self.__targetNamespace.addSchema(self) 4806 4807 self.__targetNamespace.configureCategories(self.__SchemaCategories) 4808 if self.__defaultNamespace is not None: 4809 self.__defaultNamespace.configureCategories(self.__SchemaCategories) 4810 4811 self.__attributeMap = self.__attributeMap.copy() 4812 self.__annotations = [] 4813 # @todo: This isn't right if namespaces are introduced deeper in the document 4814 self.__referencedNamespaces = self._namespaceContext().inScopeNamespaces().values()
4815 4816 __TopLevelComponentMap = { 4817 'element' : ElementDeclaration, 4818 'attribute' : AttributeDeclaration, 4819 'notation' : NotationDeclaration, 4820 'simpleType' : SimpleTypeDefinition, 4821 'complexType' : ComplexTypeDefinition, 4822 'group' : ModelGroupDefinition, 4823 'attributeGroup' : AttributeGroupDefinition 4824 } 4825 4826 @classmethod
4827 - def CreateFromDocument (cls, xmls, **kw):
4828 if not ('schema_signature' in kw): 4829 kw['schema_signature'] = pyxb.utils.utility.HashForText(xmls) 4830 return cls.CreateFromDOM(domutils.StringToDOM(xmls, **kw), **kw)
4831 4832 @classmethod
4833 - def CreateFromLocation (cls, **kw):
4834 """Create a schema from a schema location. 4835 4836 Reads an XML document from the schema location and creates a schema 4837 using it. All keyword parameters are passed to L{CreateFromDOM}. 4838 4839 @keyword schema_location: A file path or a URI. If this is a relative 4840 URI and C{parent_uri} is present, the actual location will be 4841 L{normallzed<pyxb.utils.utility.NormalizeLocation>}. 4842 @keyword parent_uri: The context within which schema_location will be 4843 normalized, if necessary. 4844 @keyword absolute_schema_location: A file path or URI. This value is 4845 not normalized, and supersedes C{schema_location}. 4846 """ 4847 schema_location = kw.pop('absolute_schema_location', pyxb.utils.utility.NormalizeLocation(kw.get('schema_location'), kw.get('parent_uri'), kw.get('prefix_map'))) 4848 kw['location_base'] = kw['schema_location'] = schema_location 4849 assert isinstance(schema_location, basestring), 'Unexpected value %s type %s for schema_location' % (schema_location, type(schema_location)) 4850 uri_content_archive_directory = kw.get('uri_content_archive_directory') 4851 return cls.CreateFromDocument(pyxb.utils.utility.TextFromURI(schema_location, archive_directory=uri_content_archive_directory), **kw)
4852 4853 @classmethod
4854 - def CreateFromStream (cls, stream, **kw):
4855 return cls.CreateFromDocument(stream.read(), **kw)
4856 4857 @classmethod
4858 - def CreateFromDOM (cls, node, namespace_context=None, schema_location=None, schema_signature=None, generation_uid=None, **kw):
4859 """Take the root element of the document, and scan its attributes under 4860 the assumption it is an XMLSchema schema element. That means 4861 recognize namespace declarations and process them. Also look for 4862 and set the default namespace. All other attributes are passed up 4863 to the parent class for storage.""" 4864 4865 # Get the context of any schema that is including (not importing) this 4866 # one. 4867 including_context = kw.get('including_context') 4868 4869 root_node = node 4870 if Node.DOCUMENT_NODE == node.nodeType: 4871 root_node = root_node.documentElement 4872 if Node.ELEMENT_NODE != root_node.nodeType: 4873 raise pyxb.LogicError('Must be given a DOM node of type ELEMENT') 4874 4875 assert (namespace_context is None) or isinstance(namespace_context, pyxb.namespace.resolution.NamespaceContext) 4876 ns_ctx = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(root_node, 4877 parent_context=namespace_context, 4878 including_context=including_context) 4879 4880 tns = ns_ctx.targetNamespace() 4881 if tns is None: 4882 raise pyxb.SchemaValidationError('No targetNamespace associated with content (not a schema?)') 4883 schema = cls(namespace_context=ns_ctx, schema_location=schema_location, schema_signature=schema_signature, generation_uid=generation_uid, **kw) 4884 schema.__namespaceData = ns_ctx 4885 4886 if schema.targetNamespace() != ns_ctx.targetNamespace(): 4887 raise pyxb.SchemaValidationError('targetNamespace %s conflicts with %s' % (schema.targetNamespace(), ns_ctx.targetNamespace())) 4888 4889 # Update the attribute map 4890 for ai in range(root_node.attributes.length): 4891 schema._setAttributeFromDOM(root_node.attributes.item(ai)) 4892 4893 # Verify that the root node is an XML schema element 4894 if not xsd.nodeIsNamed(root_node, 'schema'): 4895 raise pyxb.SchemaValidationError('Root node %s of document is not an XML schema element' % (root_node.nodeName,)) 4896 4897 for cn in root_node.childNodes: 4898 if Node.ELEMENT_NODE == cn.nodeType: 4899 rv = schema.__processTopLevelNode(cn) 4900 if rv is None: 4901 _log.info('Unrecognized: %s %s', cn.nodeName, cn.toxml("utf-8")) 4902 elif Node.TEXT_NODE == cn.nodeType: 4903 # Non-element content really should just be whitespace. 4904 # If something else is seen, print it for inspection. 4905 text = cn.data.strip() 4906 if text: 4907 _log.info('Ignored text: %s', text) 4908 elif Node.COMMENT_NODE == cn.nodeType: 4909 pass 4910 else: 4911 # ATTRIBUTE_NODE 4912 # CDATA_SECTION_NODE 4913 # ENTITY_NODE 4914 # PROCESSING_INSTRUCTION 4915 # DOCUMENT_NODE 4916 # DOCUMENT_TYPE_NODE 4917 # NOTATION_NODE 4918 _log.info('Ignoring non-element: %s', cn) 4919 4920 # Do not perform resolution yet: we may be done with this schema, but 4921 # the namespace may incorporate additional ones, and we can't resolve 4922 # until everything's present. 4923 return schema
4924 4925 _SA_All = '#all' 4926
4927 - def __ebvForNode (self, attr, dom_node, candidate_map):
4928 ebv = domutils.NodeAttribute(dom_node, attr) 4929 if ebv is None: 4930 ebv = self.schemaAttribute('%sDefault' % (attr,)) 4931 rv = 0 4932 if ebv == self._SA_All: 4933 for v in candidate_map.values(): 4934 rv += v 4935 else: 4936 for candidate in ebv.split(): 4937 rv += candidate_map.get(candidate, 0) 4938 return rv
4939
4940 - def blockForNode (self, dom_node, candidate_map):
4941 """Return a bit mask indicating a set of options read from the node's "block" attribute or the schema's "blockDefault" attribute. 4942 4943 A value of '#all' means enable every options; otherwise, the attribute 4944 value should be a list of tokens, for which the corresponding value 4945 will be added to the return value. 4946 4947 @param dom_node: the node from which the "block" attribute will be retrieved 4948 @type dom_node: C{xml.dom.Node} 4949 @param candidate_map: map from strings to bitmask values 4950 """ 4951 return self.__ebvForNode('block', dom_node, candidate_map)
4952
4953 - def finalForNode (self, dom_node, candidate_map):
4954 """Return a bit mask indicating a set of options read from the node's 4955 "final" attribute or the schema's "finalDefault" attribute. 4956 4957 A value of '#all' means enable every options; otherwise, the attribute 4958 value should be a list of tokens, for which the corresponding value 4959 will be added to the return value. 4960 4961 @param dom_node: the node from which the "final" attribute will be retrieved 4962 @type dom_node: C{xml.dom.Node} 4963 @param candidate_map: map from strings to bitmask values 4964 """ 4965 return self.__ebvForNode('final', dom_node, candidate_map)
4966
4967 - def targetNamespaceForNode (self, dom_node, declaration_type):
4968 """Determine the target namespace for a local attribute or element declaration. 4969 4970 Look at the node's C{form} attribute, or if none the schema's 4971 C{attributeFormDefault} or C{elementFormDefault} value. If the 4972 resulting value is C{"qualified"} and the parent schema has a 4973 non-absent target namespace, return it to use as the declaration 4974 target namespace. Otherwise, return None to indicate that the 4975 declaration has no namespace. 4976 4977 @param dom_node: The node defining an element or attribute declaration 4978 @param declaration_type: Either L{AttributeDeclaration} or L{ElementDeclaration} 4979 @return: L{pyxb.namespace.Namespace} or None 4980 """ 4981 4982 form_type = domutils.NodeAttribute(dom_node, 'form') 4983 if form_type is None: 4984 if declaration_type == ElementDeclaration: 4985 form_type = self.schemaAttribute('elementFormDefault') 4986 elif declaration_type == AttributeDeclaration: 4987 form_type = self.schemaAttribute('attributeFormDefault') 4988 else: 4989 raise pyxb.LogicError('Expected ElementDeclaration or AttributeDeclaration: got %s' % (declaration_type,)) 4990 tns = None 4991 if (self._QUALIFIED == form_type): 4992 tns = self.targetNamespace() 4993 if tns.isAbsentNamespace(): 4994 tns = None 4995 else: 4996 if (self._UNQUALIFIED != form_type): 4997 raise pyxb.SchemaValidationError('Form type neither %s nor %s' % (self._QUALIFIED, self._UNQUALIFIED)) 4998 return tns
4999
5000 - def __requireInProlog (self, node_name):
5001 """Throw a SchemaValidationException referencing the given 5002 node if we have passed the sequence point representing the end 5003 of prolog elements.""" 5004 5005 if self.__pastProlog: 5006 raise pyxb.SchemaValidationError('Unexpected node %s after prolog' % (node_name,))
5007
5008 - def __processInclude (self, node):
5009 self.__requireInProlog(node.nodeName) 5010 # See section 4.2.1 of Structures. 5011 abs_uri = pyxb.utils.utility.NormalizeLocation(domutils.NodeAttribute(node, 'schemaLocation'), self.__location) 5012 (has_schema, schema_instance) = self.targetNamespace().lookupSchemaByLocation(abs_uri) 5013 if not has_schema: 5014 kw = { 'absolute_schema_location': abs_uri, 5015 'including_context': self.__namespaceData, 5016 'generation_uid': self.generationUID(), 5017 'uri_content_archive_directory': self._uriContentArchiveDirectory(), 5018 } 5019 try: 5020 schema_instance = self.CreateFromLocation(**kw) 5021 except pyxb.SchemaUniquenessError, e: 5022 _log.warning('Skipping apparent redundant inclusion of %s defining %s (hash matches %s)', e.schemaLocation(), e.namespace(), e.existingSchema().location()) 5023 except Exception, e: 5024 _log.exception('INCLUDE %s caught', abs_uri) 5025 raise 5026 if schema_instance: 5027 if self.targetNamespace() != schema_instance.targetNamespace(): 5028 raise pyxb.SchemaValidationError('Included namespace %s not consistent with including namespace %s' % (schema_instance.targetNamespace(), self.targetNamespace())) 5029 self.__includedSchema.add(schema_instance) 5030 return node
5031
5032 - def __processImport (self, node):
5033 """Process an import directive. 5034 5035 This attempts to locate schema (named entity) information for 5036 a namespace that is referenced by this schema. 5037 """ 5038 5039 self.__requireInProlog(node.nodeName) 5040 import_eii = _ImportElementInformationItem(self, node) 5041 if import_eii.schema() is not None: 5042 self.__importedSchema.add(import_eii.schema()) 5043 self.targetNamespace().importNamespace(import_eii.namespace()) 5044 ins = import_eii.namespace() 5045 if ins.prefix() is None: 5046 ins.setPrefix(import_eii.prefix()) 5047 self.__importEIIs.add(import_eii) 5048 return node
5049
5050 - def __processRedefine (self, node):
5051 self.__requireInProlog(node.nodeName) 5052 raise pyxb.IncompleteImplementationError('redefine not implemented')
5053
5054 - def __processAnnotation (self, node):
5055 self._addAnnotation(Annotation.CreateFromDOM(node)) 5056 return self
5057
5058 - def __processTopLevelNode (self, node):
5059 """Process a DOM node from the top level of the schema. 5060 5061 This should return a non-None value if the node was 5062 successfully recognized.""" 5063 if xsd.nodeIsNamed(node, 'include'): 5064 return self.__processInclude(node) 5065 if xsd.nodeIsNamed(node, 'import'): 5066 return self.__processImport(node) 5067 if xsd.nodeIsNamed(node, 'redefine'): 5068 return self.__processRedefine(node) 5069 if xsd.nodeIsNamed(node, 'annotation'): 5070 return self.__processAnnotation(node) 5071 5072 component = self.__TopLevelComponentMap.get(node.localName) 5073 if component is not None: 5074 self.__pastProlog = True 5075 kw = { 'scope' : _ScopedDeclaration_mixin.SCOPE_global, 5076 'schema' : self, 5077 'owner' : self } 5078 return self._addNamedComponent(component.CreateFromDOM(node, **kw)) 5079 5080 raise pyxb.SchemaValidationError('Unexpected top-level element %s' % (node.nodeName,))
5081
5082 - def _addAnnotation (self, annotation):
5083 self.__annotations.append(annotation) 5084 return annotation
5085
5086 - def _addNamedComponent (self, nc):
5087 tns = self.targetNamespace() 5088 assert tns is not None 5089 if not isinstance(nc, _NamedComponent_mixin): 5090 raise pyxb.LogicError('Attempt to add unnamed %s instance to dictionary' % (nc.__class__,)) 5091 if nc.isAnonymous(): 5092 raise pyxb.LogicError('Attempt to add anonymous component to dictionary: %s', (nc.__class__,)) 5093 if isinstance(nc, _ScopedDeclaration_mixin): 5094 assert _ScopedDeclaration_mixin.SCOPE_global == nc.scope() 5095 if isinstance(nc, (SimpleTypeDefinition, ComplexTypeDefinition)): 5096 return self.__addTypeDefinition(nc) 5097 if isinstance(nc, AttributeDeclaration): 5098 return self.__addAttributeDeclaration(nc) 5099 if isinstance(nc, AttributeGroupDefinition): 5100 return self.__addAttributeGroupDefinition(nc) 5101 if isinstance(nc, ModelGroupDefinition): 5102 return tns.addCategoryObject('modelGroupDefinition', nc.name(), nc) 5103 if isinstance(nc, ElementDeclaration): 5104 return tns.addCategoryObject('elementDeclaration', nc.name(), nc) 5105 if isinstance(nc, NotationDeclaration): 5106 return tns.addCategoryObject('notationDeclaration', nc.name(), nc) 5107 if isinstance(nc, IdentityConstraintDefinition): 5108 return tns.addCategoryObject('identityConstraintDefinition', nc.name(), nc) 5109 raise pyxb.IncompleteImplementationError('No support to record named component of type %s' % (nc.__class__,))
5110
5111 - def __addTypeDefinition (self, td):
5112 local_name = td.name() 5113 assert self.__targetNamespace 5114 tns = self.targetNamespace() 5115 old_td = tns.typeDefinitions().get(local_name) 5116 if (old_td is not None) and (old_td != td): 5117 if isinstance(td, ComplexTypeDefinition) != isinstance(old_td, ComplexTypeDefinition): 5118 raise pyxb.SchemaValidationError('Name %s used for both simple and complex types' % (td.name(),)) 5119 5120 if not old_td._allowUpdateFromOther(td): 5121 raise pyxb.SchemaValidationError('Attempt to re-define non-builtin type definition %s' % (tns.createExpandedName(local_name),)) 5122 5123 # Copy schema-related information from the new definition 5124 # into the old one, and continue to use the old one. 5125 td = tns._replaceComponent(td, old_td._updateFromOther(td)) 5126 else: 5127 tns.addCategoryObject('typeDefinition', td.name(), td) 5128 assert td is not None 5129 return td
5130
5131 - def __addAttributeDeclaration (self, ad):
5132 local_name = ad.name() 5133 assert self.__targetNamespace 5134 tns = self.targetNamespace() 5135 old_ad = tns.attributeDeclarations().get(local_name) 5136 if (old_ad is not None) and (old_ad != ad): 5137 if not old_ad._allowUpdateFromOther(ad): 5138 raise pyxb.SchemaValidationError('Attempt to re-define non-builtin attribute declaration %s' % (tns.createExpandedName(local_name),)) 5139 5140 # Copy schema-related information from the new definition 5141 # into the old one, and continue to use the old one. 5142 ad = tns._replaceComponent(ad, old_ad._updateFromOther(ad)) 5143 else: 5144 tns.addCategoryObject('attributeDeclaration', ad.name(), ad) 5145 assert ad is not None 5146 return ad
5147
5148 - def __addAttributeGroupDefinition (self, agd):
5149 local_name = agd.name() 5150 assert self.__targetNamespace 5151 tns = self.targetNamespace() 5152 old_agd = tns.attributeGroupDefinitions().get(local_name) 5153 if (old_agd is not None) and (old_agd != agd): 5154 if not old_agd._allowUpdateFromOther(agd): 5155 raise pyxb.SchemaValidationError('Attempt to re-define non-builtin attribute group definition %s' % (tns.createExpandedName(local_name),)) 5156 5157 # Copy schema-related information from the new definition 5158 # into the old one, and continue to use the old one. 5159 tns._replaceComponent(agd, old_agd._updateFromOther(agd)) 5160 else: 5161 tns.addCategoryObject('attributeGroupDefinition', agd.name(), agd) 5162 assert agd is not None 5163 return agd
5164
5165 - def __str__ (self):
5166 return 'SCH[%s]' % (self.location(),)
5167
5168 5169 -def _AddSimpleTypes (namespace):
5170 """Add to the schema the definitions of the built-in types of XMLSchema. 5171 This should only be invoked by L{pyxb.namespace} when the built-in 5172 namespaces are initialized. """ 5173 # Add the ur type 5174 #schema = namespace.schema() 5175 schema = Schema(namespace_context=pyxb.namespace.XMLSchema.initialNamespaceContext(), schema_location='URN:noLocation:PyXB:XMLSchema', generation_uid=pyxb.namespace.BuiltInObjectUID, _bypass_preload=True) 5176 td = schema._addNamedComponent(ComplexTypeDefinition.UrTypeDefinition(schema, in_builtin_definition=True)) 5177 assert td.isResolved() 5178 # Add the simple ur type 5179 td = schema._addNamedComponent(SimpleTypeDefinition.SimpleUrTypeDefinition(schema, in_builtin_definition=True)) 5180 assert td.isResolved() 5181 # Add definitions for all primitive and derived simple types 5182 pts_std_map = {} 5183 for dtc in datatypes._PrimitiveDatatypes: 5184 name = dtc.__name__.rstrip('_') 5185 td = schema._addNamedComponent(SimpleTypeDefinition.CreatePrimitiveInstance(name, schema, dtc)) 5186 assert td.isResolved() 5187 assert dtc.SimpleTypeDefinition() == td 5188 pts_std_map.setdefault(dtc, td) 5189 for dtc in datatypes._DerivedDatatypes: 5190 name = dtc.__name__.rstrip('_') 5191 parent_std = pts_std_map[dtc.XsdSuperType()] 5192 td = schema._addNamedComponent(SimpleTypeDefinition.CreateDerivedInstance(name, schema, parent_std, dtc)) 5193 assert td.isResolved() 5194 assert dtc.SimpleTypeDefinition() == td 5195 pts_std_map.setdefault(dtc, td) 5196 for dtc in datatypes._ListDatatypes: 5197 list_name = dtc.__name__.rstrip('_') 5198 element_name = dtc._ItemType.__name__.rstrip('_') 5199 element_std = schema.targetNamespace().typeDefinitions().get(element_name) 5200 assert element_std is not None 5201 td = schema._addNamedComponent(SimpleTypeDefinition.CreateListInstance(list_name, schema, element_std, dtc)) 5202 assert td.isResolved() 5203 global _PastAddBuiltInTypes 5204 _PastAddBuiltInTypes = True 5205 5206 return schema
5207 5208 import sys 5209 import pyxb.namespace.builtin 5210 pyxb.namespace.builtin._InitializeBuiltinNamespaces(sys.modules[__name__]) 5211 5212 ## Local Variables: 5213 ## fill-column:78 5214 ## End: 5215