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