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