Package pyxb :: Package namespace :: Module resolution
[hide private]
[frames] | no frames]

Source Code for Module pyxb.namespace.resolution

  1  # Copyright 2009, Peter A. Bigot 
  2  # 
  3  # Licensed under the Apache License, Version 2.0 (the "License"); you may 
  4  # not use this file except in compliance with the License. You may obtain a 
  5  # copy of the License at: 
  6  # 
  7  #            http://www.apache.org/licenses/LICENSE-2.0 
  8  # 
  9  # Unless required by applicable law or agreed to in writing, software 
 10  # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
 11  # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
 12  # License for the specific language governing permissions and limitations 
 13  # under the License. 
 14   
 15  """Classes and global objects related to resolving U{XML 
 16  Namespaces<http://www.w3.org/TR/2006/REC-xml-names-20060816/index.html>}.""" 
 17   
 18  import pyxb 
 19  import os 
 20  import fnmatch 
 21  import pyxb.utils.utility 
 22  import archive 
 23  import utility 
24 25 -class _Resolvable_mixin (pyxb.cscRoot):
26 """Mix-in indicating that this object may have references to unseen named components. 27 28 This class is mixed-in to those XMLSchema components that have a reference 29 to another component that is identified by a QName. Resolution of that 30 component may need to be delayed if the definition of the component has 31 not yet been read. 32 """ 33 34 #_TraceResolution = True 35 _TraceResolution = False 36
37 - def isResolved (self):
38 """Determine whether this named component is resolved. 39 40 Override this in the child class.""" 41 raise pyxb.LogicError('Resolved check not implemented in %s' % (self.__class__,))
42
43 - def _resolve (self):
44 """Perform whatever steps are required to resolve this component. 45 46 Resolution is performed in the context of the namespace to which the 47 component belongs. Invoking this method may fail to complete the 48 resolution process if the component itself depends on unresolved 49 components. The sole caller of this should be 50 L{_NamespaceResolution_mixin.resolveDefinitions}. 51 52 This method is permitted (nay, encouraged) to raise an exception if 53 resolution requires interpreting a QName and the named component 54 cannot be found. 55 56 Override this in the child class. In the prefix, if L{isResolved} is 57 true, return right away. If something prevents you from completing 58 resolution, invoke L{self._queueForResolution()} (so it is retried 59 later) and immediately return self. Prior to leaving after successful 60 resolution discard any cached dom node by setting C{self.__domNode=None}. 61 62 @return: C{self}, whether or not resolution succeeds. 63 @raise pyxb.SchemaValidationError: if resolution requlres a reference to an unknown component 64 """ 65 raise pyxb.LogicError('Resolution not implemented in %s' % (self.__class__,))
66
67 - def _queueForResolution (self, why=None, depends_on=None):
68 """Short-hand to requeue an object if the class implements _namespaceContext(). 69 """ 70 if (why is not None) and self._TraceResolution: 71 print 'Resolution delayed for %s: %s\n\tDepends on: %s' % (self, why, depends_on) 72 self._namespaceContext().queueForResolution(self, depends_on)
73
74 -class _NamespaceResolution_mixin (pyxb.cscRoot):
75 """Mix-in that aggregates those aspects of XMLNamespaces relevant to 76 resolving component references. 77 """ 78 79 # A set of namespaces which some schema imported while processing with 80 # this namespace as target. 81 __importedNamespaces = None 82 83 # A set of namespaces which appear in namespace declarations of schema 84 # with this namespace as target. 85 __referencedNamespaces = None 86 87 # A list of Namespace._Resolvable_mixin instances that have yet to be 88 # resolved. 89 __unresolvedComponents = None 90 91 # A map from Namespace._Resolvable_mixin instances in 92 # __unresolvedComponents to sets of other unresolved objects on which they 93 # depend. 94 __unresolvedDependents = None 95
96 - def _reset (self):
97 """CSC extension to reset fields of a Namespace. 98 99 This one handles component-resolution--related data.""" 100 getattr(super(_NamespaceResolution_mixin, self), '_reset', lambda *args, **kw: None)() 101 self.__unresolvedComponents = [] 102 self.__unresolvedDependents = {} 103 self.__importedNamespaces = set() 104 self.__referencedNamespaces = set()
105
106 - def _getState_csc (self, kw):
107 kw.update({ 108 'importedNamespaces': self.__importedNamespaces, 109 'referencedNamespaces': self.__referencedNamespaces, 110 }) 111 return getattr(super(_NamespaceResolution_mixin, self), '_getState_csc', lambda _kw: _kw)(kw)
112
113 - def _setState_csc (self, kw):
114 self.__importedNamespaces = kw['importedNamespaces'] 115 self.__referencedNamespaces = kw['referencedNamespaces'] 116 return getattr(super(_NamespaceResolution_mixin, self), '_setState_csc', lambda _kw: self)(kw)
117
118 - def importNamespace (self, namespace):
119 self.__importedNamespaces.add(namespace) 120 return self
121
122 - def _referenceNamespace (self, namespace):
123 self._activate() 124 self.__referencedNamespaces.add(namespace) 125 return self
126
127 - def importedNamespaces (self):
128 """Return the set of namespaces which some schema imported while 129 processing with this namespace as target.""" 130 return frozenset(self.__importedNamespaces)
131
132 - def _transferReferencedNamespaces (self, module_record):
133 assert isinstance(module_record, archive.ModuleRecord) 134 module_record._setReferencedNamespaces(self.__referencedNamespaces) 135 self.__referencedNamespaces.clear()
136
137 - def referencedNamespaces (self):
138 """Return the set of namespaces which appear in namespace declarations 139 of schema with this namespace as target.""" 140 return frozenset(self.__referencedNamespaces) 141 rn = self.__referencedNamespaces.copy() 142 for mr in self.moduleRecords(): 143 if mr.isIncorporated(): 144 rn.update(mr.referencedNamespaces()) 145 return rn
146
147 - def queueForResolution (self, resolvable, depends_on=None):
148 """Invoked to note that a component may have references that will need 149 to be resolved. 150 151 Newly created named components are often unresolved, as are components 152 which, in the course of resolution, are found to depend on another 153 unresolved component. 154 155 @param resolvable: An instance of L{_Resolvable_mixin} that is later to 156 be resolved. 157 158 @keyword depends_on: C{None}, or an instance of L{_Resolvable_mixin} 159 which C{resolvable} requires to be resolved in order to resolve 160 itself. 161 162 @return: C{resolvable} 163 """ 164 assert isinstance(resolvable, _Resolvable_mixin) 165 if not resolvable.isResolved(): 166 assert depends_on is None or isinstance(depends_on, _Resolvable_mixin) 167 self.__unresolvedComponents.append(resolvable) 168 if depends_on is not None and not depends_on.isResolved(): 169 import pyxb.xmlschema.structures 170 assert isinstance(depends_on, _Resolvable_mixin) 171 assert isinstance(depends_on, pyxb.xmlschema.structures._NamedComponent_mixin) 172 self.__unresolvedDependents.setdefault(resolvable, set()).add(depends_on) 173 return resolvable
174
175 - def needsResolution (self):
176 """Return C{True} iff this namespace has not been resolved.""" 177 return self.__unresolvedComponents is not None
178
179 - def _replaceComponent_csc (self, existing_def, replacement_def):
180 """Replace a component definition if present in the list of unresolved components. 181 """ 182 try: 183 index = self.__unresolvedComponents.index(existing_def) 184 print 'Replacing unresolved %s' % (existing_def,) 185 if (replacement_def is None) or (replacement_def in self.__unresolvedComponents): 186 del self.__unresolvedComponents[index] 187 else: 188 assert isinstance(replacement_def, _Resolvable_mixin) 189 self.__unresolvedComponents[index] = replacement_def 190 # Rather than assume the replacement depends on the same 191 # resolvables as the original, just wipe the dependency record: 192 # it'll get recomputed later if it's still important. 193 if existing_def in self.__unresolvedDependents: 194 del self.__unresolvedDependents[existing_def] 195 except ValueError: 196 pass 197 return getattr(super(_NamespaceResolution_mixin, self), '_replaceComponent_csc', lambda *args, **kw: replacement_def)(existing_def, replacement_def)
198
199 - def resolveDefinitions (self, allow_unresolved=False):
200 """Loop until all references within the associated resolvable objects 201 have been resolved. 202 203 This method iterates through all components on the unresolved list, 204 invoking the _resolve method of each. If the component could not be 205 resolved in this pass, it iis placed back on the list for the next 206 iteration. If an iteration completes without resolving any of the 207 unresolved components, a pyxb.NotInNamespaceError exception is raised. 208 209 @note: Do not invoke this until all top-level definitions for the 210 namespace have been provided. The resolution routines are entitled to 211 raise a validation exception if a reference to an unrecognized 212 component is encountered. 213 """ 214 num_loops = 0 215 if not self.needsResolution(): 216 return True 217 218 while 0 < len(self.__unresolvedComponents): 219 # Save the list of unresolved objects, reset the list to capture 220 # any new objects defined during resolution, and attempt the 221 # resolution for everything that isn't resolved. 222 unresolved = self.__unresolvedComponents 223 #print 'Looping for %d unresolved definitions: %s' % (len(unresolved), ' '.join([ str(_r) for _r in unresolved])) 224 num_loops += 1 225 #assert num_loops < 18 226 227 self.__unresolvedComponents = [] 228 self.__unresolvedDependents = {} 229 for resolvable in unresolved: 230 # Attempt the resolution. 231 resolvable._resolve() 232 233 # Either we resolved it, or we queued it to try again later 234 assert resolvable.isResolved() or (resolvable in self.__unresolvedComponents), 'Lost resolvable %s' % (resolvable,) 235 236 # We only clone things that have scope None. We never 237 # resolve things that have scope None. Therefore, we 238 # should never have resolved something that has 239 # clones. 240 if (resolvable.isResolved() and (resolvable._clones() is not None)): 241 assert False 242 if self.__unresolvedComponents == unresolved: 243 if allow_unresolved: 244 return False 245 # This only happens if we didn't code things right, or the 246 # there is a circular dependency in some named component 247 # (i.e., the schema designer didn't do things right). 248 failed_components = [] 249 import pyxb.xmlschema.structures 250 for d in self.__unresolvedComponents: 251 if isinstance(d, pyxb.xmlschema.structures._NamedComponent_mixin): 252 failed_components.append('%s named %s' % (d.__class__.__name__, d.name())) 253 else: 254 if isinstance(d, pyxb.xmlschema.structures.AttributeUse): 255 print d.attributeDeclaration() 256 failed_components.append('Anonymous %s' % (d.__class__.__name__,)) 257 raise pyxb.NotInNamespaceError('Infinite loop in resolution:\n %s' % ("\n ".join(failed_components),)) 258 259 # Replace the list of unresolved components with None, so that 260 # attempts to subsequently add another component fail. 261 self.__unresolvedComponents = None 262 self.__unresolvedDependents = None 263 264 # NOTE: Dependencies may require that we keep these around for a while 265 # longer. 266 # 267 # Remove the namespace context from everything, since we won't be 268 # resolving anything else. 269 self._releaseNamespaceContexts() 270 271 return True
272
273 - def _unresolvedComponents (self):
274 """Returns a reference to the list of unresolved components.""" 275 return self.__unresolvedComponents
276
277 - def _unresolvedDependents (self):
278 """Returns a map from unresolved components to sets of components that 279 must be resolved first.""" 280 return self.__unresolvedDependents
281
282 -def ResolveSiblingNamespaces (sibling_namespaces):
283 """Resolve all components in the sibling_namespaces. 284 285 @param sibling_namespaces : A set of namespaces expected to be closed 286 under dependency.""" 287 288 for ns in sibling_namespaces: 289 ns.configureCategories([archive.NamespaceArchive._AnonymousCategory()]) 290 ns.validateComponentModel() 291 292 def cmp_for_deps (ns1, ns2): 293 """Sort namespaces so dependencies get resolved first""" 294 if ns2 not in dependency_map.get(ns1, set()): 295 return -1 296 if ns1 not in dependency_map.get(ns2, set()): 297 return 1 298 return 0
299 300 need_resolved_set = set(sibling_namespaces) 301 dependency_map = {} 302 last_state = None 303 while need_resolved_set: 304 need_resolved_list = list(need_resolved_set) 305 if dependency_map: 306 need_resolved_list.sort(cmp_for_deps) 307 need_resolved_set = set() 308 dependency_map = {} 309 for ns in need_resolved_list: 310 if not ns.needsResolution(): 311 continue 312 #print 'Attempting resolution %s' % (ns.uri(),) 313 if not ns.resolveDefinitions(allow_unresolved=True): 314 print 'Holding incomplete resolution %s' % (ns.uri(),) 315 deps = dependency_map.setdefault(ns, set()) 316 for (c, dcs) in ns._unresolvedDependents().iteritems(): 317 for dc in dcs: 318 dns = dc.expandedName().namespace() 319 if dns != ns: 320 deps.add(dns) 321 print '%s depends on %s' % (ns, ' ; '.join([ str(_dns) for _dns in deps ])) 322 need_resolved_set.add(ns) 323 # Exception termination check: if we have the same set of incompletely 324 # resolved namespaces, and each has the same number of unresolved 325 # components, assume there's an truly unresolvable dependency: either 326 # due to circularity, or because there was an external namespace that 327 # was missed from the sibling list. 328 state = [] 329 for ns in need_resolved_set: 330 state.append( (ns, len(ns._unresolvedComponents())) ) 331 state = tuple(state) 332 if last_state == state: 333 raise pyxb.LogicError('Unexpected external dependency in sibling namespaces: %s' % ("\n ".join( [str(_ns) for _ns in need_resolved_set ]),)) 334 last_state = state 335
336 -class NamespaceContext (object):
337 """Records information associated with namespaces at a DOM node. 338 """ 339
340 - def __str__ (self):
341 rv = [ 'NamespaceContext ' ] 342 if self.defaultNamespace() is not None: 343 rv.extend([ '(defaultNamespace=', str(self.defaultNamespace()), ') ']) 344 if self.targetNamespace() is not None: 345 rv.extend([ '(targetNamespace=', str(self.targetNamespace()), ') ']) 346 rv.append("\n") 347 for (pfx, ns) in self.inScopeNamespaces().items(): 348 if pfx is not None: 349 rv.append(' xmlns:%s=%s' % (pfx, str(ns))) 350 return ''.join(rv)
351 352 __TargetNamespaceAttributes = { } 353 @classmethod
354 - def _AddTargetNamespaceAttribute (cls, expanded_name, attribute_name):
355 assert expanded_name is not None 356 cls.__TargetNamespaceAttributes[expanded_name] = attribute_name
357 @classmethod
358 - def _TargetNamespaceAttribute (cls, expanded_name):
359 return cls.__TargetNamespaceAttributes.get(expanded_name, None)
360 361 # Support for holding onto referenced namespaces until we have a target 362 # namespace to give them to. 363 __pendingReferencedNamespaces = None 364
365 - def defaultNamespace (self):
366 """The default namespace in effect at this node. E.g., C{xmlns="URN:default"}.""" 367 return self.__defaultNamespace
368 __defaultNamespace = None 369 370 # If C{True}, this context is within a schema that has no target 371 # namespace, and we should use the target namespace as a fallback if no 372 # default namespace is available and no namespace prefix appears on a 373 # QName. This situation arises when a top-level schema has an absent 374 # target namespace, or when a schema with an absent target namespace is 375 # being included into a schema with a non-absent target namespace. 376 __fallbackToTargetNamespace = False 377
378 - def targetNamespace (self):
379 """The target namespace in effect at this node. Usually from the 380 C{targetNamespace} attribute. If no namespace is specified for the 381 schema, an absent namespace was assigned upon creation and will be 382 returned.""" 383 return self.__targetNamespace
384 __targetNamespace = None 385
386 - def inScopeNamespaces (self):
387 """Map from prefix strings to L{Namespace} instances associated with those 388 prefixes. The prefix C{None} identifies the default namespace.""" 389 return self.__inScopeNamespaces
390 __inScopeNamespaces = None 391
392 - def prefixForNamespace (self, namespace):
393 """Return a prefix associated with the given namespace in this 394 context, or None if the namespace is the default or is not in 395 scope.""" 396 for (pfx, ns) in self.__inScopeNamespaces.items(): 397 if namespace == ns: 398 return pfx 399 return None
400 401 @classmethod
402 - def GetNodeContext (cls, node, **kw):
403 """Get the L{NamespaceContext} instance that was assigned to the node. 404 405 If none has been assigned and keyword parameters are present, create 406 one treating this as the root node and the keyword parameters as 407 configuration information (e.g., default_namespace). 408 409 @raise pyxb.LogicError: no context is available and the keywords 410 required to create one were not provided 411 """ 412 try: 413 return node.__namespaceContext 414 except AttributeError: 415 return NamespaceContext(node, **kw)
416
417 - def setNodeContext (self, node):
418 node.__namespaceContext = self
419
420 - def processXMLNS (self, prefix, uri):
421 if not self.__mutableInScopeNamespaces: 422 self.__inScopeNamespaces = self.__inScopeNamespaces.copy() 423 self.__mutableInScopeNamespaces = True 424 if uri: 425 if prefix is None: 426 ns = self.__defaultNamespace = utility.NamespaceForURI(uri, create_if_missing=True) 427 self.__inScopeNamespaces[None] = self.__defaultNamespace 428 else: 429 ns = utility.NamespaceForURI(uri, create_if_missing=True) 430 self.__inScopeNamespaces[prefix] = ns 431 #if ns.prefix() is None: 432 # ns.setPrefix(prefix) 433 # @todo should we record prefix in namespace so we can use it 434 # during generation? I'd rather make the user specify what to 435 # use. 436 if self.__targetNamespace: 437 self.__targetNamespace._referenceNamespace(ns) 438 else: 439 self.__pendingReferencedNamespaces.add(ns) 440 else: 441 # NB: XMLNS 6.2 says that you can undefine a default 442 # namespace, but does not say anything explicitly about 443 # undefining a prefixed namespace. XML-Infoset 2.2 444 # paragraph 6 implies you can do this, but expat blows up 445 # if you try it. I don't think it's legal. 446 if prefix is not None: 447 raise pyxb.NamespaceError(self, 'Attempt to undefine non-default namespace %s' % (attr.localName,)) 448 self.__inScopeNamespaces.pop(prefix, None) 449 self.__defaultNamespace = None
450
451 - def finalizeTargetNamespace (self, tns_uri=None, including_context=None):
452 if tns_uri is not None: 453 assert 0 < len(tns_uri) 454 # Do not prevent overwriting target namespace; need this for WSDL 455 # files where an embedded schema inadvertently inherits a target 456 # namespace from its enclosing definitions element. Note that if 457 # we don't check this here, we do have to check it when schema 458 # documents are included into parent schema documents. 459 self.__targetNamespace = utility.NamespaceForURI(tns_uri, create_if_missing=True) 460 elif self.__targetNamespace is None: 461 if including_context is not None: 462 self.__targetNamespace = including_context.targetNamespace() 463 self.__fallbackToTargetNamespace = True 464 elif tns_uri is None: 465 self.__targetNamespace = utility.CreateAbsentNamespace() 466 else: 467 self.__targetNamespace = utility.NamespaceForURI(tns_uri, create_if_missing=True) 468 if self.__pendingReferencedNamespaces is not None: 469 [ self.__targetNamespace._referenceNamespace(_ns) for _ns in self.__pendingReferencedNamespaces ] 470 self.__pendingReferencedNamespace = None 471 assert self.__targetNamespace is not None 472 if (not self.__fallbackToTargetNamespace) and self.__targetNamespace.isAbsentNamespace(): 473 self.__fallbackToTargetNamespace = True
474
475 - def __init__ (self, 476 dom_node=None, 477 parent_context=None, 478 including_context=None, 479 recurse=True, 480 default_namespace=None, 481 target_namespace=None, 482 in_scope_namespaces=None, 483 expanded_name=None, 484 finalize_target_namespace=True): # MUST BE True for WSDL to work with minidom
485 """Determine the namespace context that should be associated with the 486 given node and, optionally, its element children. 487 488 @param dom_node: The DOM node 489 @type dom_node: C{xml.dom.Element} 490 @keyword parent_context: Optional value that specifies the context 491 associated with C{dom_node}'s parent node. If not provided, only the 492 C{xml} namespace is in scope. 493 @type parent_context: L{NamespaceContext} 494 @keyword recurse: If True (default), create namespace contexts for all 495 element children of C{dom_node} 496 @type recurse: C{bool} 497 @keyword default_namespace: Optional value to set as the default 498 namespace. Values from C{parent_context} would override this, as 499 would an C{xmlns} attribute in the C{dom_node}. 500 @type default_namespace: L{NamespaceContext} 501 @keyword target_namespace: Optional value to set as the target 502 namespace. Values from C{parent_context} would override this, as 503 would a C{targetNamespace} attribute in the C{dom_node} 504 @type target_namespace: L{NamespaceContext} 505 @keyword in_scope_namespaces: Optional value to set as the initial set 506 of in-scope namespaces. The always-present namespaces are added to 507 this if necessary. 508 @type in_scope_namespaces: C{dict} mapping C{string} to L{Namespace}. 509 """ 510 import builtin 511 512 if dom_node is not None: 513 try: 514 assert dom_node.__namespaceContext is None 515 except AttributeError: 516 pass 517 dom_node.__namespaceContext = self 518 519 self.__defaultNamespace = default_namespace 520 self.__targetNamespace = target_namespace 521 self.__inScopeNamespaces = builtin._UndeclaredNamespaceMap 522 self.__mutableInScopeNamespaces = False 523 524 if in_scope_namespaces is not None: 525 if parent_context is not None: 526 raise LogicError('Cannot provide both parent_context and in_scope_namespaces') 527 self.__inScopeNamespaces = builtin._UndeclaredNamespaceMap.copy() 528 self.__inScopeNamespaces.update(in_scope_namespaces) 529 self.__mutableInScopeNamespaces = True 530 531 if parent_context is not None: 532 self.__inScopeNamespaces = parent_context.inScopeNamespaces() 533 self.__mutableInScopeNamespaces = False 534 self.__defaultNamespace = parent_context.defaultNamespace() 535 self.__targetNamespace = parent_context.targetNamespace() 536 self.__fallbackToTargetNamespace = parent_context.__fallbackToTargetNamespace 537 538 if self.__targetNamespace is None: 539 self.__pendingReferencedNamespaces = set() 540 attribute_map = {} 541 if dom_node is not None: 542 if expanded_name is None: 543 expanded_name = pyxb.namespace.ExpandedName(dom_node) 544 for ai in range(dom_node.attributes.length): 545 attr = dom_node.attributes.item(ai) 546 if builtin.XMLNamespaces.uri() == attr.namespaceURI: 547 prefix = attr.localName 548 if 'xmlns' == prefix: 549 prefix = None 550 self.processXMLNS(prefix, attr.value) 551 else: 552 if attr.namespaceURI is not None: 553 uri = utility.NamespaceForURI(attr.namespaceURI, create_if_missing=True) 554 key = pyxb.namespace.ExpandedName(uri, attr.localName) 555 else: 556 key = pyxb.namespace.ExpandedName(None, attr.localName) 557 attribute_map[key] = attr.value 558 559 if finalize_target_namespace: 560 tns_uri = None 561 tns_attr = self._TargetNamespaceAttribute(expanded_name) 562 if tns_attr is not None: 563 tns_uri = attribute_map.get(tns_attr) 564 self.finalizeTargetNamespace(tns_uri, including_context=including_context) 565 566 # Store in each node the in-scope namespaces at that node; 567 # we'll need them for QName interpretation of attribute 568 # values. 569 if (dom_node is not None) and recurse: 570 from xml.dom import Node 571 assert Node.ELEMENT_NODE == dom_node.nodeType 572 for cn in dom_node.childNodes: 573 if Node.ELEMENT_NODE == cn.nodeType: 574 NamespaceContext(cn, self, True)
575
576 - def interpretQName (self, name, namespace=None):
577 """Convert the provided name into an L{ExpandedName}, i.e. a tuple of 578 L{Namespace} and local name. 579 580 If the name includes a prefix, that prefix must map to an in-scope 581 namespace in this context. Absence of a prefix maps to 582 L{defaultNamespace()}, which must be provided (or defaults to the 583 target namespace, if that is absent). 584 585 @param name: A QName. 586 @type name: C{str} or C{unicode} 587 @param name: Optional namespace to use for unqualified names when 588 there is no default namespace. Note that a defined default namespace, 589 even if absent, supersedes this value. 590 @return: An L{ExpandedName} tuple: ( L{Namespace}, C{str} ) 591 @raise pyxb.SchemaValidationError: The prefix is not in scope 592 @raise pyxb.SchemaValidationError: No prefix is given and the default namespace is absent 593 """ 594 assert isinstance(name, (str, unicode)) 595 if 0 <= name.find(':'): 596 (prefix, local_name) = name.split(':', 1) 597 assert self.inScopeNamespaces() is not None 598 namespace = self.inScopeNamespaces().get(prefix) 599 if namespace is None: 600 raise pyxb.SchemaValidationError('No namespace declared for QName %s prefix' % (name,)) 601 else: 602 local_name = name 603 # Context default supersedes caller-provided namespace 604 if self.defaultNamespace() is not None: 605 namespace = self.defaultNamespace() 606 # If there's no default namespace, but there is a fallback 607 # namespace, use that instead. 608 if (namespace is None) and self.__fallbackToTargetNamespace: 609 namespace = self.targetNamespace() 610 if namespace is None: 611 raise pyxb.SchemaValidationError('QName %s with absent default namespace cannot be resolved' % (local_name,)) 612 # Anything we're going to look stuff up in requires a component model. 613 # Make sure we can load one, unless we're looking up in the thing 614 # we're constructing (in which case it's being built right now). 615 if (namespace != self.targetNamespace()): 616 namespace.validateComponentModel() 617 return pyxb.namespace.ExpandedName(namespace, local_name)
618
619 - def queueForResolution (self, component, depends_on=None):
620 """Forwards to L{queueForResolution()<Namespace.queueForResolution>} in L{targetNamespace()}.""" 621 assert isinstance(component, _Resolvable_mixin) 622 return self.targetNamespace().queueForResolution(component, depends_on)
623 624 ## Local Variables: 625 ## fill-column:78 626 ## End: 627