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