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