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

Source Code for Package pyxb.namespace

  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 U{XML Namespaces<http://www.w3.org/TR/2006/REC-xml-names-20060816/index.html>}. 
 16   
 17  Since namespaces hold all referenceable objects, this module also defines the 
 18  infrastructure for resolving named object references, such as schema 
 19  components. 
 20  """ 
 21   
 22  import pyxb 
 23  import os 
 24  import fnmatch 
 25  import pyxb.utils.utility 
 26  import xml.dom 
27 28 -class ExpandedName (pyxb.cscRoot):
29 30 """Represent an U{expanded name 31 <http://www.w3.org/TR/REC-xml-names/#dt-expname>}, which pairs a 32 namespace with a local name. 33 34 Because a large number of local elements, and most attributes, have no 35 namespace associated with them, this is optimized for representing names 36 with an absent namespace. The hash and equality test methods are set so 37 that a plain string is equivalent to a tuple of C{None} and that string. 38 39 Note that absent namespaces can be represented in two ways: with a 40 namespace of C{None} (the name "has no namespace"), and with a namespace 41 that is an L{absent namespace <Namespace.CreateAbsentNamespace>} (the name 42 "has an absent namespace"). Hash code calculations are done so that the 43 two alternatives produce the same hash; however, comparison is done so 44 that the two are distinguished. The latter is the intended behavior; the 45 former should not be counted upon. 46 47 This class allows direct lookup of the named object within a category by 48 using the category name as an accessor function. That is, if the 49 namespace of the expanded name C{en} has a category 'typeDefinition', then 50 the following two expressions are equivalent:: 51 52 en.typeDefinition() 53 en.namespace().categoryMap('typeDefinition').get(en.localName()) 54 55 This class descends from C{tuple} so that its values can be used as 56 dictionary keys without concern for pointer equivalence. 57 """
58 - def namespace (self):
59 """The L{Namespace} part of the expanded name.""" 60 return self.__namespace
61 __namespace = None 62
63 - def namespaceURI (self):
64 """Return the URI of the namespace, or C{None} if the namespace is absent.""" 65 return self.__namespaceURI
66 __namespaceURI = None 67
68 - def localName (self):
69 """The local part of the expanded name.""" 70 return self.__localName
71 __localName = None 72 73 # Cached tuple representation 74 __expandedName = None 75
76 - def validateComponentModel (self):
77 """Pass model validation through to namespace part.""" 78 return self.namespace().validateComponentModel()
79
80 - def uriTuple (self):
81 """Return a tuple consisting of the namespace URI and the local name. 82 83 This presents the expanded name as base Python types for persistent 84 storage. Be aware, though, that it will lose the association of the 85 name with an absent namespace, if that matters to you.""" 86 return ( self.__namespaceURI, self.__localName )
87 88 # Treat unrecognized attributes as potential accessor functions
89 - def __getattr__ (self, name):
90 # Don't try to recognize private names (like __setstate__) 91 if name.startswith('__'): 92 return super(ExpandedName, self).__getattr__(name) 93 if self.namespace() is None: 94 return lambda: None 95 # NOTE: This will raise pyxb.NamespaceError if the category does not exist. 96 category_value = self.namespace().categoryMap(name).get(self.localName()) 97 return lambda : category_value
98
99 - def createName (self, local_name):
100 """Return a new expanded name in the namespace of this name. 101 102 @param local_name: The local name portion of an expanded name. 103 @return: An instance of L{ExpandedName}. 104 """ 105 return ExpandedName(self.namespace(), local_name)
106
107 - def adoptName (self, name):
108 """Return the input name, except if the input name has no namespace, 109 return a name that uses the namespace from this name with the local 110 name from the input name. 111 112 Use this when the XML document has an unqualified name and we're 113 processing using an absent default namespace. 114 115 @warning: Be careful when using a global name to adopt a name from a 116 local element: if the local element (with no namespace) has the same 117 localName as but is different from the global element (with a 118 namespace), this will improperly provide a namespace when one should 119 not be present. See the comments in 120 L{pyxb.binding.basis.element.elementForName}. 121 """ 122 123 if not isinstance(name, ExpandedName): 124 name = ExpandedName(name) 125 if name.namespace() is None: 126 name = self.createName(name.localName()) 127 return name
128
129 - def __init__ (self, *args, **kw):
130 """Create an expanded name. 131 132 Expected argument patterns are: 133 134 ( C{str} ) -- the local name in an absent namespace 135 ( L{ExpandedName} ) -- a copy of the given expanded name 136 ( C{xml.dom.Node} ) -- The name extracted from node.namespaceURI and node.localName 137 ( C{str}, C{str} ) -- the namespace URI and the local name 138 ( L{Namespace}, C{str} ) -- the namespace and the local name 139 ( L{ExpandedName}, C{str}) -- the namespace from the expanded name, and the local name 140 141 Wherever C{str} occurs C{unicode} is also permitted. 142 143 @keyword fallback_namespace: Optional Namespace instance to use if the 144 namespace would otherwise be None. This is only used if it is an 145 absent namespace. 146 147 """ 148 fallback_namespace = kw.get('fallback_namespace') 149 if 0 == len(args): 150 raise pyxb.LogicError('Too few arguments to ExpandedName constructor') 151 if 2 < len(args): 152 raise pyxb.LogicError('Too many arguments to ExpandedName constructor') 153 if 2 == len(args): 154 # Namespace(str, unicode, Namespace) and local name (str, unicode) 155 ( ns, ln ) = args 156 else: 157 # Local name (str, unicode) or ExpandedName or Node 158 assert 1 == len(args) 159 ln = args[0] 160 ns = None 161 if isinstance(ln, basestring): 162 pass 163 elif isinstance(ln, tuple) and (2 == len(ln)): 164 (ns, ln) = ln 165 elif isinstance(ln, ExpandedName): 166 ns = ln.namespace() 167 ln = ln.localName() 168 elif isinstance(ln, xml.dom.Node): 169 if not(ln.nodeType in (xml.dom.Node.ELEMENT_NODE, xml.dom.Node.ATTRIBUTE_NODE)): 170 raise pyxb.LogicError('Cannot create expanded name from non-element DOM node %s' % (ln.nodeType,)) 171 ns = ln.namespaceURI 172 ln = ln.localName 173 else: 174 raise pyxb.LogicError('Unrecognized argument type %s' % (type(ln),)) 175 if (ns is None) and (fallback_namespace is not None): 176 if fallback_namespace.isAbsentNamespace(): 177 ns = fallback_namespace 178 if isinstance(ns, (str, unicode)): 179 ns = NamespaceForURI(ns, create_if_missing=True) 180 if isinstance(ns, ExpandedName): 181 ns = ns.namespace() 182 if (ns is not None) and not isinstance(ns, Namespace): 183 raise pyxb.LogicError('ExpandedName must include a valid (perhaps absent) namespace, or None.') 184 self.__namespace = ns 185 if self.__namespace is not None: 186 self.__namespaceURI = self.__namespace.uri() 187 self.__localName = ln 188 assert self.__localName is not None 189 self.__expandedName = ( self.__namespace, self.__localName ) 190 self.__uriTuple = ( self.__namespaceURI, self.__localName )
191 192
193 - def __str__ (self):
194 assert self.__localName is not None 195 if self.__namespaceURI is not None: 196 return '{%s}%s' % (self.__namespaceURI, self.__localName) 197 return self.localName()
198
199 - def __hash__ (self):
200 if self.__namespaceURI is None: 201 # Handle both str and unicode hashes 202 return type(self.__localName).__hash__(self.__localName) 203 return tuple.__hash__(self.__expandedName)
204
205 - def __cmp__ (self, other):
206 if other is None: # None is below everything else 207 return cmp(1, -1) 208 if isinstance(other, (str, unicode)): 209 other = ( None, other ) 210 if not isinstance(other, tuple): 211 other = other.__uriTuple 212 if isinstance(other[0], Namespace): 213 other = ( other[0].uri(), other[1] ) 214 return cmp(self.__uriTuple, other)
215
216 - def getAttribute (self, dom_node):
217 """Return the value of the attribute identified by this name in the given node. 218 219 @return: An instance of C{xml.dom.Attr}, or C{None} if the node does 220 not have an attribute with this name. 221 """ 222 if dom_node.hasAttributeNS(self.__namespaceURI, self.__localName): 223 return dom_node.getAttributeNS(self.__namespaceURI, self.__localName) 224 return None
225
226 - def nodeMatches (self, dom_node):
227 """Return C{True} iff the dom node expanded name matches this expanded name.""" 228 return (dom_node.localName == self.__localName) and (dom_node.namespaceURI == self.__namespaceURI)
229
230 -class NamedObjectMap (dict):
231 """An extended dictionary intended to assist with QName resolution. 232 233 These dictionaries have an attribute that identifies a category of named 234 objects within a Namespace; the specifications for various documents 235 require that certain groups of objects must be unique, while uniqueness is 236 not required between groups. The dictionary also retains a pointer to the 237 Namespace instance for which it holds objects."""
238 - def namespace (self):
239 """The namespace to which the object map belongs.""" 240 return self.__namespace
241 __namespace = None 242
243 - def category (self):
244 """The category of objects (e.g., typeDefinition, elementDeclaration).""" 245 return self.__category
246 __category = None 247
248 - def __init__ (self, category, namespace, *args, **kw):
249 self.__category = category 250 self.__namespace = namespace 251 super(NamedObjectMap, self).__init__(*args, **kw)
252
253 -class _NamespaceCategory_mixin (pyxb.cscRoot):
254 """Mix-in that aggregates those aspects of XMLNamespaces that hold 255 references to categories of named objects. 256 257 Arbitrary groups of named objects, each requiring unique names within 258 themselves, can be saved. Unless configured otherwise, the Namespace 259 instance is extended with accessors that provide direct access to 260 individual category maps. The name of the method is the category name 261 with a suffix of "s"; e.g., if a category "typeDefinition" exists, it can 262 be accessed from the namespace using the syntax C{ns.typeDefinitions()}. 263 264 Note that the returned value from the accessor is a live reference to 265 the category map; changes made to the map are reflected in the 266 namespace. 267 """ 268 269 # Map from category strings to NamedObjectMap instances that 270 # contain the dictionary for that category. 271 __categoryMap = None 272
273 - def _reset (self):
274 """CSC extension to reset fields of a Namespace. 275 276 This one handles category-related data.""" 277 getattr(super(_NamespaceCategory_mixin, self), '_reset', lambda *args, **kw: None)() 278 self.__categoryMap = { }
279
280 - def categories (self):
281 """The list of individual categories held in this namespace.""" 282 return self.__categoryMap.keys()
283
284 - def _categoryMap (self):
285 """Return the whole map from categories to named objects.""" 286 return self.__categoryMap
287
288 - def categoryMap (self, category):
289 """Map from local names to NamedObjectMap instances for the given category.""" 290 try: 291 return self.__categoryMap[category] 292 except KeyError: 293 raise pyxb.NamespaceError(self, '%s has no category %s' % (self, category))
294
295 - def __defineCategoryAccessors (self):
296 """Define public methods on the Namespace which provide access to 297 individual NamedObjectMaps based on their category. 298 299 """ 300 for category in self.categories(): 301 accessor_name = category + 's' 302 setattr(self, accessor_name, lambda _map=self.categoryMap(category): _map)
303
304 - def configureCategories (self, categories):
305 """Ensure there is a map for each of the given categories. 306 307 Category configuration 308 L{activates<archive._NamespaceArchivable_mixin.isActive>} a namespace. 309 310 Existing maps are not affected.""" 311 312 self._activate() 313 if self.__categoryMap is None: 314 self.__categoryMap = { } 315 for category in categories: 316 if not (category in self.__categoryMap): 317 self.__categoryMap[category] = NamedObjectMap(category, self) 318 self.__defineCategoryAccessors() 319 return self
320
321 - def addCategoryObject (self, category, local_name, named_object):
322 """Allow access to the named_object by looking up the local_name in 323 the given category. 324 325 Raises pyxb.NamespaceUniquenessError if an object with the same name 326 already exists in the category.""" 327 name_map = self.categoryMap(category) 328 old_object = name_map.get(local_name) 329 if (old_object is not None) and (old_object != named_object): 330 raise pyxb.NamespaceUniquenessError(self, '%s: name %s used for multiple values in %s' % (self, local_name, category)) 331 name_map[local_name] = named_object 332 return named_object
333
334 - def replaceCategoryObject (self, category, local_name, old_object, new_object):
335 """Replace the referenced object in the category. 336 337 The new object will be added only if the old_object matches the 338 current entry for local_name in the category.""" 339 name_map = self.categoryMap(category) 340 if old_object == name_map.get(local_name): 341 name_map[local_name] = new_object 342 return name_map[local_name]
343
344 - def _replaceComponent_csc (self, existing_def, replacement_def):
345 """Replace a component definition where present in the category maps. 346 347 @note: This is a high-cost operation, as every item in every category 348 map must be examined to see whether its value field matches 349 C{existing_def}.""" 350 for (cat, registry) in self.__categoryMap.items(): 351 for (k, v) in registry.items(): 352 if v == existing_def: 353 print 'Replacing value for %s in %s' % (k, cat) 354 del registry[k] 355 if replacement_def is not None: 356 registry[k] = replacement_def 357 return getattr(super(_NamespaceCategory_mixin, self), '_replaceComponent_csc', lambda *args, **kw: replacement_def)(existing_def, replacement_def)
358 359 # Verify that the namespace category map has no components recorded. This 360 # is the state that should hold prior to loading a saved namespace; at 361 # tthe moment, we do not support aggregating components defined separately 362 # into the same namespace. That should be done at the schema level using 363 # the "include" element.
364 - def __checkCategoriesEmpty (self):
365 if self.__categoryMap is None: 366 return True 367 assert isinstance(self.__categoryMap, dict) 368 if 0 == len(self.__categoryMap): 369 return True 370 for k in self.categories(): 371 if 0 < len(self.categoryMap(k)): 372 return False 373 return True
374
375 - def _namedObjects (self):
376 objects = set() 377 for category_map in self.__categoryMap.values(): 378 objects.update(category_map.values()) 379 return objects
380
381 - def _loadNamedObjects (self, category_map):
382 """Add the named objects from the given map into the set held by this namespace. 383 It is an error to name something which is already present.""" 384 self.configureCategories(category_map.keys()) 385 for category in category_map.keys(): 386 current_map = self.categoryMap(category) 387 new_map = category_map[category] 388 for (local_name, component) in new_map.iteritems(): 389 existing_component = current_map.get(local_name) 390 if existing_component is None: 391 current_map[local_name] = component 392 elif existing_component._allowUpdateFromOther(component): 393 existing_component._updateFromOther(component) 394 else: 395 raise pyxb.NamespaceError(self, 'Load attempted to override %s %s in %s' % (category, ln, self.uri())) 396 self.__defineCategoryAccessors()
397
398 - def hasSchemaComponents (self):
399 """Return C{True} iff schema components have been associated with this namespace. 400 401 This only checks whether the corresponding categories have been added, 402 not whether there are any entries in those categories. It is useful 403 for identifying namespaces that were incorporated through a 404 declaration but never actually referenced.""" 405 return 'typeDefinition' in self.__categoryMap
406
407 - def _associateOrigins (self, module_record):
408 assert module_record.namespace() == self 409 module_record.resetCategoryObjects() 410 self.configureCategories([archive.NamespaceArchive._AnonymousCategory()]) 411 origin_set = module_record.origins() 412 for (cat, cat_map) in self.__categoryMap.iteritems(): 413 for (n, v) in cat_map.iteritems(): 414 if isinstance(v, archive._ArchivableObject_mixin) and (v._objectOrigin() in origin_set): 415 v._objectOrigin().addCategoryMember(cat, n, v)
416
417 -class _ComponentDependency_mixin (pyxb.utils.utility.PrivateTransient_mixin, pyxb.cscRoot):
418 """Mix-in for components that can depend on other components.""" 419 420 __PrivateTransient = set() 421 422 # Cached frozenset of components on which this component depends. 423 __bindingRequires = None 424 __PrivateTransient.add('bindingRequires') 425
426 - def _resetClone_csc (self, **kw):
427 """CSC extension to reset fields of a component. This one clears 428 dependency-related data, since the clone will have to revise its 429 dependencies. 430 @rtype: C{None}""" 431 getattr(super(_ComponentDependency_mixin, self), '_resetClone_csc', lambda *_args, **_kw: None)(**kw) 432 self.__bindingRequires = None
433
434 - def bindingRequires (self, reset=False, include_lax=False):
435 """Return a set of components upon whose bindings this component's 436 bindings depend. 437 438 For example, bindings that are extensions or restrictions depend on 439 their base types. Complex type definition bindings require that the 440 types of their attribute declarations be available at the class 441 definition, and the types of their element declarations in the 442 postscript. 443 444 @keyword include_lax: if C{False} (default), only the requirements of 445 the class itself are returned. If C{True}, all requirements are 446 returned. 447 @rtype: C{set(L{pyxb.xmlschema.structures._SchemaComponent_mixin})} 448 """ 449 if reset or (self.__bindingRequires is None): 450 if isinstance(self, resolution._Resolvable_mixin) and not (self.isResolved()): 451 raise pyxb.LogicError('Unresolved %s in %s: %s' % (self.__class__.__name__, self._namespaceContext().targetNamespace(), self.name())) 452 self.__bindingRequires = self._bindingRequires_vx(include_lax) 453 return self.__bindingRequires
454
455 - def _bindingRequires_vx (self, include_lax):
456 """Placeholder for subclass method that identifies the necessary components. 457 458 @note: Override in subclasses. 459 460 @return: The component instances on which this component depends 461 @rtype: C{frozenset} 462 @raise LogicError: A subclass failed to implement this method 463 """ 464 raise pyxb.LogicError('%s does not implement _bindingRequires_vx' % (type(self),))
465
466 -class _NamespaceComponentAssociation_mixin (pyxb.cscRoot):
467 """Mix-in for managing components defined within this namespace. 468 469 The component set includes not only top-level named components (such as 470 those accessible through category maps), but internal anonymous 471 components, such as those involved in representing the content model of a 472 complex type definition. We need to be able to get a list of these 473 components, sorted in dependency order, so that generated bindings do not 474 attempt to refer to a binding that has not yet been generated.""" 475 476 # A set containing all components, named or unnamed, that belong to this 477 # namespace. 478 __components = None 479
480 - def _reset (self):
481 """CSC extension to reset fields of a Namespace. 482 483 This one handles data related to component association with a 484 namespace.""" 485 getattr(super(_NamespaceComponentAssociation_mixin, self), '_reset', lambda *args, **kw: None)() 486 self.__components = set() 487 self.__origins = set() 488 self.__schemaMap = { }
489
490 - def _associateComponent (self, component):
491 """Record that the responsibility for the component belongs to this namespace.""" 492 self._activate() 493 assert self.__components is not None 494 assert isinstance(component, _ComponentDependency_mixin) 495 assert component not in self.__components 496 self.__components.add(component)
497
498 - def _replaceComponent_csc (self, existing_def, replacement_def):
499 """Replace a component definition in the set of associated components. 500 501 @raise KeyError: C{existing_def} is not in the set of components.""" 502 503 self.__components.remove(existing_def) 504 if replacement_def is not None: 505 self.__components.add(replacement_def) 506 return getattr(super(_NamespaceComponentAssociation_mixin, self), '_replaceComponent_csc', lambda *args, **kw: replacement_def)(existing_def, replacement_def)
507
508 - def addSchema (self, schema):
509 for sr in self.__origins: 510 if isinstance(sr, archive._SchemaOrigin) and sr.match(schema=schema): 511 print 'Schema at %s already registered in %s' % (schema.location(), self) 512 raise pyxb.SchemaUniquenessError(self, schema.location(), sr.schema()) 513 sr = archive._SchemaOrigin(schema=schema) 514 schema.generationUID().associateObject(sr) 515 self.__origins.add(sr) 516 return sr
517
518 - def lookupSchemaByLocation (self, schema_location):
519 for sr in self.__origins: 520 if isinstance(sr, archive._SchemaOrigin) and sr.match(location=schema_location): 521 return (True, sr.schema()) 522 for mr in self.moduleRecords(): 523 if mr.hasMatchingOrigin(location=schema_location): 524 return (True, None) 525 return (False, None)
526
527 - def schemas (self):
528 s = set() 529 for sr in self.__origins: 530 if isinstance(sr, archive._SchemaOrigin) and (sr.schema() is not None): 531 s.add(sr.schema()) 532 return s
533 534 __origins = None 535
536 - def components (self):
537 """Return a frozenset of all components, named or unnamed, belonging 538 to this namespace.""" 539 return frozenset(self.__components)
540
541 - def _releaseNamespaceContexts (self):
542 for c in self.__components: 543 c._clearNamespaceContext()
544 545 import archive 546 import resolution 547 548 from utility import *
549 550 -class Namespace (_NamespaceCategory_mixin, resolution._NamespaceResolution_mixin, _NamespaceComponentAssociation_mixin, archive._NamespaceArchivable_mixin):
551 """Represents an XML namespace (a URI). 552 553 There is at most one L{Namespace} class instance per namespace (URI). The 554 instance also supports associating arbitrary L{maps<NamedObjectMap>} from 555 names to objects, in separate categories. The default categories are 556 configured externally; for example, the 557 L{Schema<pyxb.xmlschema.structures.Schema>} component defines a category 558 for each named component in XMLSchema, and the customizing subclass for 559 WSDL definitions adds categories for the service bindings, messages, etc. 560 561 Namespaces can be written to and loaded from pickled files. See 562 L{NamespaceArchive} for information. 563 """ 564 565 # The URI for the namespace. If the URI is None, this is an absent 566 # namespace. 567 __uri = None 568 569 # An identifier, unique within a program using PyXB, used to distinguish 570 # absent namespaces. Currently this value is not accessible to the user, 571 # and exists solely to provide a unique identifier when printing the 572 # namespace as a string. The class variable is used as a one-up counter, 573 # which is assigned to the instance variable when an absent namespace 574 # instance is created. 575 __absentNamespaceID = 0 576 577 # A prefix bound to this namespace by standard. Current set known are applies to 578 # xml and xmlns. 579 __boundPrefix = None 580 581 # A prefix set as a preferred prefix, generally by processing a namespace 582 # declaration. 583 __prefix = None 584 585 # A map from URIs to Namespace instances. Namespaces instances 586 # must be unique for their URI. See __new__(). 587 __Registry = { } 588 589 # A set of all absent namespaces created. 590 __AbsentNamespaces = set() 591 592 # Optional description of the namespace 593 __description = None 594 595 # Indicates whether this namespace is built-in to the system 596 __isBuiltinNamespace = False 597 598 # Indicates whether this namespace is undeclared (available always) 599 __isUndeclaredNamespace = False 600 601 # Indicates whether this namespace was loaded from an archive 602 __isLoadedNamespace = False 603 604 # Archive from which the namespace can be read, or None if no archive 605 # defines this namespace. 606 __namespaceArchive = None 607 608 # Indicates whether this namespace has been written to an archive 609 __hasBeenArchived = False 610 611 # Holds the module path for builtin modules until we get a ModuleRecord to 612 # store that in. 613 __builtinModulePath = None 614 615 # A set of options defining how the Python bindings for this namespace 616 # were generated. Not currently used, since we don't have different 617 # binding configurations yet. 618 __bindingConfiguration = None 619 620 # The namespace to use as the default namespace when constructing the 621 # The namespace context used when creating built-in components that belong 622 # to this namespace. This is used to satisfy the low-level requirement 623 # that all schema components have a namespace context; normally, that 624 # context is built dynamically from the schema element. 625 __initialNamespaceContext = None 626 627 # The default_namespace parameter when creating the initial namespace 628 # context. Only used with built-in namespaces. 629 __contextDefaultNamespace = None 630 631 # The map from prefixes to namespaces as defined by the schema element for 632 # this namespace. Only used with built-in namespaces. 633 __contextInScopeNamespaces = None 634 635 @classmethod
636 - def _NamespaceForURI (cls, uri):
637 """If a Namespace instance for the given URI exists, return it; otherwise return None. 638 639 Note; Absent namespaces are not stored in the registry. If you use 640 one (e.g., for a schema with no target namespace), don't lose hold of 641 it.""" 642 assert uri is not None 643 return cls.__Registry.get(uri, None)
644 645
646 - def __getnewargs__ (self):
647 """Pickling support. 648 649 To ensure that unpickled Namespace instances are unique per 650 URI, we ensure that the routine that creates unpickled 651 instances knows what it's supposed to return.""" 652 if self.uri() is None: 653 raise pyxb.LogicError('Illegal to serialize absent namespaces') 654 return (self.uri(),)
655
656 - def __new__ (cls, *args, **kw):
657 """Pickling and singleton support. 658 659 This ensures that no more than one Namespace instance exists 660 for any given URI. We could do this up in __init__, but that 661 doesn't normally get called when unpickling instances; this 662 does. See also __getnewargs__().""" 663 (uri,) = args 664 if not (uri in cls.__Registry): 665 instance = object.__new__(cls) 666 # Do this one step of __init__ so we can do checks during unpickling 667 instance.__uri = uri 668 instance._reset() 669 # Absent namespaces are not stored in the registry. 670 if uri is None: 671 cls.__AbsentNamespaces.add(instance) 672 return instance 673 cls.__Registry[uri] = instance 674 return cls.__Registry[uri]
675 676 @classmethod
677 - def AvailableNamespaces (cls):
678 """Return a set of all Namespace instances defined so far.""" 679 return cls.__AbsentNamespaces.union(cls.__Registry.values())
680
681 - def __init__ (self, uri, 682 description=None, 683 builtin_namespace=None, 684 builtin_module_path=None, 685 is_undeclared_namespace=False, 686 is_loaded_namespace=False, 687 bound_prefix=None, 688 default_namespace=None, 689 in_scope_namespaces=None):
690 """Create a new Namespace. 691 692 The URI must be non-None, and must not already be assigned to 693 a Namespace instance. See NamespaceForURI(). 694 695 User-created Namespace instances may also provide a description. 696 697 Users should never provide a builtin_namespace parameter. 698 """ 699 700 # New-style superclass invocation 701 super(Namespace, self).__init__() 702 703 self.__contextDefaultNamespace = default_namespace 704 self.__contextInScopeNamespaces = in_scope_namespaces 705 706 # Make sure that we're not trying to do something restricted to 707 # built-in namespaces 708 is_builtin_namespace = not (builtin_namespace is None) 709 if not is_builtin_namespace: 710 if bound_prefix is not None: 711 raise pyxb.LogicError('Only permanent Namespaces may have bound prefixes') 712 713 # We actually set the uri when this instance was allocated; 714 # see __new__(). 715 assert self.__uri == uri 716 self.__boundPrefix = bound_prefix 717 self.__description = description 718 self.__isBuiltinNamespace = is_builtin_namespace 719 self.__builtinNamespaceVariable = builtin_namespace 720 self.__builtinModulePath = builtin_module_path 721 self.__isUndeclaredNamespace = is_undeclared_namespace 722 self.__isLoadedNamespace = is_loaded_namespace 723 724 self._reset() 725 726 assert (self.__uri is None) or (self.__Registry[self.__uri] == self)
727
728 - def _reset (self):
729 assert not self.isActive() 730 getattr(super(Namespace, self), '_reset', lambda *args, **kw: None)() 731 self.__initialNamespaceContext = None
732
733 - def uri (self):
734 """Return the URI for the namespace represented by this instance. 735 736 If the URI is None, this is an absent namespace, used to hold 737 declarations not associated with a namespace (e.g., from schema with 738 no target namespace).""" 739 return self.__uri
740
741 - def setPrefix (self, prefix):
742 if self.__boundPrefix is not None: 743 if self.__boundPrefix == prefix: 744 return self 745 raise pyxb.NamespaceError(self, 'Cannot change the prefix of a bound namespace') 746 self.__prefix = prefix 747 return self
748
749 - def prefix (self):
750 if self.__boundPrefix: 751 return self.__boundPrefix 752 return self.__prefix
753
754 - def isAbsentNamespace (self):
755 """Return True iff this namespace is an absent namespace. 756 757 Absent namespaces have no namespace URI; they exist only to 758 hold components created from schemas with no target 759 namespace.""" 760 return self.__uri is None
761
762 - def fallbackNamespace (self):
763 """When known to be operating in this namespace, provide the Namespace 764 instance to be used when names are associated with no namespace.""" 765 if self.isAbsentNamespace(): 766 return self 767 return None
768 769 @classmethod
770 - def CreateAbsentNamespace (cls):
771 """Create an absent namespace. 772 773 Use this instead of the standard constructor, in case we need 774 to augment it with a uuid or the like.""" 775 rv = Namespace(None) 776 rv.__absentNamespaceID = cls.__absentNamespaceID 777 cls.__absentNamespaceID += 1 778 779 return rv
780
781 - def _overrideAbsentNamespace (self, uri):
782 assert self.isAbsentNamespace() 783 self.__uri = uri
784
785 - def boundPrefix (self):
786 """Return the standard prefix to be used for this namespace. 787 788 Only a few namespace prefixes are bound to namespaces: xml and xmlns 789 are two. In all other cases, this method should return None. The 790 infrastructure attempts to prevent user creation of Namespace 791 instances that have bound prefixes.""" 792 return self.__boundPrefix
793
794 - def isBuiltinNamespace (self):
795 """Return True iff this namespace was defined by the infrastructure. 796 797 That is the case for all namespaces in the Namespace module.""" 798 return self.__isBuiltinNamespace
799
801 assert self.__builtinNamespaceVariable is not None 802 return 'pyxb.namespace.%s' % (self.__builtinNamespaceVariable,)
803
804 - def builtinModulePath (self):
805 if not self.__builtinModulePath: 806 raise pyxb.LogicError('Namespace has no built-in module: %s' % (self,)) 807 mr = self.lookupModuleRecordByUID(BuiltInObjectUID) 808 assert mr is not None 809 assert mr.modulePath() == self.__builtinModulePath 810 return self.__builtinModulePath
811
812 - def isUndeclaredNamespace (self):
813 """Return True iff this namespace is always available 814 regardless of whether there is a declaration for it. 815 816 This is the case only for the 817 xml(http://www.w3.org/XML/1998/namespace) and 818 xmlns(http://www.w3.org/2000/xmlns/) namespaces.""" 819 return self.__isUndeclaredNamespace
820
821 - def isLoadedNamespace (self):
822 """Return C{True} iff this namespace was loaded from a namespace archive.""" 823 return self.__isLoadedNamespace
824
825 - def hasBeenArchived (self):
826 """Return C{True} iff this namespace has been saved to a namespace archive. 827 See also L{isLoadedNamespace}.""" 828 return self.__hasBeenArchived
829
830 - def description (self, description=None):
831 """Get, or set, a textual description of the namespace.""" 832 if description is not None: 833 self.__description = description 834 return self.__description
835
836 - def nodeIsNamed (self, node, *local_names):
837 return (node.namespaceURI == self.uri()) and (node.localName in local_names)
838
839 - def createExpandedName (self, local_name):
840 return ExpandedName(self, local_name)
841
842 - def __getstate__ (self):
843 """Support pickling. 844 845 Well, no, not really. Because namespace instances must be unique, we 846 represent them as their URI, and that's done by __getnewargs__ 847 above. All the interesting information is in the ModuleRecords.""" 848 return {}
849
850 - def _defineBuiltins_ox (self, structures_module):
851 pass
852 853 __definedBuiltins = False
854 - def _defineBuiltins (self, structures_module):
855 assert self.isBuiltinNamespace() 856 if not self.__definedBuiltins: 857 mr = self.lookupModuleRecordByUID(BuiltInObjectUID, create_if_missing=True, module_path=self.__builtinModulePath) 858 self._defineBuiltins_ox(structures_module) 859 self.__definedBuiltins = True 860 mr.markIncorporated() 861 return self
862
863 - def _loadComponentsFromArchives (self, structures_module):
864 """Attempts to load the named objects held in this namespace. 865 866 The base class implementation looks at the set of available archived 867 namespaces, and if one contains this namespace unserializes its named 868 object maps. 869 870 Sub-classes may choose to look elsewhere, if this version fails or 871 before attempting it. 872 873 There is no guarantee that any particular category of named object has 874 been located when this returns. Caller must check. 875 """ 876 for mr in self.moduleRecords(): 877 if mr.isLoadable(): 878 if mr.isPublic(): 879 print 'Load %s from %s' % (mr, mr.archive()) 880 try: 881 mr.archive().readNamespaces() 882 except pyxb.NamespaceArchiveError, e: 883 print e 884 else: 885 print 'Ignoring private module %s in validation' % (mr,) 886 self._activate()
887 888 __didValidation = False 889 __inValidation = False
890 - def validateComponentModel (self, structures_module=None):
891 """Ensure this namespace is ready for use. 892 893 If the namespace does not have a map of named objects, the system will 894 attempt to load one. 895 """ 896 if not self.__didValidation: 897 # assert not self.__inValidation, 'Nested validation of %s' % (self.uri(),) 898 if structures_module is None: 899 import pyxb.xmlschema.structures as structures_module 900 if self.isBuiltinNamespace(): 901 self._defineBuiltins(structures_module) 902 try: 903 self.__inValidation = True 904 self._loadComponentsFromArchives(structures_module) 905 self.__didValidation = True 906 finally: 907 self.__inValidation = False 908 return True
909
910 - def _replaceComponent (self, existing_def, replacement_def):
911 """Replace the existing definition with another. 912 913 This is used in a situation where building the component model 914 resulted in a new component instance being created and registered, but 915 for which an existing component is to be preferred. An example is 916 when parsing the schema for XMLSchema itself: the built-in datatype 917 components should be retained instead of the simple type definition 918 components dynamically created from the schema. 919 920 By providing the value C{None} as the replacement definition, this can 921 also be used to remove components. 922 923 @note: Invoking this requires scans of every item in every category 924 map in the namespace. 925 926 @return: C{replacement_def} 927 """ 928 # We need to do replacements in the category map handler, the 929 # resolver, and the component associator. 930 return self._replaceComponent_csc(existing_def, replacement_def)
931
932 - def initialNamespaceContext (self):
933 """Obtain the namespace context to be used when creating components in this namespace. 934 935 Usually applies only to built-in namespaces, but is also used in the 936 autotests when creating a namespace without a xs:schema element. . 937 Note that we must create the instance dynamically, since the 938 information that goes into it has cross-dependencies that can't be 939 resolved until this module has been completely loaded.""" 940 941 if self.__initialNamespaceContext is None: 942 isn = { } 943 if self.__contextInScopeNamespaces is not None: 944 for (k, v) in self.__contextInScopeNamespaces.items(): 945 isn[k] = self.__identifyNamespace(v) 946 kw = { 'target_namespace' : self 947 , 'default_namespace' : self.__identifyNamespace(self.__contextDefaultNamespace) 948 , 'in_scope_namespaces' : isn } 949 self.__initialNamespaceContext = resolution.NamespaceContext(None, **kw) 950 return self.__initialNamespaceContext
951 952
953 - def __identifyNamespace (self, nsval):
954 """Identify the specified namespace, which should be a built-in. 955 956 Normally we can just use a reference to the Namespace module instance, 957 but when creating those instances we sometimes need to refer to ones 958 for which the instance has not yet been created. In that case, we use 959 the name of the instance, and resolve the namespace when we need to 960 create the initial context.""" 961 if nsval is None: 962 return self 963 if isinstance(nsval, (str, unicode)): 964 nsval = globals().get(nsval) 965 if isinstance(nsval, Namespace): 966 return nsval 967 raise pyxb.LogicError('Cannot identify namespace from %s' % (nsval,))
968
969 - def __str__ (self):
970 if self.__uri is None: 971 return 'AbsentNamespace%d' % (self.__absentNamespaceID,) 972 assert self.__uri is not None 973 if self.__boundPrefix is not None: 974 rv = '%s=%s' % (self.__boundPrefix, self.__uri) 975 else: 976 rv = self.__uri 977 return rv
978 979 from builtin import * 980 981 resolution.NamespaceContext._AddTargetNamespaceAttribute(XMLSchema.createExpandedName('schema'), ExpandedName('targetNamespace')) 982 983 ## Local Variables: 984 ## fill-column:78 985 ## End: 986