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

Source Code for Module pyxb.namespace.resolution

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