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