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

Source Code for Package pyxb.namespace

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