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.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 return self
1456 1457 __substitutionGroupAttribute = None 1458 1459 __typeAttribute = None 1460 1461 __nillable = False
1462 - def nillable (self):
1463 return self.__nillable
1464 1465 __identityConstraintDefinitions = None
1467 """A list of IdentityConstraintDefinition instances.""" 1468 return self.__identityConstraintDefinitions
1469 1470 __substitutionGroupAffiliation = None
1472 """None, or a reference to an ElementDeclaration.""" 1473 return self.__substitutionGroupAffiliation
1474 1475 SGE_none = 0 #<<< No substitution group exclusion specified 1476 SGE_extension = 0x01 #<<< Substitution by an extension of the base type 1477 SGE_restriction = 0x02 #<<< Substitution by a restriction of the base type 1478 SGE_substitution = 0x04 #<<< Substitution by replacement (?) 1479 1480 _SGE_Map = { 'extension' : SGE_extension 1481 , 'restriction' : SGE_restriction } 1482 _DS_Map = _SGE_Map.copy() 1483 _DS_Map.update( { 'substitution' : SGE_substitution } ) 1484 1485 # Subset of SGE marks formed by bitmask. SGE_substitution is disallowed. 1486 __substitutionGroupExclusions = SGE_none 1487 1488 # Subset of SGE marks formed by bitmask 1489 __disallowedSubstitutions = SGE_none 1490 1491 __abstract = False
1492 - def abstract (self):
1493 return self.__abstract
1494
1495 - def hasWildcardElement (self):
1496 """Return False, since element declarations are not wildcards.""" 1497 return False
1498 1499 # bR:ED
1500 - def _bindingRequires_vx (self, include_lax):
1501 """Element declarations depend on the type definition of their 1502 content.""" 1503 return frozenset([self.__typeDefinition])
1504
1505 - def __init__ (self, *args, **kw):
1506 super(ElementDeclaration, self).__init__(*args, **kw)
1507 1508 # CFD:ED CFD:ElementDeclaration 1509 @classmethod
1510 - def CreateFromDOM (cls, node, **kw):
1511 """Create an element declaration from the given DOM node. 1512 1513 wxs is a Schema instance within which the element is being 1514 declared. 1515 1516 scope is the _ScopeDeclaration_mixin context into which the 1517 element declaration is recorded. It can be SCOPE_global, a 1518 complex type definition, or None in the case of elements 1519 declared in a named model group. 1520 1521 node is a DOM element. The name must be 'element', and the 1522 node must be in the XMLSchema namespace.""" 1523 1524 scope = kw['scope'] 1525 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or _ScopedDeclaration_mixin.IsValidScope(scope) 1526 1527 # Node should be an XMLSchema element node 1528 assert xsd.nodeIsNamed(node, 'element') 1529 1530 # Might be top-level, might be local 1531 name = domutils.NodeAttribute(node, 'name') 1532 if xsd.nodeIsNamed(node.parentNode, 'schema'): 1533 assert _ScopedDeclaration_mixin.SCOPE_global == scope 1534 elif domutils.NodeAttribute(node, 'ref') is None: 1535 # Scope may be None or a CTD. 1536 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition) 1537 else: 1538 raise pyxb.SchemaValidationError('Created reference as element declaration') 1539 1540 rv = cls(name=name, node=node, **kw) 1541 rv._annotationFromDOM(node) 1542 rv._valueConstraintFromDOM(node) 1543 1544 rv.__substitutionGroupAttribute = domutils.NodeAttribute(node, 'substitutionGroup') 1545 1546 kw.pop('node', None) 1547 kw['owner'] = rv 1548 1549 identity_constraints = [] 1550 for cn in node.childNodes: 1551 if (Node.ELEMENT_NODE == cn.nodeType) and xsd.nodeIsNamed(cn, 'key', 'unique', 'keyref'): 1552 identity_constraints.append(IdentityConstraintDefinition.CreateFromDOM(cn, **kw)) 1553 rv.__identityConstraintDefinitions = identity_constraints 1554 1555 rv.__typeDefinition = None 1556 rv.__typeAttribute = domutils.NodeAttribute(node, 'type') 1557 simpleType_node = domutils.LocateUniqueChild(node, 'simpleType') 1558 complexType_node = domutils.LocateUniqueChild(node, 'complexType') 1559 if rv.__typeAttribute is not None: 1560 if (simpleType_node is not None) and (complexType_node is not None): 1561 raise pyxb.SchemaValidationError('Cannot combine type attribute with simpleType or complexType child') 1562 if (rv.__typeDefinition is None) and (simpleType_node is not None): 1563 rv.__typeDefinition = SimpleTypeDefinition.CreateFromDOM(simpleType_node, **kw) 1564 if (rv.__typeDefinition is None) and (complexType_node is not None): 1565 rv.__typeDefinition = ComplexTypeDefinition.CreateFromDOM(complexType_node, **kw) 1566 if rv.__typeDefinition is None: 1567 if rv.__typeAttribute is None: 1568 # Scan for particle types which were supposed to be enclosed in a complexType 1569 for cn in node.childNodes: 1570 if Particle.IsParticleNode(cn): 1571 raise pyxb.SchemaValidationError('Node %s in element must be wrapped by complexType.' % (cn.localName,)) 1572 rv.__typeDefinition = ComplexTypeDefinition.UrTypeDefinition() 1573 rv.__isResolved = (rv.__typeDefinition is not None) and (rv.__substitutionGroupAttribute is None) 1574 if not rv.__isResolved: 1575 rv._queueForResolution('creation') 1576 1577 attr_val = domutils.NodeAttribute(node, 'nillable') 1578 if attr_val is not None: 1579 rv.__nillable = datatypes.boolean(attr_val) 1580 1581 attr_val = domutils.NodeAttribute(node, 'abstract') 1582 if attr_val is not None: 1583 rv.__abstract = datatypes.boolean(attr_val) 1584 1585 schema = kw['schema'] 1586 rv.__disallowedSubstitutions = schema.blockForNode(node, cls._DS_Map) 1587 rv.__substitutionGroupExclusions = schema.finalForNode(node, cls._SGE_Map) 1588 1589 return rv
1590
1591 - def isAdaptable (self, ctd):
1592 """Determine whether this element declaration is adaptable. 1593 1594 OK, this gets ugly. First, if this declaration isn't resolved, it's 1595 clearly not adaptable. 1596 1597 Now: For it to be adaptable, we must know enough about its type to 1598 verify that it is derivation-consistent with any other uses of the 1599 same name in the same complex type. If the element's type is 1600 resolved, that's good enough. 1601 1602 If the element's type isn't resolved, we're golden as long as 1603 type-equivalent types were used. But it's also allowed for the 1604 derived ctd to use the element name constraining it to a derivation of 1605 the element base type. (Go see namespace 1606 http://www.opengis.net/ows/1.1 types PositionType, PositionType2D, 1607 BoundingBox, and WGS84BoundingBox for an example). So, we really do 1608 have to have the element's type resolved. 1609 1610 Except that if a CTD's content incorporates an element with the same 1611 type as the CTD (i.e., nested), this will never happen, because the 1612 CTD can't get resolved until after it has been resolved. 1613 (Go see {http://www.opengis.net/ows/1.1}ContentsBaseType and 1614 {http://www.opengis.net/ows/1.1}DatasetDescriptionSummaryBaseType for 1615 an example). 1616 1617 So, we give the world a break and assume that if the type we're trying 1618 to resolve is the same as the type of an element in that type, then 1619 the element type will be resolved by the point it's needed. In point 1620 of fact, it won't, but we'll only notice that if a CTD contains an 1621 element whose type is a restriction of the CTD. In that case, 1622 isDerivationConsistent will blow chunks and somebody'll have to come 1623 back and finish up this mess. 1624 """ 1625 1626 if not self.isResolved(): 1627 return False 1628 if self.typeDefinition().isResolved(): 1629 return True 1630 # Aw, dammit. See if we're gonna need the type resolved before we can 1631 # adapt this thing. 1632 existing_decl = ctd.lookupScopedElementDeclaration(self.expandedName()) 1633 if existing_decl is None: 1634 # Nobody else has this name, so we don't have to check for 1635 # consistency. 1636 return True 1637 # OK, we've got a name clash. Are the two types trivially equivalent? 1638 if self.typeDefinition().isTypeEquivalent(existing_decl.typeDefinition()): 1639 # Yes! Go for it. 1640 return True 1641 # No. Can't proceed until the type definition is resolved. Hope it 1642 # can be.... 1643 _log.warning('Require %s to be resolved; might be a loop.', self.typeDefinition()) 1644 return False
1645 1646 # aFS:ED
1647 - def _adaptForScope (self, owner, ctd):
1648 rv = self 1649 assert isinstance(ctd, ComplexTypeDefinition), '%s is not a CTD' % (ctd,) 1650 if not isinstance(self.scope(), ComplexTypeDefinition): 1651 assert owner is not None 1652 rv = self._clone(owner, ctd._objectOrigin()) 1653 rv._setScope(ctd) 1654 ctd._recordLocalDeclaration(rv) 1655 return rv
1656 1657 __isResolved = False
1658 - def isResolved (self):
1659 return self.__isResolved
1660 1661 # res:ED res:ElementDeclaration
1662 - def _resolve (self):
1663 if self.isResolved(): 1664 return self 1665 1666 #if self._scopeIsIndeterminate(): 1667 # _log.debug('WARNING: Resolving ED %s with indeterminate scope (is this a problem?)', self.expandedName()) 1668 if self.__substitutionGroupAttribute is not None: 1669 sg_en = self._namespaceContext().interpretQName(self.__substitutionGroupAttribute) 1670 sga = sg_en.elementDeclaration() 1671 if sga is None: 1672 raise pyxb.SchemaValidationError('Element declaration refers to unrecognized substitution group %s' % (sg_en,)) 1673 self.__substitutionGroupAffiliation = sga 1674 1675 if self.__typeDefinition is None: 1676 assert self.__typeAttribute is not None 1677 type_en = self._namespaceContext().interpretQName(self.__typeAttribute) 1678 self.__typeDefinition = type_en.typeDefinition() 1679 if self.__typeDefinition is None: 1680 raise pyxb.SchemaValidationError('Type declaration %s cannot be found' % (type_en,)) 1681 1682 self.__isResolved = True 1683 return self
1684
1685 - def _walkParticleTree (self, visit, arg):
1686 visit(self, None, arg)
1687
1688 - def __str__ (self):
1689 if self.typeDefinition() is not None: 1690 return 'ED[%s:%s]' % (self.name(), self.typeDefinition().name()) 1691 return 'ED[%s:?]' % (self.name(),)
1692
1693 1694 -class ComplexTypeDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _AttributeWildcard_mixin):
1695 __PrivateTransient = set() 1696 1697 # The type resolved from the base attribute. 1698 __baseTypeDefinition = None
1699 - def baseTypeDefinition (self):
1700 "The type resolved from the base attribute.""" 1701 return self.__baseTypeDefinition
1702 1703 DM_empty = 0 #<<< No derivation method specified 1704 DM_extension = 0x01 #<<< Derivation by extension 1705 DM_restriction = 0x02 #<<< Derivation by restriction 1706 1707 _DM_Map = { 'extension' : DM_extension 1708 , 'restriction' : DM_restriction } 1709 1710 # How the type was derived (a DM_* value) 1711 # (This field is used to identify unresolved definitions.) 1712 __derivationMethod = None
1713 - def derivationMethod (self):
1714 """How the type was derived.""" 1715 return self.__derivationMethod
1716 1717 # Derived from the final and finalDefault attributes 1718 __final = DM_empty 1719 1720 # Derived from the abstract attribute 1721 __abstract = False
1722 - def abstract (self):
1723 return self.__abstract
1724 1725 # A frozenset() of AttributeUse instances. 1726 __attributeUses = None
1727 - def attributeUses (self):
1728 """A frozenset() of AttributeUse instances.""" 1729 return self.__attributeUses
1730 1731 # A map from NCNames to AttributeDeclaration instances that are 1732 # local to this type. 1733 __scopedAttributeDeclarations = None
1734 - def lookupScopedAttributeDeclaration (self, expanded_name):
1735 """Find an attribute declaration with the given name that is local to this type. 1736 1737 Returns None if there is no such local attribute declaration.""" 1738 if self.__scopedAttributeDeclarations is None: 1739 return None 1740 return self.__scopedAttributeDeclarations.get(expanded_name)
1741 1742 # A map from NCNames to ElementDeclaration instances that are 1743 # local to this type. 1744 __scopedElementDeclarations = None
1745 - def lookupScopedElementDeclaration (self, expanded_name):
1746 """Find an element declaration with the given name that is local to this type. 1747 1748 Returns None if there is no such local element declaration.""" 1749 if self.__scopedElementDeclarations is None: 1750 return None 1751 return self.__scopedElementDeclarations.get(expanded_name)
1752 1753 __localScopedDeclarations = None
1754 - def localScopedDeclarations (self, reset=False):
1755 """Return a list of element and attribute declarations that were 1756 introduced in this definition (i.e., their scope is this CTD). 1757 1758 @note: This specifically returns a list, with element declarations 1759 first, because name binding should privilege the elements over the 1760 attributes. Within elements and attributes, the components are sorted 1761 by expanded name, to ensure consistency across a series of binding 1762 generations. 1763 1764 @keyword reset: If C{False} (default), a cached previous value (if it 1765 exists) will be returned. 1766 """ 1767 if reset or (self.__localScopedDeclarations is None): 1768 rve = [ _ed for _ed in self.__scopedElementDeclarations.values() if (self == _ed.scope()) ] 1769 rve.sort(lambda _a, _b: cmp(_a.expandedName(), _b.expandedName())) 1770 rva = [ _ad for _ad in self.__scopedAttributeDeclarations.values() if (self == _ad.scope()) ] 1771 rva.sort(lambda _a, _b: cmp(_a.expandedName(), _b.expandedName())) 1772 self.__localScopedDeclarations = rve 1773 self.__localScopedDeclarations.extend(rva) 1774 return self.__localScopedDeclarations
1775
1776 - def _recordLocalDeclaration (self, decl):
1777 """Record the given declaration as being locally scoped in 1778 this type.""" 1779 assert isinstance(decl, _ScopedDeclaration_mixin) 1780 if isinstance(decl, ElementDeclaration): 1781 scope_map = self.__scopedElementDeclarations 1782 elif isinstance(decl, AttributeDeclaration): 1783 scope_map = self.__scopedAttributeDeclarations 1784 else: 1785 raise pyxb.LogicError('Unexpected instance of %s recording as local declaration' % (type(decl),)) 1786 decl_en = decl.expandedName() 1787 existing_decl = scope_map.setdefault(decl_en, decl) 1788 if decl != existing_decl: 1789 if isinstance(decl, ElementDeclaration): 1790 # Test cos-element-consistent 1791 existing_type = existing_decl.typeDefinition() 1792 pending_type = decl.typeDefinition() 1793 if not pending_type.isDerivationConsistent(existing_type): 1794 raise pyxb.SchemaValidationError('Conflicting element declarations for %s: existing %s versus new %s' % (decl.expandedName(), existing_type, pending_type)) 1795 elif isinstance(decl, AttributeDeclaration): 1796 raise pyxb.SchemaValidationError('Multiple attribute declarations for %s' % (decl.expandedName(),)) 1797 else: 1798 assert False, 'Unrecognized type %s' % (type(decl),) 1799 decl._baseDeclaration(existing_decl) 1800 return self
1801
1802 - def _isHierarchyRoot (self):
1803 """Return C{True} iff this is the root of a complex type definition hierarchy. 1804 """ 1805 base = self.__baseTypeDefinition 1806 return isinstance(base, SimpleTypeDefinition) or base.isUrTypeDefinition()
1807 1808 CT_EMPTY = 'EMPTY' #<<< No content 1809 CT_SIMPLE = 'SIMPLE' #<<< Simple (character) content 1810 CT_MIXED = 'MIXED' #<<< Children may be elements or other (e.g., character) content 1811 CT_ELEMENT_ONLY = 'ELEMENT_ONLY' #<<< Expect only element content. 1812
1813 - def _contentTypeTag (self):
1814 """Return the value of the content type identifier, i.e. one of the 1815 CT_ constants. Return value is None if no content type has been 1816 defined.""" 1817 if isinstance(self.__contentType, tuple): 1818 return self.__contentType[0] 1819 return self.__contentType
1820
1821 - def _contentTypeComponent (self):
1822 if isinstance(self.__contentType, tuple): 1823 return self.__contentType[1] 1824 return None
1825 1826 # Identify the sort of content in this type. 1827 __contentType = None
1828 - def contentType (self):
1829 """Identify the sort of content in this type. 1830 1831 Valid values are: 1832 - C{CT_EMPTY} 1833 - ( C{CT_SIMPLE}, a L{SimpleTypeDefinition} instance ) 1834 - ( C{CT_MIXED}, a L{Particle} instance ) 1835 - ( C{CT_ELEMENT_ONLY}, a L{Particle} instance ) 1836 """ 1837 return self.__contentType
1838
1839 - def contentTypeAsString (self):
1840 if self.CT_EMPTY == self.contentType(): 1841 return 'EMPTY' 1842 ( tag, particle ) = self.contentType() 1843 if self.CT_SIMPLE == tag: 1844 return 'Simple [%s]' % (particle,) 1845 if self.CT_MIXED == tag: 1846 return 'Mixed [%s]' % (particle,) 1847 if self.CT_ELEMENT_ONLY == tag: 1848 return 'Element [%s]' % (particle,) 1849 raise pyxb.LogicError('Unhandled content type')
1850 1851 # Derived from the block and blockDefault attributes 1852 __prohibitedSubstitutions = DM_empty 1853 1854 # @todo: Extracted from children of various types 1855 __annotations = None 1856
1857 - def __init__ (self, *args, **kw):
1858 super(ComplexTypeDefinition, self).__init__(*args, **kw) 1859 self.__derivationMethod = kw.get('derivation_method') 1860 self.__scopedElementDeclarations = { } 1861 self.__scopedAttributeDeclarations = { }
1862
1863 - def hasWildcardElement (self):
1864 """Return True iff this type includes a wildcard element in 1865 its content model.""" 1866 if self.CT_EMPTY == self.contentType(): 1867 return False 1868 ( tag, particle ) = self.contentType() 1869 if self.CT_SIMPLE == tag: 1870 return False 1871 return particle.hasWildcardElement()
1872
1873 - def _updateFromOther_csc (self, other):
1874 """Override fields in this instance with those from the other. 1875 1876 This method is invoked only by Schema._addNamedComponent, and 1877 then only when a built-in type collides with a schema-defined 1878 type. Material like facets is not (currently) held in the 1879 built-in copy, so the DOM information is copied over to the 1880 built-in STD, which is subsequently re-resolved. 1881 1882 Returns self. 1883 """ 1884 assert self != other 1885 assert self.isNameEquivalent(other) 1886 super(ComplexTypeDefinition, self)._updateFromOther_csc(other) 1887 1888 if not other.isResolved(): 1889 if pyxb.namespace.BuiltInObjectUID != self._objectOrigin().generationUID(): 1890 self.__derivationMethod = None 1891 1892 return self
1893 1894 __UrTypeDefinition = None 1895 @classmethod
1896 - def UrTypeDefinition (cls, schema=None, in_builtin_definition=False):
1897 """Create the ComplexTypeDefinition instance that approximates 1898 the ur-type. 1899 1900 See section 3.4.7. 1901 """ 1902 1903 # The first time, and only the first time, this is called, a 1904 # namespace should be provided which is the XMLSchema 1905 # namespace for this run of the system. Please, do not try to 1906 # allow this by clearing the type definition. 1907 #if in_builtin_definition and (cls.__UrTypeDefinition is not None): 1908 # raise pyxb.LogicError('Multiple definitions of UrType') 1909 if cls.__UrTypeDefinition is None: 1910 # NOTE: We use a singleton subclass of this class 1911 assert schema is not None 1912 1913 ns_ctx = schema.targetNamespace().initialNamespaceContext() 1914 1915 kw = { 'name' : 'anyType', 1916 'schema' : schema, 1917 'namespace_context' : ns_ctx, 1918 'binding_namespace' : schema.targetNamespace(), 1919 'derivation_method' : cls.DM_restriction, 1920 'scope' : _ScopedDeclaration_mixin.SCOPE_global } 1921 bi = _UrTypeDefinition(**kw) 1922 1923 # The ur-type is its own baseTypeDefinition 1924 bi.__baseTypeDefinition = bi 1925 1926 # No constraints on attributes 1927 bi._setAttributeWildcard(Wildcard(namespace_constraint=Wildcard.NC_any, process_contents=Wildcard.PC_lax, **kw)) 1928 1929 # There isn't anything to look up, but context is still global. 1930 # No declarations will be created, so use indeterminate scope to 1931 # be consistent with validity checks in Particle constructor. 1932 # Content is mixed, with elements completely unconstrained. @todo: 1933 # not associated with a schema (it should be) 1934 kw = { 'namespace_context' : ns_ctx 1935 , 'schema' : schema 1936 , 'scope': _ScopedDeclaration_mixin.XSCOPE_indeterminate } 1937 w = Wildcard(namespace_constraint=Wildcard.NC_any, process_contents=Wildcard.PC_lax, **kw) 1938 p = Particle(w, min_occurs=0, max_occurs=None, **kw) 1939 m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[ p ], **kw) 1940 bi.__contentType = ( cls.CT_MIXED, Particle(m, **kw) ) 1941 1942 # No attribute uses 1943 bi.__attributeUses = set() 1944 1945 # No constraints on extension or substitution 1946 bi.__final = cls.DM_empty 1947 bi.__prohibitedSubstitutions = cls.DM_empty 1948 1949 bi.__abstract = False 1950 1951 # Refer to it by name 1952 bi.setNameInBinding(bi.name()) 1953 1954 # The ur-type is always resolved 1955 bi.__derivationMethod = cls.DM_restriction 1956 1957 cls.__UrTypeDefinition = bi 1958 return cls.__UrTypeDefinition
1959
1960 - def isBuiltin (self):
1961 """Indicate whether this simple type is a built-in type.""" 1962 return (self.UrTypeDefinition() == self)
1963 1964 # bR:CTD
1965 - def _bindingRequires_vx (self, include_lax):
1966 """Complex type definitions depend on their base type definition, the 1967 type definitions of any local attribute declarations, and if strict 1968 the type definitions of any local element declarations.""" 1969 rv = set() 1970 assert self.__baseTypeDefinition is not None 1971 rv.add(self.__baseTypeDefinition) 1972 for decl in self.localScopedDeclarations(): 1973 if include_lax or isinstance(decl, AttributeDeclaration): 1974 rv.add(decl.typeDefinition()) 1975 if include_lax: 1976 ct = self._contentTypeComponent() 1977 if ct is not None: 1978 rv.add(ct) 1979 return frozenset(rv)
1980 1981 # CFD:CTD CFD:ComplexTypeDefinition 1982 @classmethod
1983 - def CreateFromDOM (cls, node, **kw):
1984 # Node should be an XMLSchema complexType node 1985 assert xsd.nodeIsNamed(node, 'complexType') 1986 1987 name = domutils.NodeAttribute(node, 'name') 1988 1989 rv = cls(name=name, node=node, derivation_method=None, **kw) 1990 1991 if name is None: 1992 assert not isinstance(rv.owner(), Schema) 1993 1994 # Most of the time, the scope will be global. It can be something 1995 # else only if this is an anonymous CTD (created within an element 1996 # declaration which itself may be global, in a containing CTD, or in a 1997 # model group). 1998 if not (rv._scopeIsGlobal() or rv.isAnonymous()): 1999 raise pyxb.LogicError('Attempt to create non-global complex type definition') 2000 2001 kw.pop('node', None) 2002 kw['owner'] = rv 2003 kw['scope'] = rv 2004 2005 return rv.__setContentFromDOM(node, **kw)
2006 2007 __baseAttribute = None 2008 2009 2010 __ckw = None 2011 __anyAttribute = None 2012 __attributeGroupAttributes = None 2013 __usesC1 = None 2014 __usesC1C2 = None 2015 __attributeGroups = None 2016 __PrivateTransient.update(['ckw', 'anyAttribute', 'attributeGroupAttributes', 'usesC1', 'usesC1C2', 'attributeGroups' ]) 2017 2018 # Handle attributeUses, attributeWildcard, contentType
2019 - def __completeProcessing (self, method, content_style):
2020 2021 if self.__usesC1C2 is None: 2022 # Handle clauses 1 and 2 (common between simple and complex types) 2023 uses_c1 = self.__usesC1 # attribute children 2024 uses_c2 = set() # attribute group children 2025 self.__attributeGroups = [] 2026 for ag_attr in self.__attributeGroupAttributes: 2027 ag_en = self._namespaceContext().interpretQName(ag_attr) 2028 agd = ag_en.attributeGroupDefinition() 2029 if agd is None: 2030 raise pyxb.SchemaValidationError('Attribute group %s cannot be found' % (ag_en,)) 2031 if not agd.isResolved(): 2032 self._queueForResolution('unresolved attribute group', depends_on=agd) 2033 return self 2034 self.__attributeGroups.append(agd) 2035 uses_c2.update(agd.attributeUses()) 2036 2037 uses_c1c2 = uses_c1.union(uses_c2) 2038 for au in uses_c1c2: 2039 if not au.isResolved(): 2040 self._queueForResolution('attribute use not resolved') 2041 return self 2042 ad = au.attributeDeclaration() 2043 if not ad.isResolved(): 2044 ad_en = ad.expandedName() 2045 self._queueForResolution('unresolved attribute declaration %s from base type' % (ad_en,), depends_on=ad) 2046 return self 2047 2048 self.__usesC1C2 = frozenset([ _u._adaptForScope(self) for _u in uses_c1c2 ]) 2049 2050 # Handle clause 3. Note the slight difference in description between 2051 # simple and complex content is just that the complex content doesn't 2052 # bother to check that the base type definition is a complex type 2053 # definition. So the same code should work for both, and we don't 2054 # bother to check content_style. 2055 uses_c3 = set() # base attributes 2056 if isinstance(self.__baseTypeDefinition, ComplexTypeDefinition): 2057 # NB: The base type definition should be resolved, which means 2058 # that all its attribute uses have been adapted for scope already 2059 uses_c3 = set(self.__baseTypeDefinition.__attributeUses) 2060 assert self.__baseTypeDefinition.isResolved() 2061 for au in uses_c3: 2062 if not au.isResolved(): 2063 self._queueForResolution('unresolved attribute use from base type', depends_on=au) 2064 return self 2065 ad = au.attributeDeclaration() 2066 if not ad.isResolved(): 2067 ad_en = ad.expandedName() 2068 self._queueForResolution('unresolved attribute declaration %s from base type' % (ad_en,), depends_on=ad) 2069 return self 2070 assert not au.attributeDeclaration()._scopeIsIndeterminate() 2071 2072 if self.DM_restriction == method: 2073 # Exclude attributes per clause 3. Note that this process 2074 # handles both 3.1 and 3.2, since we have not yet filtered 2075 # uses_c1 for prohibited attributes. 2076 for au in self.__usesC1C2: 2077 matching_uses = au.matchingQNameMembers(uses_c3) 2078 assert matching_uses is not None 2079 assert 1 >= len(matching_uses), 'Multiple inherited attribute uses with name %s' 2080 for au2 in matching_uses: 2081 assert au2.isResolved() 2082 uses_c3.remove(au2) 2083 au._setRestrictionOf(au2) 2084 else: 2085 # In theory, the same attribute name can't appear in the base 2086 # and sub types because that would violate the local 2087 # declaration constraint. 2088 assert self.DM_extension == method 2089 2090 use_map = { } 2091 for au in self.__usesC1C2.union(uses_c3): 2092 assert au.isResolved() 2093 ad_en = au.attributeDeclaration().expandedName() 2094 if ad_en in use_map: 2095 raise pyxb.SchemaValidationError('Multiple definitions for %s in CTD %s' % (ad_en, self.expandedName())) 2096 use_map[ad_en] = au 2097 2098 # Past the last point where we might not resolve this instance. Store 2099 # the attribute uses, also recording local attribute declarations. 2100 self.__attributeUses = frozenset(use_map.values()) 2101 if not self._scopeIsIndeterminate(): 2102 for au in self.__attributeUses: 2103 assert not au.attributeDeclaration()._scopeIsIndeterminate(), 'indeterminate scope for %s' % (au,) 2104 2105 # @todo: Handle attributeWildcard 2106 # Clause 1 2107 local_wildcard = None 2108 if self.__anyAttribute is not None: 2109 local_wildcard = Wildcard.CreateFromDOM(self.__anyAttribute) 2110 2111 # Clause 2 2112 complete_wildcard = _AttributeWildcard_mixin.CompleteWildcard(self._namespaceContext(), self.__attributeGroups, local_wildcard) 2113 2114 # Clause 3 2115 if self.DM_restriction == method: 2116 # Clause 3.1 2117 self._setAttributeWildcard(complete_wildcard) 2118 else: 2119 assert (self.DM_extension == method) 2120 assert self.baseTypeDefinition().isResolved() 2121 # 3.2.1 2122 base_wildcard = None 2123 if isinstance(self.baseTypeDefinition(), ComplexTypeDefinition): 2124 base_wildcard = self.baseTypeDefinition().attributeWildcard() 2125 # 3.2.2 2126 if base_wildcard is not None: 2127 if complete_wildcard is None: 2128 # 3.2.2.1.1 2129 self._setAttributeWildcard(base_wildcard) 2130 else: 2131 # 3.2.2.1.2 2132 self._setAttributeWildcard(Wildcard (process_contents=complete_wildcard.processContents(), 2133 namespace_constraint = Wildcard.IntensionalUnion([complete_wildcard.namespaceConstraint(), 2134 base_wildcard.namespaceConstraint()]), 2135 annotation=complete_wildcard.annotation(), 2136 namespace_context=self._namespaceContext())) 2137 else: 2138 # 3.2.2.2 2139 self._setAttributeWildcard(complete_wildcard) 2140 2141 # @todo: Make sure we didn't miss any child nodes 2142 2143 # Remove local attributes we will never use again 2144 del self.__usesC1 2145 del self.__usesC1C2 2146 del self.__attributeGroups 2147 self.__ckw = None 2148 2149 # Only now that we've succeeded do we store the method, which 2150 # marks this component resolved. 2151 2152 self.__derivationMethod = method 2153 return self
2154
2155 - def __simpleContent (self, method, **kw):
2156 # Do content type 2157 if isinstance(self.__baseTypeDefinition, ComplexTypeDefinition): 2158 # Clauses 1, 2, and 3 might apply 2159 parent_content_type = self.__baseTypeDefinition.__contentType 2160 if ((type(parent_content_type) == tuple) \ 2161 and (self.CT_SIMPLE == parent_content_type[0]) \ 2162 and (self.DM_restriction == method)): 2163 # Clause 1 2164 assert self.__ctscRestrictionNode is not None 2165 std = self.__ctscClause2STD 2166 if std is None: 2167 std = parent_content_type[1] 2168 assert isinstance(std, SimpleTypeDefinition) 2169 if not std.isResolved(): 2170 return None 2171 restriction_node = self.__ctscRestrictionNode 2172 self.__ctscClause2STD = None 2173 self.__ctscRestrictionNode = None 2174 return ( self.CT_SIMPLE, std._createRestriction(self, restriction_node) ) 2175 if ((type(parent_content_type) == tuple) \ 2176 and (self.CT_MIXED == parent_content_type[0]) \ 2177 and parent_content_type[1].isEmptiable()): 2178 # Clause 2 2179 assert isinstance(self.__ctscClause2STD, SimpleTypeDefinition) 2180 return ( self.CT_SIMPLE, self.__ctscClause2STD ) 2181 # Clause 3 2182 return parent_content_type 2183 # Clause 4 2184 return ( self.CT_SIMPLE, self.__baseTypeDefinition )
2185 2186 __ctscClause2STD = None 2187 __ctscRestrictionNode = None 2188 __effectiveMixed = None 2189 __effectiveContent = None 2190 __pendingDerivationMethod = None 2191 __isComplexContent = None 2192 __ctscRestrictionMode = None 2193 __contentStyle = None 2194
2195 - def __setComplexContentFromDOM (self, type_node, content_node, definition_node_list, method, **kw):
2196 # Do content type. Cache the keywords that need to be used 2197 # for newly created schema components. 2198 ckw = kw.copy() 2199 ckw['namespace_context'] = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(type_node) 2200 2201 # Definition 1: effective mixed 2202 mixed_attr = None 2203 if content_node is not None: 2204 mixed_attr = domutils.NodeAttribute(content_node, 'mixed') 2205 if mixed_attr is None: 2206 mixed_attr = domutils.NodeAttribute(type_node, 'mixed') 2207 if mixed_attr is not None: 2208 effective_mixed = datatypes.boolean(mixed_attr) 2209 else: 2210 effective_mixed = False 2211 2212 # Definition 2: effective content 2213 test_2_1_1 = True 2214 test_2_1_2 = False 2215 test_2_1_3 = False 2216 typedef_node = None 2217 for cn in definition_node_list: 2218 if Node.ELEMENT_NODE != cn.nodeType: 2219 continue 2220 if xsd.nodeIsNamed(cn, 'simpleContent', 'complexContent'): 2221 # Should have found the content node earlier. 2222 raise pyxb.LogicError('Missed explicit wrapper in complexType content') 2223 if Particle.IsTypedefNode(cn): 2224 typedef_node = cn 2225 test_2_1_1 = False 2226 if xsd.nodeIsNamed(cn, 'all', 'sequence') \ 2227 and (not domutils.HasNonAnnotationChild(cn)): 2228 test_2_1_2 = True 2229 if xsd.nodeIsNamed(cn, 'choice') \ 2230 and (not domutils.HasNonAnnotationChild(cn)): 2231 mo_attr = domutils.NodeAttribute(cn, 'minOccurs') 2232 if ((mo_attr is not None) \ 2233 and (0 == datatypes.integer(mo_attr))): 2234 test_2_1_3 = True 2235 satisfied_predicates = 0 2236 if test_2_1_1: 2237 satisfied_predicates += 1 2238 if test_2_1_2: 2239 satisfied_predicates += 1 2240 if test_2_1_3: 2241 satisfied_predicates += 1 2242 if 1 == satisfied_predicates: 2243 if effective_mixed: 2244 # Clause 2.1.4 2245 assert (typedef_node is None) or test_2_1_2 2246 m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[], **ckw) 2247 effective_content = Particle(m, **ckw) 2248 else: 2249 # Clause 2.1.5 2250 effective_content = self.CT_EMPTY 2251 else: 2252 # Clause 2.2 2253 assert typedef_node is not None 2254 effective_content = Particle.CreateFromDOM(typedef_node, **kw) 2255 2256 # For issues related to soapenc:Array and the fact that PyXB 2257 # determines the content of types derived from it is empty, see 2258 # http://tech.groups.yahoo.com/group/soapbuilders/message/5879 and 2259 # lament the fact that the WSDL spec is not compatible with XSD. It 2260 # is *not* an error in PyXB. 2261 2262 self.__effectiveMixed = effective_mixed 2263 self.__effectiveContent = effective_content 2264 self.__ckw = ckw
2265
2266 - def __complexContent (self, method):
2267 ckw = self.__ckw 2268 2269 # Shared from clause 3.1.2 2270 if self.__effectiveMixed: 2271 ct = self.CT_MIXED 2272 else: 2273 ct = self.CT_ELEMENT_ONLY 2274 # Clause 3 2275 if self.DM_restriction == method: 2276 # Clause 3.1 2277 if self.CT_EMPTY == self.__effectiveContent: 2278 # Clause 3.1.1 2279 content_type = self.CT_EMPTY # ASSIGN CT_EMPTY 2280 else: 2281 # Clause 3.1.2(.2) 2282 content_type = ( ct, self.__effectiveContent ) # ASSIGN RESTRICTION 2283 assert 0 == len(self.__scopedElementDeclarations) 2284 # Reference the parent element declarations; normally this 2285 # would happen naturally as a consequence of appending this 2286 # type's content model to the parent's, but with restriction 2287 # there is no such re-use unless we do this. 2288 self.__scopedElementDeclarations.update(self.__baseTypeDefinition.__scopedElementDeclarations) 2289 else: 2290 # Clause 3.2 2291 assert self.DM_extension == method 2292 assert self.__baseTypeDefinition.isResolved() 2293 parent_content_type = self.__baseTypeDefinition.contentType() 2294 if self.CT_EMPTY == self.__effectiveContent: 2295 content_type = parent_content_type # ASSIGN EXTENSION PARENT ONLY 2296 elif self.CT_EMPTY == parent_content_type: 2297 # Clause 3.2.2 2298 content_type = ( ct, self.__effectiveContent ) # ASSIGN EXTENSION LOCAL ONLY 2299 else: 2300 assert type(parent_content_type) == tuple 2301 m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[ parent_content_type[1], self.__effectiveContent ], **ckw) 2302 content_type = ( ct, Particle(m, **ckw) ) # ASSIGN EXTENSION PARENT AND LOCAL 2303 2304 assert (self.CT_EMPTY == content_type) or ((type(content_type) == tuple) and (content_type[1] is not None)) 2305 return content_type
2306
2307 - def isResolved (self):
2308 """Indicate whether this complex type is fully defined. 2309 2310 All built-in type definitions are resolved upon creation. 2311 Schema-defined type definitionss are held unresolved until the 2312 schema has been completely read, so that references to later 2313 schema-defined types can be resolved. Resolution is performed 2314 after the entire schema has been scanned and type-definition 2315 instances created for all topLevel{Simple,Complex}Types. 2316 2317 If a built-in type definition is also defined in a schema 2318 (which it should be), the built-in definition is kept, with 2319 the schema-related information copied over from the matching 2320 schema-defined type definition. The former then replaces the 2321 latter in the list of type definitions to be resolved. See 2322 Schema._addNamedComponent. 2323 """ 2324 # Only unresolved nodes have an unset derivationMethod 2325 return (self.__derivationMethod is not None)
2326 2327 # Back door to allow the ur-type to re-resolve itself. Only needed when 2328 # we're generating bindings for XMLSchema itself.
2329 - def _setDerivationMethod (self, derivation_method):
2330 self.__derivationMethod = derivation_method 2331 return self
2332
2333 - def __setContentFromDOM (self, node, **kw):
2334 schema = kw.get('schema') 2335 assert schema is not None 2336 self.__prohibitedSubstitutions = schema.blockForNode(node, self._DM_Map) 2337 self.__final = schema.finalForNode(node, self._DM_Map) 2338 2339 attr_val = domutils.NodeAttribute(node, 'abstract') 2340 if attr_val is not None: 2341 self.__abstract = datatypes.boolean(attr_val) 2342 2343 # Assume we're in the short-hand case: the entire content is 2344 # implicitly wrapped in a complex restriction of the ur-type. 2345 definition_node_list = node.childNodes 2346 is_complex_content = True 2347 self.__baseTypeDefinition = ComplexTypeDefinition.UrTypeDefinition() 2348 method = self.DM_restriction 2349 2350 # Determine whether above assumption is correct by looking for 2351 # element content and seeing if it's one of the wrapper 2352 # elements. 2353 first_elt = domutils.LocateFirstChildElement(node) 2354 content_node = None 2355 clause2_std = None 2356 ctsc_restriction_node = None 2357 if first_elt: 2358 have_content = False 2359 if xsd.nodeIsNamed(first_elt, 'simpleContent'): 2360 have_content = True 2361 is_complex_content = False 2362 elif xsd.nodeIsNamed(first_elt, 'complexContent'): 2363 have_content = True 2364 else: 2365 # Not one of the wrappers; use implicit wrapper around 2366 # the children 2367 if not Particle.IsParticleNode(first_elt, 'attributeGroup', 'attribute', 'anyAttribute'): 2368 raise pyxb.SchemaValidationError('Unexpected element %s at root of complexType' % (first_elt.nodeName,)) 2369 if have_content: 2370 # Repeat the search to verify that only the one child is present. 2371 content_node = domutils.LocateFirstChildElement(node, require_unique=True) 2372 assert content_node == first_elt 2373 2374 # Identify the contained restriction or extension 2375 # element, and extract the base type. 2376 ions = domutils.LocateFirstChildElement(content_node, absent_ok=False) 2377 if xsd.nodeIsNamed(ions, 'restriction'): 2378 method = self.DM_restriction 2379 if not is_complex_content: 2380 # Clause 2 of complex type with simple content 2381 ctsc_restriction_node = ions 2382 ions_st = domutils.LocateUniqueChild(ions,'simpleType') 2383 if ions_st is not None: 2384 clause2_std = SimpleTypeDefinition.CreateFromDOM(ions_st, **kw) 2385 elif xsd.nodeIsNamed(ions, 'extension'): 2386 method = self.DM_extension 2387 else: 2388 raise pyxb.SchemaValidationError('Expected restriction or extension as sole child of %s in %s' % (content_node.nodeName, self.name())) 2389 self.__baseAttribute = domutils.NodeAttribute(ions, 'base') 2390 if self.__baseAttribute is None: 2391 raise pyxb.SchemaValidationError('Element %s missing base attribute' % (ions.nodeName,)) 2392 self.__baseTypeDefinition = None 2393 # The content is defined by the restriction/extension element 2394 definition_node_list = ions.childNodes 2395 # deriviationMethod is assigned after resolution completes 2396 self.__pendingDerivationMethod = method 2397 self.__isComplexContent = is_complex_content 2398 self.__ctscRestrictionNode = ctsc_restriction_node 2399 self.__ctscClause2STD = clause2_std 2400 2401 (attributes, attribute_group_attrs, any_attribute) = self._attributeRelevantChildren(definition_node_list) 2402 self.__usesC1 = set() 2403 for cn in attributes: 2404 au = AttributeUse.CreateFromDOM(cn, **kw) 2405 self.__usesC1.add(au) 2406 self.__attributeGroupAttributes = attribute_group_attrs 2407 self.__anyAttribute = any_attribute 2408 2409 if self.__isComplexContent: 2410 self.__setComplexContentFromDOM(node, content_node, definition_node_list, self.__pendingDerivationMethod, **kw) 2411 2412 # Creation does not attempt to do resolution. Queue up the newly created 2413 # whatsis so we can resolve it after everything's been read in. 2414 self._annotationFromDOM(node) 2415 2416 if not self.isResolved(): 2417 self._queueForResolution('creation') 2418 2419 return self
2420 2421 # Resolution of a CTD can be delayed for the following reasons: 2422 # 2423 # * It extends or restricts a base type that has not been resolved 2424 # [_resolve] 2425 # 2426 # * It refers to an attribute or attribute group that has not been 2427 # resolved [__completeProcessing] 2428 # 2429 # * It includes an attribute that matches in NCName and namespace 2430 # an unresolved attribute from the base type 2431 # [__completeProcessing] 2432 # 2433 # * The content model includes a particle which cannot be resolved 2434 # (so has not contributed any local element declarations). 2435 # res:CTD
2436 - def _resolve (self):
2437 if self.isResolved(): 2438 return self 2439 2440 # @todo: implement prohibitedSubstitutions, final, annotations 2441 2442 # See whether we've resolved through to the base type 2443 if self.__baseTypeDefinition is None: 2444 base_en = self._namespaceContext().interpretQName(self.__baseAttribute) 2445 base_type = base_en.typeDefinition() 2446 if base_type is None: 2447 raise pyxb.SchemaValidationError('Cannot locate %s: need import?' % (base_en,)) 2448 if not base_type.isResolved(): 2449 # Have to delay resolution until the type this 2450 # depends on is available. 2451 self._queueForResolution('unresolved base type %s' % (base_en,), depends_on=base_type) 2452 return self 2453 self.__baseTypeDefinition = base_type 2454 2455 # Only build the content once. This will not complete if the content 2456 # is a restriction of an unresolved simple type; otherwise, it only 2457 # depends on the base type which we know is good. 2458 if self.__contentType is None: 2459 if self.__isComplexContent: 2460 content_type = self.__complexContent(self.__pendingDerivationMethod) 2461 self.__contentStyle = 'complex' 2462 else: 2463 # The definition node list is not relevant to simple content 2464 content_type = self.__simpleContent(self.__pendingDerivationMethod) 2465 if content_type is None: 2466 self._queueForResolution('restriction of unresolved simple type') 2467 return self 2468 self.__contentStyle = 'simple' 2469 assert content_type is not None 2470 self.__contentType = content_type 2471 2472 # Last chance for failure is if we haven't been able to 2473 # extract all the element declarations that might appear in 2474 # this complex type. That technically wouldn't stop this from 2475 # being resolved, but it does prevent us from using it as a 2476 # context. 2477 if isinstance(self.__contentType, tuple) and isinstance(self.__contentType[1], Particle): 2478 prt = self.__contentType[1] 2479 if not prt.isAdaptable(self): 2480 self._queueForResolution('content particle %s is not deep-resolved' % (prt,)) 2481 return self 2482 self.__contentType = (self.__contentType[0], prt._adaptForScope(self, self)) 2483 2484 return self.__completeProcessing(self.__pendingDerivationMethod, self.__contentStyle)
2485
2486 - def pythonSupport (self):
2487 """Complex type definitions have no built-in type support.""" 2488 return None
2489
2490 - def __str__ (self):
2491 if self.isAnonymous(): 2492 return 'CTD{Anonymous}[%x]' % (id(self),) 2493 return 'CTD[%s]' % (self.expandedName(),)
2494
2495 -class _UrTypeDefinition (ComplexTypeDefinition, _Singleton_mixin):
2496 """Subclass ensures there is only one ur-type."""
2497 - def pythonSupport (self):
2498 """The ur-type does have a Python class backing it up.""" 2499 return datatypes.anyType
2500
2501 - def _resolve (self):
2502 # The ur type is always resolved, except when it gets unresolved 2503 # through being updated from an instance read from the schema. 2504 return self._setDerivationMethod(self.DM_restriction)
2505
2506 2507 -class AttributeGroupDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _AttributeWildcard_mixin):
2508 """An XMLSchema U{Attribute Group Definition<http://www.w3.org/TR/xmlschema-1/#cAttribute_Group_Definitions>} component.""" 2509 __PrivateTransient = set() 2510 2511 # A frozenset of AttributeUse instances 2512 __attributeUses = None 2513
2514 - def __init__ (self, *args, **kw):
2515 super(AttributeGroupDefinition, self).__init__(*args, **kw)
2516 #assert 'scope' in kw 2517 #assert self._scopeIsIndeterminate() 2518
2519 - def __str__ (self):
2520 return 'AGD[%s]' % (self.expandedName(),)
2521 2522 @classmethod
2523 - def CreateBaseInstance (cls, name, schema, attribute_uses):
2524 """Create an attribute declaration component for a specified namespace.""" 2525 kw = { 'name' : name, 2526 'schema' : schema, 2527 'namespace_context' : schema.targetNamespace().initialNamespaceContext(), 2528 'scope' : _ScopedDeclaration_mixin.SCOPE_global } 2529 bi = cls(**kw) 2530 bi.__attributeUses = frozenset(attribute_uses) 2531 bi.__isResolved = True 2532 return bi
2533 2534 __anyAttribute = None 2535 __attributeGroupAttributes = None 2536 __refAttribute = None 2537 __PrivateTransient.update(['anyAttribute', 'attributeGroupAttributes']) 2538 2539 2540 # CFD:AGD CFD:AttributeGroupDefinition 2541 @classmethod
2542 - def CreateFromDOM (cls, node, **kw):
2543 """Create an attribute group definition from the given DOM node. 2544 2545 """ 2546 2547 assert xsd.nodeIsNamed(node, 'attributeGroup') 2548 name = domutils.NodeAttribute(node, 'name') 2549 2550 # Attribute group definitions can only appear at the top level of the 2551 # schema, and any definitions in them are scope indeterminate until 2552 # they're referenced in a complex type. 2553 kw.update({ 'scope' : _ScopedDeclaration_mixin.XSCOPE_indeterminate }) 2554 rv = cls(name=name, node=node, **kw) 2555 2556 rv._annotationFromDOM(node) 2557 2558 # Attribute group definitions must not be references 2559 rv.__refAttribute = domutils.NodeAttribute(node, 'ref') 2560 if rv.__refAttribute is not None: 2561 raise pyxb.SchemaValidationError('Attribute reference at top level') 2562 2563 kw.pop('node', None) 2564 kw['owner'] = rv 2565 2566 (attributes, attribute_group_attrs, any_attribute) = rv._attributeRelevantChildren(node.childNodes) 2567 rv.__attributeUses = set() 2568 for cn in attributes: 2569 rv.__attributeUses.add(AttributeUse.CreateFromDOM(cn, **kw)) 2570 rv.__attributeGroupAttributes = attribute_group_attrs 2571 rv.__anyAttribute = any_attribute 2572 2573 # Unconditionally queue for resolution, to avoid repeating the 2574 # wildcard code. 2575 rv._queueForResolution('creation') 2576 2577 return rv
2578 2579 # Indicates whether we have resolved any references 2580 __isResolved = False
2581 - def isResolved (self):
2582 return self.__isResolved
2583
2584 - def _resolve (self):
2585 if self.__isResolved: 2586 return self 2587 2588 uses = self.__attributeUses 2589 attribute_groups = [] 2590 for ag_attr in self.__attributeGroupAttributes: 2591 ag_en = self._namespaceContext().interpretQName(ag_attr) 2592 agd = ag_en.attributeGroupDefinition() 2593 if agd is None: 2594 raise pyxb.SchemaValidationError('Attribute group %s cannot be found' % (ag_en,)) 2595 attribute_groups.append(agd) 2596 uses = uses.union(agd.attributeUses()) 2597 2598 self.__attributeUses = frozenset(uses) 2599 2600 # "Complete wildcard" per CTD 2601 local_wildcard = None 2602 if self.__anyAttribute is not None: 2603 local_wildcard = Wildcard.CreateFromDOM(self.__anyAttribute) 2604 self._setAttributeWildcard(_AttributeWildcard_mixin.CompleteWildcard(self._namespaceContext(), attribute_groups, local_wildcard)) 2605 2606 self.__isResolved = True 2607 return self
2608 2609 # bR:AGD
2610 - def _bindingRequires_vx (self, include_lax):
2611 """Attribute group declarations require their uses, but only if lax.""" 2612 if not include_lax: 2613 return frozenset() 2614 return frozenset(self.attributeUses())
2615
2616 - def attributeUses (self):
2617 return self.__attributeUses
2618
2619 -class ModelGroupDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, _Annotated_mixin):
2620 """An XMLSchema U{Model Group Definition<http://www.w3.org/TR/xmlschema-1/#cModel_Group_Definitions>} component.""" 2621 # Reference to a _ModelGroup 2622 __modelGroup = None 2623
2624 - def modelGroup (self):
2625 """The model group for which this definition provides a name.""" 2626 return self.__modelGroup
2627 2628 # CFD:MGD CFD:ModelGroupDefinition 2629 @classmethod
2630 - def CreateFromDOM (cls, node, **kw):
2631 """Create a Model Group Definition from a DOM element node. 2632 2633 wxs is a Schema instance within which the model group is being 2634 defined. 2635 2636 node is a DOM element. The name must be 'group', and the node 2637 must be in the XMLSchema namespace. The node must have a 2638 'name' attribute, and must not have a 'ref' attribute. 2639 """ 2640 assert xsd.nodeIsNamed(node, 'group') 2641 2642 assert domutils.NodeAttribute(node, 'ref') is None 2643 2644 name = domutils.NodeAttribute(node, 'name') 2645 kw['scope'] = _ScopedDeclaration_mixin.XSCOPE_indeterminate 2646 rv = cls(name=name, node=node, **kw) 2647 rv._annotationFromDOM(node) 2648 2649 kw.pop('node', None) 2650 kw['owner'] = rv 2651 2652 for cn in node.childNodes: 2653 if Node.ELEMENT_NODE != cn.nodeType: 2654 continue 2655 if ModelGroup.IsGroupMemberNode(cn): 2656 assert not rv.__modelGroup 2657 # Model group definitions always occur at the top level of the 2658 # schema, so the elements declared in them are not bound to a 2659 # scope until they are referenced in a complex type. 2660 rv.__modelGroup = ModelGroup.CreateFromDOM(cn, model_group_definition=rv, **kw) 2661 assert rv.__modelGroup is not None 2662 return rv
2663 2664 # bR:MGD
2665 - def _bindingRequires_vx (self, include_lax):
2666 """Model group definitions depend on the contained model group.""" 2667 if not include_lax: 2668 return frozenset() 2669 return frozenset([self.__modelGroup])
2670
2671 - def __str__ (self):
2672 return 'MGD[%s: %s]' % (self.name(), self.modelGroup())
2673
2674 2675 -class ModelGroup (_ParticleTree_mixin, _SchemaComponent_mixin, _Annotated_mixin):
2676 """An XMLSchema U{Model Group<http://www.w3.org/TR/xmlschema-1/#cModel_Group>} component.""" 2677 C_INVALID = 0 2678 C_ALL = 0x01 2679 C_CHOICE = 0x02 2680 C_SEQUENCE = 0x03 2681 2682 # One of the C_* values above. Set at construction time from the 2683 # keyword parameter "compositor". 2684 __compositor = C_INVALID
2685 - def compositor (self):
2686 return self.__compositor
2687 2688 @classmethod
2689 - def CompositorToString (cls, compositor):
2690 """Map a compositor value to a string.""" 2691 if cls.C_ALL == compositor: 2692 return 'all' 2693 if cls.C_CHOICE == compositor: 2694 return 'choice' 2695 if cls.C_SEQUENCE == compositor: 2696 return 'sequence' 2697 return 'invalid'
2698
2699 - def compositorToString (self):
2700 """Return a string representing the compositor value.""" 2701 return self.CompositorToString(self.__compositor)
2702 2703 # A list of Particle instances. Set at construction time from 2704 # the keyword parameter "particles". 2705 __particles = None
2706 - def particles (self):
2707 return self.__particles
2708
2709 - def isAdaptable (self, ctd):
2710 """A model group has an unresolvable particle if any of its 2711 particles is unresolvable. Duh.""" 2712 for p in self.particles(): 2713 if not p.isAdaptable(ctd): 2714 return False 2715 return True
2716
2717 - def effectiveTotalRange (self, particle):
2718 """Return the minimum and maximum of the number of elements that can 2719 appear in a sequence matched by this particle. 2720 2721 See U{http://www.w3.org/TR/xmlschema-1/#cos-seq-range} 2722 """ 2723 if self.__compositor in (self.C_ALL, self.C_SEQUENCE): 2724 sum_minoccurs = 0 2725 sum_maxoccurs = 0 2726 for prt in self.__particles: 2727 (prt_min, prt_max) = prt.effectiveTotalRange() 2728 sum_minoccurs += prt_min 2729 if sum_maxoccurs is not None: 2730 if prt_max is None: 2731 sum_maxoccurs = None 2732 else: 2733 sum_maxoccurs += prt_max 2734 prod_maxoccurs = particle.maxOccurs() 2735 if prod_maxoccurs is not None: 2736 if sum_maxoccurs is None: 2737 prod_maxoccurs = None 2738 else: 2739 prod_maxoccurs *= sum_maxoccurs 2740 return (sum_minoccurs * particle.minOccurs(), prod_maxoccurs) 2741 assert self.__compositor == self.C_CHOICE 2742 if 0 == len(self.__particles): 2743 min_minoccurs = 0 2744 max_maxoccurs = 0 2745 else: 2746 (min_minoccurs, max_maxoccurs) = self.__particles[0].effectiveTotalRange() 2747 for prt in self.__particles[1:]: 2748 (prt_min, prt_max) = prt.effectiveTotalRange() 2749 if prt_min < min_minoccurs: 2750 min_minoccurs = prt_min 2751 if prt_max is None: 2752 max_maxoccurs = None 2753 elif (max_maxoccurs is not None) and (prt_max > max_maxoccurs): 2754 max_maxoccurs = prt_max 2755 min_minoccurs *= particle.minOccurs() 2756 if (max_maxoccurs is not None) and (particle.maxOccurs() is not None): 2757 max_maxoccurs *= particle.maxOccurs() 2758 return (min_minoccurs, max_maxoccurs)
2759 2760 # The ModelGroupDefinition that names this ModelGroup, or None if 2761 # the ModelGroup is anonymous. This is set at construction time 2762 # from the keyword parameter "model_group_definition". 2763 __modelGroupDefinition = None
2764 - def modelGroupDefinition (self):
2765 """The ModelGroupDefinition that names this group, or None if it is unnamed.""" 2766 return self.__modelGroupDefinition
2767
2768 - def __init__ (self, compositor, particles, *args, **kw):
2769 """Create a new model group. 2770 2771 compositor must be a legal compositor value (one of C_ALL, C_CHOICE, C_SEQUENCE). 2772 2773 particles must be a list of zero or more Particle instances. 2774 2775 scope is the _ScopeDeclaration_mixin context into which new 2776 declarations are recorded. It can be SCOPE_global, a complex 2777 type definition, or None if this is (or is within) a named 2778 model group. 2779 2780 model_group_definition is an instance of ModelGroupDefinition 2781 if this is a named model group. It defaults to None 2782 indicating a local group. 2783 """ 2784 2785 super(ModelGroup, self).__init__(*args, **kw) 2786 assert 'scope' in kw 2787 self.__compositor = compositor 2788 self.__particles = particles 2789 self.__modelGroupDefinition = kw.get('model_group_definition')
2790
2791 - def hasWildcardElement (self):
2792 """Return True if the model includes a wildcard amongst its particles.""" 2793 for p in self.particles(): 2794 if p.hasWildcardElement(): 2795 return True 2796 return False
2797 2798 # bR:MG
2799 - def _bindingRequires_vx (self, include_lax):
2800 if not include_lax: 2801 return frozenset() 2802 return frozenset(self.__particles)
2803 2804 # CFD:MG CFD:ModelGroup 2805 @classmethod
2806 - def CreateFromDOM (cls, node, **kw):
2807 """Create a model group from the given DOM node. 2808 2809 wxs is a Schema instance within which the model group is being 2810 defined. 2811 2812 node is a DOM element. The name must be one of ( 'all', 2813 'choice', 'sequence' ), and the node must be in the XMLSchema 2814 namespace. 2815 2816 scope is the _ScopeDeclaration_mxin context that is assigned 2817 to declarations that appear within the model group. It can be 2818 None, indicating no scope defined, or a complex type 2819 definition. 2820 """ 2821 2822 scope = kw['scope'] 2823 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition) 2824 2825 if xsd.nodeIsNamed(node, 'all'): 2826 compositor = cls.C_ALL 2827 elif xsd.nodeIsNamed(node, 'choice'): 2828 compositor = cls.C_CHOICE 2829 else: 2830 assert xsd.nodeIsNamed(node, 'sequence') 2831 compositor = cls.C_SEQUENCE 2832 particles = [] 2833 # Remove the owner from particle constructor arguments: we need to set it later 2834 kw.pop('owner', None) 2835 for cn in node.childNodes: 2836 if Node.ELEMENT_NODE != cn.nodeType: 2837 continue 2838 if Particle.IsParticleNode(cn): 2839 # NB: Ancestor of particle is set in the ModelGroup constructor 2840 particles.append(Particle.CreateFromDOM(node=cn, **kw)) 2841 elif not xsd.nodeIsNamed(cn, 'annotation'): 2842 raise pyxb.SchemaValidationError('Unexpected element %s in model group' % (cn.nodeName,)) 2843 rv = cls(compositor, particles, node=node, **kw) 2844 for p in particles: 2845 p._setOwner(rv) 2846 rv._annotationFromDOM(node) 2847 return rv
2848 2849 @classmethod
2850 - def IsGroupMemberNode (cls, node):
2851 return xsd.nodeIsNamed(node, 'all', 'choice', 'sequence')
2852 2853 # aFS:MG
2854 - def _adaptForScope (self, owner, ctd):
2855 rv = self 2856 assert isinstance(ctd, ComplexTypeDefinition) 2857 maybe_rv = self._clone(owner, ctd._objectOrigin()) 2858 scoped_particles = [ _p._adaptForScope(maybe_rv, ctd) for _p in self.particles() ] 2859 do_clone = (self._scope() != ctd) or (self.particles() != scoped_particles) 2860 if do_clone: 2861 rv = maybe_rv 2862 rv.__particles = scoped_particles 2863 return rv
2864
2865 - def _walkParticleTree (self, visit, arg):
2866 visit(self, True, arg) 2867 for p in self.particles(): 2868 p._walkParticleTree(visit, arg) 2869 visit(self, False, arg)
2870
2871 - def __str__ (self):
2872 comp = None 2873 if self.C_ALL == self.compositor(): 2874 comp = 'ALL' 2875 elif self.C_CHOICE == self.compositor(): 2876 comp = 'CHOICE' 2877 elif self.C_SEQUENCE == self.compositor(): 2878 comp = 'SEQUENCE' 2879 return '%s:(%s)' % (comp, ",".join( [ str(_p) for _p in self.particles() ] ) )
2880
2881 -class Particle (_ParticleTree_mixin, _SchemaComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin):
2882 """An XMLSchema U{Particle<http://www.w3.org/TR/xmlschema-1/#cParticle>} component.""" 2883 2884 # The minimum number of times the term may appear. 2885 __minOccurs = 1
2886 - def minOccurs (self):
2887 """The minimum number of times the term may appear. 2888 2889 Defaults to 1.""" 2890 return self.__minOccurs
2891 2892 # Upper limit on number of times the term may appear. 2893 __maxOccurs = 1
2894 - def maxOccurs (self):
2895 """Upper limit on number of times the term may appear. 2896 2897 If None, the term may appear any number of times; otherwise, 2898 this is an integral value indicating the maximum number of times 2899 the term may appear. The default value is 1; the value, unless 2900 None, must always be at least minOccurs(). 2901 """ 2902 return self.__maxOccurs
2903 2904 # A reference to a ModelGroup, WildCard, or ElementDeclaration 2905 __term = None
2906 - def term (self):
2907 """A reference to a ModelGroup, Wildcard, or ElementDeclaration.""" 2908 return self.__term
2909 __pendingTerm = None 2910 2911 __refAttribute = None 2912 __resolvableType = None 2913
2914 - def effectiveTotalRange (self):
2915 """Extend the concept of effective total range to all particles. 2916 2917 See U{http://www.w3.org/TR/xmlschema-1/#cos-seq-range} and 2918 U{http://www.w3.org/TR/xmlschema-1/#cos-choice-range} 2919 """ 2920 if isinstance(self.__term, ModelGroup): 2921 return self.__term.effectiveTotalRange(self) 2922 return (self.minOccurs(), self.maxOccurs())
2923
2924 - def isEmptiable (self):
2925 """Return C{True} iff this particle can legitimately match an empty 2926 sequence (no content). 2927 2928 See U{http://www.w3.org/TR/xmlschema-1/#cos-group-emptiable} 2929 """ 2930 return 0 == self.effectiveTotalRange()[0]
2931
2932 - def hasWildcardElement (self):
2933 """Return True iff this particle has a wildcard in its term. 2934 2935 Note that the wildcard may be in a nested model group.""" 2936 return self.term().hasWildcardElement()
2937
2938 - def __init__ (self, term, *args, **kw):
2939 """Create a particle from the given DOM node. 2940 2941 term is a XML Schema Component: one of ModelGroup, 2942 ElementDeclaration, and Wildcard. 2943 2944 The following keyword arguments are processed: 2945 2946 min_occurs is a non-negative integer value with default 1, 2947 denoting the minimum number of terms required by the content 2948 model. 2949 2950 max_occurs is a positive integer value with default 1, or None 2951 indicating unbounded, denoting the maximum number of terms 2952 allowed by the content model. 2953 2954 scope is the _ScopeDeclaration_mxin context that is assigned 2955 to declarations that appear within the particle. It can be 2956 None, indicating no scope defined, or a complex type 2957 definition. 2958 """ 2959 2960 super(Particle, self).__init__(*args, **kw) 2961 2962 min_occurs = kw.get('min_occurs', 1) 2963 max_occurs = kw.get('max_occurs', 1) 2964 2965 assert 'scope' in kw 2966 assert (self._scopeIsIndeterminate()) or isinstance(self._scope(), ComplexTypeDefinition) 2967 2968 if term is not None: 2969 self.__term = term 2970 2971 assert isinstance(min_occurs, (types.IntType, types.LongType)) 2972 self.__minOccurs = min_occurs 2973 assert (max_occurs is None) or isinstance(max_occurs, (types.IntType, types.LongType)) 2974 self.__maxOccurs = max_occurs 2975 if self.__maxOccurs is not None: 2976 if self.__minOccurs > self.__maxOccurs: 2977 raise pyxb.LogicError('Particle minOccurs %s is greater than maxOccurs %s on creation' % (min_occurs, max_occurs))
2978 2979 # res:Particle
2980 - def _resolve (self):
2981 if self.isResolved(): 2982 return self 2983 2984 # @RESOLUTION@ 2985 if ModelGroup == self.__resolvableType: 2986 ref_en = self._namespaceContext().interpretQName(self.__refAttribute) 2987 group_decl = ref_en.modelGroupDefinition() 2988 if group_decl is None: 2989 raise pyxb.SchemaValidationError('Model group reference %s cannot be found' % (ref_en,)) 2990 2991 self.__pendingTerm = group_decl.modelGroup() 2992 assert self.__pendingTerm is not None 2993 elif ElementDeclaration == self.__resolvableType: 2994 # 3.9.2 says use 3.3.2, which is Element. The element inside a 2995 # particle is a localElement, so we either get the one it refers 2996 # to (which is top-level), or create a local one here. 2997 if self.__refAttribute is not None: 2998 assert self.__pendingTerm is None 2999 ref_en = self._namespaceContext().interpretQName(self.__refAttribute) 3000 self.__pendingTerm = ref_en.elementDeclaration() 3001 if self.__pendingTerm is None: 3002 raise pyxb.SchemaValidationError('Unable to locate element referenced by %s' % (ref_en,)) 3003 assert self.__pendingTerm is not None 3004 3005 # Whether this is a local declaration or one pulled in from the 3006 # global type definition symbol space, its name is now reserved in 3007 # this type. 3008 assert self.__pendingTerm is not None 3009 else: 3010 assert False 3011 3012 self.__term = self.__pendingTerm 3013 assert self.__term is not None 3014 return self
3015
3016 - def isResolved (self):
3017 return self.__term is not None
3018 3019 # CFD:Particle 3020 @classmethod
3021 - def CreateFromDOM (cls, node, **kw):
3022 """Create a particle from the given DOM node. 3023 3024 wxs is a Schema instance within which the model group is being 3025 defined. 3026 3027 node is a DOM element. The name must be one of ( 'group', 3028 'element', 'any', 'all', 'choice', 'sequence' ), and the node 3029 must be in the XMLSchema namespace. 3030 3031 scope is the _ScopeDeclaration_mxin context that is assigned 3032 to declarations that appear within the model group. It can be 3033 None, indicating no scope defined, or a complex type 3034 definition. 3035 """ 3036 scope = kw['scope'] 3037 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition) 3038 3039 kw.update({ 'min_occurs' : 1 3040 , 'max_occurs' : 1 3041 , 'node' : node }) 3042 3043 if not Particle.IsParticleNode(node): 3044 raise pyxb.LogicError('Attempted to create particle from illegal element %s' % (node.nodeName,)) 3045 attr_val = domutils.NodeAttribute(node, 'minOccurs') 3046 if attr_val is not None: 3047 kw['min_occurs'] = datatypes.nonNegativeInteger(attr_val) 3048 attr_val = domutils.NodeAttribute(node, 'maxOccurs') 3049 if attr_val is not None: 3050 if 'unbounded' == attr_val: 3051 kw['max_occurs'] = None 3052 else: 3053 kw['max_occurs'] = datatypes.nonNegativeInteger(attr_val) 3054 3055 rv = cls(None, **kw) 3056 3057 kw.pop('node', None) 3058 kw['owner'] = rv 3059 3060 rv.__refAttribute = domutils.NodeAttribute(node, 'ref') 3061 rv.__pendingTerm = None 3062 rv.__resolvableType = None 3063 if xsd.nodeIsNamed(node, 'group'): 3064 # 3.9.2 says use 3.8.2, which is ModelGroup. The group 3065 # inside a particle is a groupRef. If there is no group 3066 # with that name, this throws an exception as expected. 3067 if rv.__refAttribute is None: 3068 raise pyxb.SchemaValidationError('group particle without reference') 3069 rv.__resolvableType = ModelGroup 3070 elif xsd.nodeIsNamed(node, 'element'): 3071 if rv.__refAttribute is None: 3072 schema = kw.get('schema') 3073 assert schema is not None 3074 target_namespace = schema.targetNamespaceForNode(node, ElementDeclaration) 3075 incoming_tns = kw.get('target_namespace') 3076 if incoming_tns is not None: 3077 assert incoming_tns == target_namespace 3078 else: 3079 kw['target_namespace'] = target_namespace 3080 rv.__term = ElementDeclaration.CreateFromDOM(node=node, **kw) 3081 else: 3082 # NOTE: 3.3.3 clause 2.2 specifies that if ref is used, all 3083 # the other configuration attributes like nillable and default 3084 # must be absent. We don't even bother looking for them. 3085 rv.__resolvableType = ElementDeclaration 3086 assert not xsd.nodeIsNamed(node.parentNode, 'schema') 3087 elif xsd.nodeIsNamed(node, 'any'): 3088 # 3.9.2 says use 3.10.2, which is Wildcard. 3089 rv.__term = Wildcard.CreateFromDOM(node=node) 3090 elif ModelGroup.IsGroupMemberNode(node): 3091 # Choice, sequence, and all inside a particle are explicit 3092 # groups (or a restriction of explicit group, in the case 3093 # of all) 3094 rv.__term = ModelGroup.CreateFromDOM(node, **kw) 3095 else: 3096 raise pyxb.LogicError('Unhandled node in Particle.CreateFromDOM: %s' % (node.toxml("utf-8"),)) 3097 3098 if not rv.isResolved(): 3099 rv._queueForResolution('creation') 3100 return rv
3101 3102 # bR:PRT
3103 - def _bindingRequires_vx (self, include_lax):
3104 if not include_lax: 3105 return frozenset() 3106 return frozenset([ self.__term ])
3107 3108 # aFS:PRT
3109 - def _adaptForScope (self, owner, ctd):
3110 rv = self 3111 assert isinstance(ctd, ComplexTypeDefinition) 3112 maybe_rv = self._clone(owner, ctd._objectOrigin()) 3113 term = rv.__term._adaptForScope(maybe_rv, ctd) 3114 do_clone = (self._scope() != ctd) or (rv.__term != term) 3115 if do_clone: 3116 rv = maybe_rv 3117 rv.__term = term 3118 return rv
3119
3120 - def isAdaptable (self, ctd):
3121 """A particle has an unresolvable particle if it cannot be 3122 resolved, or if it has resolved to a term which is a model 3123 group that has an unresolvable particle. 3124 """ 3125 if not self.isResolved(): 3126 return False 3127 return self.term().isAdaptable(ctd)
3128
3129 - def walkParticleTree (self, visit, arg):
3130 """The entry-point to walk a particle tree defining a content model. 3131 3132 See L{_ParticleTree_mixin._walkParticleTree}.""" 3133 self._walkParticleTree(visit, arg)
3134
3135 - def _walkParticleTree (self, visit, arg):
3136 visit(self, True, arg) 3137 self.__term._walkParticleTree(visit, arg) 3138 visit(self, False, arg)
3139 3140 @classmethod
3141 - def IsTypedefNode (cls, node):
3142 return xsd.nodeIsNamed(node, 'group', 'all', 'choice', 'sequence')
3143 3144 @classmethod
3145 - def IsParticleNode (cls, node, *others):
3146 return xsd.nodeIsNamed(node, 'group', 'all', 'choice', 'sequence', 'element', 'any', *others)
3147
3148 - def __str__ (self):
3149 #return 'PART{%s:%d,%s}' % (self.term(), self.minOccurs(), self.maxOccurs()) 3150 return 'PART{%s:%d,%s}[%x]' % ('TERM', self.minOccurs(), self.maxOccurs(), id(self))
3151
3152 3153 # 3.10.1 3154 -class Wildcard (_ParticleTree_mixin, _SchemaComponent_mixin, _Annotated_mixin):
3155 """An XMLSchema U{Wildcard<http://www.w3.org/TR/xmlschema-1/#cParticle>} component.""" 3156 3157 NC_any = '##any' #<<< The namespace constraint "##any" 3158 NC_not = '##other' #<<< A flag indicating constraint "##other" 3159 NC_targetNamespace = '##targetNamespace' 3160 NC_local = '##local' 3161 3162 __namespaceConstraint = None
3163 - def namespaceConstraint (self):
3164 """A constraint on the namespace for the wildcard. 3165 3166 Valid values are: 3167 - L{Wildcard.NC_any} 3168 - A tuple ( L{Wildcard.NC_not}, a_namespace ) 3169 - set(of_namespaces) 3170 3171 Note that namespace are represented by 3172 L{Namespace<pyxb.namespace.Namespace>} instances, not the URIs that 3173 actually define a namespace. Absence of a namespace is represented by 3174 C{None}, both in the "not" pair and in the set. 3175 """ 3176 return self.__namespaceConstraint
3177 3178 @classmethod
3179 - def IntensionalUnion (cls, constraints):
3180 """http://www.w3.org/TR/xmlschema-1/#cos-aw-union""" 3181 assert 0 < len(constraints) 3182 o1 = constraints.pop(0) 3183 while 0 < len(constraints): 3184 o2 = constraints.pop(0) 3185 # 1 3186 if (o1 == o2): 3187 continue 3188 # 2 3189 if (cls.NC_any == o1) or (cls.NC_any == o2): 3190 o1 = cls.NC_any 3191 continue 3192 # 3 3193 if isinstance(o1, set) and isinstance(o2, set): 3194 o1 = o1.union(o2) 3195 continue 3196 # 4 3197 if (isinstance(o1, tuple) and isinstance(o2, tuple)) and (o1[1] != o2[1]): 3198 o1 = ( cls.NC_not, None ) 3199 continue 3200 # At this point, one must be a negated namespace and the 3201 # other a set. Identify them. 3202 c_tuple = None 3203 c_set = None 3204 if isinstance(o1, tuple): 3205 assert isinstance(o2, set) 3206 c_tuple = o1 3207 c_set = o2 3208 else: 3209 assert isinstance(o1, set) 3210 assert isinstance(o2, tuple) 3211 c_tuple = o2 3212 c_set = o1 3213 negated_ns = c_tuple[1] 3214 if negated_ns is not None: 3215 # 5.1 3216 if (negated_ns in c_set) and (None in c_set): 3217 o1 = cls.NC_any 3218 continue 3219 # 5.2 3220 if negated_ns in c_set: 3221 o1 = ( cls.NC_not, None ) 3222 continue 3223 # 5.3 3224 if None in c_set: 3225 raise pyxb.SchemaValidationError('Union of wildcard namespace constraints not expressible') 3226 o1 = c_tuple 3227 continue 3228 # 6 3229 if None in c_set: 3230 o1 = cls.NC_any 3231 else: 3232 o1 = ( cls.NC_not, None ) 3233 return o1
3234 3235 @classmethod
3236 - def IntensionalIntersection (cls, constraints):
3237 """http://www.w3.org/TR/xmlschema-1/#cos-aw-intersect""" 3238 assert 0 < len(constraints) 3239 o1 = constraints.pop(0) 3240 while 0 < len(constraints): 3241 o2 = constraints.pop(0) 3242 # 1 3243 if (o1 == o2): 3244 continue 3245 # 2 3246 if (cls.NC_any == o1) or (cls.NC_any == o2): 3247 if cls.NC_any == o1: 3248 o1 = o2 3249 continue 3250 # 4 3251 if isinstance(o1, set) and isinstance(o2, set): 3252 o1 = o1.intersection(o2) 3253 continue 3254 if isinstance(o1, tuple) and isinstance(o2, tuple): 3255 ns1 = o1[1] 3256 ns2 = o2[1] 3257 # 5 3258 if (ns1 is not None) and (ns2 is not None) and (ns1 != ns2): 3259 raise pyxb.SchemaValidationError('Intersection of wildcard namespace constraints not expressible') 3260 # 6 3261 assert (ns1 is None) or (ns2 is None) 3262 if ns1 is None: 3263 assert ns2 is not None 3264 o1 = ( cls.NC_not, ns2 ) 3265 else: 3266 assert ns1 is not None 3267 o1 = ( cls.NC_not, ns1 ) 3268 continue 3269 # 3 3270 # At this point, one must be a negated namespace and the 3271 # other a set. Identify them. 3272 c_tuple = None 3273 c_set = None 3274 if isinstance(o1, tuple): 3275 assert isinstance(o2, set) 3276 c_tuple = o1 3277 c_set = o2 3278 else: 3279 assert isinstance(o1, set) 3280 assert isinstance(o2, tuple) 3281 c_tuple = o2 3282 c_set = o1 3283 negated_ns = c_tuple[1] 3284 if negated_ns in c_set: 3285 c_set.remove(negated_ns) 3286 if None in c_set: 3287 c_set.remove(None) 3288 o1 = c_set 3289 return o1
3290 3291 PC_skip = 'skip' #<<< No constraint is applied 3292 PC_lax = 'lax' #<<< Validate against available uniquely determined declaration 3293 PC_strict = 'strict' #<<< Validate against declaration or xsi:type which must be available 3294 3295 # One of PC_* 3296 __processContents = None
3297 - def processContents (self):
3298 return self.__processContents
3299
3300 - def hasWildcardElement (self):
3301 """Return True, since Wildcard components are wildcards.""" 3302 return True
3303
3304 - def __init__ (self, *args, **kw):
3305 assert 0 == len(args) 3306 super(Wildcard, self).__init__(*args, **kw) 3307 self.__namespaceConstraint = kw['namespace_constraint'] 3308 self.__processContents = kw['process_contents']
3309
3310 - def isAdaptable (self, ctd):
3311 return True
3312
3313 - def _walkParticleTree (self, visit, arg):
3314 visit(self, None, arg)
3315 3316 # aFS:WC
3317 - def _adaptForScope (self, owner, ctd):
3318 """Wildcards are scope-independent; return self""" 3319 return self
3320 3321 # CFD:Wildcard 3322 @classmethod
3323 - def CreateFromDOM (cls, node, **kw):
3324 namespace_context = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(node) 3325 assert xsd.nodeIsNamed(node, 'any', 'anyAttribute') 3326 nc = domutils.NodeAttribute(node, 'namespace') 3327 if nc is None: 3328 namespace_constraint = cls.NC_any 3329 else: 3330 if cls.NC_any == nc: 3331 namespace_constraint = cls.NC_any 3332 elif cls.NC_not == nc: 3333 namespace_constraint = ( cls.NC_not, namespace_context.targetNamespace() ) 3334 else: 3335 ncs = set() 3336 for ns_uri in nc.split(): 3337 if cls.NC_local == ns_uri: 3338 ncs.add(None) 3339 elif cls.NC_targetNamespace == ns_uri: 3340 ncs.add(namespace_context.targetNamespace()) 3341 else: 3342 ncs.add(pyxb.namespace.NamespaceForURI(ns_uri, create_if_missing=True)) 3343 namespace_constraint = frozenset(ncs) 3344 3345 pc = domutils.NodeAttribute(node, 'processContents') 3346 if pc is None: 3347 process_contents = cls.PC_strict 3348 else: 3349 if pc in [ cls.PC_skip, cls.PC_lax, cls.PC_strict ]: 3350 process_contents = pc 3351 else: 3352 raise pyxb.SchemaValidationError('illegal value "%s" for any processContents attribute' % (pc,)) 3353 3354 rv = cls(node=node, namespace_constraint=namespace_constraint, process_contents=process_contents, **kw) 3355 rv._annotationFromDOM(node) 3356 return rv
3357
3358 # 3.11.1 3359 -class IdentityConstraintDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, _Annotated_mixin, pyxb.namespace.resolution._Resolvable_mixin):
3360 """An XMLSchema U{Identity Constraint Definition<http://www.w3.org/TR/xmlschema-1/#cIdentity-constraint_Definitions>} component.""" 3361 3362 ICC_KEY = 0x01 3363 ICC_KEYREF = 0x02 3364 ICC_UNIQUE = 0x04 3365 3366 __identityConstraintCategory = None
3367 - def identityConstraintCategory (self):
3369 3370 __selector = None
3371 - def selector (self):
3372 return self.__selector
3373 3374 __fields = None
3375 - def fields (self):
3376 return self.__fields
3377 3378 __referencedKey = None 3379 __referAttribute = None 3380 __icc = None 3381 3382 __annotations = None
3383 - def annotations (self):
3384 return self.__annotations
3385 3386 # CFD:ICD CFD:IdentityConstraintDefinition 3387 @classmethod
3388 - def CreateFromDOM (cls, node, **kw):
3389 name = domutils.NodeAttribute(node, 'name') 3390 scope = kw['scope'] 3391 assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or _ScopedDeclaration_mixin.IsValidScope(scope) 3392 rv = cls(name=name, node=node, **kw) 3393 3394 kw.pop('node', None) 3395 kw['owner'] = rv 3396 3397 #self._annotationFromDOM(node); 3398 rv.__isResolved = True 3399 icc = None 3400 if xsd.nodeIsNamed(node, 'key'): 3401 icc = rv.ICC_KEY 3402 elif xsd.nodeIsNamed(node, 'keyref'): 3403 icc = rv.ICC_KEYREF 3404 rv.__referAttribute = domutils.NodeAttribute(node, 'refer') 3405 if rv.__referAttribute is None: 3406 raise pyxb.SchemaValidationError('Require refer attribute on keyref elements') 3407 rv.__isResolved = False 3408 elif xsd.nodeIsNamed(node, 'unique'): 3409 icc = rv.ICC_UNIQUE 3410 else: 3411 raise pyxb.LogicError('Unexpected identity constraint node %s' % (node.toxml("utf-8"),)) 3412 rv.__icc = icc 3413 3414 cn = domutils.LocateUniqueChild(node, 'selector') 3415 rv.__selector = domutils.NodeAttribute(cn, 'xpath') 3416 if rv.__selector is None: 3417 raise pyxb.SchemaValidationError('selector element missing xpath attribute') 3418 3419 rv.__fields = [] 3420 for cn in domutils.LocateMatchingChildren(node, 'field'): 3421 xp_attr = domutils.NodeAttribute(cn, 'xpath') 3422 if xp_attr is None: 3423 raise pyxb.SchemaValidationError('field element missing xpath attribute') 3424 rv.__fields.append(xp_attr) 3425 3426 rv._annotationFromDOM(node) 3427 rv.__annotations = [] 3428 if rv.annotation() is not None: 3429 rv.__annotations.append(rv) 3430 3431 for cn in node.childNodes: 3432 if (Node.ELEMENT_NODE != cn.nodeType): 3433 continue 3434 an = None 3435 if xsd.nodeIsNamed(cn, 'selector', 'field'): 3436 an = domutils.LocateUniqueChild(cn, 'annotation') 3437 elif xsd.nodeIsNamed(cn, 'annotation'): 3438 an = cn 3439 if an is not None: 3440 rv.__annotations.append(Annotation.CreateFromDOM(an, **kw)) 3441 3442 rv.__identityConstraintCategory = icc 3443 if rv.ICC_KEYREF != rv.__identityConstraintCategory: 3444 rv._namespaceContext().targetNamespace().addCategoryObject('identityConstraintDefinition', rv.name(), rv) 3445 3446 if not rv.isResolved(): 3447 rv._queueForResolution('creation') 3448 return rv
3449 3450 __isResolved = False
3451 - def isResolved (self):
3452 return self.__isResolved
3453 3454 # res:ICD res:IdentityConstraintDefinition
3455 - def _resolve (self):
3456 if self.isResolved(): 3457 return self 3458 3459 icc = self.__icc 3460 if self.ICC_KEYREF == icc: 3461 refer_en = self._namespaceContext().interpretQName(self.__referAttribute) 3462 refer = refer_en.identityConstraintDefinition() 3463 if refer is None: 3464 self._queueForResolution('Identity constraint definition %s cannot be found' % (refer_en,), depends_on=refer) 3465 return self 3466 self.__referencedKey = refer 3467 self.__isResolved = True 3468 return self
3469 3470 # bR:ICD
3471 - def _bindingRequires_vx (self, include_lax):
3472 """Constraint definitions that are by reference require the referenced constraint.""" 3473 rv = set() 3474 if include_lax and (self.__referencedKey is not None): 3475 rv.add(self.__referencedKey) 3476 return frozenset(rv)
3477
3478 3479 3480 # 3.12.1 3481 -class NotationDeclaration (_SchemaComponent_mixin, _NamedComponent_mixin, _Annotated_mixin):
3482 """An XMLSchema U{Notation Declaration<http://www.w3.org/TR/xmlschema-1/#cNotation_Declarations>} component.""" 3483 __systemIdentifier = None
3484 - def systemIdentifier (self):
3485 return self.__systemIdentifier
3486 3487 __publicIdentifier = None
3488 - def publicIdentifier (self):
3489 return self.__publicIdentifier
3490 3491 # CFD:ND CFD:NotationDeclaration 3492 @classmethod
3493 - def CreateFromDOM (cls, node, **kw):
3494 name = domutils.NodeAttribute(node, 'name') 3495 rv = cls(name=name, node=node, **kw) 3496 3497 rv.__systemIdentifier = domutils.NodeAttribute(node, 'system') 3498 rv.__publicIdentifier = domutils.NodeAttribute(node, 'public') 3499 3500 rv._annotationFromDOM(node) 3501 return rv
3502
3503 # 3.13.1 3504 -class Annotation (_SchemaComponent_mixin):
3505 """An XMLSchema U{Annotation<http://www.w3.org/TR/xmlschema-1/#cAnnotation>} component.""" 3506 3507 __applicationInformation = None
3508 - def applicationInformation (self):
3509 return self.__applicationInformation
3510 3511 __userInformation = None
3512 - def userInformation (self):
3513 return self.__userInformation
3514 3515 # Define so superclasses can take keywords
3516 - def __init__ (self, **kw):
3517 application_information = kw.pop('application_information', None) 3518 user_information = kw.pop('user_information', None) 3519 super(Annotation, self).__init__(**kw) 3520 if (user_information is not None) and (not isinstance(user_information, list)): 3521 user_information = [ unicode(user_information) ] 3522 if (application_information is not None) and (not isinstance(application_information, list)): 3523 application_information = [ unicode(application_information) ] 3524 self.__userInformation = user_information 3525 self.__applicationInformation = application_information
3526 3527 # @todo: what the hell is this? From 3.13.2, I think it's a place 3528 # to stuff attributes from the annotation element, which makes 3529 # sense, as well as from the annotation's parent element, which 3530 # doesn't. Apparently it's for attributes that don't belong to 3531 # the XMLSchema namespace; so maybe we're not supposed to add 3532 # those to the other components. Note that these are attribute 3533 # information items, not attribute uses. 3534 __attributes = None 3535 3536 # CFD:Annotation 3537 @classmethod
3538 - def CreateFromDOM (cls, node, **kw):
3539 rv = cls(node=node, **kw) 3540 3541 # @todo:: Scan for attributes in the node itself that do not 3542 # belong to the XMLSchema namespace. 3543 3544 # Node should be an XMLSchema annotation node 3545 assert xsd.nodeIsNamed(node, 'annotation') 3546 app_info = [] 3547 user_info = [] 3548 for cn in node.childNodes: 3549 if xsd.nodeIsNamed(cn, 'appinfo'): 3550 app_info.append(cn) 3551 elif xsd.nodeIsNamed(cn, 'documentation'): 3552 user_info.append(cn) 3553 else: 3554 pass 3555 if 0 < len(app_info): 3556 rv.__applicationInformation = app_info 3557 if 0 < len(user_info): 3558 rv.__userInformation = user_info 3559 3560 return rv
3561 3562 __RemoveMultiQuote_re = re.compile('""+')
3563 - def asDocString (self):
3564 """Return the text in a form suitable for embedding in a 3565 triple-double-quoted docstring. 3566 3567 Any sequence of two or more double quotes is replaced by a sequence of 3568 single quotes that is the same length. Following this, spaces are 3569 added at the start and the end as necessary to ensure a double quote 3570 does not appear in those positions.""" 3571 rv = self.text() 3572 rv = self.__RemoveMultiQuote_re.sub(lambda _mo: "'" * (_mo.end(0) - _mo.start(0)), rv) 3573 if rv.startswith('"'): 3574 rv = ' ' + rv 3575 if rv.endswith('"'): 3576 rv = rv + ' ' 3577 return rv
3578
3579 - def text (self):
3580 if self.__userInformation is None: 3581 return '' 3582 text = [] 3583 # Values in userInformation are DOM "documentation" elements. 3584 # We want their combined content. 3585 for dn in self.__userInformation: 3586 for cn in dn.childNodes: 3587 if Node.TEXT_NODE == cn.nodeType: 3588 text.append(cn.data) 3589 return ''.join(text)
3590
3591 - def __str__ (self):
3592 """Return the catenation of all user information elements in the 3593 annotation as a single unicode string. Returns the empty string if 3594 there are no user information elements.""" 3595 return self.text()
3596
3597 # Section 3.14. 3598 -class SimpleTypeDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin):
3599 """An XMLSchema U{Simple Type Definition<http://www.w3.org/TR/xmlschema-1/#Simple_Type_Definitions>} component.""" 3600 3601 # Reference to the SimpleTypeDefinition on which this is based. 3602 # The value must be non-None except for the simple ur-type 3603 # definition. 3604 __baseTypeDefinition = None
3605 - def baseTypeDefinition (self):
3606 return self.__baseTypeDefinition
3607 3608 __memberTypes = None 3609 __itemTypeAttribute = None 3610 __baseAttribute = None 3611 __memberTypesAttribute = None 3612 __localFacets = None 3613 3614 # A map from a subclass of facets.Facet to an instance of that class. 3615 # Presence of a facet class as a key in this map is the indicator that the 3616 # type definition and its subtypes are permitted to use the corresponding 3617 # facet. All facets in force for this type are present in the map, 3618 # including those constraints inherited parent types. 3619 __facets = None
3620 - def facets (self):
3621 assert (self.__facets is None) or (type(self.__facets) == types.DictType) 3622 return self.__facets
3623 3624 # The facets.FundamentalFacet instances that describe this type 3625 __fundamentalFacets = None
3626 - def fundamentalFacets (self):
3627 """A frozenset of instances of facets.FundamentallFacet.""" 3628 return self.__fundamentalFacets
3629 3630 STD_empty = 0 #<<< Marker indicating an empty set of STD forms 3631 STD_extension = 0x01 #<<< Representation for extension in a set of STD forms 3632 STD_list = 0x02 #<<< Representation for list in a set of STD forms 3633 STD_restriction = 0x04 #<<< Representation of restriction in a set of STD forms 3634 STD_union = 0x08 #<<< Representation of union in a set of STD forms 3635 3636 _STD_Map = { 'extension' : STD_extension 3637 , 'list' : STD_list 3638 , 'restriction' : STD_restriction 3639 , 'union' : STD_union } 3640 3641 # Bitmask defining the subset that comprises the final property 3642 __final = STD_empty 3643 @classmethod
3644 - def _FinalToString (cls, final_value):
3645 """Convert a final value to a string.""" 3646 tags = [] 3647 if final_value & cls.STD_extension: 3648 tags.append('extension') 3649 if final_value & cls.STD_list: 3650 tags.append('list') 3651 if final_value & cls.STD_restriction: 3652 tags.append('restriction') 3653 if final_value & cls.STD_union: 3654 tags.append('union') 3655 return ' '.join(tags)
3656 3657 VARIETY_absent = 0x01 #<<< Only used for the ur-type 3658 VARIETY_atomic = 0x02 #<<< Use for types based on a primitive type 3659 VARIETY_list = 0x03 #<<< Use for lists of atomic-variety types 3660 VARIETY_union = 0x04 #<<< Use for types that aggregate other types 3661 3662 # Derivation alternative 3663 _DA_empty = 'none specified' 3664 _DA_restriction = 'restriction' 3665 _DA_list = 'list' 3666 _DA_union = 'union' 3667
3668 - def _derivationAlternative (self):
3669 return self.__derivationAlternative
3670 __derivationAlternative = None 3671 3672 # Identify the sort of value collection this holds. This field is 3673 # used to identify unresolved definitions. 3674 __variety = None
3675 - def variety (self):
3676 return self.__variety
3677 @classmethod
3678 - def VarietyToString (cls, variety):
3679 """Convert a variety value to a string.""" 3680 if cls.VARIETY_absent == variety: 3681 return 'absent' 3682 if cls.VARIETY_atomic == variety: 3683 return 'atomic' 3684 if cls.VARIETY_list == variety: 3685 return 'list' 3686 if cls.VARIETY_union == variety: 3687 return 'union' 3688 return '?NoVariety?'
3689 3690 # For atomic variety only, the root (excepting ur-type) type. 3691 __primitiveTypeDefinition = None
3692 - def primitiveTypeDefinition (self, throw_if_absent=True):
3693 if throw_if_absent: 3694 assert self.VARIETY_atomic == self.variety() 3695 if self.__primitiveTypeDefinition is None: 3696 raise pyxb.LogicError('Expected primitive type for %s in %s', self, self.targetNamespace()) 3697 return self.__primitiveTypeDefinition
3698 3699 # For list variety only, the type of items in the list 3700 __itemTypeDefinition = None
3701 - def itemTypeDefinition (self):
3702 assert self.VARIETY_list == self.variety() 3703 if self.__itemTypeDefinition is None: 3704 raise pyxb.LogicError('Expected item type') 3705 return self.__itemTypeDefinition
3706 3707 # For union variety only, the sequence of candidate members 3708 __memberTypeDefinitions = None
3709 - def memberTypeDefinitions (self):
3710 assert self.VARIETY_union == self.variety() 3711 if self.__memberTypeDefinitions is None: 3712 raise pyxb.LogicError('Expected member types') 3713 return self.__memberTypeDefinitions
3714 3715 # bR:STD
3716 - def _bindingRequires_vx (self, include_lax):
3717 """Implement base class method. 3718 3719 This STD depends on its baseTypeDefinition, unless its variety 3720 is absent. Other dependencies are on item, primitive, or 3721 member type definitions.""" 3722 type_definitions = set() 3723 if self != self.baseTypeDefinition(): 3724 type_definitions.add(self.baseTypeDefinition()) 3725 if self.VARIETY_absent == self.variety(): 3726 type_definitions = set() 3727 elif self.VARIETY_atomic == self.variety(): 3728 if self != self.primitiveTypeDefinition(): 3729 type_definitions.add(self.primitiveTypeDefinition()) 3730 elif self.VARIETY_list == self.variety(): 3731 assert self != self.itemTypeDefinition() 3732 type_definitions.add(self.itemTypeDefinition()) 3733 else: 3734 assert self.VARIETY_union == self.variety() 3735 assert self not in self.memberTypeDefinitions() 3736 type_definitions.update(self.memberTypeDefinitions()) 3737 # NB: This type also depends on the value type definitions for 3738 # any facets that apply to it. This fact only matters when 3739 # generating the datatypes_facets source. That, and the fact 3740 # that there are dependency loops (e.g., integer requires a 3741 # nonNegativeInteger for its length facet) means we don't 3742 # bother adding in those. 3743 return frozenset(type_definitions)
3744 3745 # A non-property field that holds a reference to the DOM node from 3746 # which the type is defined. The value is held only between the 3747 # point where the simple type definition instance is created until 3748 # the point it is resolved. 3749 __domNode = None 3750 3751 # Indicate that this instance was defined as a built-in rather 3752 # than from a DOM instance. 3753 __isBuiltin = False 3754 3755 # Allocate one of these. Users should use one of the Create* 3756 # factory methods instead. 3757
3758 - def __init__ (self, *args, **kw):
3759 super(SimpleTypeDefinition, self).__init__(*args, **kw) 3760 self.__variety = kw['variety']
3761
3762 - def __setstate__ (self, state):
3763 """Extend base class unpickle support to retain link between 3764 this instance and the Python class that it describes. 3765 3766 This is because the pythonSupport value is a class reference, 3767 not an instance reference, so it wasn't deserialized, and its 3768 class member link was never set. 3769 """ 3770 super_fn = getattr(super(SimpleTypeDefinition, self), '__setstate__', lambda _state: self.__dict__.update(_state)) 3771 super_fn(state) 3772 if self.__pythonSupport is not None: 3773 self.__pythonSupport._SimpleTypeDefinition(self)
3774
3775 - def __str__ (self):
3776 if self.name() is not None: 3777 elts = [ self.name(), ':' ] 3778 else: 3779 elts = [ '<anonymous>:' ] 3780 if self.VARIETY_absent == self.variety(): 3781 elts.append('the ur-type') 3782 elif self.VARIETY_atomic == self.variety(): 3783 elts.append('restriction of %s' % (self.baseTypeDefinition().name(),)) 3784 elif self.VARIETY_list == self.variety(): 3785 elts.append('list of %s' % (self.itemTypeDefinition().name(),)) 3786 elif self.VARIETY_union == self.variety(): 3787 elts.append('union of %s' % (" ".join([str(_mtd.name()) for _mtd in self.memberTypeDefinitions()],))) 3788 else: 3789 # Gets here if the type has not been resolved. 3790 elts.append('?') 3791 #raise pyxb.LogicError('Unexpected variety %s' % (self.variety(),)) 3792 if self.__facets: 3793 felts = [] 3794 for (k, v) in self.__facets.items(): 3795 if v is not None: 3796 felts.append(str(v)) 3797 elts.append("\n %s" % (','.join(felts),)) 3798 if self.__fundamentalFacets: 3799 elts.append("\n ") 3800 elts.append(','.join( [str(_f) for _f in self.__fundamentalFacets ])) 3801 return 'STD[%s]' % (''.join(elts),)
3802
3803 - def _updateFromOther_csc (self, other):
3804 """Override fields in this instance with those from the other. 3805 3806 This method is invoked only by Schema._addNamedComponent, and 3807 then only when a built-in type collides with a schema-defined 3808 type. Material like facets is not (currently) held in the 3809 built-in copy, so the DOM information is copied over to the 3810 built-in STD, which is subsequently re-resolved. 3811 3812 Returns self. 3813 """ 3814 assert self != other 3815 assert self.isNameEquivalent(other) 3816 super(SimpleTypeDefinition, self)._updateFromOther_csc(other) 3817 3818 # The other STD should be an unresolved schema-defined type. 3819 assert other.__baseTypeDefinition is None, 'Update from resolved STD %s' % (other,) 3820 assert other.__domNode is not None 3821 self.__domNode = other.__domNode 3822 3823 # Preserve the python support 3824 if other.__pythonSupport is not None: 3825 # @todo: ERROR multiple references 3826 self.__pythonSupport = other.__pythonSupport 3827 3828 # Mark this instance as unresolved so it is re-examined 3829 self.__variety = None 3830 return self
3831
3832 - def isBuiltin (self):
3833 """Indicate whether this simple type is a built-in type.""" 3834 return self.__isBuiltin
3835 3836 __SimpleUrTypeDefinition = None 3837 @classmethod
3838 - def SimpleUrTypeDefinition (cls, schema=None, in_builtin_definition=False):
3839 """Create the SimpleTypeDefinition instance that approximates the simple ur-type. 3840 3841 See section 3.14.7.""" 3842 3843 #if in_builtin_definition and (cls.__SimpleUrTypeDefinition is not None): 3844 # raise pyxb.LogicError('Multiple definitions of SimpleUrType') 3845 if cls.__SimpleUrTypeDefinition is None: 3846 # Note: We use a singleton subclass 3847 assert schema is not None 3848 3849 ns_ctx = schema.targetNamespace().initialNamespaceContext() 3850 3851 kw = { 'name' : 'anySimpleType', 3852 'schema' : schema, 3853 'namespace_context' : ns_ctx, 3854 'binding_namespace' : schema.targetNamespace(), 3855 'variety' : cls.VARIETY_absent, 3856 'scope' : _ScopedDeclaration_mixin.SCOPE_global } 3857 bi = _SimpleUrTypeDefinition(**kw) 3858 bi._setPythonSupport(datatypes.anySimpleType) 3859 3860 # The baseTypeDefinition is the ur-type. 3861 bi.__baseTypeDefinition = ComplexTypeDefinition.UrTypeDefinition() 3862 # The simple ur-type has an absent variety, not an atomic 3863 # variety, so does not have a primitiveTypeDefinition 3864 3865 # No facets on the ur type 3866 bi.__facets = {} 3867 bi.__fundamentalFacets = frozenset() 3868 3869 bi.__resolveBuiltin() 3870 3871 cls.__SimpleUrTypeDefinition = bi 3872 return cls.__SimpleUrTypeDefinition
3873 3874 @classmethod
3875 - def _CreateXMLInstance (cls, name, schema):
3876 """Create STD instances for built-in types. 3877 3878 For example, xml:space is a restriction of NCName; xml:lang is a union. 3879 3880 """ 3881 from pyxb.binding import xml_ 3882 kw = { 'schema' : schema, 3883 'binding_namespace' : schema.targetNamespace(), 3884 'namespace_context' : schema.targetNamespace().initialNamespaceContext(), 3885 'scope' : _ScopedDeclaration_mixin.SCOPE_global, 3886 'variety' : cls.VARIETY_atomic } 3887 if 'space' == name: 3888 bi = cls(**kw) 3889 bi.__derivationAlternative = cls._DA_restriction 3890 bi.__baseTypeDefinition = datatypes.NCName.SimpleTypeDefinition() 3891 bi.__primitiveTypeDefinition = bi.__baseTypeDefinition.__primitiveTypeDefinition 3892 bi._setPythonSupport(xml_.STD_ANON_space) 3893 bi.setNameInBinding('STD_ANON_space') 3894 elif 'lang' == name: 3895 bi = cls(**kw) 3896 bi.__baseTypeDefinition = cls.SimpleUrTypeDefinition() 3897 bi.__memberTypes = [ datatypes.language.SimpleTypeDefinition() ] 3898 bi.__derivationAlternative = cls._DA_union 3899 bi.__primitiveTypeDefinition = bi 3900 bi._setPythonSupport(xml_.STD_ANON_lang) 3901 bi.setNameInBinding('STD_ANON_lang') 3902 else: 3903 raise pyxb.IncompleteImplementationError('No implementation for xml:%s' % (name,)) 3904 bi.__facets = { } 3905 for v in bi.pythonSupport().__dict__.values(): 3906 if isinstance(v, facets.ConstrainingFacet): 3907 bi.__facets[v.__class__] = v 3908 return bi
3909 3910 @classmethod
3911 - def CreatePrimitiveInstance (cls, name, schema, python_support):
3912 """Create a primitive simple type in the target namespace. 3913 3914 This is mainly used to pre-load standard built-in primitive 3915 types, such as those defined by XMLSchema Datatypes. You can 3916 use it for your own schemas as well, if you have special types 3917 that require explicit support to for Pythonic conversion. 3918 3919 All parameters are required and must be non-None. 3920 """ 3921 3922 kw = { 'name' : name, 3923 'schema' : schema, 3924 'binding_namespace' : schema.targetNamespace(), 3925 'namespace_context' : schema.targetNamespace().initialNamespaceContext(), 3926 'scope' : _ScopedDeclaration_mixin.SCOPE_global, 3927 'variety' : cls.VARIETY_atomic } 3928 3929 bi = cls(**kw) 3930 bi._setPythonSupport(python_support) 3931 3932 # Primitive types are based on the ur-type, and have 3933 # themselves as their primitive type definition. 3934 bi.__baseTypeDefinition = cls.SimpleUrTypeDefinition() 3935 bi.__primitiveTypeDefinition = bi 3936 3937 # Primitive types are built-in 3938 bi.__resolveBuiltin() 3939 assert bi.isResolved() 3940 return bi
3941 3942 @classmethod
3943 - def CreateDerivedInstance (cls, name, schema, parent_std, python_support):
3944 """Create a derived simple type in the target namespace. 3945 3946 This is used to pre-load standard built-in derived types. You 3947 can use it for your own schemas as well, if you have special 3948 types that require explicit support to for Pythonic 3949 conversion. 3950 """ 3951 assert parent_std 3952 assert parent_std.__variety in (cls.VARIETY_absent, cls.VARIETY_atomic) 3953 kw = { 'name' : name, 3954 'schema' : schema, 3955 'binding_namespace' : schema.targetNamespace(), 3956 'namespace_context' : schema.targetNamespace().initialNamespaceContext(), 3957 'scope' : _ScopedDeclaration_mixin.SCOPE_global, 3958 'variety' : parent_std.__variety } 3959 3960 bi = cls(**kw) 3961 bi._setPythonSupport(python_support) 3962 3963 # We were told the base type. If this is atomic, we re-use 3964 # its primitive type. Note that these all may be in different 3965 # namespaces. 3966 bi.__baseTypeDefinition = parent_std 3967 if cls.VARIETY_atomic == bi.__variety: 3968 bi.__primitiveTypeDefinition = bi.__baseTypeDefinition.__primitiveTypeDefinition 3969 3970 # Derived types are built-in 3971 bi.__resolveBuiltin() 3972 return bi
3973 3974 @classmethod
3975 - def CreateListInstance (cls, name, schema, item_std, python_support):
3976 """Create a list simple type in the target namespace. 3977 3978 This is used to preload standard built-in list types. You can 3979 use it for your own schemas as well, if you have special types 3980 that require explicit support to for Pythonic conversion; but 3981 note that such support is identified by the item_std. 3982 """ 3983 3984 kw = { 'name' : name, 3985 'schema' : schema, 3986 'binding_namespace' : schema.targetNamespace(), 3987 'namespace_context' : schema.targetNamespace().initialNamespaceContext(), 3988 'scope' : _ScopedDeclaration_mixin.SCOPE_global, 3989 'variety' : cls.VARIETY_list } 3990 bi = cls(**kw) 3991 bi._setPythonSupport(python_support) 3992 3993 # The base type is the ur-type. We were given the item type. 3994 bi.__baseTypeDefinition = cls.SimpleUrTypeDefinition() 3995 assert item_std 3996 bi.__itemTypeDefinition = item_std 3997 3998 # List types are built-in 3999 bi.__resolveBuiltin() 4000 return bi
4001 4002 @classmethod
4003 - def CreateUnionInstance (cls, name, schema, member_stds):
4004 """(Placeholder) Create a union simple type in the target namespace. 4005 4006 This function has not been implemented.""" 4007 raise pyxb.IncompleteImplementationError('No support for built-in union types')
4008
4009 - def __singleSimpleTypeChild (self, body, other_elts_ok=False):
4010 simple_type_child = None 4011 for cn in body.childNodes: 4012 if (Node.ELEMENT_NODE == cn.nodeType): 4013 if not xsd.nodeIsNamed(cn, 'simpleType'): 4014 if other_elts_ok: 4015 continue 4016 raise pyxb.SchemaValidationError('Context requires element to be xs:simpleType') 4017 assert not simple_type_child 4018 simple_type_child = cn 4019 if simple_type_child is None: 4020 raise pyxb.SchemaValidationError('Content requires an xs:simpleType member (or a base attribute)') 4021 return simple_type_child
4022 4023 # The __initializeFrom* methods are responsible for identifying 4024 # the variety and the baseTypeDefinition. The remainder of the 4025 # resolution is performed by the __completeResolution method. 4026 # Note that in some cases resolution might yet be premature, so 4027 # variety is not saved until it is complete. All this stuff is 4028 # from section 3.14.2. 4029
4030 - def __initializeFromList (self, body, **kw):
4031 self.__baseTypeDefinition = self.SimpleUrTypeDefinition() 4032 self.__itemTypeAttribute = domutils.NodeAttribute(body, 'itemType') 4033 if self.__itemTypeAttribute is None: 4034 # NOTE: The newly created anonymous item type will 4035 # not be resolved; the caller needs to handle 4036 # that. 4037 self.__itemTypeDefinition = self.CreateFromDOM(self.__singleSimpleTypeChild(body), **kw) 4038 return self.__completeResolution(body, self.VARIETY_list, self._DA_list)
4039
4040 - def __initializeFromRestriction (self, body, **kw):
4041 if self.__baseTypeDefinition is None: 4042 self.__baseAttribute = domutils.NodeAttribute(body, 'base') 4043 if self.__baseAttribute is None: 4044 self.__baseTypeDefinition = self.CreateFromDOM(self.__singleSimpleTypeChild(body, other_elts_ok=True), **kw) 4045 return self.__completeResolution(body, None, self._DA_restriction)
4046 4047 __localMemberTypes = None
4048 - def __initializeFromUnion (self, body, **kw):
4049 self.__baseTypeDefinition = self.SimpleUrTypeDefinition() 4050 self.__memberTypesAttribute = domutils.NodeAttribute(body, 'memberTypes') 4051 if self.__localMemberTypes is None: 4052 self.__localMemberTypes = [] 4053 for cn in body.childNodes: 4054 if (Node.ELEMENT_NODE == cn.nodeType) and xsd.nodeIsNamed(cn, 'simpleType'): 4055 self.__localMemberTypes.append(self.CreateFromDOM(cn, **kw)) 4056 return self.__completeResolution(body, self.VARIETY_union, self._DA_union)
4057
4058 - def __resolveBuiltin (self):
4059 if self.hasPythonSupport(): 4060 self.__facets = { } 4061 for v in self.pythonSupport().__dict__.values(): 4062 if isinstance(v, facets.ConstrainingFacet): 4063 self.__facets[v.__class__] = v 4064 if v.ownerTypeDefinition() is None: 4065 v.setFromKeywords(_constructor=True, owner_type_definition=self) 4066 self.__isBuiltin = True 4067 return self
4068
4069 - def __defineDefaultFacets (self, variety):
4070 """Create facets for varieties that can take facets that are undeclared. 4071 4072 This means unions, which per section 4.1.2.3 of 4073 http://www.w3.org/TR/xmlschema-2/ can have enumeration or 4074 pattern restrictions.""" 4075 if self.VARIETY_union != variety: 4076 return self 4077 self.__facets.setdefault(facets.CF_pattern) 4078 self.__facets.setdefault(facets.CF_enumeration) 4079 return self
4080
4081 - def __processHasFacetAndProperty (self, variety):
4082 """Identify the facets and properties for this stype. 4083 4084 This method simply identifies the facets that apply to this 4085 specific type, and records property values. Only 4086 explicitly-associated facets and properties are stored; others 4087 from base types will also affect this type. The information 4088 is taken from the applicationInformation children of the 4089 definition's annotation node, if any. If there is no support 4090 for the XMLSchema_hasFacetAndProperty namespace, this is a 4091 no-op. 4092 4093 Upon return, self.__facets is a map from the class for an 4094 associated fact to None, and self.__fundamentalFacets is a 4095 frozenset of instances of FundamentalFacet. 4096 4097 The return value is self. 4098 """ 4099 self.__facets = { } 4100 self.__fundamentalFacets = frozenset() 4101 if self.annotation() is None: 4102 return self.__defineDefaultFacets(variety) 4103 app_info = self.annotation().applicationInformation() 4104 if app_info is None: 4105 return self.__defineDefaultFacets(variety) 4106 facet_map = { } 4107 fundamental_facets = set() 4108 seen_facets = set() 4109 for ai in app_info: 4110 for cn in ai.childNodes: 4111 if Node.ELEMENT_NODE != cn.nodeType: 4112 continue 4113 if pyxb.namespace.XMLSchema_hfp.nodeIsNamed(cn, 'hasFacet'): 4114 facet_name = domutils.NodeAttribute(cn, 'name')# , pyxb.namespace.XMLSchema_hfp) 4115 if facet_name is None: 4116 raise pyxb.SchemaValidationError('hasFacet missing name attribute in %s' % (cn,)) 4117 if facet_name in seen_facets: 4118 raise pyxb.SchemaValidationError('Multiple hasFacet specifications for %s' % (facet_name,)) 4119 seen_facets.add(facet_name) 4120 facet_class = facets.ConstrainingFacet.ClassForFacet(facet_name) 4121 #facet_map[facet_class] = facet_class(base_type_definition=self) 4122 facet_map[facet_class] = None 4123 if pyxb.namespace.XMLSchema_hfp.nodeIsNamed(cn, 'hasProperty'): 4124 fundamental_facets.add(facets.FundamentalFacet.CreateFromDOM(cn, self)) 4125 if 0 < len(facet_map): 4126 assert self.__baseTypeDefinition == self.SimpleUrTypeDefinition() 4127 self.__facets = facet_map 4128 assert type(self.__facets) == types.DictType 4129 if 0 < len(fundamental_facets): 4130 self.__fundamentalFacets = frozenset(fundamental_facets) 4131 return self
4132 4133 # NB: Must be done after resolution of the base type
4134 - def __updateFacets (self, body):
4135 4136 # Create local list consisting of facet classes matched in children 4137 # and the map of keywords used to initialize the local instance. 4138 4139 local_facets = {} 4140 for fc in facets.Facet.Facets: 4141 children = domutils.LocateMatchingChildren(body, fc.Name()) 4142 if 0 < len(children): 4143 fi = fc(base_type_definition=self.__baseTypeDefinition, 4144 owner_type_definition=self) 4145 if isinstance(fi, facets._LateDatatype_mixin): 4146 fi.bindValueDatatype(self) 4147 for cn in children: 4148 kw = { 'annotation': domutils.LocateUniqueChild(cn, 'annotation') } 4149 for ai in range(0, cn.attributes.length): 4150 attr = cn.attributes.item(ai) 4151 # Convert name from unicode to string 4152 kw[str(attr.localName)] = attr.value 4153 try: 4154 fi.setFromKeywords(**kw) 4155 except pyxb.PyXBException as e: 4156 raise pyxb.SchemaValidationError('Error assigning facet %s in %s: %s' % (fc.Name(), self.expandedName(), e)) 4157 local_facets[fc] = fi 4158 self.__localFacets = local_facets 4159 4160 # We want a map from the union of the facet classes from this STD up 4161 # through its baseTypeDefinition (if present). Map elements should be 4162 # to None if the facet has not been constrained, or to the nearest 4163 # ConstrainingFacet instance if it is. ConstrainingFacet instances 4164 # created for local constraints also need a pointer to the 4165 # corresponding facet from the ancestor type definition, because those 4166 # constraints also affect this type. 4167 base_facets = {} 4168 4169 # Built-ins didn't get their facets() setting configured, so use the 4170 # _FacetMap() instead. 4171 if self.__baseTypeDefinition.isBuiltin(): 4172 pstd = self.__baseTypeDefinition.pythonSupport() 4173 if pstd != datatypes.anySimpleType: 4174 base_facets.update(pstd._FacetMap()) 4175 elif self.__baseTypeDefinition.facets(): 4176 assert type(self.__baseTypeDefinition.facets()) == types.DictType 4177 base_facets.update(self.__baseTypeDefinition.facets()) 4178 base_facets.update(self.facets()) 4179 4180 self.__facets = self.__localFacets 4181 for fc in base_facets.keys(): 4182 self.__facets.setdefault(fc, base_facets[fc]) 4183 assert type(self.__facets) == types.DictType
4184
4185 - def _createRestriction (self, owner, body):
4186 """Create a new simple type with this as its base. 4187 4188 The type is owned by the provided owner, and may have facet 4189 restrictions defined by the body. 4190 @param owner: the owner for the newly created type 4191 @type owner: L{ComplexTypeDefinition} 4192 @param body: the DOM node from which facet information will be extracted 4193 @type body: C{xml.dom.Node} 4194 @rtype: L{SimpleTypeDefinition} 4195 """ 4196 std = SimpleTypeDefinition(owner=owner, namespace_context=owner._namespaceContext(), variety=None, scope=self._scope(), schema=owner._schema()) 4197 std.__baseTypeDefinition = self 4198 return std.__completeResolution(body, None, self._DA_restriction)
4199 4200 # Complete the resolution of some variety of STD. Note that the 4201 # variety is compounded by an alternative, since there is no 4202 # 'restriction' variety.
4203 - def __completeResolution (self, body, variety, alternative):
4204 assert self.__variety is None 4205 if self.__baseTypeDefinition is None: 4206 assert self.__baseAttribute is not None 4207 base_en = self._namespaceContext().interpretQName(self.__baseAttribute) 4208 base_type = base_en.typeDefinition() 4209 if not isinstance(base_type, SimpleTypeDefinition): 4210 raise pyxb.SchemaValidationError('Unable to locate base type %s' % (base_en,)) 4211 self.__baseTypeDefinition = base_type 4212 # If the base type exists but has not yet been resolved, 4213 # delay processing this type until the one it depends on 4214 # has been completed. 4215 assert self.__baseTypeDefinition != self 4216 if not self.__baseTypeDefinition.isResolved(): 4217 self._queueForResolution('base type %s is not resolved' % (self.__baseTypeDefinition,), depends_on=self.__baseTypeDefinition) 4218 return self 4219 if variety is None: 4220 # 3.14.1 specifies that the variety is the variety of the base 4221 # type definition which, by the way, can't be the ur type. 4222 variety = self.__baseTypeDefinition.__variety 4223 assert variety is not None 4224 4225 if self.VARIETY_absent == variety: 4226 # The ur-type is always resolved. So are restrictions of it, 4227 # which is how we might get here. 4228 pass 4229 elif self.VARIETY_atomic == variety: 4230 # Atomic types (and their restrictions) use the primitive 4231 # type, which is the highest type that is below the 4232 # ur-type (which is not atomic). 4233 ptd = self 4234 while isinstance(ptd, SimpleTypeDefinition) and (self.VARIETY_atomic == ptd.__baseTypeDefinition.variety()): 4235 ptd = ptd.__baseTypeDefinition 4236 4237 self.__primitiveTypeDefinition = ptd 4238 elif self.VARIETY_list == variety: 4239 if self._DA_list == alternative: 4240 if self.__itemTypeAttribute is not None: 4241 it_en = self._namespaceContext().interpretQName(self.__itemTypeAttribute) 4242 self.__itemTypeDefinition = it_en.typeDefinition() 4243 if not isinstance(self.__itemTypeDefinition, SimpleTypeDefinition): 4244 raise pyxb.SchemaValidationError('Unable to locate STD %s for items' % (it_en,)) 4245 elif self._DA_restriction == alternative: 4246 self.__itemTypeDefinition = self.__baseTypeDefinition.__itemTypeDefinition 4247 else: 4248 raise pyxb.LogicError('completeResolution list variety with alternative %s' % (alternative,)) 4249 elif self.VARIETY_union == variety: 4250 if self._DA_union == alternative: 4251 # First time we try to resolve, create the member type 4252 # definitions. If something later prevents us from resolving 4253 # this type, we don't want to create them again, because we 4254 # might already have references to them. 4255 if self.__memberTypeDefinitions is None: 4256 mtd = [] 4257 # If present, first extract names from memberTypes, 4258 # and add each one to the list 4259 if self.__memberTypesAttribute is not None: 4260 for mn in self.__memberTypesAttribute.split(): 4261 # THROW if type has not been defined 4262 mn_en = self._namespaceContext().interpretQName(mn) 4263 std = mn_en.typeDefinition() 4264 if std is None: 4265 raise pyxb.SchemaValidationError('Unable to locate member type %s' % (mn_en,)) 4266 # Note: We do not need these to be resolved (here) 4267 assert isinstance(std, SimpleTypeDefinition) 4268 mtd.append(std) 4269 # Now look for local type definitions 4270 mtd.extend(self.__localMemberTypes) 4271 self.__memberTypeDefinitions = mtd 4272 assert None not in self.__memberTypeDefinitions 4273 4274 # Replace any member types that are themselves unions with the 4275 # members of those unions, in order. Note that doing this 4276 # might indicate we can't resolve this type yet, which is why 4277 # we separated the member list creation and the substitution 4278 # phases 4279 mtd = [] 4280 for mt in self.__memberTypeDefinitions: 4281 assert isinstance(mt, SimpleTypeDefinition) 4282 if not mt.isResolved(): 4283 self._queueForResolution('member type not resolved', depends_on=mt) 4284 return self 4285 if self.VARIETY_union == mt.variety(): 4286 mtd.extend(mt.memberTypeDefinitions()) 4287 else: 4288 mtd.append(mt) 4289 elif self._DA_restriction == alternative: 4290 assert self.__baseTypeDefinition 4291 # Base type should have been resolved before we got here 4292 assert self.__baseTypeDefinition.isResolved() 4293 mtd = self.__baseTypeDefinition.__memberTypeDefinitions 4294 assert mtd is not None 4295 else: 4296 raise pyxb.LogicError('completeResolution union variety with alternative %s' % (alternative,)) 4297 # Save a unique copy 4298 self.__memberTypeDefinitions = mtd[:] 4299 else: 4300 raise pyxb.LogicError('completeResolution with variety 0x%02x' % (variety,)) 4301 4302 # Determine what facets, if any, apply to this type. This 4303 # should only do something if this is a primitive type. 4304 self.__processHasFacetAndProperty(variety) 4305 self.__updateFacets(body) 4306 4307 self.__derivationAlternative = alternative 4308 self.__variety = variety 4309 self.__domNode = None 4310 return self
4311
4312 - def isResolved (self):
4313 """Indicate whether this simple type is fully defined. 4314 4315 Type resolution for simple types means that the corresponding 4316 schema component fields have been set. Specifically, that 4317 means variety, baseTypeDefinition, and the appropriate 4318 additional fields depending on variety. See _resolve() for 4319 more information. 4320 """ 4321 # Only unresolved nodes have an unset variety 4322 return (self.__variety is not None)
4323 4324 # STD:res
4325 - def _resolve (self):
4326 """Attempt to resolve the type. 4327 4328 Type resolution for simple types means that the corresponding 4329 schema component fields have been set. Specifically, that 4330 means variety, baseTypeDefinition, and the appropriate 4331 additional fields depending on variety. 4332 4333 All built-in STDs are resolved upon creation. Schema-defined 4334 STDs are held unresolved until the schema has been completely 4335 read, so that references to later schema-defined STDs can be 4336 resolved. Resolution is performed after the entire schema has 4337 been scanned and STD instances created for all 4338 topLevelSimpleTypes. 4339 4340 If a built-in STD is also defined in a schema (which it should 4341 be for XMLSchema), the built-in STD is kept, with the 4342 schema-related information copied over from the matching 4343 schema-defined STD. The former then replaces the latter in 4344 the list of STDs to be resolved. 4345 4346 Types defined by restriction have the same variety as the type 4347 they restrict. If a simple type restriction depends on an 4348 unresolved type, this method simply queues it for resolution 4349 in a later pass and returns. 4350 """ 4351 if self.__variety is not None: 4352 return self 4353 assert self.__domNode 4354 node = self.__domNode 4355 4356 kw = { 'owner' : self 4357 , 'schema' : self._schema() } 4358 4359 bad_instance = False 4360 # The guts of the node should be exactly one instance of 4361 # exactly one of these three types. 4362 candidate = domutils.LocateUniqueChild(node, 'list') 4363 if candidate: 4364 self.__initializeFromList(candidate, **kw) 4365 4366 candidate = domutils.LocateUniqueChild(node, 'restriction') 4367 if candidate: 4368 if self.__variety is None: 4369 self.__initializeFromRestriction(candidate, **kw) 4370 else: 4371 bad_instance = True 4372 4373 candidate = domutils.LocateUniqueChild(node, 'union') 4374 if candidate: 4375 if self.__variety is None: 4376 self.__initializeFromUnion(candidate, **kw) 4377 else: 4378 bad_instance = True 4379 4380 if self.__baseTypeDefinition is None: 4381 raise pyxb.SchemaValidationError('xs:simpleType must have list, union, or restriction as child') 4382 4383 if self._schema() is not None: 4384 self.__final = self._schema().finalForNode(node, self._STD_Map) 4385 4386 # It is NOT an error to fail to resolve the type. 4387 if bad_instance: 4388 raise pyxb.SchemaValidationError('Expected exactly one of list, restriction, union as child of simpleType') 4389 4390 return self
4391 4392 # CFD:STD CFD:SimpleTypeDefinition 4393 @classmethod
4394 - def CreateFromDOM (cls, node, **kw):
4395 # Node should be an XMLSchema simpleType node 4396 assert xsd.nodeIsNamed(node, 'simpleType') 4397 4398 name = domutils.NodeAttribute(node, 'name') 4399 4400 rv = cls(name=name, node=node, variety=None, **kw) 4401 rv._annotationFromDOM(node) 4402 4403 # Creation does not attempt to do resolution. Queue up the newly created 4404 # whatsis so we can resolve it after everything's been read in. 4405 rv.__domNode = node 4406 rv._queueForResolution('creation') 4407 4408 return rv
4409 4410 # pythonSupport is None, or a subclass of datatypes.simpleTypeDefinition. 4411 # When set, this simple type definition instance must be uniquely 4412 # associated with the python support type. 4413 __pythonSupport = None 4414
4415 - def _setPythonSupport (self, python_support):
4416 # Includes check that python_support is not None 4417 assert issubclass(python_support, basis.simpleTypeDefinition) 4418 # Can't share support instances 4419 self.__pythonSupport = python_support 4420 self.__pythonSupport._SimpleTypeDefinition(self) 4421 if self.nameInBinding() is None: 4422 self.setNameInBinding(self.__pythonSupport.__name__) 4423 return self.__pythonSupport
4424
4425 - def hasPythonSupport (self):
4426 return self.__pythonSupport is not None
4427
4428 - def pythonSupport (self):
4429 if self.__pythonSupport is None: 4430 raise pyxb.LogicError('%s: No support defined' % (self.name(),)) 4431 return self.__pythonSupport
4432
4433 - def stringToPython (self, string):
4434 return self.pythonSupport().stringToPython(string)
4435
4436 - def pythonToString (self, value):
4437 return self.pythonSupport().pythonToString(value)
4438
4439 -class _SimpleUrTypeDefinition (SimpleTypeDefinition, _Singleton_mixin):
4440 """Subclass ensures there is only one simple ur-type.""" 4441 pass
4442
4443 -class _ImportElementInformationItem (_Annotated_mixin):
4444 """Data associated with an 4445 U{import<http://www.w3.org/TR/xmlschema-1/#composition-schemaImport>} 4446 statement within a schema.""" 4447
4448 - def id (self):
4449 """The value of the C{id} attribute from the import statement.""" 4450 return self.__id
4451 __id = None 4452
4453 - def namespace (self):
4454 """The L{pyxb.namespace.Namespace} instance corresponding to the value 4455 of the C{namespace} attribute from the import statement.""" 4456 return self.__namespace
4457 __namespace = None 4458
4459 - def schemaLocation (self):
4460 """The value of the C{schemaLocation} attribute from the import 4461 statement, normalized relative to the location of the importing 4462 schema.""" 4463 return self.__schemaLocation
4464 __schemaLocation = None 4465
4466 - def prefix (self):
4467 """The prefix from a namespace declaration for L{namespace} that was 4468 active in the context of the import element, or C{None} if there was 4469 no relevant namespace declaration in scope at that point. 4470 4471 This is propagated to be used as the default prefix for the 4472 corresponding namespace if no prefix had been assigned. 4473 """ 4474 return self.__prefix
4475 __prefix = None 4476
4477 - def schema (self):
4478 """The L{Schema} instance corresponding to the imported schema, if 4479 available. 4480 4481 Normally C{import} statements will be fulfilled by loading components 4482 from a L{namespace archive<pyxb.namespace.NamespaceArchive>} in which 4483 the corresponding namespace is marked as public. Where there are 4484 cycles in the namespace dependency graph, or the schema for a 4485 namespace are associated with a restricted profile of another 4486 namespace, there may be no such archive and instead the components are 4487 obtained using this schema.""" 4488 return self.__schema
4489 __schema = None 4490
4491 - def __init__ (self, importing_schema, node, **kw):
4492 """Gather the information relative to an C{import} statement. 4493 4494 If the imported namespace can be loaded from an archive, the 4495 C{schemaLocation} attribute is ignored. Otherwise, it attempts to 4496 retrieve and parse the corresponding schema (if this has not already 4497 been done). 4498 4499 @param importing_schema: The L{Schema} instance in which the import 4500 was found. 4501 @param node: The C{xml.dom.DOM} node incorporating the schema 4502 information. 4503 4504 @raise Exception: Any exception raised when attempting to retrieve and 4505 parse data from the schema location. 4506 """ 4507 4508 super(_ImportElementInformationItem, self).__init__(**kw) 4509 uri = domutils.NodeAttribute(node, 'namespace') 4510 if uri is None: 4511 raise pyxb.IncompleteImplementationError('import statements without namespace not supported') 4512 schema_location = pyxb.utils.utility.NormalizeLocation(domutils.NodeAttribute(node, 'schemaLocation'), importing_schema.location()) 4513 self.__schemaLocation = schema_location 4514 ns = self.__namespace = pyxb.namespace.NamespaceForURI(uri, create_if_missing=True) 4515 need_schema = not (ns.isLoadable() or ns.isBuiltinNamespace()) 4516 if not need_schema: 4517 # Discard location if we expect to be able to learn about this 4518 # namespace from an archive or a built-in description 4519 self.__schemaLocation = None 4520 4521 ns_ctx = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(node) 4522 if self.schemaLocation() is not None: 4523 # @todo: NOTICE 4524 (has_schema, schema_instance) = self.__namespace.lookupSchemaByLocation(schema_location) 4525 if not has_schema: 4526 ckw = { 'absolute_schema_location' : schema_location, 4527 'generation_uid' : importing_schema.generationUID(), 4528 'uri_content_archive_directory' : importing_schema._uriContentArchiveDirectory(), 4529 } 4530 try: 4531 schema_instance = Schema.CreateFromLocation(**ckw) 4532 except Exception as e: 4533 _log.exception('Import %s cannot read schema location %s (%s)', ns, self.__schemaLocation, schema_location) 4534 raise 4535 self.__schema = schema_instance 4536 elif need_schema: 4537 _log.warning('No information available on imported namespace %s', uri) 4538 4539 # If we think we found a schema, make sure it's in the right 4540 # namespace. 4541 if self.__schema is not None: 4542 if ns != self.__schema.targetNamespace(): 4543 raise pyxb.SchemaValidationError('Import expected namespace %s but got %s' % (ns, self.__schema.targetNamespace())) 4544 4545 self.__prefix = ns_ctx.prefixForNamespace(self.namespace()) 4546 4547 self._annotationFromDOM(node)
4548
4549 -class Schema (_SchemaComponent_mixin):
4550 """An XMLSchema U{Schema<http://www.w3.org/TR/xmlschema-1/#Schemas>}.""" 4551
4552 - def __getstate__ (self):
4553 raise pyxb.LogicError('Attempt to serialize Schema instance')
4554 4555 # List of annotations 4556 __annotations = None 4557 4558 # True when we have started seeing elements, attributes, or 4559 # notations. 4560 __pastProlog = False 4561
4562 - def location (self):
4563 """URI or path to where the schema can be found. 4564 4565 For schema created by a user, the location should be provided to the 4566 constructor using the C{schema_location} keyword. In the case of 4567 imported or included schema, the including schema's location is used 4568 as the base URI for determining the absolute URI of the included 4569 schema from its (possibly relative) location value. For files, 4570 the scheme and authority portions are generally absent, as is often 4571 the abs_path part.""" 4572 return self.__location
4573 __location = None 4574
4575 - def locationTag (self):
4576 return self.__locationTag
4577 __locationTag = None 4578
4579 - def signature (self):
4580 return self.__signature
4581 __signature = None 4582
4583 - def generationUID (self):
4584 return self.__generationUID
4585 __generationUID = None 4586
4587 - def originRecord (self):
4588 return self.__originRecord
4589 __originRecord = None 4590
4591 - def targetNamespace (self):
4592 """The targetNamespace of a componen. 4593 4594 This is None, or a reference to a Namespace in which the 4595 component is declared (either as a global or local to one of 4596 the namespace's complex type definitions). This is immutable 4597 after creation. 4598 """ 4599 return self.__targetNamespace
4600 __targetNamespace = None 4601
4602 - def defaultNamespace (self):
4603 """Default namespace of the schema. 4604 4605 Will be None unless the schema has an 'xmlns' attribute. The 4606 value must currently be provided as a keyword parameter to the 4607 constructor. """ 4608 return self.__defaultNamespace
4609 __defaultNamespace = None 4610
4611 - def referencedNamespaces (self):
4612 return self.__referencedNamespaces
4613 __referencedNamespaces = None 4614 4615 __namespaceData = None 4616
4617 - def importEIIs (self):
4618 return self.__importEIIs
4619 __importEIIs = None 4620
4621 - def importedSchema (self):
4622 return self.__importedSchema
4623 __importedSchema = None
4624 - def includedSchema (self):
4625 return self.__includedSchema
4626 __includedSchema = None 4627 4628 _QUALIFIED = "qualified" 4629 _UNQUALIFIED = "unqualified" 4630 4631 # Default values for standard recognized schema attributes 4632 __attributeMap = { pyxb.namespace.ExpandedName(None, 'attributeFormDefault') : _UNQUALIFIED 4633 , pyxb.namespace.ExpandedName(None, 'elementFormDefault') : _UNQUALIFIED 4634 , pyxb.namespace.ExpandedName(None, 'blockDefault') : '' 4635 , pyxb.namespace.ExpandedName(None, 'finalDefault') : '' 4636 , pyxb.namespace.ExpandedName(None, 'id') : None 4637 , pyxb.namespace.ExpandedName(None, 'targetNamespace') : None 4638 , pyxb.namespace.ExpandedName(None, 'version') : None 4639 , pyxb.namespace.XML.createExpandedName('lang') : None 4640 } 4641
4642 - def _setAttributeFromDOM (self, attr):
4643 """Override the schema attribute with the given DOM value.""" 4644 self.__attributeMap[pyxb.namespace.ExpandedName(attr.name)] = attr.nodeValue 4645 return self
4646
4647 - def _setAttributesFromMap (self, attr_map):
4648 """Override the schema attributes with values from the given map.""" 4649 self.__attributeMap.update(attr_map) 4650 return self
4651
4652 - def schemaHasAttribute (self, attr_name):
4653 """Return True iff the schema has an attribute with the given (nc)name.""" 4654 if isinstance(attr_name, basestring): 4655 attr_name = pyxb.namespace.ExpandedName(None, attr_name) 4656 return self.__attributeMap.has_key(attr_name)
4657
4658 - def schemaAttribute (self, attr_name):
4659 """Return the schema attribute value associated with the given (nc)name. 4660 4661 @param attr_name: local name for the attribute in the schema element. 4662 @return: the value of the corresponding attribute, or C{None} if it 4663 has not been defined and has no default. 4664 @raise KeyError: C{attr_name} is not a valid attribute for a C{schema} element. 4665 """ 4666 if isinstance(attr_name, basestring): 4667 attr_name = pyxb.namespace.ExpandedName(None, attr_name) 4668 return self.__attributeMap[attr_name]
4669 4670 __SchemaCategories = ( 'typeDefinition', 'attributeGroupDefinition', 'modelGroupDefinition', 4671 'attributeDeclaration', 'elementDeclaration', 'notationDeclaration', 4672 'identityConstraintDefinition' ) 4673
4674 - def _uriContentArchiveDirectory (self):
4676 __uriContentArchiveDirectory = None 4677
4678 - def __init__ (self, *args, **kw):
4679 # Force resolution of available namespaces if not already done 4680 if not kw.get('_bypass_preload', False): 4681 pyxb.namespace.archive.NamespaceArchive.PreLoadArchives() 4682 4683 assert 'schema' not in kw 4684 self.__uriContentArchiveDirectory = kw.get('uri_content_archive_directory') 4685 self.__location = kw.get('schema_location') 4686 if self.__location is not None: 4687 schema_path = self.__location 4688 if 0 <= schema_path.find(':'): 4689 schema_path = urlparse.urlparse(schema_path)[2] # .path 4690 self.__locationTag = os.path.split(schema_path)[1].split('.')[0] 4691 4692 self.__generationUID = kw.get('generation_uid') 4693 if self.__generationUID is None: 4694 _log.warning('No generationUID provided') 4695 self.__generationUID = pyxb.utils.utility.UniqueIdentifier() 4696 4697 self.__signature = kw.get('schema_signature') 4698 4699 super(Schema, self).__init__(*args, **kw) 4700 self.__importEIIs = set() 4701 self.__includedSchema = set() 4702 self.__importedSchema = set() 4703 self.__targetNamespace = self._namespaceContext().targetNamespace() 4704 if not isinstance(self.__targetNamespace, pyxb.namespace.Namespace): 4705 raise pyxb.LogicError('Schema constructor requires valid Namespace instance as target_namespace') 4706 4707 # NB: This will raise pyxb.SchemaUniquenessError if it appears this 4708 # schema has already been incorporated into the target namespace. 4709 self.__originRecord = self.__targetNamespace.addSchema(self) 4710 4711 self.__targetNamespace.configureCategories(self.__SchemaCategories) 4712 if self.__defaultNamespace is not None: 4713 self.__defaultNamespace.configureCategories(self.__SchemaCategories) 4714 4715 self.__attributeMap = self.__attributeMap.copy() 4716 self.__annotations = [] 4717 # @todo: This isn't right if namespaces are introduced deeper in the document 4718 self.__referencedNamespaces = self._namespaceContext().inScopeNamespaces().values()
4719 4720 __TopLevelComponentMap = { 4721 'element' : ElementDeclaration, 4722 'attribute' : AttributeDeclaration, 4723 'notation' : NotationDeclaration, 4724 'simpleType' : SimpleTypeDefinition, 4725 'complexType' : ComplexTypeDefinition, 4726 'group' : ModelGroupDefinition, 4727 'attributeGroup' : AttributeGroupDefinition 4728 } 4729 4730 @classmethod
4731 - def CreateFromDocument (cls, xmls, **kw):
4732 if not ('schema_signature' in kw): 4733 kw['schema_signature'] = pyxb.utils.utility.HashForText(xmls) 4734 return cls.CreateFromDOM(domutils.StringToDOM(xmls, **kw), **kw)
4735 4736 @classmethod
4737 - def CreateFromLocation (cls, **kw):
4738 """Create a schema from a schema location. 4739 4740 Reads an XML document from the schema location and creates a schema 4741 using it. All keyword parameters are passed to L{CreateFromDOM}. 4742 4743 @keyword schema_location: A file path or a URI. If this is a relative 4744 URI and C{parent_uri} is present, the actual location will be 4745 L{normallzed<pyxb.utils.utility.NormalizeLocation>}. 4746 @keyword parent_uri: The context within which schema_location will be 4747 normalized, if necessary. 4748 @keyword absolute_schema_location: A file path or URI. This value is 4749 not normalized, and supersedes C{schema_location}. 4750 """ 4751 schema_location = kw.pop('absolute_schema_location', pyxb.utils.utility.NormalizeLocation(kw.get('schema_location'), kw.get('parent_uri'), kw.get('prefix_map'))) 4752 kw['location_base'] = kw['schema_location'] = schema_location 4753 assert isinstance(schema_location, basestring), 'Unexpected value %s type %s for schema_location' % (schema_location, type(schema_location)) 4754 uri_content_archive_directory = kw.get('uri_content_archive_directory') 4755 return cls.CreateFromDocument(pyxb.utils.utility.TextFromURI(schema_location, archive_directory=uri_content_archive_directory), **kw)
4756 4757 @classmethod
4758 - def CreateFromStream (cls, stream, **kw):
4759 return cls.CreateFromDocument(stream.read(), **kw)
4760 4761 @classmethod
4762 - def CreateFromDOM (cls, node, namespace_context=None, schema_location=None, schema_signature=None, generation_uid=None, **kw):
4763 """Take the root element of the document, and scan its attributes under 4764 the assumption it is an XMLSchema schema element. That means 4765 recognize namespace declarations and process them. Also look for 4766 and set the default namespace. All other attributes are passed up 4767 to the parent class for storage.""" 4768 4769 # Get the context of any schema that is including (not importing) this 4770 # one. 4771 including_context = kw.get('including_context') 4772 4773 root_node = node 4774 if Node.DOCUMENT_NODE == node.nodeType: 4775 root_node = root_node.documentElement 4776 if Node.ELEMENT_NODE != root_node.nodeType: 4777 raise pyxb.LogicError('Must be given a DOM node of type ELEMENT') 4778 4779 assert (namespace_context is None) or isinstance(namespace_context, pyxb.namespace.resolution.NamespaceContext) 4780 ns_ctx = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(root_node, 4781 parent_context=namespace_context, 4782 including_context=including_context) 4783 4784 tns = ns_ctx.targetNamespace() 4785 if tns is None: 4786 raise pyxb.SchemaValidationError('No targetNamespace associated with content (not a schema?)') 4787 schema = cls(namespace_context=ns_ctx, schema_location=schema_location, schema_signature=schema_signature, generation_uid=generation_uid, **kw) 4788 schema.__namespaceData = ns_ctx 4789 4790 if schema.targetNamespace() != ns_ctx.targetNamespace(): 4791 raise pyxb.SchemaValidationError('targetNamespace %s conflicts with %s' % (schema.targetNamespace(), ns_ctx.targetNamespace())) 4792 4793 # Update the attribute map 4794 for ai in range(root_node.attributes.length): 4795 schema._setAttributeFromDOM(root_node.attributes.item(ai)) 4796 4797 # Verify that the root node is an XML schema element 4798 if not xsd.nodeIsNamed(root_node, 'schema'): 4799 raise pyxb.SchemaValidationError('Root node %s of document is not an XML schema element' % (root_node.nodeName,)) 4800 4801 for cn in root_node.childNodes: 4802 if Node.ELEMENT_NODE == cn.nodeType: 4803 rv = schema.__processTopLevelNode(cn) 4804 if rv is None: 4805 _log.info('Unrecognized: %s %s', cn.nodeName, cn.toxml("utf-8")) 4806 elif Node.TEXT_NODE == cn.nodeType: 4807 # Non-element content really should just be whitespace. 4808 # If something else is seen, print it for inspection. 4809 text = cn.data.strip() 4810 if text: 4811 _log.info('Ignored text: %s', text) 4812 elif Node.COMMENT_NODE == cn.nodeType: 4813 pass 4814 else: 4815 # ATTRIBUTE_NODE 4816 # CDATA_SECTION_NODE 4817 # ENTITY_NODE 4818 # PROCESSING_INSTRUCTION 4819 # DOCUMENT_NODE 4820 # DOCUMENT_TYPE_NODE 4821 # NOTATION_NODE 4822 _log.info('Ignoring non-element: %s', cn) 4823 4824 # Do not perform resolution yet: we may be done with this schema, but 4825 # the namespace may incorporate additional ones, and we can't resolve 4826 # until everything's present. 4827 return schema
4828 4829 _SA_All = '#all' 4830
4831 - def __ebvForNode (self, attr, dom_node, candidate_map):
4832 ebv = domutils.NodeAttribute(dom_node, attr) 4833 if ebv is None: 4834 ebv = self.schemaAttribute('%sDefault' % (attr,)) 4835 rv = 0 4836 if ebv == self._SA_All: 4837 for v in candidate_map.values(): 4838 rv += v 4839 else: 4840 for candidate in ebv.split(): 4841 rv += candidate_map.get(candidate, 0) 4842 return rv
4843
4844 - def blockForNode (self, dom_node, candidate_map):
4845 """Return a bit mask indicating a set of options read from the node's "block" attribute or the schema's "blockDefault" attribute. 4846 4847 A value of '#all' means enable every options; otherwise, the attribute 4848 value should be a list of tokens, for which the corresponding value 4849 will be added to the return value. 4850 4851 @param dom_node: the node from which the "block" attribute will be retrieved 4852 @type dom_node: C{xml.dom.Node} 4853 @param candidate_map: map from strings to bitmask values 4854 """ 4855 return self.__ebvForNode('block', dom_node, candidate_map)
4856
4857 - def finalForNode (self, dom_node, candidate_map):
4858 """Return a bit mask indicating a set of options read from the node's 4859 "final" attribute or the schema's "finalDefault" attribute. 4860 4861 A value of '#all' means enable every options; otherwise, the attribute 4862 value should be a list of tokens, for which the corresponding value 4863 will be added to the return value. 4864 4865 @param dom_node: the node from which the "final" attribute will be retrieved 4866 @type dom_node: C{xml.dom.Node} 4867 @param candidate_map: map from strings to bitmask values 4868 """ 4869 return self.__ebvForNode('final', dom_node, candidate_map)
4870
4871 - def targetNamespaceForNode (self, dom_node, declaration_type):
4872 """Determine the target namespace for a local attribute or element declaration. 4873 4874 Look at the node's C{form} attribute, or if none the schema's 4875 C{attributeFormDefault} or C{elementFormDefault} value. If the 4876 resulting value is C{"qualified"} and the parent schema has a 4877 non-absent target namespace, return it to use as the declaration 4878 target namespace. Otherwise, return None to indicate that the 4879 declaration has no namespace. 4880 4881 @param dom_node: The node defining an element or attribute declaration 4882 @param declaration_type: Either L{AttributeDeclaration} or L{ElementDeclaration} 4883 @return: L{pyxb.namespace.Namespace} or None 4884 """ 4885 4886 form_type = domutils.NodeAttribute(dom_node, 'form') 4887 if form_type is None: 4888 if declaration_type == ElementDeclaration: 4889 form_type = self.schemaAttribute('elementFormDefault') 4890 elif declaration_type == AttributeDeclaration: 4891 form_type = self.schemaAttribute('attributeFormDefault') 4892 else: 4893 raise pyxb.LogicError('Expected ElementDeclaration or AttributeDeclaration: got %s' % (declaration_type,)) 4894 tns = None 4895 if (self._QUALIFIED == form_type): 4896 tns = self.targetNamespace() 4897 if tns.isAbsentNamespace(): 4898 tns = None 4899 else: 4900 if (self._UNQUALIFIED != form_type): 4901 raise pyxb.SchemaValidationError('Form type neither %s nor %s' % (self._QUALIFIED, self._UNQUALIFIED)) 4902 return tns
4903
4904 - def __requireInProlog (self, node_name):
4905 """Throw a SchemaValidationException referencing the given 4906 node if we have passed the sequence point representing the end 4907 of prolog elements.""" 4908 4909 if self.__pastProlog: 4910 raise pyxb.SchemaValidationError('Unexpected node %s after prolog' % (node_name,))
4911
4912 - def __processInclude (self, node):
4913 self.__requireInProlog(node.nodeName) 4914 # See section 4.2.1 of Structures. 4915 abs_uri = pyxb.utils.utility.NormalizeLocation(domutils.NodeAttribute(node, 'schemaLocation'), self.__location) 4916 (has_schema, schema_instance) = self.targetNamespace().lookupSchemaByLocation(abs_uri) 4917 if not has_schema: 4918 kw = { 'absolute_schema_location': abs_uri, 4919 'including_context': self.__namespaceData, 4920 'generation_uid': self.generationUID(), 4921 'uri_content_archive_directory': self._uriContentArchiveDirectory(), 4922 } 4923 try: 4924 schema_instance = self.CreateFromLocation(**kw) 4925 except pyxb.SchemaUniquenessError as e: 4926 _log.warning('Skipping apparent redundant inclusion of %s defining %s (hash matches %s)', e.schemaLocation(), e.namespace(), e.existingSchema().location()) 4927 except Exception as e: 4928 _log.exception('INCLUDE %s caught', abs_uri) 4929 raise 4930 if schema_instance: 4931 if self.targetNamespace() != schema_instance.targetNamespace(): 4932 raise pyxb.SchemaValidationError('Included namespace %s not consistent with including namespace %s' % (schema_instance.targetNamespace(), self.targetNamespace())) 4933 self.__includedSchema.add(schema_instance) 4934 return node
4935
4936 - def __processImport (self, node):
4937 """Process an import directive. 4938 4939 This attempts to locate schema (named entity) information for 4940 a namespace that is referenced by this schema. 4941 """ 4942 4943 self.__requireInProlog(node.nodeName) 4944 import_eii = _ImportElementInformationItem(self, node) 4945 if import_eii.schema() is not None: 4946 self.__importedSchema.add(import_eii.schema()) 4947 self.targetNamespace().importNamespace(import_eii.namespace()) 4948 ins = import_eii.namespace() 4949 if ins.prefix() is None: 4950 ins.setPrefix(import_eii.prefix()) 4951 self.__importEIIs.add(import_eii) 4952 return node
4953
4954 - def __processRedefine (self, node):
4955 self.__requireInProlog(node.nodeName) 4956 raise pyxb.IncompleteImplementationError('redefine not implemented')
4957
4958 - def __processAnnotation (self, node):
4959 self._addAnnotation(Annotation.CreateFromDOM(node)) 4960 return self
4961
4962 - def __processTopLevelNode (self, node):
4963 """Process a DOM node from the top level of the schema. 4964 4965 This should return a non-None value if the node was 4966 successfully recognized.""" 4967 if xsd.nodeIsNamed(node, 'include'): 4968 return self.__processInclude(node) 4969 if xsd.nodeIsNamed(node, 'import'): 4970 return self.__processImport(node) 4971 if xsd.nodeIsNamed(node, 'redefine'): 4972 return self.__processRedefine(node) 4973 if xsd.nodeIsNamed(node, 'annotation'): 4974 return self.__processAnnotation(node) 4975 4976 component = self.__TopLevelComponentMap.get(node.localName) 4977 if component is not None: 4978 self.__pastProlog = True 4979 kw = { 'scope' : _ScopedDeclaration_mixin.SCOPE_global, 4980 'schema' : self, 4981 'owner' : self } 4982 return self._addNamedComponent(component.CreateFromDOM(node, **kw)) 4983 4984 raise pyxb.SchemaValidationError('Unexpected top-level element %s' % (node.nodeName,))
4985
4986 - def _addAnnotation (self, annotation):
4987 self.__annotations.append(annotation) 4988 return annotation
4989
4990 - def _addNamedComponent (self, nc):
4991 tns = self.targetNamespace() 4992 assert tns is not None 4993 if not isinstance(nc, _NamedComponent_mixin): 4994 raise pyxb.LogicError('Attempt to add unnamed %s instance to dictionary' % (nc.__class__,)) 4995 if nc.isAnonymous(): 4996 raise pyxb.LogicError('Attempt to add anonymous component to dictionary: %s', (nc.__class__,)) 4997 if isinstance(nc, _ScopedDeclaration_mixin): 4998 assert _ScopedDeclaration_mixin.SCOPE_global == nc.scope() 4999 if isinstance(nc, (SimpleTypeDefinition, ComplexTypeDefinition)): 5000 return self.__addTypeDefinition(nc) 5001 if isinstance(nc, AttributeDeclaration): 5002 return self.__addAttributeDeclaration(nc) 5003 if isinstance(nc, AttributeGroupDefinition): 5004 return self.__addAttributeGroupDefinition(nc) 5005 if isinstance(nc, ModelGroupDefinition): 5006 return tns.addCategoryObject('modelGroupDefinition', nc.name(), nc) 5007 if isinstance(nc, ElementDeclaration): 5008 return tns.addCategoryObject('elementDeclaration', nc.name(), nc) 5009 if isinstance(nc, NotationDeclaration): 5010 return tns.addCategoryObject('notationDeclaration', nc.name(), nc) 5011 if isinstance(nc, IdentityConstraintDefinition): 5012 return tns.addCategoryObject('identityConstraintDefinition', nc.name(), nc) 5013 assert False, 'No support to record named component of type %s' % (nc.__class__,)
5014
5015 - def __addTypeDefinition (self, td):
5016 local_name = td.name() 5017 assert self.__targetNamespace 5018 tns = self.targetNamespace() 5019 old_td = tns.typeDefinitions().get(local_name) 5020 if (old_td is not None) and (old_td != td): 5021 if isinstance(td, ComplexTypeDefinition) != isinstance(old_td, ComplexTypeDefinition): 5022 raise pyxb.SchemaValidationError('Name %s used for both simple and complex types' % (td.name(),)) 5023 5024 if not old_td._allowUpdateFromOther(td): 5025 raise pyxb.SchemaValidationError('Attempt to re-define non-builtin type definition %s' % (tns.createExpandedName(local_name),)) 5026 5027 # Copy schema-related information from the new definition 5028 # into the old one, and continue to use the old one. 5029 td = tns._replaceComponent(td, old_td._updateFromOther(td)) 5030 else: 5031 tns.addCategoryObject('typeDefinition', td.name(), td) 5032 assert td is not None 5033 return td
5034
5035 - def __addAttributeDeclaration (self, ad):
5036 local_name = ad.name() 5037 assert self.__targetNamespace 5038 tns = self.targetNamespace() 5039 old_ad = tns.attributeDeclarations().get(local_name) 5040 if (old_ad is not None) and (old_ad != ad): 5041 if not old_ad._allowUpdateFromOther(ad): 5042 raise pyxb.SchemaValidationError('Attempt to re-define non-builtin attribute declaration %s' % (tns.createExpandedName(local_name),)) 5043 5044 # Copy schema-related information from the new definition 5045 # into the old one, and continue to use the old one. 5046 ad = tns._replaceComponent(ad, old_ad._updateFromOther(ad)) 5047 else: 5048 tns.addCategoryObject('attributeDeclaration', ad.name(), ad) 5049 assert ad is not None 5050 return ad
5051
5052 - def __addAttributeGroupDefinition (self, agd):
5053 local_name = agd.name() 5054 assert self.__targetNamespace 5055 tns = self.targetNamespace() 5056 old_agd = tns.attributeGroupDefinitions().get(local_name) 5057 if (old_agd is not None) and (old_agd != agd): 5058 if not old_agd._allowUpdateFromOther(agd): 5059 raise pyxb.SchemaValidationError('Attempt to re-define non-builtin attribute group definition %s' % (tns.createExpandedName(local_name),)) 5060 5061 # Copy schema-related information from the new definition 5062 # into the old one, and continue to use the old one. 5063 tns._replaceComponent(agd, old_agd._updateFromOther(agd)) 5064 else: 5065 tns.addCategoryObject('attributeGroupDefinition', agd.name(), agd) 5066 assert agd is not None 5067 return agd
5068
5069 - def __str__ (self):
5070 return 'SCH[%s]' % (self.location(),)
5071
5072 5073 -def _AddSimpleTypes (namespace):
5074 """Add to the schema the definitions of the built-in types of XMLSchema. 5075 This should only be invoked by L{pyxb.namespace} when the built-in 5076 namespaces are initialized. """ 5077 # Add the ur type 5078 #schema = namespace.schema() 5079 schema = Schema(namespace_context=pyxb.namespace.XMLSchema.initialNamespaceContext(), schema_location='URN:noLocation:PyXB:XMLSchema', generation_uid=pyxb.namespace.BuiltInObjectUID, _bypass_preload=True) 5080 td = schema._addNamedComponent(ComplexTypeDefinition.UrTypeDefinition(schema, in_builtin_definition=True)) 5081 assert td.isResolved() 5082 # Add the simple ur type 5083 td = schema._addNamedComponent(SimpleTypeDefinition.SimpleUrTypeDefinition(schema, in_builtin_definition=True)) 5084 assert td.isResolved() 5085 # Add definitions for all primitive and derived simple types 5086 pts_std_map = {} 5087 for dtc in datatypes._PrimitiveDatatypes: 5088 name = dtc.__name__.rstrip('_') 5089 td = schema._addNamedComponent(SimpleTypeDefinition.CreatePrimitiveInstance(name, schema, dtc)) 5090 assert td.isResolved() 5091 assert dtc.SimpleTypeDefinition() == td 5092 pts_std_map.setdefault(dtc, td) 5093 for dtc in datatypes._DerivedDatatypes: 5094 name = dtc.__name__.rstrip('_') 5095 parent_std = pts_std_map[dtc.XsdSuperType()] 5096 td = schema._addNamedComponent(SimpleTypeDefinition.CreateDerivedInstance(name, schema, parent_std, dtc)) 5097 assert td.isResolved() 5098 assert dtc.SimpleTypeDefinition() == td 5099 pts_std_map.setdefault(dtc, td) 5100 for dtc in datatypes._ListDatatypes: 5101 list_name = dtc.__name__.rstrip('_') 5102 element_name = dtc._ItemType.__name__.rstrip('_') 5103 element_std = schema.targetNamespace().typeDefinitions().get(element_name) 5104 assert element_std is not None 5105 td = schema._addNamedComponent(SimpleTypeDefinition.CreateListInstance(list_name, schema, element_std, dtc)) 5106 assert td.isResolved() 5107 global _PastAddBuiltInTypes 5108 _PastAddBuiltInTypes = True 5109 5110 return schema
5111 5112 import sys 5113 import pyxb.namespace.builtin 5114 pyxb.namespace.builtin._InitializeBuiltinNamespaces(sys.modules[__name__]) 5115 5116 ## Local Variables: 5117 ## fill-column:78 5118 ## End: 5119