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

Source Code for Package pyxb.namespace

   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 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)
656
657 - def __getnewargs__ (self):
658 """Pickling support. 659 660 To ensure that unpickled Namespace instances are unique per 661 URI, we ensure that the routine that creates unpickled 662 instances knows what it's supposed to return.""" 663 if self.uri() is None: 664 raise pyxb.LogicError('Illegal to serialize absent namespaces') 665 return (self.uri(),)
666
667 - def __new__ (cls, *args, **kw):
668 """Pickling and singleton support. 669 670 This ensures that no more than one Namespace instance exists 671 for any given URI. We could do this up in __init__, but that 672 doesn't normally get called when unpickling instances; this 673 does. See also __getnewargs__().""" 674 (uri,) = args 675 if not (uri in cls.__Registry): 676 instance = object.__new__(cls) 677 # Do this one step of __init__ so we can do checks during unpickling 678 instance.__uri = uri 679 instance._reset() 680 # Absent namespaces are not stored in the registry. 681 if uri is None: 682 cls.__AbsentNamespaces.add(instance) 683 return instance 684 cls.__Registry[uri] = instance 685 return cls.__Registry[uri]
686 687 @classmethod
688 - def AvailableNamespaces (cls):
689 """Return a set of all Namespace instances defined so far.""" 690 return cls.__AbsentNamespaces.union(cls.__Registry.values())
691
692 - def __init__ (self, uri, 693 description=None, 694 builtin_namespace=None, 695 builtin_module_path=None, 696 is_undeclared_namespace=False, 697 is_loaded_namespace=False, 698 bound_prefix=None, 699 default_namespace=None, 700 in_scope_namespaces=None):
701 """Create a new Namespace. 702 703 The URI must be non-None, and must not already be assigned to 704 a Namespace instance. See _NamespaceForURI(). 705 706 User-created Namespace instances may also provide a description. 707 708 Users should never provide a builtin_namespace parameter. 709 """ 710 711 # New-style superclass invocation 712 super(Namespace, self).__init__() 713 714 self.__contextDefaultNamespace = default_namespace 715 self.__contextInScopeNamespaces = in_scope_namespaces 716 717 # Make sure that we're not trying to do something restricted to 718 # built-in namespaces 719 is_builtin_namespace = not (builtin_namespace is None) 720 if not is_builtin_namespace: 721 if bound_prefix is not None: 722 raise pyxb.LogicError('Only permanent Namespaces may have bound prefixes') 723 724 # We actually set the uri when this instance was allocated; 725 # see __new__(). 726 assert self.__uri == uri 727 self.__boundPrefix = bound_prefix 728 self.__description = description 729 self.__isBuiltinNamespace = is_builtin_namespace 730 self.__builtinNamespaceVariable = builtin_namespace 731 self.__builtinModulePath = builtin_module_path 732 self.__isUndeclaredNamespace = is_undeclared_namespace 733 self.__isLoadedNamespace = is_loaded_namespace 734 735 self._reset() 736 737 assert (self.__uri is None) or (self.__Registry[self.__uri] == self)
738
739 - def _reset (self):
740 assert not self.isActive() 741 getattr(super(Namespace, self), '_reset', lambda *args, **kw: None)() 742 self.__initialNamespaceContext = None
743
744 - def uri (self):
745 """Return the URI for the namespace represented by this instance. 746 747 If the URI is None, this is an absent namespace, used to hold 748 declarations not associated with a namespace (e.g., from schema with 749 no target namespace).""" 750 return self.__uri
751
752 - def setPrefix (self, prefix):
753 if self.__boundPrefix is not None: 754 if self.__boundPrefix == prefix: 755 return self 756 raise pyxb.NamespaceError(self, 'Cannot change the prefix of a bound namespace') 757 self.__prefix = prefix 758 return self
759
760 - def prefix (self):
761 if self.__boundPrefix: 762 return self.__boundPrefix 763 return self.__prefix
764
765 - def isAbsentNamespace (self):
766 """Return True iff this namespace is an absent namespace. 767 768 Absent namespaces have no namespace URI; they exist only to 769 hold components created from schemas with no target 770 namespace.""" 771 return self.__uri is None
772
773 - def fallbackNamespace (self):
774 """When known to be operating in this namespace, provide the Namespace 775 instance to be used when names are associated with no namespace.""" 776 if self.isAbsentNamespace(): 777 return self 778 return None
779 780 @classmethod
781 - def CreateAbsentNamespace (cls):
782 """Create an absent namespace. 783 784 Use this instead of the standard constructor, in case we need 785 to augment it with a uuid or the like.""" 786 rv = Namespace(None) 787 rv.__absentNamespaceID = cls.__absentNamespaceID 788 cls.__absentNamespaceID += 1 789 790 return rv
791
792 - def _overrideAbsentNamespace (self, uri):
793 assert self.isAbsentNamespace() 794 self.__uri = uri
795
796 - def boundPrefix (self):
797 """Return the standard prefix to be used for this namespace. 798 799 Only a few namespace prefixes are bound to namespaces: xml and xmlns 800 are two. In all other cases, this method should return None. The 801 infrastructure attempts to prevent user creation of Namespace 802 instances that have bound prefixes.""" 803 return self.__boundPrefix
804
805 - def isBuiltinNamespace (self):
806 """Return True iff this namespace was defined by the infrastructure. 807 808 That is the case for all namespaces in the Namespace module.""" 809 return self.__isBuiltinNamespace
810
812 assert self.__builtinNamespaceVariable is not None 813 return 'pyxb.namespace.%s' % (self.__builtinNamespaceVariable,)
814
815 - def builtinModulePath (self):
816 from pyxb.namespace import builtin 817 if not self.__builtinModulePath: 818 raise pyxb.LogicError('Namespace has no built-in module: %s' % (self,)) 819 mr = self.lookupModuleRecordByUID(builtin.BuiltInObjectUID) 820 assert mr is not None 821 assert mr.modulePath() == self.__builtinModulePath 822 return self.__builtinModulePath
823
824 - def isUndeclaredNamespace (self):
825 """Return True iff this namespace is always available 826 regardless of whether there is a declaration for it. 827 828 This is the case only for the 829 xml(http://www.w3.org/XML/1998/namespace) and 830 xmlns(http://www.w3.org/2000/xmlns/) namespaces.""" 831 return self.__isUndeclaredNamespace
832
833 - def isLoadedNamespace (self):
834 """Return C{True} iff this namespace was loaded from a namespace archive.""" 835 return self.__isLoadedNamespace
836
837 - def hasBeenArchived (self):
838 """Return C{True} iff this namespace has been saved to a namespace archive. 839 See also L{isLoadedNamespace}.""" 840 return self.__hasBeenArchived
841
842 - def description (self, description=None):
843 """Get, or set, a textual description of the namespace.""" 844 if description is not None: 845 self.__description = description 846 return self.__description
847
848 - def nodeIsNamed (self, node, *local_names):
849 return (node.namespaceURI == self.uri()) and (node.localName in local_names)
850
851 - def createExpandedName (self, local_name):
852 return ExpandedName(self, local_name)
853
854 - def __getstate__ (self):
855 """Support pickling. 856 857 Well, no, not really. Because namespace instances must be unique, we 858 represent them as their URI, and that's done by __getnewargs__ 859 above. All the interesting information is in the ModuleRecords.""" 860 return {}
861
862 - def _defineBuiltins_ox (self, structures_module):
863 pass
864 865 __definedBuiltins = False
866 - def _defineBuiltins (self, structures_module):
867 assert self.isBuiltinNamespace() 868 if not self.__definedBuiltins: 869 from pyxb.namespace import builtin 870 mr = self.lookupModuleRecordByUID(builtin.BuiltInObjectUID, create_if_missing=True, module_path=self.__builtinModulePath) 871 self._defineBuiltins_ox(structures_module) 872 self.__definedBuiltins = True 873 mr.markIncorporated() 874 return self
875
876 - def _loadComponentsFromArchives (self, structures_module):
877 """Attempts to load the named objects held in this namespace. 878 879 The base class implementation looks at the set of available archived 880 namespaces, and if one contains this namespace unserializes its named 881 object maps. 882 883 Sub-classes may choose to look elsewhere, if this version fails or 884 before attempting it. 885 886 There is no guarantee that any particular category of named object has 887 been located when this returns. Caller must check. 888 """ 889 for mr in self.moduleRecords(): 890 if mr.isLoadable(): 891 if mr.isPublic(): 892 _log.info('Load %s from %s', mr, mr.archive()) 893 try: 894 mr.archive().readNamespaces() 895 except pyxb.NamespaceArchiveError as e: 896 _log.exception("Failure reading namespaces in archive") 897 else: 898 _log.info('Ignoring private module %s in validation', mr) 899 self._activate()
900 901 __didValidation = False 902 __inValidation = False
903 - def validateComponentModel (self, structures_module=None):
904 """Ensure this namespace is ready for use. 905 906 If the namespace does not have a map of named objects, the system will 907 attempt to load one. 908 """ 909 if not self.__didValidation: 910 # assert not self.__inValidation, 'Nested validation of %s' % (self.uri(),) 911 if structures_module is None: 912 import pyxb.xmlschema.structures as structures_module 913 if self.isBuiltinNamespace(): 914 self._defineBuiltins(structures_module) 915 try: 916 self.__inValidation = True 917 self._loadComponentsFromArchives(structures_module) 918 self.__didValidation = True 919 finally: 920 self.__inValidation = False 921 return True
922
923 - def _replaceComponent (self, existing_def, replacement_def):
924 """Replace the existing definition with another. 925 926 This is used in a situation where building the component model 927 resulted in a new component instance being created and registered, but 928 for which an existing component is to be preferred. An example is 929 when parsing the schema for XMLSchema itself: the built-in datatype 930 components should be retained instead of the simple type definition 931 components dynamically created from the schema. 932 933 By providing the value C{None} as the replacement definition, this can 934 also be used to remove components. 935 936 @note: Invoking this requires scans of every item in every category 937 map in the namespace. 938 939 @return: C{replacement_def} 940 """ 941 # We need to do replacements in the category map handler, the 942 # resolver, and the component associator. 943 return self._replaceComponent_csc(existing_def, replacement_def)
944
945 - def initialNamespaceContext (self):
946 """Obtain the namespace context to be used when creating components in this namespace. 947 948 Usually applies only to built-in namespaces, but is also used in the 949 autotests when creating a namespace without a xs:schema element. . 950 Note that we must create the instance dynamically, since the 951 information that goes into it has cross-dependencies that can't be 952 resolved until this module has been completely loaded.""" 953 954 if self.__initialNamespaceContext is None: 955 isn = { } 956 if self.__contextInScopeNamespaces is not None: 957 for (k, v) in self.__contextInScopeNamespaces.items(): 958 isn[k] = self.__identifyNamespace(v) 959 kw = { 'target_namespace' : self 960 , 'default_namespace' : self.__identifyNamespace(self.__contextDefaultNamespace) 961 , 'in_scope_namespaces' : isn } 962 self.__initialNamespaceContext = resolution.NamespaceContext(None, **kw) 963 return self.__initialNamespaceContext
964 965
966 - def __identifyNamespace (self, nsval):
967 """Identify the specified namespace, which should be a built-in. 968 969 Normally we can just use a reference to the Namespace module instance, 970 but when creating those instances we sometimes need to refer to ones 971 for which the instance has not yet been created. In that case, we use 972 the name of the instance, and resolve the namespace when we need to 973 create the initial context.""" 974 if nsval is None: 975 return self 976 if isinstance(nsval, (str, unicode)): 977 nsval = globals().get(nsval) 978 if isinstance(nsval, Namespace): 979 return nsval 980 raise pyxb.LogicError('Cannot identify namespace from %s' % (nsval,))
981
982 - def __str__ (self):
983 if self.__uri is None: 984 return 'AbsentNamespace%d' % (self.__absentNamespaceID,) 985 assert self.__uri is not None 986 if self.__boundPrefix is not None: 987 rv = '%s=%s' % (self.__boundPrefix, self.__uri) 988 else: 989 rv = self.__uri 990 return rv
991 992 from pyxb.namespace.builtin import XMLSchema_instance 993 from pyxb.namespace.builtin import XMLNamespaces 994 from pyxb.namespace.builtin import XMLSchema 995 from pyxb.namespace.builtin import XHTML 996 from pyxb.namespace.builtin import XML 997 from pyxb.namespace.builtin import XMLSchema_hfp 998 from pyxb.namespace.builtin import BuiltInObjectUID 999 1000 resolution.NamespaceContext._AddTargetNamespaceAttribute(XMLSchema.createExpandedName('schema'), ExpandedName('targetNamespace')) 1001 1002 ## Local Variables: 1003 ## fill-column:78 1004 ## End: 1005