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

# Source Code for Module pyxb.namespace.builtin

      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 built-in U{XML Namespaces<http://www.w3.org/TR/2006/REC-xml-names-20060816/index.html>}."""
     17
     18  import pyxb
     19  import logging
     20
     21  _log = logging.getLogger(__name__)
     22
     23  # A unique identifier for components that are built-in to the PyXB system
     24  BuiltInObjectUID = pyxb.utils.utility.UniqueIdentifier('PyXB-' + pyxb.__version__ + '-Builtin')
     25
     26  from pyxb.namespace import Namespace
     27
     28 -class _XMLSchema_instance (Namespace):
     29      """Extension of L{Namespace} that pre-defines components available in the
     30      XMLSchema Instance namespace."""
     31
     32      PT_strict = 'strict'
     33      """xsi:type is validated and supersedes the declared type.  If no xsi:type is
     34      present, the declared element type will be used.  If xsi:type is
     35      present, it must resolve to valid type.  The resolved type must be
     36      a subclass of the declared type (if available), and will be used
     37      for the binding."""
     38
     39      PT_lax = 'lax'
     40      """xsi:type supersedes the declared type without validation.  If
     41      no xsi:type is present, or it is present and fails to resolve to a
     42      type, the declared element type will be used.  If xsi:type is
     43      present and resolves to valid type, that type will be used for the
     44      binding, even if it is not a subclass of the declared type."""
     45
     46      PT_skip = 'skip'
     47      """xsi:type attributes are ignored.  The declared element type
     48      will be used."""
     49
     50      __processType = PT_strict
     51
     52      type = None
     53      """An expanded name for {http://www.w3.org/2001/XMLSchema-instance}type."""
     54
     55      nil = None
     56      """An expanded name for {http://www.w3.org/2001/XMLSchema-instance}nil."""
     57
     58 -    def __init__ (self, *args, **kw):
     59          super(_XMLSchema_instance, self).__init__(*args, **kw)
     60          self.type = self.createExpandedName('type')
     61          self.nil = self.createExpandedName('nil')
     62
     63      # NB: Because Namespace instances are singletons, I've made this
     64      # is an instance method even though it looks and behaves like a
     65      # class method.
     66 -    def ProcessTypeAttribute (self, value=None):
     67          """Specify how PyXB should interpret U{xsi:type
     68          <http://www.w3.org/TR/xmlschema-1/#xsi_type>} attributes when
     69          converting a document to a binding instance.
     70
     71          The default value is L{PT_strict}.
     72
     73          xsi:type should only be provided when using an abstract class,
     74          or a concrete class that happens to be the same as the
     75          xsi:type value, or when accepting a wildcard that has an
     76          unrecognized element name.  In practice, web services tend to
     77          set it on nodes just to inform their lax-processing clients
     78          how to interpret the value.
     79
     80          @param value: One of L{PT_strict}, L{PT_lax}, L{PT_skip}, or C{None} (no change)
     81          @return: The current configuration for processing xsi:type attributes
     82          """
     83
     84          if value in (self.PT_strict, self.PT_lax, self.PT_skip):
     85              self.__processType = value
     86          elif value is not None:
     87              raise pyxb.ValueError(value)
     88          return self.__processType
     89
     90 -    def _InterpretTypeAttribute (self, type_name, ns_ctx, fallback_namespace, type_class):
     91          """Interpret the value of an xsi:type attribute as configured
     92          by L{ProcessTypeAttribute}.
     93
     94          @param type_name: The QName value from U{xsi:type
     95          <http://www.w3.org/TR/xmlschema-1/#xsi_type>}.  If this is
     96          C{None}, C{type_class} is used as C{ret_type_class}.
     97
     98          @param ns_ctx: The NamespaceContext within which C{type_name}
     99          should be resolved
    100
    101          @param fallback_namespace: The namespace that should be used
    102          if C{type_name} has no prefix
    103
    104          @param type_class: The value to return if C{type_name} is
    105          missing or acceptably invalid (viz., due to L{PT_skip})
    106
    107          @return: A tuple C{(did_replace, ret_type_class)} where
    108          C{did_replace} is C{True} iff the C{ret_type_class} is not the
    109          same as C{type_class}, and C{ret_type_class} is the class that
    110          should be used.
    111
    112          @raises pyxb.BadDocumentError: if the processing type
    113          configuration is L{PT_strict} and C{type_name} fails to
    114          resolve to a type definition that is consistent with any
    115          provided C{type_class}.
    116          """
    117          did_replace = False
    118          if type_name is None:
    119              return (did_replace, type_class)
    120          pt = self.__processType
    121          if self.PT_skip == pt:
    122              return (did_replace, type_class)
    123          type_en = ns_ctx.interpretQName(type_name, namespace=fallback_namespace)
    124          try:
    125              alternative_type_class = type_en.typeBinding()
    126          except KeyError:
    127              alternative_type_class = None
    128          if self.PT_strict == pt:
    129              if alternative_type_class is None:
    130                  raise pyxb.BadDocumentError('No type binding for %s' % (type_name,))
    131              if (type_class is not None) and (not (type_class._IsUrType() or issubclass(alternative_type_class, type_class))):
    132                  raise pyxb.BadDocumentError('%s value %s is not subclass of element type %s' % (type_name, type_en, type_class._ExpandedName))
    133          if (self.PT_strict == pt) or ((self.PT_lax == pt) and (alternative_type_class is not None)):
    134              type_class = alternative_type_class
    135              did_replace = True
    136          return (did_replace, type_class)
    137
    138 -    def _defineBuiltins_ox (self, structures_module):
    139          """Ensure this namespace is ready for use.
    140
    141          Overrides base class implementation, since there is no schema
    142          for this namespace. """
    143
    144          assert structures_module is not None
    145          schema = structures_module.Schema(namespace_context=self.initialNamespaceContext(), schema_location="URN:noLocation:PyXB:xsi", generation_uid=BuiltInObjectUID, _bypass_preload=True)
    146          schema._addNamedComponent(structures_module.AttributeDeclaration.CreateBaseInstance('type', schema))
    147          schema._addNamedComponent(structures_module.AttributeDeclaration.CreateBaseInstance('nil', schema))
    148          schema._addNamedComponent(structures_module.AttributeDeclaration.CreateBaseInstance('schemaLocation', schema))
    149          schema._addNamedComponent(structures_module.AttributeDeclaration.CreateBaseInstance('noNamespaceSchemaLocation', schema))
    150          return self
    151
    152 -class _XML (Namespace):
    153      """Extension of L{Namespace} that pre-defines components available in the
    154      XML (xml) namespace.  Specifically those are the attribute declarations:
    155
    156        - C{xml:space}
    157        - C{xml:lang}
    158        - C{xml:base}
    159        - C{xml:id}
    160
    161      the encompassing attribute group declaration:
    162
    163        - C{xml:specialAttrs}
    164
    165      and the anonymous types that support these."""
    166
    167 -    def _defineBuiltins_ox (self, structures_module):
    168          """Ensure this namespace is ready for use.
    169
    170          Overrides base class implementation, since there is no schema
    171          for this namespace. """
    172
    173          assert structures_module is not None
    174          import pyxb.binding.datatypes as xsd
    175          from pyxb.namespace import archive
    176
    177          self.configureCategories([archive.NamespaceArchive._AnonymousCategory()])
    178
    179          schema = structures_module.Schema(namespace_context=self.initialNamespaceContext(), schema_location="URN:noLocation:PyXB:XML", generation_uid=BuiltInObjectUID, _bypass_preload=True)
    180
    181          std_space = structures_module.SimpleTypeDefinition._CreateXMLInstance('space', schema)
    182          std_space._setAnonymousName(self, anon_name='STD_ANON_space')
    183          std_space._setBindingNamespace(self)
    184          std_lang = structures_module.SimpleTypeDefinition._CreateXMLInstance('lang', schema)
    185          std_lang._setAnonymousName(self, anon_name='STD_ANON_lang')
    186          std_lang._setBindingNamespace(self)
    187
    188          base = schema._addNamedComponent(structures_module.AttributeDeclaration.CreateBaseInstance('base', schema, std=xsd.anyURI.SimpleTypeDefinition()))
    189          id = schema._addNamedComponent(structures_module.AttributeDeclaration.CreateBaseInstance('id', schema, std=xsd.ID.SimpleTypeDefinition()))
    190          space = schema._addNamedComponent(structures_module.AttributeDeclaration.CreateBaseInstance('space', schema, std=std_space))
    191          lang = schema._addNamedComponent(structures_module.AttributeDeclaration.CreateBaseInstance('lang', schema, std=std_lang))
    192
    193          schema._addNamedComponent(structures_module.AttributeGroupDefinition.CreateBaseInstance('specialAttrs', schema, [
    194                      structures_module.AttributeUse.CreateBaseInstance(schema, space),
    195                      structures_module.AttributeUse.CreateBaseInstance(schema, base),
    196                      structures_module.AttributeUse.CreateBaseInstance(schema, lang),
    197                      structures_module.AttributeUse.CreateBaseInstance(schema, id),
    198                      ]))
    199
    200          return self
    201
    202 -class _XMLSchema (Namespace):
    203      """Extension of L{Namespace} that pre-defines components available in the
    204      XMLSchema namespace.
    205
    206      The types are defined when L{pyxb.xmlschema.structures} is imported.
    207      """
    208
    209 -    def _defineBuiltins_ox (self, structures_module):
    210          """Register the built-in types into the XMLSchema namespace."""
    211
    212          # Defer the definitions to the structures module
    213          assert structures_module is not None
    214          structures_module._AddSimpleTypes(self)
    215
    216          # A little validation here
    217          assert structures_module.ComplexTypeDefinition.UrTypeDefinition() == self.typeDefinitions()['anyType']
    218          assert structures_module.SimpleTypeDefinition.SimpleUrTypeDefinition() == self.typeDefinitions()['anySimpleType']
    219
    220          # Provide access to the binding classes
    221          self.configureCategories(['typeBinding', 'elementBinding'])
    222          for ( en, td ) in self.typeDefinitions().iteritems():
    223              if td.pythonSupport() is not None:
    224                  self.addCategoryObject('typeBinding', en, td.pythonSupport())
    225
    226  XMLSchema_instance = _XMLSchema_instance('http://www.w3.org/2001/XMLSchema-instance',
    227                                           description='XML Schema Instance',
    228                                           builtin_namespace='XMLSchema_instance')
    229  """Namespace and URI for the XMLSchema Instance namespace.  This is always
    230  built-in, and does not (cannot) have an associated schema."""
    231
    232  XMLNamespaces = Namespace('http://www.w3.org/2000/xmlns/',
    233                            description='Namespaces in XML',
    234                            builtin_namespace='XMLNamespaces',
    235                            is_undeclared_namespace=True,
    236                            bound_prefix='xmlns')
    237  """Namespaces in XML.  Not really a namespace, but is always available as C{xmlns}."""
    238
    239  # http://www.w3.org/2001/XMLSchema.xsd
    240  XMLSchema = _XMLSchema('http://www.w3.org/2001/XMLSchema',
    241                         description='XML Schema',
    242                         builtin_namespace='XMLSchema',
    243                         builtin_module_path='pyxb.binding.datatypes',
    244                         in_scope_namespaces = { 'xs' : None })
    245  """Namespace and URI for the XMLSchema namespace (often C{xs}, or C{xsd})"""
    246
    247  # http://www.w3.org/1999/xhtml.xsd
    248  XHTML = Namespace('http://www.w3.org/1999/xhtml',
    249                    description='Family of document types that extend HTML',
    250                    builtin_namespace='XHTML',
    251                    default_namespace=XMLSchema)
    252  """There really isn't a schema for this, but it's used as the default
    253  namespace in the XML schema, so define it."""
    254
    255  # http://www.w3.org/2001/xml.xsd
    256  XML = _XML('http://www.w3.org/XML/1998/namespace',
    257             description='XML namespace',
    258             builtin_namespace='XML',
    259             builtin_module_path='pyxb.binding.xml_',
    260             is_undeclared_namespace=True,
    261             bound_prefix='xml',
    262             default_namespace=XHTML,
    263             in_scope_namespaces = { 'xs' : XMLSchema })
    264  """Namespace and URI for XML itself (always available as C{xml})"""
    265
    266  # http://www.w3.org/2001/XMLSchema-hasFacetAndProperty
    267  XMLSchema_hfp = Namespace('http://www.w3.org/2001/XMLSchema-hasFacetAndProperty',
    268                            description='Facets appearing in appinfo section',
    269                            builtin_namespace='XMLSchema_hfp',
    270                            default_namespace=XMLSchema,
    271                            in_scope_namespaces = { 'hfp' : None
    272                                                  , 'xhtml' : XHTML })
    273  """Elements appearing in appinfo elements to support data types."""
    274
    275  # List of built-in namespaces.
    276  BuiltInNamespaces = [
    277    XMLSchema_instance,
    278    XMLSchema_hfp,
    279    XMLSchema,
    280    XMLNamespaces,
    281    XML,
    282    XHTML
    283  ]
    284
    285  __InitializedBuiltinNamespaces = False
    286
    287 -def _InitializeBuiltinNamespaces (structures_module):
    288      """Invoked at the end of the L{pyxb.xmlschema.structures} module to
    289      initialize the component models of the built-in namespaces.
    290
    291      @param structures_module: The L{pyxb.xmlschema.structures} module may not
    292      be importable by that name at the time this is invoked (because it is
    293      still being processed), so it gets passed in as a parameter."""
    294      global __InitializedBuiltinNamespaces
    295      if not __InitializedBuiltinNamespaces:
    296          __InitializedBuiltinNamespaces = True
    297          [ _ns._defineBuiltins(structures_module) for _ns in BuiltInNamespaces ]
    298
    299  # Set up the prefixes for xml, xmlns, etc.
    300  _UndeclaredNamespaceMap = { }
    301  [ _UndeclaredNamespaceMap.setdefault(_ns.boundPrefix(), _ns) for _ns in BuiltInNamespaces if _ns.isUndeclaredNamespace() ]
    302