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