Package pyxb :: Package binding :: Module generate |
[hide private]
[frames] | no frames]

# Source Code for Module pyxb.binding.generate

       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  """The really ugly code that generates the Python bindings.  This
      17  whole thing is going to be refactored once customized generation makes
      18  it to the top of the task queue."""
      19
      20  import pyxb
      21  import pyxb.xmlschema as xs
      22  import io
      23  import datetime
      24  import errno
      25
      26  from pyxb.utils import utility
      27  from pyxb.utils import templates
      28  from pyxb.binding import basis
      29  from pyxb.binding import datatypes
      30  from pyxb.binding import facets
      31
      32  import types
      33  import sys
      34  import os.path
      35  import logging
      36  import logging.config
      37
      38  _log = logging.getLogger(__name__)
      39
      40 -def PrefixModule (value, text=None):
      41      if text is None:
      42          text = value.__name__
      43      if value.__module__ == datatypes.__name__:
      44          return 'pyxb.binding.datatypes.%s' % (text,)
      45      if value.__module__ == facets.__name__:
      46          return 'pyxb.binding.facets.%s' % (text,)
      47      raise ValueError('No standard name for module of value', value)
      48
      49 -class ReferenceLiteral (object):
      50      """Base class for something that requires fairly complex activity
      51      in order to generate its literal value."""
      52
      53      # Either a STD or a subclass of _Enumeration_mixin, this is the
      54      # class in which the referenced object is a member.
      55      __ownerClass = None
      56
      57      # The value to be used as a literal for this object
      58      __literal = None
      59
      60 -    def __init__ (self, **kw):
      61          # NB: Pre-extend __init__
      62          self.__ownerClass = kw.get('type_definition')
      63
      64 -    def setLiteral (self, literal):
      65          self.__literal = literal
      66          return literal
      67
      68 -    def asLiteral (self):
      69          return self.__literal
      70
      71 -    def _addTypePrefix (self, text, **kw):
      72          if self.__ownerClass is not None:
      73              text = '%s.%s' % (pythonLiteral(self.__ownerClass, **kw), text)
      74          return text
      75
      76 -class ReferenceFacetMember (ReferenceLiteral):
      77      __facetClass = None
      78
      79 -    def __init__ (self, **kw):
      80          variable = kw.get('variable')
      81          assert (variable is None) or isinstance(variable, facets.Facet)
      82
      83          if variable is not None:
      84              kw.setdefault('type_definition', variable.ownerTypeDefinition())
      85              self.__facetClass = type(variable)
      86          self.__facetClass = kw.get('facet_class', self.__facetClass)
      87
      88          super(ReferenceFacetMember, self).__init__(**kw)
      89
      90          self.setLiteral(self._addTypePrefix('_CF_%s' % (self.__facetClass.Name(),), **kw))
      91
      92 -class ReferenceWildcard (ReferenceLiteral):
      93      __wildcard = None
      94
      95 -    def __init__ (self, wildcard, **kw):
      96          self.__wildcard = wildcard
      97          super(ReferenceWildcard, self).__init__(**kw)
      98
      99          template_map = { }
     100          template_map['Wildcard'] = 'pyxb.binding.content.Wildcard'
     101          if (xs.structures.Wildcard.NC_any == wildcard.namespaceConstraint()):
     102              template_map['nc'] = templates.replaceInText('%{Wildcard}.NC_any', **template_map)
     103          elif isinstance(wildcard.namespaceConstraint(), (set, frozenset)):
     104              namespaces = []
     105              for ns in wildcard.namespaceConstraint():
     106                  if ns is None:
     107                      namespaces.append(None)
     108                  else:
     109                      namespaces.append(ns.uri())
     110              template_map['nc'] = 'set([%s])' % (",".join( [ repr(_ns) for _ns in namespaces ]))
     111          else:
     112              assert isinstance(wildcard.namespaceConstraint(), tuple)
     113              ns = wildcard.namespaceConstraint()[1]
     114              if ns is not None:
     115                  ns = ns.uri()
     116              template_map['nc'] = templates.replaceInText('(%{Wildcard}.NC_not, %{namespace})', namespace=repr(ns), **template_map)
     117          template_map['pc'] = wildcard.processContents()
     118          self.setLiteral(templates.replaceInText('%{Wildcard}(process_contents=%{Wildcard}.PC_%{pc}, namespace_constraint=%{nc})', **template_map))
     119
     120 -class ReferenceSchemaComponent (ReferenceLiteral):
     121      __component = None
     122
     123 -    def __init__ (self, component, **kw):
     124          self.__component = component
     125          binding_module = kw['binding_module']
     126          super(ReferenceSchemaComponent, self).__init__(**kw)
     127          rv = binding_module.referenceSchemaComponent(component)
     128          self.setLiteral(rv)
     129
     130 -class ReferenceNamespace (ReferenceLiteral):
     131      __namespace = None
     132
     133 -    def __init__ (self, **kw):
     134          self.__namespace = kw['namespace']
     135          binding_module = kw['binding_module']
     136          super(ReferenceNamespace, self).__init__(**kw)
     137          rv = binding_module.referenceNamespace(self.__namespace)
     138          self.setLiteral(rv)
     139
     140 -class ReferenceExpandedName (ReferenceLiteral):
     141      __expandedName = None
     142
     143 -    def __init__ (self, **kw):
     144          self.__expandedName = kw['expanded_name']
     145          super(ReferenceExpandedName, self).__init__(**kw)
     146          self.setLiteral('pyxb.namespace.ExpandedName(%s, %s)' % (pythonLiteral(self.__expandedName.namespace(), **kw), pythonLiteral(self.__expandedName.localName(), **kw)))
     147
     148 -class ReferenceFacet (ReferenceLiteral):
     149      __facet = None
     150
     151 -    def __init__ (self, **kw):
     152          self.__facet = kw['facet']
     153          super(ReferenceFacet, self).__init__(**kw)
     154          self.setLiteral('%s._CF_%s' % (pythonLiteral(self.__facet.ownerTypeDefinition(), **kw), self.__facet.Name()))
     155
     156 -class ReferenceEnumerationMember (ReferenceLiteral):
     157      enumerationElement = None
     158
     159 -    def __init__ (self, **kw):
     160          # NB: Pre-extended __init__
     161
     162          # All we really need is the enumeration element, so we can get
     163          # its tag, and a type definition or datatype, so we can create
     164          # the proper prefix.
     165
     166          # See if we were given a value, from which we can extract the
     167          # other information.
     168          value = kw.get('enum_value')
     169          assert (value is None) or isinstance(value, facets._Enumeration_mixin)
     170
     171          # Must provide facet_instance, or a value from which it can be
     172          # obtained.
     173          facet_instance = kw.get('facet_instance')
     174          if facet_instance is None:
     175              assert isinstance(value, facets._Enumeration_mixin)
     176              facet_instance = value._CF_enumeration
     177          assert isinstance(facet_instance, facets.CF_enumeration)
     178
     179          # Must provide the enumeration_element, or a facet_instance
     180          # and value from which it can be identified.
     181          self.enumerationElement = kw.get('enumeration_element')
     182          if self.enumerationElement is None:
     183              assert value is not None
     184              self.enumerationElement = facet_instance.elementForValue(value)
     185          assert isinstance(self.enumerationElement, facets._EnumerationElement)
     186          assert self.enumerationElement.tag() is not None
     187
     188          # If no type definition was provided, use the value datatype
     189          # for the facet.
     190          kw.setdefault('type_definition', facet_instance.valueDatatype())
     191
     192          super(ReferenceEnumerationMember, self).__init__(**kw)
     193
     194          self.setLiteral(self._addTypePrefix(self.enumerationElement.tag(), **kw))
     195
     196 -def pythonLiteral (value, **kw):
     197      # For dictionaries, apply translation to all values (not keys)
     198      if isinstance(value, types.DictionaryType):
     199          return ', '.join([ '%s=%s' % (k, pythonLiteral(v, **kw)) for (k, v) in value.iteritems() ])
     200
     201      # For lists, apply translation to all members
     202      if isinstance(value, types.ListType):
     203          return [ pythonLiteral(_v, **kw) for _v in value ]
     204
     205      # ExpandedName is a tuple, but not here
     206      if isinstance(value, pyxb.namespace.ExpandedName):
     207          return pythonLiteral(ReferenceExpandedName(expanded_name=value, **kw))
     208
     209      # For other collection types, do what you do for list
     210      if isinstance(value, (types.TupleType, set)):
     211          return type(value)(pythonLiteral(list(value), **kw))
     212
     213      # Value is a binding value for which there should be an
     214      # enumeration constant.  Return that constant.
     215      if isinstance(value, facets._Enumeration_mixin):
     216          return pythonLiteral(ReferenceEnumerationMember(enum_value=value, **kw))
     217
     218      # Value is an instance of a Python binding, e.g. one of the
     219      # XMLSchema datatypes.  Use its value, applying the proper prefix
     220      # for the module.
     221      if isinstance(value, basis.simpleTypeDefinition):
     222          return PrefixModule(value, value.pythonLiteral())
     223
     224      if isinstance(value, pyxb.namespace.Namespace):
     225          return pythonLiteral(ReferenceNamespace(namespace=value, **kw))
     226
     227      if isinstance(value, type):
     228          if issubclass(value, basis.simpleTypeDefinition):
     229              return PrefixModule(value)
     230          if issubclass(value, facets.Facet):
     231              return PrefixModule(value)
     232
     233      # String instances go out as their representation
     234      if isinstance(value, types.StringTypes):
     235          return utility.QuotedEscaped(value,)
     236
     237      if isinstance(value, facets.Facet):
     238          return pythonLiteral(ReferenceFacet(facet=value, **kw))
     239
     240      # Treat pattern elements as their value
     241      if isinstance(value, facets._PatternElement):
     242          return pythonLiteral(value.pattern)
     243
     244      # Treat enumeration elements as their value
     245      if isinstance(value, facets._EnumerationElement):
     246          return pythonLiteral(value.value())
     247
     248      # Wildcards expand to a pyxb.binding.content.Wildcard instance
     249      if isinstance(value, xs.structures.Wildcard):
     250          return pythonLiteral(ReferenceWildcard(value, **kw))
     251
     252      # Schema components have a single name through their lifespan
     253      if isinstance(value, xs.structures._SchemaComponent_mixin):
     254          return pythonLiteral(ReferenceSchemaComponent(value, **kw))
     255
     256      # Other special cases
     257      if isinstance(value, ReferenceLiteral):
     258          return value.asLiteral()
     259
     260      # Represent namespaces by their URI
     261      if isinstance(value, pyxb.namespace.Namespace):
     262          return repr(value.uri())
     263
     264      # Standard Python types
     265      if isinstance(value, (types.NoneType, types.BooleanType, types.FloatType, types.IntType, types.LongType)):
     266          return repr(value)
     267
     268      raise Exception('Unexpected literal type %s' % (type(value),))
     269
     270 -def _GenerateAutomaton (automaton, template_map, containing_state, lines, **kw):
     271      binding_module = kw['binding_module']
     272      name = utility.PrepareIdentifier('BuildAutomaton', binding_module.uniqueInModule(), protected=True)
     273      au_src = []
     274      au_src.append(templates.replaceInText('''
     275  def %{name} ():
     276      # Remove this helper function from the namespace after it is invoked
     277      global %{name}
     278      del %{name}
     279      import pyxb.utils.fac as fac
     280  ''', name=name))
     281
     282      def stateSortKey (st):
     283          if isinstance(st.symbol, xs.structures.ModelGroup):
     284              return st.symbol.facStateSortKey()
     285          return st.symbol[0].facStateSortKey()
     286
     287      def counterConditionSortKey (cc):
     288          return cc.metadata.facStateSortKey()
     289
     290      def updateInstructionSortKey (ui):
     291          return counterConditionSortKey(ui.counterCondition)
     292
     293      def transitionSortKey (xit):
     294          # The destination of a transition is not unique; need to
     295          # differentiate using the update instructions.  Which
     296          # themselves should be sorted.
     297          st = xit.consumingState()
     298
     299          # Transitions into/out-of subautomata might not include a
     300          # consuming state.  Give those a sort value None.
     301          ssk = None
     302          if st is not None:
     303              ssk = stateSortKey(st)
     304          keys = [ ssk ]
     305          keys.extend(map(updateInstructionSortKey, sorted(xit.updateInstructions, key=updateInstructionSortKey)))
     306          return tuple(keys)
     307
     308      au_src.append('    counters = set()')
     309      counter_map = {}
     310      sorted_counter_conditions = sorted(automaton.counterConditions, key=counterConditionSortKey)
     311      for cc in sorted_counter_conditions:
     312          cc_id = 'cc_%u' % (len(counter_map),)
     313          counter_map[cc] = cc_id
     314          au_src.append('    %s = fac.CounterCondition(min=%r, max=%r, metadata=%r)' % (cc_id, cc.min, cc.max, cc.metadata._location()))
     315          au_src.append('    counters.add(%s)' % (cc_id,))
     316      state_map = {}
     317      au_src.append('    states = []')
     318      sorted_states = sorted(automaton.states, key=stateSortKey)
     319      for st in sorted_states:
     320          st_id = 'st_%u' % (len(state_map),)
     321          state_map[st] = st_id
     322          if st.subAutomata is not None:
     323              au_src.append('    sub_automata = []')
     324              for sa in st.subAutomata:
     325                  au_src.append('    sub_automata.append(%s)' % (_GenerateAutomaton(sa, template_map, st_id, lines, **kw),))
     326          if st.finalUpdate is None:
     327              au_src.append('    final_update = None')
     328          else:
     329              au_src.append('    final_update = set()')
     330              for ui in sorted(st.finalUpdate, key=updateInstructionSortKey):
     331                  au_src.append('    final_update.add(fac.UpdateInstruction(%s, %r))' % (counter_map[ui.counterCondition], ui.doIncrement))
     332          if isinstance(st.symbol, xs.structures.ModelGroup):
     333              au_src.append('    symbol = %r' % (st.symbol._location(),))
     334          else:
     335              (particle, symbol) = st.symbol
     336              if isinstance(symbol, xs.structures.Wildcard):
     337                  au_src.append(templates.replaceInText('    symbol = pyxb.binding.content.WildcardUse(%{wildcard}, %{location})', wildcard=binding_module.literal(symbol, **kw), location=repr(particle._location())))
     338              elif isinstance(symbol, xs.structures.ElementDeclaration):
     339                  binding_module.importForDeclaration(symbol)
     340                  au_src.append(templates.replaceInText('    symbol = pyxb.binding.content.ElementUse(%{ctd}._UseForTag(%{field_tag}), %{location})', field_tag=binding_module.literal(symbol.expandedName(), **kw), location=repr(particle._location()), **template_map))
     341          au_src.append('    %s = fac.State(symbol, is_initial=%r, final_update=final_update, is_unordered_catenation=%r)' % (st_id, st.isInitial, st.isUnorderedCatenation))
     342          if st.subAutomata is not None:
     343              au_src.append('    %s._set_subAutomata(*sub_automata)' % (st_id,))
     344          au_src.append('    states.append(%s)' % (st_id,))
     345      for st in sorted_states:
     346          au_src.append('    transitions = []')
     347          for xit in sorted(st.transitionSet, key=transitionSortKey):
     348              au_src.append('    transitions.append(fac.Transition(%s, [' % (state_map[xit.destination],))
     349              sorted_ui = sorted(xit.updateInstructions, key=updateInstructionSortKey)
     350              au_src.append('        %s ]))' % (',\n        '.join(map(lambda _ui: 'fac.UpdateInstruction(%s, %r)' % (counter_map[_ui.counterCondition], _ui.doIncrement), sorted_ui))))
     351          au_src.append('    %s._set_transitionSet(transitions)' % (state_map[st],))
     352      au_src.append('    return fac.Automaton(states, counters, %r, containing_state=%s)' % (automaton.nullable, containing_state))
     353      lines.extend(au_src)
     354      return '%s()' % (name,)
     355
     356 -def GenerateAutomaton (ctd, **kw):
     357      aux = _CTDAuxData.Get(ctd)
     358      binding_module = kw['binding_module']
     359      template_map = { 'ctd' : binding_module.literal(ctd, **kw) }
     360      automaton = aux.automaton
     361      if automaton is None:
     362          return None
     363      lines = []
     364      name = _GenerateAutomaton(automaton, template_map, 'None', lines, **kw)
     365      return (name, lines)
     366
     367 -def _useEnumerationTags (td):
     368      if td is None:
     369          return False
     370      assert isinstance(td, xs.structures.SimpleTypeDefinition)
     371      ptd = td.baseTypeDefinition()
     372      python_support = None
     373      # Atomic types that use strings as their representation
     374      if (ptd.VARIETY_atomic == ptd.variety()):
     375          python_support = ptd.primitiveTypeDefinition().pythonSupport()
     376          return issubclass(python_support, basestring)
     377      # Derivations from anySimpleType use strings too
     378      if (ptd.VARIETY_absent == ptd.variety()):
     379          return True
     380      # Union types?  Yeah, I suppose so.  Though this only applies to
     381      # members lifted up into the union.
     382      if (ptd.VARIETY_union == ptd.variety()):
     383          return True
     384      # List types have spaces so no tags.
     385      return False
     386
     387 -def GenerateFacets (td, generator, **kw):
     388      binding_module = kw['binding_module']
     389      outf = binding_module.bindingIO()
     390      facet_instances = []
     391      gen_enum_tag = _useEnumerationTags(td)
     392      for (fc, fi) in td.facets().iteritems():
     393          #if (fi is None) or (fi.ownerTypeDefinition() != td):
     394          #    continue
     395          if (fi is None) and (fc in td.baseTypeDefinition().facets()):
     396              # Nothing new here
     397              continue
     398          if (fi is not None) and (fi.ownerTypeDefinition() != td):
     399              # Did this one in an ancestor
     400              continue
     401          argset = { }
     402          is_collection = issubclass(fc, facets._CollectionFacet_mixin)
     403          if issubclass(fc, facets._LateDatatype_mixin):
     404              vdt = td
     405              if fc.LateDatatypeBindsSuperclass():
     406                  vdt = vdt.baseTypeDefinition()
     407              argset['value_datatype'] = vdt
     408          if fi is not None:
     409              if not is_collection:
     410                  argset['value'] = fi.value()
     411              if isinstance(fi, facets.CF_enumeration):
     412                  argset['enum_prefix'] = fi.enumPrefix()
     413          facet_var = ReferenceFacetMember(type_definition=td, facet_class=fc, **kw)
     414          outf.write("%s = %s(%s)\n" % binding_module.literal( (facet_var, fc, argset ), **kw))
     415          facet_instances.append(binding_module.literal(facet_var, **kw))
     416          if (fi is not None) and is_collection:
     417              for i in fi.iteritems():
     418                  if isinstance(i, facets._EnumerationElement):
     419                      enum_config = '%s.addEnumeration(unicode_value=%s, tag=%s)' % binding_module.literal( ( facet_var, i.unicodeValue(), i.tag() ), **kw)
     420                      if gen_enum_tag and (i.tag() is not None):
     421                          enum_member = ReferenceEnumerationMember(type_definition=td, facet_instance=fi, enumeration_element=i, **kw)
     422                          outf.write("%s = %s\n" % (binding_module.literal(enum_member, **kw), enum_config))
     423                          if fi.enumPrefix() is not None:
     424                              outf.write("%s_%s = %s\n" % (fi.enumPrefix(), i.tag(), binding_module.literal(enum_member, **kw)))
     425                      else:
     426                          outf.write("%s\n" % (enum_config,))
     427                  if isinstance(i, facets._PatternElement):
     428                      outf.write("%s.addPattern(pattern=%s)\n" % binding_module.literal( (facet_var, i.pattern ), **kw))
     429      if gen_enum_tag and (xs.structures.SimpleTypeDefinition.VARIETY_union == td.variety()):
     430          # If the union has enumerations of its own, there's no need to
     431          # inherit anything, because they supersede anything implicitly
     432          # inherited.
     433          fi = td.facets().get(facets.CF_enumeration)
     434          if fi is None:
     435              # Need to expose any enumerations in members up in this class
     436              for mtd in td.memberTypeDefinitions():
     437                  if not _useEnumerationTags(mtd):
     438                      continue
     439                  fi = mtd.facets().get(facets.CF_enumeration)
     440                  if fi is None:
     441                      continue
     442                  for i in fi.iteritems():
     443                      assert isinstance(i, facets._EnumerationElement)
     444                      etd = i.enumeration().ownerTypeDefinition()
     445                      enum_member = ReferenceEnumerationMember(type_definition=td, facet_instance=fi, enumeration_element=i, **kw)
     446                      outf.write("%-50s%s\n" % ('%s = %s' % binding_module.literal( (enum_member, i.unicodeValue()) ),
     447                                                '# originally %s.%s' % (binding_module.literal(etd), i.tag())))
     448      if 2 <= len(facet_instances):
     449          map_args = ",\n   ".join(facet_instances)
     450      else:
     451          map_args = ','.join(facet_instances)
     452      outf.write("%s._InitializeFacetMap(%s)\n" % (binding_module.literal(td, **kw), map_args))
     453
     454 -def _VCAppendAuxInit (vc_source, aux_init, binding_module, kw):
     455      if vc_source.fixed() is not None:
     456          aux_init.append('fixed=True')
     457          aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.fixed(), **kw),))
     458      elif vc_source.default() is not None:
     459          aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.default(), **kw),))
     460
     461 -def GenerateSTD (std, generator):
     462
     463      binding_module = generator.moduleForComponent(std)
     464      outf = binding_module.bindingIO()
     465
     466      class_keywords = frozenset(basis.simpleTypeDefinition._ReservedSymbols)
     467      class_unique = set()
     468
     469      kw = { }
     470      kw['binding_module'] = binding_module
     471      kw['class_keywords'] = class_keywords
     472      kw['class_unique'] = class_unique
     473
     474      parent_classes = [ binding_module.literal(std.baseTypeDefinition(), **kw) ]
     475      enum_facet = std.facets().get(facets.CF_enumeration)
     476      if (enum_facet is not None) and (enum_facet.ownerTypeDefinition() == std):
     477          parent_classes.append('pyxb.binding.basis.enumeration_mixin')
     478
     479      template_map = { }
     480      binding_name = template_map['std'] = binding_module.literal(std, **kw)
     481      if (std.expandedName() is not None) and (std.expandedName().localName() != binding_name):
     482          _log.warning('Simple type %s renamed to %s', std.expandedName(), binding_name)
     483
     484      template_map['superclasses'] = ''
     485      if 0 < len(parent_classes):
     486          template_map['superclasses'] = ', '.join(parent_classes)
     487      template_map['expanded_name'] = binding_module.literal(std.expandedName(), **kw)
     488      if std.expandedName() is not None:
     489          template_map['qname'] = unicode(std.expandedName())
     490      else:
     491          template_map['qname'] = '[anonymous]'
     492      template_map['namespaceReference'] = binding_module.literal(std.bindingNamespace(), **kw)
     493      template_map['xsd_location'] = repr(std._location())
     494      if std.annotation() is not None:
     495          template_map['documentation'] = std.annotation().asDocString()
     496          template_map['documentation_expr'] = binding_module.literal(std.annotation().text())
     497      else:
     498          template_map['documentation'] = ''
     499          template_map['documentation_expr'] = binding_module.literal(None)
     500
     501      # @todo: Extensions of LIST will be wrong in below
     502
     503      common_template = '''
     504      """%{documentation}"""
     505
     506      _ExpandedName = %{expanded_name}
     507      _XSDLocation = %{xsd_location}
     508      _Documentation = %{documentation_expr}
     509  '''
     510      if xs.structures.SimpleTypeDefinition.VARIETY_absent == std.variety():
     511          template = '''
     512  # The ur simple type: %{qname}
     513  class %{std} (%{superclasses}):
     514  ''' + common_template
     515          if not template_map['documentation']:
     516              template_map['documentation'] = 'The ur simple type.'
     517      elif xs.structures.SimpleTypeDefinition.VARIETY_atomic == std.variety():
     518          template = '''
     519  # Atomic simple type: %{qname}
     520  class %{std} (%{superclasses}):
     521  ''' + common_template
     522          if not template_map['documentation']:
     523              template_map['documentation'] = 'An atomic simple type.'
     524      elif xs.structures.SimpleTypeDefinition.VARIETY_list == std.variety():
     525          template = '''
     526  # List simple type: %{qname}
     527  # superclasses %{superclasses}
     528  class %{std} (pyxb.binding.basis.STD_list):
     529  ''' + common_template + '''
     530      _ItemType = %{itemtype}
     531  '''
     532          template_map['itemtype'] = binding_module.literal(std.itemTypeDefinition(), **kw)
     533          if not template_map['documentation']:
     534              template_map['documentation'] = templates.replaceInText('Simple type that is a list of %{itemtype}.', **template_map)
     535      elif xs.structures.SimpleTypeDefinition.VARIETY_union == std.variety():
     536          template = '''
     537  # Union simple type: %{qname}
     538  # superclasses %{superclasses}
     539  class %{std} (pyxb.binding.basis.STD_union):
     540  ''' + common_template + '''
     541      _MemberTypes = ( %{membertypes}, )
     542  '''
     543          template_map['membertypes'] = ", ".join( [ binding_module.literal(_mt, **kw) for _mt in std.memberTypeDefinitions() ])
     544          if not template_map['documentation']:
     545              template_map['documentation'] = templates.replaceInText('Simple type that is a union of %{membertypes}.', **template_map)
     546      else:
     547          raise pyxb.LogicError("Unhandled STD variety")
     548
     549      outf.write(templates.replaceInText(template, **template_map))
     550
     551      GenerateFacets(std, generator, **kw)
     552
     553      if std.name() is not None:
     554          outf.write(templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{std})\n",
     555                                             localName=binding_module.literal(std.name(), **kw), **template_map))
     556
     557 -def elementDeclarationMap (ed, binding_module, **kw):
     558      template_map = { }
     559      template_map['qname'] = unicode(ed.expandedName())
     560      template_map['decl_location'] = repr(ed._location())
     561      template_map['namespaceReference'] = binding_module.literal(ed.bindingNamespace(), **kw)
     562      if (ed.SCOPE_global == ed.scope()):
     563          binding_name = template_map['class'] = binding_module.literal(ed, **kw)
     564          if ed.expandedName().localName() != binding_name:
     565              _log.warning('Element %s renamed to %s', ed.expandedName(), binding_name)
     566          template_map['localName'] = binding_module.literal(ed.name(), **kw)
     567          template_map['map_update'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('elementBinding', %{localName}, %{class})", **template_map)
     568      else:
     569          template_map['scope'] = binding_module.literal(ed.scope(), **kw)
     570      if ed.annotation() is not None:
     571          template_map['documentation'] = binding_module.literal(unicode(ed.annotation()))
     572      if ed.abstract():
     573          template_map['abstract'] = binding_module.literal(ed.abstract(), **kw)
     574      if ed.nillable():
     575          template_map['nillable'] = binding_module.literal(ed.nillable(), **kw)
     576      if ed.default():
     577          template_map['defaultValue'] = binding_module.literal(ed.default(), **kw)
     578      template_map['typeDefinition'] = binding_module.literal(ed.typeDefinition(), **kw)
     579      if ed.substitutionGroupAffiliation():
     580          template_map['substitution_group'] = binding_module.literal(ed.substitutionGroupAffiliation(), **kw)
     581      aux_init = []
     582      for k in ( 'nillable', 'abstract', 'scope', 'documentation' ):
     583          if k in template_map:
     584              aux_init.append('%s=%s' % (k, template_map[k]))
     585      aux_init.append('location=%s' % (template_map['decl_location'],))
     586      _VCAppendAuxInit(ed, aux_init, binding_module, kw)
     587      template_map['element_aux_init'] = ''
     588      if 0 < len(aux_init):
     589          template_map['element_aux_init'] = ', ' + ', '.join(aux_init)
     590
     591      return template_map
     592
     593  import pyxb.utils.fac
     594  import operator
     595  import functools
     596
     597  # A Symbol in the term tree is a pair consisting of the containing
     598  # particle (for location information) and one of an
     599  # ElementDeclaration, Wildcard, or tuple of sub-term-trees for All
     600  # model groups.
     601
     602 -def BuildTermTree (node):
     603      """Construct a L{FAC term tree<pyxb.utils.fac.Node>} for a L{particle<xs.structures.Particle>}.
     604
     605      This translates the XML schema content model of particles, model
     606      groups, element declarations, and wildcards into a tree expressing
     607      the corresponding content as a regular expression with numerical
     608      constraints.
     609
     610      @param node: An instance of L{xs.structures.Particle}
     611
     612      @return: An instance of L{pyxb.utils.fac.Node}
     613      """
     614
     615      def _generateTermTree_visitor (node, entered, arg):
     616          """Helper for constructing a L{FAC term tree<pyxb.utils.fac.Node>}.
     617
     618          This is passed to L{xs.structures.Particle.walkParticleTree}.
     619
     620          @param node: An instance of L{xs.structures._ParticleTree_mixin}
     621
     622          @param entered: C{True} entering an interior tree node, C{False}
     623          leaving an interior tree node, C{None} at a leaf node.
     624
     625          @param arg: A list of pairs C{(particle, terms)} where C{particle}
     626          is the L{xs.structures.Particle} instance containing a list of
     627          L{term trees<pyxb.utils.fac.Node>}.
     628          """
     629
     630          if entered is None:
     631              (parent_particle, terms) = arg.peekNodeTermPair()
     632              assert isinstance(parent_particle, xs.structures.Particle)
     633              assert isinstance(node, (xs.structures.ElementDeclaration, xs.structures.Wildcard))
     634              node._setFacStateSortKey(arg.nextSequenceNumber())
     635              terms.append(pyxb.utils.fac.Symbol((parent_particle, node)))
     636          elif entered:
     637              node._setFacStateSortKey(arg.nextSequenceNumber())
     638              arg.addNode(node)
     639          else:
     640              (xnode, terms) = arg.popNodeTermPair()
     641              assert xnode == node
     642              (parent_particle, siblings) = arg.peekNodeTermPair()
     643              if 1 == len(terms):
     644                  term = terms[0]
     645                  # Either node is a Particle, or it's a single-member model
     646                  # group.  If it's a non-trivial particle we need a
     647                  # numerical constraint; if it's a single-member model
     648                  # group or a trivial particle we can use the term
     649                  # directly.
     650                  if isinstance(node, xs.structures.Particle) and ((1 != node.minOccurs()) or (1 != node.maxOccurs())):
     651                      term = pyxb.utils.fac.NumericalConstraint(term, node.minOccurs(), node.maxOccurs(), metadata=node)
     652              else:
     653                  assert isinstance(parent_particle, xs.structures.Particle), 'unexpected %s' % (parent_particle,)
     654                  assert isinstance(node, xs.structures.ModelGroup)
     655                  if node.C_CHOICE == node.compositor():
     656                      term = pyxb.utils.fac.Choice(*terms, metadata=node)
     657                  elif node.C_SEQUENCE == node.compositor():
     658                      term = pyxb.utils.fac.Sequence(*terms, metadata=node)
     659                  else:
     660                      # The quadratic state explosion and need to clone
     661                      # terms that results from a naive transformation of
     662                      # unordered catenation to choices among sequences of
     663                      # nodes and recursively-defined catenation expressions
     664                      # is not worth the pain.  Create a "symbol" for the
     665                      # state and hold the alternatives in it.
     666                      assert node.C_ALL == node.compositor()
     667                      assert functools.reduce(operator.and_, map(lambda _s: isinstance(_s, pyxb.utils.fac.Node), terms), True)
     668                      term = pyxb.utils.fac.All(*terms, metadata=node)
     669              siblings.append(term)
     670
     671      class TermTreeArg (object):
     672          __sequenceNumber = None
     673          __termTreeList = None
     674          __nodeTermPairs = None
     675          def __init__ (self, node):
     676              self.__sequenceNumber = 0
     677              self.__termTreeList = []
     678              self.__nodeTermPairs = [ (node, self.__termTreeList) ]
     679
     680          def termTree (self):
     681              assert 1 == len(self.__nodeTermPairs)
     682              assert 1 == len(self.__termTreeList)
     683              return self.__termTreeList[0]
     684
     685          def peekNodeTermPair (self):
     686              return self.__nodeTermPairs[-1]
     687
     688          def popNodeTermPair (self):
     689              return self.__nodeTermPairs.pop()
     690
     691          def addNode (self, node):
     692              self.__nodeTermPairs.append((node, []))
     693
     694          def nextSequenceNumber (self):
     695              rv = self.__sequenceNumber
     696              self.__sequenceNumber += 1
     697              return rv
     698
     699      assert isinstance(node, xs.structures.Particle)
     700      ttarg = TermTreeArg(node)
     701      node.walkParticleTree(_generateTermTree_visitor, ttarg)
     702      term_tree = ttarg.termTree()
     703      return term_tree
     704
     705 -def BuildPluralityData (term_tree):
     706      """Walk a term tree to determine which element declarations may
     707      appear multiple times.
     708
     709      The bindings need to use a list for any Python attribute
     710      corresponding to an element declaration that can occur multiple
     711      times in the content model.  The number of occurrences is
     712      determined by the occurrence constraints on parent particles and
     713      the compositors of containing model groups.  All this information
     714      is available in the term tree used for the content model
     715      automaton.
     716
     717      @param term_tree: A L{FAC term tree<pyxb.utils.fac.Node>}
     718      representing the content model for a complex data type.
     719
     720      @return: Plurality data, as a pair C{(singles, multiples)} where
     721      C{singles} is a set of base L{element
     722      declarations<xs.structures.ElementDeclaration>} that are known to
     723      occur at least once and at most once in a region of the content,
     724      and C{multiples} is a similar set of declarations that are known
     725      to potentially occur more than once."""
     726
     727      def _ttMergeSets (parent, child):
     728          (p1, pm) = parent
     729          (c1, cm) = child
     730
     731          # Anything multiple in the child becomes multiple in the parent.
     732          pm.update(cm)
     733
     734          # Anything independently occuring once in both parent and child
     735          # becomes multiple in the parent.
     736          pm.update(c1.intersection(p1))
     737
     738          # Anything that was single in the parent (child) but is now
     739          # multiple is no longer single.
     740          p1.difference_update(pm)
     741          c1.difference_update(pm)
     742
     743          # Anything that was single in the parent and also single in the
     744          # child is no longer single in the parent.
     745          p1.symmetric_difference_update(c1)
     746
     747      def _ttPrePluralityWalk (node, pos, arg):
     748          # If there are multiple children, create a new list on which they
     749          # will be placed.
     750          if isinstance(node, pyxb.utils.fac.MultiTermNode):
     751              arg.append([])
     752
     753      def _ttPostPluralityWalk (node, pos, arg):
     754          # Initialize a fresh result for this node
     755          singles = set()
     756          multiples = set()
     757          combined = (singles, multiples)
     758          if isinstance(node, pyxb.utils.fac.MultiTermNode):
     759              # Get the list of children, and examine
     760              term_list = arg.pop()
     761              if isinstance(node, pyxb.utils.fac.Choice):
     762                  # For choice we aggregate the singles and multiples
     763                  # separately.
     764                  for (t1, tm) in term_list:
     765                      multiples.update(tm)
     766                      singles.update(t1)
     767              else:
     768                  # For sequence (ordered or not) we merge the children
     769                  assert isinstance(node, (pyxb.utils.fac.Sequence, pyxb.utils.fac.All))
     770                  for tt in term_list:
     771                      _ttMergeSets(combined, tt)
     772          elif isinstance(node, pyxb.utils.fac.Symbol):
     773              (particle, term) = node.metadata
     774              if isinstance(term, xs.structures.ElementDeclaration):
     775                  # One instance of the base declaration for the element
     776                  singles.add(term.baseDeclaration())
     777              elif isinstance(term, xs.structures.Wildcard):
     778                  pass
     779              else:
     780                  assert isinstance(term, list)
     781                  # Unordered catenation is the same as ordered catenation.
     782                  for tt in term:
     783                      _ttMergeSets(combined, BuildPluralityData(tt))
     784          else:
     785              assert isinstance(node, pyxb.utils.fac.NumericalConstraint)
     786              # Grab the data for the topmost tree and adjust it based on
     787              # occurrence data.
     788              combined = arg[-1].pop()
     789              (singles, multiples) = combined
     790              if 0 == node.max:
     791                  # If the node can't match at all, there are no occurrences
     792                  # at all
     793                  multiples.clear()
     794                  singles.clear()
     795              elif 1 == node.max:
     796                  # If the node can only match once, what we've got is right
     797                  pass
     798              else:
     799                  # If the node can match multiple times, there are no
     800                  # singles.
     801                  multiples.update(singles)
     802                  singles.clear()
     803          arg[-1].append(combined)
     804
     805      # Initialize state with an implied parent that currently has no
     806      # children
     807      arg = [[]]
     808      term_tree.walkTermTree(_ttPrePluralityWalk, _ttPostPluralityWalk, arg)
     809
     810      # The result term tree is the single child of that implied parent
     811      assert 1 == len(arg)
     812      arg = arg[0]
     813      assert 1 == len(arg)
     814      return arg[0]
     815
     816 -class _CTDAuxData (object):
     817      """Helper class holding information need in both preparation and generation."""
     818
     819      contentBasis = None
     820      termTree = None
     821      edSingles = None
     822      edMultiples = None
     823      automaton = None
     824      ctd = None
     825
     826 -    def __init__ (self, ctd):
     827          self.ctd = ctd
     828          ctd.__auxData = self
     829          self.contentBasis = ctd.contentType()[1]
     830          if isinstance(self.contentBasis, xs.structures.Particle):
     831              self.termTree = BuildTermTree(self.contentBasis)
     832              self.automaton = self.termTree.buildAutomaton()
     833              (self.edSingles, self.edMultiples) = BuildPluralityData(self.termTree)
     834          else:
     835              self.edSingles = set()
     836              self.edMultiples = set()
     837
     838      @classmethod
     839 -    def Create (cls, ctd):
     840          return cls(ctd)
     841
     842      @classmethod
     843 -    def Get (cls, ctd):
     844          return ctd.__auxData
     845
     846 -def GenerateCTD (ctd, generator, **kw):
     847      binding_module = generator.moduleForComponent(ctd)
     848      outf = binding_module.bindingIO()
     849
     850      prolog_template = None
     851      template_map = { }
     852      binding_name = template_map['ctd'] = binding_module.literal(ctd, **kw)
     853      if (ctd.expandedName() is not None) and (ctd.expandedName().localName() != binding_name):
     854          _log.warning('Complex type %s renamed to %s', ctd.expandedName(), binding_name)
     855
     856      base_type = ctd.baseTypeDefinition()
     857      content_type_tag = ctd._contentTypeTag()
     858
     859      template_map['base_type'] = binding_module.literal(base_type, **kw)
     860      template_map['namespaceReference'] = binding_module.literal(ctd.bindingNamespace(), **kw)
     861      template_map['expanded_name'] = binding_module.literal(ctd.expandedName(), **kw)
     862      if ctd.expandedName() is not None:
     863          template_map['qname'] = unicode(ctd.expandedName())
     864      else:
     865          template_map['qname'] = '[anonymous]'
     866      template_map['xsd_location'] = repr(ctd._location())
     867      template_map['simple_base_type'] = binding_module.literal(None, **kw)
     868      template_map['contentTypeTag'] = content_type_tag
     869      template_map['is_abstract'] = repr(not not ctd.abstract())
     870
     871      content_basis = None
     872      if (ctd.CT_SIMPLE == content_type_tag):
     873          content_basis = ctd.contentType()[1]
     874          template_map['simple_base_type'] = binding_module.literal(content_basis, **kw)
     875      elif (ctd.CT_MIXED == content_type_tag):
     876          content_basis = ctd.contentType()[1]
     877      elif (ctd.CT_ELEMENT_ONLY == content_type_tag):
     878          content_basis = ctd.contentType()[1]
     879
     880      if ctd.annotation() is not None:
     881          template_map['documentation'] = ctd.annotation().asDocString()
     882      elif isinstance(ctd.owner(), xs.structures.ElementDeclaration) \
     883        and ctd.owner().annotation() is not None:
     884          template_map['documentation'] = ctd.owner().annotation().asDocString()
     885      else:
     886          template_map['documentation'] = templates.replaceInText("Complex type %{qname} with content type %{contentTypeTag}", **template_map)
     887
     888      prolog_template = '''
     889  # Complex type %{qname} with content type %{contentTypeTag}
     890  class %{ctd} (%{superclass}):
     891      """%{documentation}"""
     892      _TypeDefinition = %{simple_base_type}
     893      _ContentTypeTag = pyxb.binding.basis.complexTypeDefinition._CT_%{contentTypeTag}
     894      _Abstract = %{is_abstract}
     895      _ExpandedName = %{expanded_name}
     896      _XSDLocation = %{xsd_location}
     897  '''
     898
     899      # Complex types that inherit from non-ur-type complex types should
     900      # have their base type as their Python superclass, so pre-existing
     901      # elements and attributes can be re-used.
     902      inherits_from_base = True
     903      template_map['superclass'] = binding_module.literal(base_type, **kw)
     904      if ctd._isHierarchyRoot():
     905          inherits_from_base = False
     906          template_map['superclass'] = 'pyxb.binding.basis.complexTypeDefinition'
     907          assert base_type.nameInBinding() is not None
     908
     909      if inherits_from_base:
     910          prolog_template += '''    _ElementMap = %{superclass}._ElementMap.copy()
     911      _AttributeMap = %{superclass}._AttributeMap.copy()
     912  '''
     913      else:
     914          prolog_template += '''    _ElementMap = {}
     915      _AttributeMap = {}
     916  '''
     917
     918      # Support for deconflicting attributes, elements, and reserved symbols
     919      class_keywords = frozenset(basis.complexTypeDefinition._ReservedSymbols)
     920      class_unique = set()
     921
     922      # Deconflict elements first, attributes are lower priority.
     923      # Expectation is that all elements that have the same tag in the
     924      # XML are combined into the same instance member, even if they
     925      # have different types.  Determine what name that should be, and
     926      # whether there might be multiple instances of elements of that
     927      # name.
     928      element_uses = []
     929
     930      definitions = []
     931
     932      definitions.append('# Base type is %{base_type}')
     933
     934      # Retain in the ctd the information about the element
     935      # infrastructure, so it can be inherited where appropriate in
     936      # subclasses.
     937
     938      if isinstance(content_basis, xs.structures.Particle):
     939          aux = _CTDAuxData.Get(ctd)
     940          elements = aux.edSingles.union(aux.edMultiples)
     941
     942          outf.postscript().append("\n\n")
     943          for ed in sorted(elements, key=lambda _c: _c.schemaOrderSortKey()):
     944              is_plural = ed in aux.edMultiples
     945              # @todo Detect and account for plurality change between this and base
     946              ef_map = ed._templateMap()
     947              if ed.scope() == ctd:
     948                  ef_map.update(elementDeclarationMap(ed, binding_module, **kw))
     949                  aux_init = []
     950                  ef_map['is_plural'] = repr(is_plural)
     951                  element_uses.append(templates.replaceInText('%{use}.name() : %{use}', **ef_map))
     952                  if 0 == len(aux_init):
     953                      ef_map['aux_init'] = ''
     954                  else:
     955                      ef_map['aux_init'] = ', ' + ', '.join(aux_init)
     956                  ef_map['element_binding'] = utility.PrepareIdentifier('%s_elt' % (ef_map['id'],), class_unique, class_keywords, private=True)
     957                  if ed.annotation() is not None:
     958                      ef_map['documentation'] = binding_module.literal(unicode(ed.annotation()))
     959                  else:
     960                      ef_map['documentation'] = binding_module.literal(None)
     961              if ed.scope() != ctd:
     962                  definitions.append(templates.replaceInText('''
     963      # Element %{id} (%{qname}) inherited from %{decl_type_en}''', decl_type_en=unicode(ed.scope().expandedName()), **ef_map))
     964                  continue
     965
     966              binding_module.importForDeclaration(ed)
     967              if ed.expandedName().localName() != ef_map['id']:
     968                  _log.warning('Element use %s.%s renamed to %s', ctd.expandedName(), ed.expandedName(), ef_map['id'])
     969              definitions.append(templates.replaceInText('''
     970      # Element %{qname} uses Python identifier %{id}
     971      %{use} = pyxb.binding.content.ElementDeclaration(%{name_expr}, '%{id}', '%{key}', %{is_plural}, %{decl_location}, %{aux_init})
     972  ''', name_expr=binding_module.literal(ed.expandedName(), **kw), **ef_map))
     973
     974              definitions.append(templates.replaceInText('''
     975      %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation})
     976  ''', **ef_map))
     977              outf.postscript().append(templates.replaceInText('''
     978  %{ctd}._AddElement(pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init}))
     979  ''', name_expr=binding_module.literal(ed.expandedName(), **kw), ctd=template_map['ctd'], **ef_map))
     980
     981          auto_defn = GenerateAutomaton(ctd, binding_module=binding_module, **kw)
     982          if auto_defn is not None:
     983              (automaton_ctor, lines) = auto_defn
     984              if lines:
     985                  outf.postscript().append("\n".join(lines))
     986                  outf.postscript().append("\n")
     987              outf.postscript().append(templates.replaceInText('%{ctd}._Automaton = %{automaton_ctor}\n', ctd=template_map['ctd'], automaton_ctor=automaton_ctor))
     988              outf.postscript().append("\n")
     989
     990      # Create definitions for all attributes.
     991      attribute_uses = []
     992
     993      # name - String value of expanded name of the attribute (attr_tag, attr_ns)
     994      # name_expr - Python expression for an expanded name identifying the attribute (attr_tag)
     995      # use - Binding variable name holding AttributeUse instance (attr_name)
     996      # id - Python identifier for attribute (python_attr_name)
     997      # key - String used as dictionary key holding instance value of attribute (value_attr_name)
     998      # inspector - Name of the method used for inspection (attr_inspector)
     999      # mutator - Name of the method use for mutation (attr_mutator)
    1000      for au in sorted(ctd.attributeUses(), key=lambda _au: _au.attributeDeclaration().schemaOrderSortKey()):
    1001          ad = au.attributeDeclaration()
    1002          assert isinstance(ad.scope(), xs.structures.ComplexTypeDefinition), 'unexpected scope %s' % (ad.scope(),)
    1003          au_map = ad._templateMap()
    1004          if ad.scope() != ctd:
    1005              definitions.append(templates.replaceInText('''
    1006      # Attribute %{id} inherited from %{decl_type_en}''', decl_type_en=unicode(ad.scope().expandedName()), **au_map))
    1007              continue
    1008          assert isinstance(au_map, dict)
    1009          aur = au
    1010          while aur.restrictionOf() is not None:
    1011              aur = aur.restrictionOf()
    1012          if au != aur:
    1013              au_map = aur.attributeDeclaration()._templateMap().copy()
    1014              definitions.append(templates.replaceInText('''
    1015      # Attribute %{id} is restricted from parent''', **au_map))
    1016
    1017          assert ad.typeDefinition() is not None
    1018          au_map['attr_type'] = binding_module.literal(ad.typeDefinition(), **kw)
    1019          au_map['decl_location'] = repr(ad._location())
    1020          au_map['use_location'] = repr(au._location())
    1021
    1022          vc_source = ad
    1023          if au.valueConstraint() is not None:
    1024              vc_source = au
    1025          aux_init = []
    1026          _VCAppendAuxInit(vc_source, aux_init, binding_module, kw)
    1027          if au.required():
    1028              aux_init.append('required=True')
    1029          if au.prohibited():
    1030              aux_init.append('prohibited=True')
    1031          if 0 == len(aux_init):
    1032              au_map['aux_init'] = ''
    1033          else:
    1034              aux_init.insert(0, '')
    1035              au_map['aux_init'] = ', '.join(aux_init)
    1036          if ad.annotation() is not None:
    1037              au_map['documentation'] = binding_module.literal(unicode(ad.annotation()))
    1038          else:
    1039              au_map['documentation'] = binding_module.literal(None)
    1040
    1041          binding_module.importForDeclaration(ad)
    1042          attribute_uses.append(templates.replaceInText('%{use}.name() : %{use}', **au_map))
    1043          if ad.expandedName().localName() != au_map['id']:
    1044              _log.warning('Attribute %s.%s renamed to %s', ctd.expandedName(), ad.expandedName(), au_map['id'])
    1045          definitions.append(templates.replaceInText('''
    1046      # Attribute %{qname} uses Python identifier %{id}
    1047      %{use} = pyxb.binding.content.AttributeUse(%{name_expr}, '%{id}', '%{key}', %{attr_type}%{aux_init})
    1048      %{use}._DeclarationLocation = %{decl_location}
    1049      %{use}._UseLocation = %{use_location}''', name_expr=binding_module.literal(ad.expandedName(), **kw), **au_map))
    1050          definitions.append(templates.replaceInText('''
    1051      %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation})
    1052  ''', ctd=template_map['ctd'], **au_map))
    1053
    1054      if ctd.attributeWildcard() is not None:
    1055          definitions.append('_AttributeWildcard = %s' % (binding_module.literal(ctd.attributeWildcard(), **kw),))
    1056      if ctd.hasWildcardElement():
    1057          definitions.append('_HasWildcardElement = True')
    1058      template_map['attribute_uses'] = ",\n        ".join(attribute_uses)
    1059      template_map['element_uses'] = ",\n        ".join(element_uses)
    1060
    1061      template_map['registration'] = ''
    1062      if ctd.name() is not None:
    1063          template_map['registration'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{ctd})",
    1064                                                                 localName=binding_module.literal(ctd.name(), **kw), **template_map)
    1065
    1066      template = ''.join([prolog_template,
    1067                 "    ", "\n    ".join(definitions), "\n",
    1068                 '''    _ElementMap.update({
    1069          %{element_uses}
    1070      })
    1071      _AttributeMap.update({
    1072          %{attribute_uses}
    1073      })
    1074  %{registration}
    1075
    1076  '''])
    1077
    1078      outf.write(template, **template_map)
    1079
    1080 -def GenerateED (ed, generator, **kw):
    1081      # Unscoped declarations should never be referenced in the binding.
    1082      assert ed._scopeIsGlobal()
    1083
    1084      binding_module = generator.moduleForComponent(ed)
    1085      outf = binding_module.bindingIO()
    1086
    1087      template_map = elementDeclarationMap(ed, binding_module, **kw)
    1088      template_map.setdefault('scope', binding_module.literal(None, **kw))
    1089      template_map.setdefault('map_update', '')
    1090
    1091      binding_module.importForDeclaration(ed)
    1092      outf.write(templates.replaceInText('''
    1093  %{class} = pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init})
    1094  %{namespaceReference}.addCategoryObject('elementBinding', %{class}.name().localName(), %{class})
    1095  ''', name_expr=binding_module.literal(ed.expandedName(), **kw), **template_map))
    1096
    1097      if ed.substitutionGroupAffiliation() is not None:
    1098          outf.postscript().append(templates.replaceInText('''
    1099  %{class}._setSubstitutionGroup(%{substitution_group})
    1100  ''', **template_map))
    1101
    1102 -def _PrepareSimpleTypeDefinition (std, generator, nsm, module_context):
    1103      std._templateMap()['_unique'] = nsm.uniqueInClass(std)
    1104      if _useEnumerationTags(std):
    1105          enum_facet = std.facets().get(pyxb.binding.facets.CF_enumeration)
    1106          if (enum_facet is not None) and (std == enum_facet.ownerTypeDefinition()):
    1107              for ei in enum_facet.iteritems():
    1108                  assert ei.tag() is None, '%s already has a tag' % (ei,)
    1109                  ei._setTag(utility.PrepareIdentifier(ei.unicodeValue(), nsm.uniqueInClass(std)))
    1110
    1111 -def _PrepareComplexTypeDefinition (ctd, generator, nsm, module_context):
    1112      kw = { 'binding_module' : module_context }
    1113      ctd._templateMap()['_unique'] = nsm.uniqueInClass(ctd)
    1114      aux = _CTDAuxData.Create(ctd)
    1115      multiples = aux.edMultiples
    1116      for cd in ctd.localScopedDeclarations():
    1117          _SetNameWithAccessors(cd, ctd, cd in multiples, module_context, nsm, kw)
    1118
    1119 -def _SetNameWithAccessors (component, container, is_plural, binding_module, nsm, kw):
    1120      use_map = component._templateMap()
    1121      class_unique = nsm.uniqueInClass(container)
    1122      assert isinstance(component, xs.structures._ScopedDeclaration_mixin)
    1123      unique_name = utility.PrepareIdentifier(component.expandedName().localName(), class_unique)
    1124      use_map['id'] = unique_name
    1125      use_map['inspector'] = unique_name
    1126      use_map['mutator'] = utility.PrepareIdentifier('set' + unique_name[0].upper() + unique_name[1:], class_unique)
    1127      use_map['use'] = utility.MakeUnique('__' + unique_name.strip('_'), class_unique)
    1128      assert component._scope() == container
    1129      assert component.nameInBinding() is None, 'Use %s but binding name %s for %s' % (use_map['use'], component.nameInBinding(), component.expandedName())
    1130      component.setNameInBinding(use_map['use'])
    1131      key_name = u'%s_%s_%s' % (unicode(nsm.namespace()), container.nameInBinding(), component.expandedName())
    1132      use_map['key'] = utility.PrepareIdentifier(key_name, class_unique, private=True)
    1133      use_map['qname'] = unicode(component.expandedName())
    1134      if isinstance(component, xs.structures.ElementDeclaration) and is_plural:
    1135          use_map['appender'] = utility.PrepareIdentifier('add' + unique_name[0].upper() + unique_name[1:], class_unique)
    1136      return use_map
    1137
    1138 -class BindingIO (object):
    1139      __prolog = None
    1140      __postscript = None
    1141      __templateMap = None
    1142      __stringIO = None
    1143      __bindingFilePath = None
    1144      __bindingFile = None
    1145
    1146 -    def __init__ (self, binding_module, **kw):
    1147          super(BindingIO, self).__init__()
    1148          self.__bindingModule = binding_module
    1149          self.__bindingFilePath = kw['binding_file_path']
    1150          self.__bindingFile = kw['binding_file']
    1151          self.__prolog = []
    1152          self.__postscript = []
    1153          self.__templateMap = kw.copy()
    1154          encoding = kw.get('encoding', pyxb._OutputEncoding)
    1155          self.__templateMap.update({ 'date' : str(datetime.datetime.now()),
    1156                                      'filePath' : self.__bindingFilePath,
    1157                                      'coding' : encoding,
    1158                                      'binding_module' : binding_module,
    1159                                      'binding_tag' : binding_module.bindingTag(),
    1160                                      'pyxbVersion' : pyxb.__version__ })
    1161          self.__stringIO = io.StringIO()
    1162          if self.__bindingFile:
    1163              prefacet = self.expand('''# %{filePath}
    1164  # -*- coding: %{coding} -*-
    1165  # PyXB bindings for %{binding_tag}
    1166  # Generated %{date} by PyXB version %{pyxbVersion}
    1167  %{binding_preface}''', binding_preface=binding_module.bindingPreface())
    1168              self.__bindingFile.write(prefacet.encode(encoding))
    1169              self.__bindingFile.flush()
    1170
    1171 -    def bindingFile (self):
    1172          return self.__bindingFile
    1173
    1174 -    def expand (self, template, **kw):
    1175          tm = self.__templateMap.copy()
    1176          tm.update(kw)
    1177          return templates.replaceInText(template, **tm)
    1178
    1179 -    def write (self, template, **kw):
    1180          txt = self.expand(template, **kw)
    1181          self.__stringIO.write(txt)
    1182
    1183 -    def bindingModule (self):
    1184          return self.__bindingModule
    1185      __bindingModule = None
    1186
    1187 -    def prolog (self):
    1188          return self.__prolog
    1189 -    def postscript (self):
    1190          return self.__postscript
    1191
    1192 -    def literal (self, *args, **kw):
    1193          kw.update(self.__templateMap)
    1194          return pythonLiteral(*args, **kw)
    1195
    1196 -    def contents (self):
    1197          rv = self.__prolog
    1198          rv.append(self.__stringIO.getvalue())
    1199          rv.extend(self.__postscript)
    1200          return ''.join(rv)
    1201
    1202 -class _ModuleNaming_mixin (object):
    1203      __anonSTDIndex = None
    1204      __anonCTDIndex = None
    1205      __uniqueInModule = None
    1206      __uniqueInClass = None
    1207      __referencedFromClass = None
    1208
    1209      _UniqueInModule = set([ 'pyxb', 'sys' ])
    1210      """Identifiers that are reserved within a module.
    1211
    1212      Subclasses extend this with the identifiers they add to the
    1213      module.  Module-level schema-derived identifiers (such as type
    1214      definition and element names) are deconflicted from this set and
    1215      from each other."""
    1216
    1217      _ReferencedFromClass = set([ 'pyxb', 'sys' ])
    1218      """Identifiers defined in module that are accessed unqualified from class.
    1219
    1220      These include standard import module names and globals such as
    1221      references to namespaces."""
    1222
    1223      __ComponentBindingModuleMap = {}
    1224
    1225 -    def generator (self):
    1226          return self.__generator
    1227      __generator = None
    1228
    1229 -    def __init__ (self, generator, *args, **kw):
    1230          super(_ModuleNaming_mixin, self).__init__(*args, **kw)
    1231          self.__generator = generator
    1232          assert isinstance(self.__generator, Generator)
    1233          self.__anonSTDIndex = 1
    1234          self.__anonCTDIndex = 1
    1235          self.__components = []
    1236          self.__componentNameMap = {}
    1237          self.__uniqueInModule = set()
    1238          self.__referencedFromClass = self._ReferencedFromClass.copy()
    1239          self.__bindingIO = None
    1240          self.__importModulePathMap = {}
    1241          self.__namespaceDeclarations = []
    1242          self.__referencedNamespaces = {}
    1243          self.__uniqueInClass = {}
    1244
    1245 -    def _importModule (self, module):
    1246          assert not isinstance(module, pyxb.namespace.Namespace)
    1247          assert isinstance(module, (_ModuleNaming_mixin, pyxb.namespace.archive.ModuleRecord)), 'Unexpected type %s' % (type(module),)
    1248          if isinstance(module, NamespaceModule):
    1249              if pyxb.namespace.XMLSchema == module.namespace():
    1250                  return
    1251              module = module.moduleRecord()
    1252          assert isinstance(module, (pyxb.namespace.archive.ModuleRecord, NamespaceGroupModule))
    1253          if not (module in self.__importModulePathMap):
    1254              module_path = module.modulePath()
    1255              if 'pyxb' == module_path.split('.', 2)[0]:
    1256                  assert 'pyxb' in self.uniqueInModule()
    1257                  assert 'pyxb' in self.__referencedFromClass
    1258                  module_path = None
    1259              else:
    1260                  module_path = utility.PrepareIdentifier('ImportedBinding_' + module_path.replace('.', '_'),
    1261                                                          self.uniqueInModule(), protected=True)
    1262                  self.__referencedFromClass.add(module_path)
    1263              self.__importModulePathMap[module] = module_path
    1264
    1265 -    def uniqueInClass (self, component):
    1266          rv = self.__uniqueInClass.get(component)
    1267          if rv is None:
    1268              rv = set()
    1269              rv.update(self.__referencedFromClass)
    1270              if isinstance(component, xs.structures.SimpleTypeDefinition):
    1271                  rv.update(basis.simpleTypeDefinition._ReservedSymbols)
    1272              else:
    1273                  assert isinstance(component, xs.structures.ComplexTypeDefinition)
    1274                  if component._isHierarchyRoot():
    1275                      rv.update(basis.complexTypeDefinition._ReservedSymbols)
    1276                  else:
    1277                      base_td = component.baseTypeDefinition()
    1278                      base_unique = base_td._templateMap().get('_unique')
    1279                      assert base_unique is not None, 'Base %s of %s has no unique' % (base_td.expandedName(), component.expandedName())
    1280                      rv.update(base_unique)
    1281              self.__uniqueInClass[component] = rv
    1282          return rv
    1283
    1284      __referencedNamespaces = None
    1285
    1286 -    def bindingIO (self):
    1287          return self.__bindingIO
    1288
    1289      __moduleUID = None
    1290 -    def moduleUID (self):
    1291          if self.__moduleUID is None:
    1292              self.__moduleUID = pyxb.utils.utility.HashForText(self._moduleUID_vx())
    1293          return self.__moduleUID
    1294
    1295 -    def _moduleUID_vx (self):
    1296          return str(id(self))
    1297
    1298 -    def bindingTag (self):
    1299          """Return a distinct string recorded in the first 4096 bytes of the binding file.
    1300
    1301          This is used to ensure uniqueness and avoid overwriting data
    1302          belonging to a different binding.  The return value comprises
    1303          the class-specialized L{_bindingTagPrefix_vx} with the
    1304          L{moduleUID}.
    1305          """
    1306          return '%s:%s' % (self._bindingTagPrefix_vx(), self.moduleUID())
    1307
    1308 -    def _bindingTagPrefix_vx (self):
    1309          raise pyxb.LogicError('Subclass %s does not define _bindingTagPrefix_vx' % (type(self),))
    1310
    1311 -    def bindingPreface (self):
    1312          """Return a block of binding text (comment or code) serving as a preface.
    1313
    1314          Normally this should describe the module contents."""
    1315          return self._bindingPreface_vx()
    1316 -    def _bindingPreface_vx (self):
    1317          return ''
    1318
    1319 -    def moduleContents (self):
    1320          template_map = {}
    1321          aux_imports = []
    1322          for (mr, as_path) in self.__importModulePathMap.iteritems():
    1323              assert self != mr
    1324              if as_path is not None:
    1325                  aux_imports.append('import %s as %s' % (mr.modulePath(), as_path))
    1326              else:
    1327                  aux_imports.append('import %s' % (mr.modulePath(),))
    1328          template_map['aux_imports'] = "\n".join(aux_imports)
    1329          template_map['namespace_decls'] = "\n".join(self.__namespaceDeclarations)
    1330          template_map['module_uid'] = self.moduleUID()
    1331          template_map['generation_uid_expr'] = repr(self.generator().generationUID())
    1332          self._finalizeModuleContents_vx(template_map)
    1333          return self.__bindingIO.contents()
    1334
    1335 -    def modulePath (self):
    1336          return self.__modulePath
    1337 -    def _setModulePath (self, path_data):
    1338          (binding_file_path, binding_file, module_path) = path_data
    1339          self.__bindingFilePath = binding_file_path
    1340          self.__bindingFile = binding_file
    1341          if module_path is None:
    1342              module_path = self.moduleRecord().modulePath()
    1343          if module_path is not None:
    1344              self.__modulePath = module_path
    1345          kw = self._initialBindingTemplateMap()
    1346          self.__bindingIO = BindingIO(self, binding_file=binding_file, binding_file_path=binding_file_path, **kw)
    1347      __modulePath = None
    1348
    1349 -    def pathFromImport (self, module, name):
    1350          """Python code reference to an object in an imported module"""
    1351          if isinstance(module, NamespaceModule):
    1352              module = module.moduleRecord()
    1353          as_path = self.__importModulePathMap[module]
    1354          if as_path is None:
    1355              as_path = module.modulePath()
    1356          return '%s.%s' % (as_path, name)
    1357
    1358 -    def bindingFile (self):
    1359          return self.__bindingFile
    1360      __bindingFile = None
    1361      __bindingFilePath = None
    1362
    1363 -    def _initializeUniqueInModule (self, unique_in_module):
    1364          self.__uniqueInModule = set(unique_in_module)
    1365
    1366 -    def uniqueInModule (self):
    1367          return self.__uniqueInModule
    1368
    1369      @classmethod
    1370 -    def BindComponentInModule (cls, component, module):
    1371          cls.__ComponentBindingModuleMap[component] = module
    1372          return module
    1373
    1374      @classmethod
    1375 -    def ComponentBindingModule (cls, component):
    1376          return cls.__ComponentBindingModuleMap.get(component)
    1377
    1378      @classmethod
    1379 -    def _RecordModule (cls, module):
    1380          cls.__RecordModuleMap[module.moduleRecord()] = module
    1381          return module
    1382      @classmethod
    1383 -    def _ForRecord (cls, module_record):
    1384          return cls.__RecordModuleMap.get(module_record)
    1385      __RecordModuleMap = { }
    1386
    1387 -    def _bindComponent (self, component):
    1388          kw = {}
    1389          rv = component.bestNCName()
    1390          if rv is None:
    1391              if isinstance(component, xs.structures.ComplexTypeDefinition):
    1392                  rv = utility.PrepareIdentifier('CTD_ANON', self.uniqueInClass(component), protected=True)
    1393              elif isinstance(component, xs.structures.SimpleTypeDefinition):
    1394                  rv = utility.PrepareIdentifier('STD_ANON', self.uniqueInClass(component), protected=True)
    1395              else:
    1396                  assert False
    1397              kw['protected'] = True
    1398          rv = utility.PrepareIdentifier(rv, self.__uniqueInModule, kw)
    1399          assert not component in self.__componentNameMap
    1400          self.__components.append(component)
    1401          self.__componentNameMap[component] = rv
    1402          return rv
    1403 -    def nameInModule (self, component):
    1404          return self.__componentNameMap.get(component)
    1405
    1406 -    def referenceSchemaComponent (self, component):
    1407          origin = component._objectOrigin()
    1408          assert origin is not None
    1409          module_record = origin.moduleRecord()
    1410          assert module_record is not None
    1411          if self.generator().generationUID() != module_record.generationUID():
    1412              self._importModule(module_record)
    1413              return self.pathFromImport(module_record, component.nameInBinding())
    1414          component_module = _ModuleNaming_mixin.ComponentBindingModule(component)
    1415          assert component_module is not None, 'No binding module for %s from %s in %s as %s' % (component, module_record, self.moduleRecord(), component.nameInBinding())
    1416          name = component_module.__componentNameMap.get(component)
    1417          if name is None:
    1418              assert isinstance(self, NamespaceModule) and (self.namespace() == component.bindingNamespace())
    1419              name = component.nameInBinding()
    1420          if self != component_module:
    1421              self._importModule(component_module)
    1422              name = self.pathFromImport(component_module, name)
    1423          return name
    1424
    1425 -    def _referencedNamespaces (self): return self.__referencedNamespaces
    1426
    1427 -    def defineNamespace (self, namespace, name, definition=None, **kw):
    1428          rv = self.__referencedNamespaces.get(namespace)
    1429          assert rv is None, 'Module %s already has reference to %s' % (self, namespace)
    1430          # All module-level namespace declarations are reserved.
    1431          # Some may have a protected name.  The unprotected name
    1432          # shall always begin with 'Namespace'.  These names may
    1433          # be referenced from class implementations as well.
    1434          assert name.startswith('Namespace'), 'unexpected %s naming %s' % (name, namespace)
    1435          name = utility.PrepareIdentifier(name, self.__uniqueInModule, **kw)
    1436          self.__referencedFromClass.add(name)
    1437          if definition is None:
    1438              if namespace.isAbsentNamespace():
    1439                  definition = 'pyxb.namespace.CreateAbsentNamespace()'
    1440              else:
    1441                  definition = 'pyxb.namespace.NamespaceForURI(%s, create_if_missing=True)' % (repr(namespace.uri()),)
    1442          self.__namespaceDeclarations.append('%s = %s' % (name, definition))
    1443          self.__namespaceDeclarations.append("%s.configureCategories(['typeBinding', 'elementBinding'])" % (name,))
    1444          self.__referencedNamespaces[namespace] = name
    1445          return name
    1446
    1447 -    def referenceNamespace (self, namespace):
    1448          rv = self.__referencedNamespaces.get(namespace)
    1449          if rv is None:
    1450              assert not (isinstance(self, NamespaceModule) and (self.namespace() == namespace))
    1451              assert namespace.isBuiltinNamespace() or not namespace.isUndeclaredNamespace()
    1452              if namespace.isBuiltinNamespace():
    1453                  rv = namespace.builtinNamespaceRepresentation()
    1454              if rv is None:
    1455                  # Not the local namespace or a built-in.  Give it a
    1456                  # local name, potentially derived from its prefix.
    1457                  # Then try to find an existing import that defines the
    1458                  # namespace.  Then define the local name within the
    1459                  # binding, either as a reference to a namespace
    1460                  # reachable from an import or by doing a runtime
    1461                  # lookup from the namespace URI if somehow no provider
    1462                  # has been imported.  (This last case should apply
    1463                  # only to namespace group modules.)
    1464                  if namespace.prefix():
    1465                      nsn = 'Namespace_%s' % (namespace.prefix(),)
    1466                  else:
    1467                      nsn = 'Namespace'
    1468                  nsdef = None
    1469                  for im in self.__importModulePathMap.iterkeys():
    1470                      if isinstance(im, pyxb.namespace.archive.ModuleRecord):
    1471                          if im.namespace() == namespace:
    1472                              nsdef = self.pathFromImport(im, 'Namespace')
    1473                              break
    1474                      elif isinstance(im, NamespaceGroupModule):
    1475                          pass
    1476                      else:
    1477                          assert False, 'unexpected import from type %s %s' % (type(im), im,)
    1478                  # If we failed to identify the namespace in an existing import,
    1479                  # and this module is not a namespace group which includes the
    1480                  # namespace as part of its content, something went wrong.
    1481                  if (nsdef is None) and not (isinstance(self, NamespaceGroupModule) and self.moduleForNamespace(namespace) is not None):
    1482                      raise pyxb.LogicError('MISSING NSDEF: %s cannot be found for %s in imports' % (namespace, nsn))
    1483
    1484                  rv =  self.defineNamespace(namespace, nsn, nsdef, protected=True)
    1485                  assert 0 < len(self.__namespaceDeclarations)
    1486              self.__referencedNamespaces[namespace] = rv
    1487          return rv
    1488
    1489 -    def importForDeclaration (self, decl):
    1490          """Import the binding from which the declaration came.
    1491
    1492          Figure out where the declaration came from.  If it's not part
    1493          of this binding, make sure we import the binding associated
    1494          with the schema from which it came.  We need that, if not for
    1495          something in the declaration itself, at least to be able to
    1496          get the Namespace for the declaration's name.  None of this is
    1497          relevant if the declaration has no namespace."""
    1498          sdecl = decl
    1499          while sdecl._cloneSource() is not None:
    1500              sdecl = sdecl._cloneSource()
    1501          assert decl.expandedName() == sdecl.expandedName()
    1502          ns = decl.expandedName().namespace()
    1503          if ns is None:
    1504              return
    1505          assert sdecl._objectOrigin().moduleRecord().namespace() == ns
    1506          mr = sdecl._objectOrigin().moduleRecord()
    1507          if isinstance(self, NamespaceModule):
    1508              need_import = self.moduleRecord().modulePath() != mr.modulePath()
    1509          elif isinstance(self, NamespaceGroupModule):
    1510              need_import = True
    1511              for nm in self.namespaceModules():
    1512                  if nm.moduleRecord().modulePath() == mr.modulePath():
    1513                      need_import = False
    1514                      break
    1515          else:
    1516              raise pyxb.LogicError('Unhandled module naming', self)
    1517          if need_import:
    1518              self._importModule(mr)
    1519
    1520 -    def literal (self, *args, **kw):
    1521          return self.__bindingIO.literal(*args, **kw)
    1522
    1523 -    def addImportsFrom (self, module):
    1524          _log.info('Importing to %s from %s', self, module)
    1525          self._importModule(module)
    1526          for c in self.__components:
    1527              local_name = self.nameInModule(c)
    1528              assert local_name is not None
    1529              rem_name = module.nameInModule(c)
    1530              if rem_name is None:
    1531                  continue
    1532              aux = ''
    1533              if local_name != rem_name:
    1534                  aux = ' as %s' % (local_name,)
    1535              self.__bindingIO.write("from %s import %s%s # %s\n" % (module.modulePath(), rem_name, aux, c.expandedName()))
    1536
    1537 -    def writeToModuleFile (self):
    1538          if self.bindingFile():
    1539              self.bindingFile().write(self.moduleContents().encode(pyxb._OutputEncoding))
    1540              self.bindingFile().close()
    1541              _log.info('Saved binding source to %s', self.__bindingFilePath)
    1542          else:
    1543              _log.info('No binding file for %s', self)
    1544
    1545 -class NamespaceModule (_ModuleNaming_mixin):
    1546      """This class represents a Python module that holds all the
    1547      declarations belonging to a specific namespace."""
    1548
    1549 -    def namespace (self):
    1550          return self.__namespace
    1551      __namespace = None
    1552
    1553 -    def moduleRecord (self):
    1554          return self.__moduleRecord
    1555      __moduleRecord = None
    1556
    1557 -    def namespaceGroupModule (self):
    1558          return self.__namespaceGroupModule
    1559 -    def setNamespaceGroupModule (self, namespace_group_module):
    1560          self.__namespaceGroupModule = namespace_group_module
    1561      __namespaceGroupModule = None
    1562
    1563      _UniqueInModule = _ModuleNaming_mixin._UniqueInModule.copy()
    1564      _UniqueInModule.update([ 'CreateFromDOM', 'CreateFromDocument' ])
    1565
    1566 -    def namespaceGroupHead (self):
    1567          return self.__namespaceGroupHead
    1568      __namespaceGroupHead = None
    1569      __namespaceGroup = None
    1570
    1571 -    def componentsInNamespace (self):
    1572          return self.__components
    1573      __components = None
    1574
    1575      @classmethod
    1576 -    def ForComponent (cls, component):
    1577          return cls.__ComponentModuleMap.get(component)
    1578      __ComponentModuleMap = { }
    1579
    1580 -    def _bindingTagPrefix_vx (self):
    1581          return 'NM'
    1582
    1583 -    def _bindingPreface_vx (self):
    1584          ns = self.namespace()
    1585          rvl = ['# Namespace %s' % (ns,)]
    1586          if ns.prefix() is not None:
    1587              rvl.append(' [xmlns:%s]' % (ns.prefix(),))
    1588          rvl.append('\n')
    1589          return ''.join(rvl)
    1590
    1591 -    def _moduleUID_vx (self):
    1592          if self.namespace().isAbsentNamespace():
    1593              return 'Absent'
    1594          return unicode(self.namespace())
    1595
    1596 -    def namespaceGroupMulti (self):
    1597          return 1 < len(self.__namespaceGroup)
    1598
    1599 -    def __init__ (self, generator, module_record, mr_scc, components=None, **kw):
    1600          super(NamespaceModule, self).__init__(generator, **kw)
    1601          self._initializeUniqueInModule(self._UniqueInModule)
    1602          self.__moduleRecord = module_record
    1603          self.__namespace = self.__moduleRecord.namespace()
    1604          self.defineNamespace(self.__namespace, 'Namespace')
    1605          self._RecordModule(self)
    1606          self.__components = components
    1607          # wow! fromkeys actually IS useful!
    1608          if self.__components is not None:
    1609              self.__ComponentModuleMap.update(dict.fromkeys(self.__components, self))
    1610          self.__namespaceBindingNames = {}
    1611          self.__componentBindingName = {}
    1612          self._setModulePath(generator.modulePathData(self))
    1613
    1614 -    def _initialBindingTemplateMap (self):
    1615          kw = { 'moduleType' : 'namespace'
    1616               , 'targetNamespace' : repr(self.__namespace.uri())
    1617               , 'namespaceURI' : self.__namespace.uri()
    1618               , 'namespaceReference' : self.referenceNamespace(self.__namespace)
    1619               , 'pyxb_version' : repr(pyxb.__version__)
    1620               }
    1621          return kw
    1622
    1623 -    def _finalizeModuleContents_vx (self, template_map):
    1624          if sys.version_info < (3, 0):
    1625              template_map['_TextType'] = 'unicode'
    1626          else:
    1627              template_map['_TextType'] = 'str'
    1628          self.bindingIO().prolog().append(self.bindingIO().expand('''
    1629  import pyxb
    1630  import pyxb.binding
    1631  import pyxb.binding.saxer
    1632  import io
    1633  import pyxb.utils.utility
    1634  import pyxb.utils.domutils
    1635  import sys
    1636
    1637  # Unique identifier for bindings created at the same time
    1638  _GenerationUID = %{generation_uid_expr}
    1639
    1640  # Version of PyXB used to generate the bindings
    1641  _PyXBVersion = %{pyxb_version}
    1642  # Generated bindings are not compatible across PyXB versions
    1643  if pyxb.__version__ != _PyXBVersion:
    1644      raise pyxb.PyXBVersionError(_PyXBVersion)
    1645
    1646  # Import bindings for namespaces imported into schema
    1647  %{aux_imports}
    1648
    1649  # NOTE: All namespace declarations are reserved within the binding
    1650  %{namespace_decls}
    1651
    1652  def CreateFromDocument (xml_text, default_namespace=None, location_base=None):
    1653      """Parse the given XML and use the document element to create a
    1654      Python instance.
    1655
    1656      @param xml_text An XML document.  This should be data (Python 2
    1657      str or Python 3 bytes), or a text (Python 2 unicode or Python 3
    1658      str) in the L{pyxb._InputEncoding} encoding.
    1659
    1660      @keyword default_namespace The L{pyxb.Namespace} instance to use as the
    1661      default namespace where there is no default namespace in scope.
    1662      If unspecified or C{None}, the namespace of the module containing
    1663      this function will be used.
    1664
    1665      @keyword location_base: An object to be recorded as the base of all
    1666      L{pyxb.utils.utility.Location} instances associated with events and
    1667      objects handled by the parser.  You might pass the URI from which
    1668      the document was obtained.
    1669      """
    1670
    1671      if pyxb.XMLStyle_saxer != pyxb._XMLStyle:
    1672          dom = pyxb.utils.domutils.StringToDOM(xml_text)
    1673          return CreateFromDOM(dom.documentElement)
    1674      if default_namespace is None:
    1675          default_namespace = Namespace.fallbackNamespace()
    1676      saxer = pyxb.binding.saxer.make_parser(fallback_namespace=default_namespace, location_base=location_base)
    1677      handler = saxer.getContentHandler()
    1678      xmld = xml_text
    1679      if isinstance(xmld, %{_TextType}):
    1680          xmld = xmld.encode(pyxb._InputEncoding)
    1681      saxer.parse(io.BytesIO(xmld))
    1682      instance = handler.rootObject()
    1683      return instance
    1684
    1685  def CreateFromDOM (node, default_namespace=None):
    1686      """Create a Python instance from the given DOM node.
    1687      The node tag must correspond to an element declaration in this module.
    1688
    1689      @deprecated: Forcing use of DOM interface is unnecessary; use L{CreateFromDocument}."""
    1690      if default_namespace is None:
    1691          default_namespace = Namespace.fallbackNamespace()
    1692      return pyxb.binding.basis.element.AnyCreateFromDOM(node, default_namespace)
    1693
    1694  ''', **template_map))
    1695
    1696      __components = None
    1697      __componentBindingName = None
    1698
    1699 -    def bindComponent (self, component):
    1700          ns_name = self._bindComponent(component)
    1701          component.setNameInBinding(ns_name)
    1702          binding_module = self
    1703          if self.__namespaceGroupModule:
    1704              self.__namespaceGroupModule._bindComponent(component)
    1705              binding_module = self.__namespaceGroupModule
    1706          return _ModuleNaming_mixin.BindComponentInModule(component, binding_module)
    1707
    1708 -    def __str__ (self):
    1709          return 'NM:%s@%s' % (self.namespace(), self.modulePath())
    1710
    1711 -class NamespaceGroupModule (_ModuleNaming_mixin):
    1712      """This class represents a Python module that holds all the
    1713      declarations belonging to a set of namespaces which have
    1714      interdependencies."""
    1715
    1716 -    def namespaceModules (self):
    1717          return self.__namespaceModules
    1718      __namespaceModules = None
    1719
    1720 -    def moduleForNamespace (self, namespace):
    1721          for nm in self.__namespaceModules:
    1722              if nm.namespace() == namespace:
    1723                  return nm
    1724          return None
    1725
    1726      __components = None
    1727      __componentBindingName = None
    1728      __uniqueInModule = None
    1729
    1730      __UniqueInGroups = set()
    1731
    1732      _GroupPrefix = '_group'
    1733
    1734 -    def __init__ (self, generator, namespace_modules, **kw):
    1735          super(NamespaceGroupModule, self).__init__(generator, **kw)
    1736          assert 1 < len(namespace_modules)
    1737          self.__namespaceModules = namespace_modules
    1738          self.__namespaceGroupHead = namespace_modules[0].namespaceGroupHead()
    1739          self._initializeUniqueInModule(self._UniqueInModule)
    1740          self._setModulePath(generator.modulePathData(self))
    1741
    1742 -    def _initialBindingTemplateMap (self):
    1743          kw = { 'moduleType' : 'namespaceGroup' }
    1744          return kw
    1745
    1746 -    def _bindingTagPrefix_vx (self):
    1747          return 'NGM'
    1748
    1749 -    def _bindingPreface_vx (self):
    1750          rvl = ['# Group contents:\n' ]
    1751          for nsm in self.namespaceModules():
    1752              rvl.append(nsm.bindingPreface())
    1753          rvl.append('\n')
    1754          return ''.join(rvl)
    1755
    1756 -    def _finalizeModuleContents_vx (self, template_map):
    1757          self.bindingIO().prolog().append(self.bindingIO().expand('''
    1758  import pyxb
    1759  import pyxb.binding
    1760  import pyxb.utils.utility
    1761
    1762  # Unique identifier for bindings created at the same time
    1763  _GenerationUID = %{generation_uid_expr}
    1764
    1765  # Import bindings for schemas in group
    1766  %{aux_imports}
    1767
    1768  # NOTE: All namespace declarations are reserved within the binding
    1769  %{namespace_decls}
    1770  ''', **template_map))
    1771
    1772 -    def _moduleUID_vx (self):
    1773          nss = []
    1774          for nsm in self.namespaceModules():
    1775              ns = nsm.namespace()
    1776              if ns.isAbsentNamespace():
    1777                  nss.append('Absent')
    1778              else:
    1779                  nss.append(unicode(ns))
    1780          nss.sort()
    1781          return u';'.join(nss)
    1782
    1783 -    def __str__ (self):
    1784          return 'NGM:%s' % (self.modulePath(),)
    1785
    1786
    1787 -def GeneratePython (schema_location=None,
    1788                      schema_text=None,
    1789                      namespace=None,
    1790                      module_prefix_elts=[],
    1791                      **kw):
    1792
    1793      generator = Generator(allow_absent_module=True, generate_to_files=False, **kw)
    1794      if schema_location is not None:
    1795          generator.addSchemaLocation(schema_location)
    1796      elif schema_text is not None:
    1797          generator.addSchema(schema_text)
    1798      modules = generator.bindingModules()
    1799
    1800      assert 1 == len(modules), '%s produced %d modules: %s' % (namespace, len(modules), u" ".join([ unicode(_m) for _m in modules]))
    1801      return modules.pop().moduleContents()
    1802
    1803  import optparse
    1804  import re
    1805
    1806 -class Generator (object):
    1807      """Configuration and data for a single binding-generation action."""
    1808
    1809      _DEFAULT_bindingRoot = '.'
    1810 -    def bindingRoot (self):
    1811          """The directory path into which generated bindings will be written.
    1812          @rtype: C{str}"""
    1813          return self.__bindingRoot
    1814 -    def setBindingRoot (self, binding_root):
    1815          self.__bindingRoot = binding_root
    1816          return self
    1817      __bindingRoot = None
    1818
    1819 -    def __moduleFilePath (self, module_elts, inhibit_extension=False):
    1820          if isinstance(module_elts, basestring):
    1821              module_elts = module_elts.split('.')
    1822          else:
    1823              module_elts = module_elts[:]
    1824          assert 0 < len(module_elts)
    1825          if not inhibit_extension:
    1826              assert not module_elts[-1].endswith('.py')
    1827              module_elts[-1] = '%s.py' % (module_elts[-1],)
    1828          return os.path.join(self.bindingRoot(), *module_elts)
    1829
    1830 -    def generateToFiles (self):
    1831          return self.__generateToFiles
    1832      __generateToFiles = None
    1833
    1834 -    def modulePathData (self, module):
    1835          # file system path to where the bindings are written
    1836          # module path from which the bindings are normally imported
    1837          # file object into which bindings are written
    1838
    1839          module_path = None
    1840          if isinstance(module, NamespaceModule):
    1841              mr = module.moduleRecord()
    1842              if mr is None:
    1843                  return ('/dev/null', None, None)
    1844              if self.generationUID() != mr.generationUID():
    1845                  return ('/dev/null', None, None)
    1846              if not self.generateToFiles():
    1847                  return ('/dev/null', None, None)
    1848              if mr.namespace().isBuiltinNamespace() and (not self.allowBuiltinGeneration()):
    1849                  return ('/dev/null', None, None)
    1850              module_path = mr.modulePath()
    1851              assert module_path is not None, 'No path specified for module %s' % (mr,)
    1852              #if pyxb.namespace.XMLSchema != ns:
    1853              #    return ('/dev/null', None, None)
    1854              #module_path="bogus.xsd"
    1855              module_elts = module_path.split('.')
    1856              if self.writeForCustomization():
    1857                  import_file_path = self.__moduleFilePath(module_elts)
    1858                  module_elts.insert(-1, 'raw')
    1859                  if not os.path.exists(import_file_path):
    1860                      raw_module_path = '.'.join(module_elts)
    1861                      fd = pyxb.utils.utility.OpenOrCreate(import_file_path)
    1862                      impt = '''# -*- coding: utf-8 -*-
    1863  from %s import *
    1864  '''  % (raw_module_path,)
    1865                      impd = impt.encode('utf-8')
    1866                      fd.write(impd)
    1867                      fd.close()
    1868              binding_file_path = self.__moduleFilePath(module_elts)
    1869              try:
    1870                  binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID())
    1871              except OSError as e:
    1872                  if errno.EEXIST == e.errno:
    1873                      raise pyxb.BindingGenerationError('Target file %s for module %s bindings exists with other content' % (binding_file_path, mr))
    1874                  raise
    1875          elif isinstance(module, NamespaceGroupModule):
    1876              if not self.generateToFiles():
    1877                  raise pyxb.BindingGenerationError('Generation of namespace groups requires generate-to-files')
    1878              module_elts = []
    1879              if self.modulePrefix():
    1880                  module_elts.extend(self.modulePrefix().split('.'))
    1881              if self.writeForCustomization():
    1882                  module_elts.append('raw')
    1883              in_use = set()
    1884              while True:
    1885                  module_elts.append(pyxb.utils.utility.PrepareIdentifier('nsgroup', in_use, protected=True))
    1886                  try:
    1887                      binding_file_path = self.__moduleFilePath(module_elts)
    1888                      _log.info('Attempting group %s uid %s at %s', module, module.moduleUID(), binding_file_path)
    1889                      binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID())
    1890                      break
    1891                  except OSError as e:
    1892                      if errno.EEXIST != e.errno:
    1893                          raise
    1894                  module_elts.pop()
    1895              module_path = '.'.join(module_elts)
    1896          else:
    1897              assert False
    1898          if self.generateToFiles():
    1899              for n in range(len(module_elts)-1):
    1900                  sub_path = self.__moduleFilePath(module_elts[:1+n], inhibit_extension=True)
    1901                  init_path = os.path.join(sub_path, '__init__.py')
    1902                  if not os.path.exists(init_path):
    1903                      open(init_path, 'w')
    1904          return (binding_file_path, binding_file, module_path)
    1905
    1906 -    def schemaRoot (self):
    1907          """The directory from which entrypoint schemas specified as
    1908          relative file paths will be read."""
    1909          return self.__schemaRoot
    1910 -    def setSchemaRoot (self, schema_root):
    1911          if not schema_root.endswith(os.sep):
    1912              schema_root = schema_root + os.sep
    1913          self.__schemaRoot = schema_root
    1914          return self
    1915      __schemaRoot = None
    1916
    1917 -    def schemaStrippedPrefix (self):
    1918          """Optional string that is stripped from the beginning of
    1919          schemaLocation values before loading from them.
    1920
    1921          This applies only to the values of schemaLocation attributes
    1922          in C{import} and C{include} elements.  Its purpose is to
    1923          convert absolute schema locations into relative ones to allow
    1924          offline processing when all schema are available in a local
    1925          directory.  See C{schemaRoot}.
    1926          """
    1927          return self.__schemaStrippedPrefix
    1928 -    def setSchemaStrippedPrefix (self, schema_stripped_prefix):
    1929          self.__schemaStrippedPrefix = schema_stripped_prefix
    1930          return self
    1931      __schemaStrippedPrefix = None
    1932
    1933 -    def locationPrefixRewriteMap (self):
    1934          """Optional map to rewrite schema locations.
    1935
    1936          This applies only to the values of schemaLocation attributes
    1937          in C{import} and C{include} elements.  Its purpose is to
    1938          convert remote or absolute schema locations into local or
    1939          relative ones to allow offline processing when all schema are
    1940          available in a local directory.  See C{schemaRoot}.
    1941          """
    1942          return self.__locationPrefixRewriteMap
    1943 -    def setLocationPrefixRewriteMap (self, location_prefix_rewrite_map):
    1944          self.__locationPrefixMap.clear()
    1945          self.__locationPrefixMap.update(location_prefix_rewrite_map)
    1946          return self
    1947 -    def addLocationPrefixRewrite (self, prefix, substituent):
    1948          """Add a rewrite entry for schema locations.
    1949
    1950          @param prefix : A text prefix that should be removed from
    1951          schema location URIs.
    1952
    1953          @param substituent : The text prefix that should replace
    1954          C{prefix} as a prefix in a schema location URI.
    1955          """
    1956
    1957          self.__locationPrefixRewriteMap[prefix] = substituent
    1958          return self
    1959 -    def argAddLocationPrefixRewrite (self, prefix_rewrite):
    1960          """Add a rewrite entry for schema locations.
    1961
    1962          Parameter values are strings of the form C{pfx=sub}.  The
    1963          effect is that a schema location that begins with C{pfx} is
    1964          rewritten so that it instead begins with C{sub}."""
    1965          try:
    1966              (prefix, substituent) = prefix_rewrite.split('=', 1)
    1967          except:
    1968              raise
    1969          self.addLocationPrefixRewrite(prefix, substituent)
    1970      __locationPrefixMap = {}
    1971
    1972 -    def schemaLocationList (self):
    1973          """A list of locations from which entrypoint schemas are to be
    1974          read.
    1975
    1976          The values in the list are either URIs, or tuples consisting
    1977          of a value and a callable which, when passed the generator
    1978          object and the value, will return a
    1979          L{pyxb.xmlschema.structures.Schema} instance.  See
    1980          L{addSchemaLocation}.
    1981
    1982          See also L{addSchemaLocation} and L{schemas}.
    1983          """
    1984          return self.__schemaLocationList
    1985 -    def setSchemaLocationList (self, schema_location_list):
    1986          self.__schemaLocationList[:] = []
    1987          self.__schemaLocationList.extend(schema_location_list)
    1988          return self
    1989 -    def addSchemaLocation (self, schema_location, converter=None):
    1990          """Add the location of an entrypoint schema.
    1991
    1992          @param schema_location: The location of the schema.  This
    1993          should be a URL; if the schema location does not have a URL
    1994          scheme (e.g., C{http:}), it is assumed to be a file, and if it
    1995          is not an absolute path is located relative to the
    1996          C{schemaRoot}.
    1997
    1998          @keyword converter: Optional callable that will be invoked
    1999          with the generator instance and the schema location, and is
    2000          expected to return a L{pyxb.xmlschema.structures.Schema}
    2001          instance.  If absent, the contents of the location are
    2002          converted directly.
    2003
    2004          @note: The C{converter} argument derives from WSDL support: we
    2005          need to add to the sequence of schema locations a URI of
    2006          something that will not parse as a schema, but does have inner
    2007          material that can if treated properly.  "Treated properly" may
    2008          include having the archive path and other namespace
    2009          manipulations configured before anything is done to it.
    2010          """
    2011          self.__schemaLocationList.append( (schema_location, converter) )
    2012          return self
    2013 -    def argAddSchemaLocation (self, schema_location):
    2014          """Add the location of an entrypoint schema.  The provided
    2015          value should be a URL; if it does not have a URL scheme (e.g.,
    2016          C{http:}), it is assumed to be a file, and if it is not an
    2017          absolute path is located relative to the C{schemaRoot}."""
    2018          self.addSchemaLocation(schema_location)
    2019      __schemaLocationList = None
    2020
    2021 -    def schemas (self):
    2022          """Schema for which bindings should be generated.
    2023
    2024          These may be L{Schema<pyxb.xmlschema.structures.Schema>}
    2025          instances, or strings; the latter is preferred, and is parsed
    2026          into a Schema instance when required.
    2027
    2028          This is the list of entrypoint schemas for binding generation.
    2029          Values in L{schemaLocationList} are read and converted into
    2030          schema, then appended to this list.  Values from L{moduleList}
    2031          are applied starting with the first schema in this list.
    2032          """
    2033          return self.__schemas[:]
    2034 -    def setSchemas (self, schemas):
    2035          self.__schemas[:] = []
    2036          self.__schemas.extend(schemas)
    2037          return self
    2038 -    def addSchema (self, schema):
    2039          self.__schemas.append(schema)
    2040          return self
    2041      __schemas = None
    2042
    2043 -    def namespaces (self):
    2044          """The set of L{namespaces<pyxb.namespace.Namespace>} for
    2045          which bindings will be generated.
    2046
    2047          This is the set of namespaces read from entrypoint schema,
    2048          closed under reference to namespaces defined by schema import.
    2049
    2050          @rtype: C{set}
    2051          """
    2052          return self.__namespaces.copy()
    2053 -    def setNamespaces (self, namespace_set):
    2054          self.__namespaces.clear()
    2055          self.__namespaces.update(namespace_set)
    2056          return self
    2057 -    def addNamespace (self, namespace):
    2058          self.__namespaces.add(namespace)
    2059          return self
    2060      __namespaces = None
    2061
    2062 -    def moduleList (self):
    2063          """A list of module names to be applied in order to the namespaces of entrypoint schemas"""
    2064          return self.__moduleList[:]
    2065 -    def _setModuleList (self, module_list):
    2066          self.__moduleList[:] = []
    2067          self.__moduleList.extend(module_list)
    2068          return self
    2069
    2070 -    def addModuleName (self, module_name):
    2071          """Add a module name corresponding to an entrypoint schema.
    2072
    2073          The namespace defined by the corresponding schema will be
    2074          written to a binding using the given module name, adjusted by
    2075          L{modulePrefix}."""
    2076          self.__moduleList.append(module_name)
    2077          return self
    2078      __moduleList = None
    2079
    2080 -    def modulePrefix (self):
    2081          """The prefix for binding modules.
    2082
    2083          The base name for the module holding a binding is taken from
    2084          the moduleList, moduleMap, or an XMLNS prefix associated with
    2085          the namespace in a containing schema.  This value, if present,
    2086          is used as a prefix to allow a deeper module hierarchy."""
    2087          return self.__modulePrefix
    2088 -    def setModulePrefix (self, module_prefix):
    2089          self.__modulePrefix = module_prefix
    2090          return self
    2091      __modulePrefix = None
    2092
    2093 -    def namespaceModuleMap (self):
    2094          """A map from namespace URIs to the module to be used for the
    2095          corresponding generated binding.
    2096
    2097          Module values are adjusted by L{modulePrefix} if that has been
    2098          specified.
    2099
    2100          An entry in this map for a namespace supersedes the module
    2101          specified in moduleList if the namespace is defined by an
    2102          entrypoint schema.
    2103
    2104          @return: A reference to the namespace module map.
    2105          """
    2106          return self.__namespaceModuleMap
    2107      __namespaceModuleMap = None
    2108
    2109 -    def archivePath (self):
    2110          """A colon-separated list of paths from which namespace
    2111          archives can be read.
    2112
    2113          The default path is the contents of the C{PYXB_ARCHIVE_PATH}
    2114          environment variable, or the standard path configured at
    2115          installation time.  Any file with the extension C{.wxs} found
    2116          in one of these directories is examined to see whether it is a
    2117          namespace archive.
    2118          """
    2119          return self.__archivePath
    2120 -    def setArchivePath (self, archive_path):
    2121          self.__archivePath = archive_path
    2122          return self
    2123      __archivePath = None
    2124
    2125 -    def noLoadNamespaces (self):
    2126          """A frozenset of namespaces that must not be loaded from an archive."""
    2127          return frozenset(self.__noLoadNamespaces)
    2128 -    def _setNoLoadNamespaces (self, namespace_set):
    2129          """Record the set of namespaces that should not be loaded from an archive.
    2130
    2131          The expectation is that any required entities in the namespace
    2132          will be defined by loading schema."""
    2133          self.__noLoadNamespaces.clear()
    2134          self.__noLoadNamespaces.update([ pyxb.namespace.NamespaceInstance(_ns) for _ns in namespace_set ])
    2135 -    def addNoLoadNamespace (self, namespace):
    2136          """Mark that the specified namespace should not be loaded from an archive.
    2137
    2138          Use this when you are generating bindings for an application
    2139          that has a restricted profile of a namespace that would
    2140          otherwise be read from an archive.  Be aware that this removes
    2141          any knowledge of any archive in which this namespace is
    2142          present as a non-private member."""
    2143          self.__noLoadNamespaces.add(pyxb.namespace.NamespaceInstance(namespace))
    2144      __noloadNamespaces = None
    2145
    2146 -    def importAugmentableNamespaces (self):
    2147          """A list of namespaces for which new bindings are allowd."""
    2148          return frozenset(self.__importAugmentableNamespaces)
    2149 -    def _setImportAugmentableNamespaces (self, namespace_set):
    2150          """Return the set of namespaces that may be augmented by import directives."""
    2151          self.__importAugmentableNamespaces.clear()
    2152          self.__importAugmentableNamespaces.update([ pyxb.namespace.NamespaceInstance(_ns) for _ns in namespace_set ])
    2153 -    def addImportAugmentableNamespace (self, namespace):
    2154          """Mark that the specified namespace may be imported by new bindings.
    2155
    2156          Normally namespaces that are available from archives are
    2157          considered to be complete, and schema locations in import
    2158          directives are ignored.  Use this to indicate that the
    2159          bindings being generated import new bindings.
    2160
    2161          Note that attempts to import schema that contributed to the
    2162          archive will only be detected if the archive was generated
    2163          from the same schemaLocation URI; if the archive was generated
    2164          from a different source component definitions might
    2165          conflict."""
    2166          self.__importAugmentableNamespaces.add(pyxb.namespace.NamespaceInstance(namespace))
    2167      __importAugmentableNamespaces = None
    2168
    2169 -    def archiveToFile (self):
    2170          """Optional file into which the archive of namespaces will be written.
    2171
    2172          Subsequent generation actions can read pre-parsed namespaces
    2173          from this file, and therefore reference the bindings that were
    2174          built earlier rather than re-generating them.
    2175
    2176          The file name should normally end with C{.wxs}."""
    2177          return self.__archiveToFile
    2178 -    def setArchiveToFile (self, archive_to_file):
    2179          self.__archiveToFile = archive_to_file
    2180          return self
    2181      __archiveToFile = None
    2182
    2183 -    def setNamespaceVisibility (self, namespace, visibility):
    2184          namespace = pyxb.namespace.NamespaceInstance(namespace)
    2185          self.__namespaceVisibilityMap[namespace] = visibility
    2186          pass
    2187 -    def _setNamespaceVisibilities (self, public, private):
    2188          if public is None:
    2189              public = set()
    2190          if private is None:
    2191              private = set()
    2192          self.__namespaceVisibilityMap.clear()
    2193          self.__namespaceVisibilityMap.update(dict.fromkeys(public, True))
    2194          self.__namespaceVisibilityMap.update(dict.fromkeys(private, False))
    2195 -    def namespaceVisibilityMap (self):
    2196          """Indicates, for specific namespaces, whether their
    2197          visibility in the archive should be public or private."""
    2198          return self.__namespaceVisibilityMap.copy()
    2199      __namespaceVisibilityMap = None
    2200
    2201 -    def defaultNamespacePublic (self):
    2202          """Indicates whether unmentioned namespaces will be public or private (default) in the archive.
    2203
    2204          A namespace is I{mentioned} if it is the target namespace of
    2205          an entrypoint schema, or appears in a namespace visibility
    2206          specification.  I.e., this default applies only to namespaces
    2207          that are modified as a result of including some schema, which
    2208          is generally a local customization of something.
    2209          """
    2210          return self.__defaultNamespacePublic
    2211 -    def setDefaultNamespacePublic (self, default_namespace_public):
    2212          self.__defaultNamespacePublic = default_namespace_public
    2213      __defaultNamespacePublic = None
    2214
    2215 -    def validateChanges (self):
    2216          """Indicates whether the bindings should validate mutations
    2217          against the content model."""
    2218          return self.__validateChanges
    2219 -    def setValidateChanges (self, validate_changes):
    2220          self.__validateChanges = validate_changes
    2221          return self
    2222      __validateChanges = None
    2223
    2224 -    def writeForCustomization (self):
    2225          """Indicates whether the binding Python code should be written into a sub-module for customization.
    2226
    2227          If enabled, a module C{path.to.namespace} will be written to
    2228          the file C{path/to/raw/namespace.py}, so that the file
    2229          C{path/to/namespace.py} can import it and override behavior."""
    2230          return self.__writeForCustomization
    2231 -    def setWriteForCustomization (self, write_for_customization):
    2232          self.__writeForCustomization = write_for_customization
    2233          return self
    2234      __writeForCustomization = None
    2235
    2236 -    def allowAbsentModule (self):
    2237          """Indicates whether the code generator is permitted to
    2238          process namespace for which no module path can be determined.
    2239
    2240          Use this only when generating bindings that will not be
    2241          referenced by other bindings."""
    2242          return self.__allowAbsentModule
    2243 -    def setAllowAbsentModule (self, allow_absent_module):
    2244          self.__allowAbsentModule = allow_absent_module
    2245          return self
    2246      __allowAbsentModule = None
    2247
    2248 -    def allowBuiltinGeneration (self):
    2249          """Indicates whether bindings will be written for namespaces that are built-in to PyXB.
    2250
    2251          This must be enabled when building bindings for the XML,
    2252          XMLSchema instance, and other built-in namespaces.  Normally
    2253          generation of these namespaces is inhibited lest it produce
    2254          inconsistencies."""
    2255          return self.__allowBuiltinGeneration
    2256 -    def setAllowBuiltinGeneration (self, allow_builtin_generation):
    2257          self.__allowBuiltinGeneration = allow_builtin_generation
    2258          return self
    2259      __allowBuiltinGeneration = None
    2260
    2261 -    def uriContentArchiveDirectory (self):
    2262          """The directory path into which any content retrieved by URI will be written.
    2263
    2264          This serves as a local cache, and to give you an opportunity
    2265          to inspect material retrieved from some other system.
    2266          @rtype: C{str}"""
    2267          return self.__uriContentArchiveDirectory
    2268 -    def setUriContentArchiveDirectory (self, ucad):
    2269          self.__uriContentArchiveDirectory = ucad
    2270      __uriContentArchiveDirectory = None
    2271
    2272 -    def loggingConfigFile (self):
    2273          """A file provided to L{logging.config.fileConfig} to control log messages.
    2274
    2275          In the absence of other configuration the Python standard logging infrastructure is used in its
    2276          default configuration.
    2277
    2278          @rtype: C{str}"""
    2279          return self.__loggingConfigFile
    2280 -    def setLoggingConfigFile (self, logging_config_file):
    2281          self.__loggingConfigFile = logging_config_file
    2282      __loggingConfigFile = None
    2283
    2284 -    def __init__ (self, *args, **kw):
    2285          """Create a configuration to be used for generating bindings.
    2286
    2287          Arguments are treated as additions to the schema location list
    2288          after all keywords have been processed.
    2289
    2290          @keyword binding_root: Invokes L{setBindingRoot}
    2291          @keyword schema_root: Invokes L{setSchemaRoot}
    2292          @keyword schema_stripped_prefix: Invokes L{setSchemaStrippedPrefix}
    2293          @keyword location_prefix_rewrite_map: Invokes L{setLocationPrefixRewriteMap}
    2294          @keyword schema_location_list: Invokes L{setSchemaLocationList}
    2295          @keyword module_list: Invokes L{_setModuleList}
    2296          @keyword module_prefix: Invokes L{setModulePrefix}
    2297          @keyword archive_path: Invokes L{setArchivePath}
    2298          @keyword no_load_namespaces: Invokes L{_setNoLoadNamespaces}
    2299          @keyword import_augmentable_namespaces: Invokes L{_setImportAugmentableNamespaces}
    2300          @keyword archive_to_file: Invokes L{setArchiveToFile}
    2301          @keyword public_namespace: Invokes L{setNamespaceVisibility}
    2302          @keyword private_namespace: Invokes L{setNamespaceVisibility}
    2303          @keyword default_namespace_public: Invokes L{setDefaultNamespacePublic}
    2304          @keyword validate_changes: Invokes L{setValidateChanges}
    2305          @keyword namespace_module_map: Initializes L{namespaceModuleMap}
    2306          @keyword schemas: Invokes L{setSchemas}
    2307          @keyword namespaces: Invokes L{setNamespaces}
    2308          @keyword write_for_customization: Invokes L{setWriteForCustomization}
    2309          @keyword allow_builtin_generation: Invokes L{setAllowBuiltinGeneration}
    2310          @keyword allow_absent_module: Invokes L{setAllowAbsentModule}
    2311          @keyword generate_to_files: Sets L{generateToFiles}
    2312          @keyword uri_content_archive_directory: Invokes L{setUriContentArchiveDirectory}
    2313          @keyword logging_config_file: Invokes L{setLoggingConfigFile}
    2314          """
    2315          argv = kw.get('argv')
    2316          if argv is not None:
    2317              kw = {}
    2318          self.__bindingRoot = kw.get('binding_root', self._DEFAULT_bindingRoot)
    2319          self.__schemaRoot = kw.get('schema_root', '.')
    2320          self.__schemaStrippedPrefix = kw.get('schema_stripped_prefix')
    2321          self.__locationPrefixRewriteMap = kw.get('location_prefix_rewrite_map', {})
    2322          self.__schemas = []
    2323          self.__schemaLocationList = kw.get('schema_location_list', [])[:]
    2324          self.__moduleList = kw.get('module_list', [])[:]
    2325          self.__modulePrefix = kw.get('module_prefix')
    2326          self.__archivePath = kw.get('archive_path', pyxb.namespace.archive.GetArchivePath())
    2327          self.__noLoadNamespaces = kw.get('no_load_namespaces', set()).copy()
    2328          self.__importAugmentableNamespaces = kw.get('import_augmentable_namespaces', set()).copy()
    2329          self.__archiveToFile = kw.get('archive_to_file')
    2330          self.__namespaceVisibilityMap = {}
    2331          self._setNamespaceVisibilities(kw.get('public_namespaces', set()), kw.get('private_namespaces', set()))
    2332          self.__defaultNamespacePublic = kw.get('default_namespace_public', False)
    2333          self.__validateChanges = kw.get('validate_changes', True)
    2334          self.__namespaceModuleMap = kw.get('namespace_module_map', {}).copy()
    2335          self.__schemas = kw.get('schemas', [])[:]
    2336          self.__namespaces = set(kw.get('namespaces', []))
    2337          self.__writeForCustomization = kw.get('write_for_customization', False)
    2338          self.__allowBuiltinGeneration = kw.get('allow_builtin_generation', False)
    2339          self.__allowAbsentModule = kw.get('allow_absent_module', False)
    2340          self.__generateToFiles = kw.get('generate_to_files', True)
    2341          self.__uriContentArchiveDirectory = kw.get('uri_content_archive_directory')
    2342          self.__loggingConfigFile = kw.get('logging_config_file')
    2343          self.__unnamedModulePaths = set()
    2344
    2345          if argv is not None:
    2346              self.applyOptionValues(*self.optionParser().parse_args(argv))
    2347          [ self.addSchemaLocation(_a) for _a in args ]
    2348
    2349          self.__generationUID = pyxb.utils.utility.UniqueIdentifier()
    2350
    2351          pyxb.namespace.XML.validateComponentModel()
    2352
    2353      __stripSpaces_re = re.compile('\s\s\s+')
    2354 -    def __stripSpaces (self, string):
    2355          return self.__stripSpaces_re.sub(' ', string)
    2356
    2357      __OptionSetters = (
    2358          ('binding_root', setBindingRoot),
    2359          ('schema_root', setSchemaRoot),
    2360          ('schema_stripped_prefix', setSchemaStrippedPrefix),
    2361          ('location_prefix_rewrite', argAddLocationPrefixRewrite),
    2362          ('schema_location', setSchemaLocationList),
    2363          ('module', _setModuleList),
    2364          ('module_prefix', setModulePrefix),
    2365          ('archive_path', setArchivePath),
    2366          ('no_load_namespace', _setNoLoadNamespaces),
    2367          ('import_augmentable_namespace', _setImportAugmentableNamespaces),
    2368          ('archive_to_file', setArchiveToFile),
    2369          ('default_namespace_public', setDefaultNamespacePublic),
    2370          ('validate_changes', setValidateChanges),
    2371          ('write_for_customization', setWriteForCustomization),
    2372          ('allow_builtin_generation', setAllowBuiltinGeneration),
    2373          ('allow_absent_module', setAllowAbsentModule),
    2374          ('uri_content_archive_directory', setUriContentArchiveDirectory),
    2375          ('logging_config_file', setLoggingConfigFile)
    2376          )
    2377 -    def applyOptionValues (self, options, args=None):
    2378          for (tag, method) in self.__OptionSetters:
    2379              v = getattr(options, tag)
    2380              if v is not None:
    2381                  method(self, v)
    2382          public_namespaces = getattr(options, 'public_namespace')
    2383          private_namespaces = getattr(options, 'private_namespace')
    2384          self._setNamespaceVisibilities(public_namespaces, private_namespaces)
    2385          if args is not None:
    2386              self.__schemaLocationList.extend(args)
    2387          pyxb.utils.utility.SetLocationPrefixRewriteMap(self.locationPrefixRewriteMap())
    2388          if self.__loggingConfigFile is not None:
    2389              logging.config.fileConfig(self.__loggingConfigFile)
    2390
    2391 -    def setFromCommandLine (self, argv=None):
    2392          if argv is None:
    2393              argv = sys.argv[1:]
    2394          (options, args) = self.optionParser().parse_args(argv)
    2395          self.applyOptionValues(options, args)
    2396          return self
    2397
    2398 -    def generationUID (self):
    2399          """A unique identifier associated with this Generator instance.
    2400
    2401          This is an instance of L{pyxb.utils.utility.UniqueIdentifier}.
    2402          Its associated objects are
    2403          L{pyxb.namespace.archive._SchemaOrigin} instances, which
    2404          identify schema that contribute to the definition of a
    2405          namespace."""
    2406          return self.__generationUID
    2407      __generationUID = None
    2408
    2409 -    def optionParser (self, reset=False):
    2410          """Return an C{optparse.OptionParser} instance tied to this configuration.
    2411
    2412          @param reset: If C{False} (default), a parser created in a
    2413          previous invocation will be returned.  If C{True}, any
    2414          previous option parser is discarded and a new one created.
    2415          @type reset: C{bool}
    2416          """
    2417          if reset or (self.__optionParser is None):
    2418              parser = optparse.OptionParser(usage="%prog [options] [more schema locations...]",
    2419                                             version='%%prog from PyXB %s' % (pyxb.__version__,),
    2420                                             description='Generate bindings from a set of XML schemas')
    2421
    2422              group = optparse.OptionGroup(parser, 'Identifying Schema', 'Specify and locate schema for which bindings should be generated.')
    2423              group.add_option('--schema-location', '-u', metavar="FILE_or_URL",
    2424                               action='append',
    2425                               help=self.__stripSpaces(self.argAddSchemaLocation.__doc__))
    2426              group.add_option('--schema-root', metavar="DIRECTORY",
    2427                               help=self.__stripSpaces(self.schemaRoot.__doc__))
    2428              group.add_option('--schema-stripped-prefix', metavar="TEXT", type='string',
    2429                               help=self.__stripSpaces(self.schemaStrippedPrefix.__doc__))
    2430              group.add_option('--location-prefix-rewrite', metavar="TEXT", type='string',
    2431                               help=self.__stripSpaces(self.argAddLocationPrefixRewrite.__doc__))
    2432              group.add_option('--uri-content-archive-directory', metavar="DIRECTORY",
    2433                               help=self.__stripSpaces(self.uriContentArchiveDirectory.__doc__))
    2434              parser.add_option_group(group)
    2435
    2436              group = optparse.OptionGroup(parser, 'Configuring Bindings', 'Specify where generated bindings should be written, and how they will be accessed from Python.')
    2437              group.add_option('--module', '-m', metavar="MODULE",
    2438                               action='append',
    2439                               help=self.__stripSpaces(self.addModuleName.__doc__))
    2440              group.add_option('--module-prefix', metavar="MODULE",
    2441                               help=self.__stripSpaces(self.modulePrefix.__doc__))
    2442              group.add_option('--binding-root', metavar="DIRECTORY",
    2443                               help=self.__stripSpaces(self.bindingRoot.__doc__))
    2444              group.add_option('-r', '--write-for-customization',
    2445                               action='store_true', dest='write_for_customization',
    2446                               help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns on the feature.'))
    2447              group.add_option('--no-write-for-customization',
    2448                               action='store_false', dest='write_for_customization',
    2449                               help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns off the feature (I{default}).'))
    2450              parser.add_option_group(group)
    2451
    2452              group = optparse.OptionGroup(parser, 'Reading Namespace Archives', 'Locating and loading (or inhibiting load of) namespace archives.')
    2453              group.add_option('--archive-path', metavar="PATH",
    2454                               help=self.__stripSpaces(self.archivePath.__doc__))
    2455              group.add_option('--import-augmentable-namespace', metavar="URI",
    2456                               action='append',
    2457                               help=self.__stripSpaces(self.addImportAugmentableNamespace.__doc__))
    2458              group.add_option('--no-load-namespace', metavar="URI",
    2459                               action='append',
    2460                               help=self.__stripSpaces(self.addNoLoadNamespace.__doc__))
    2461              parser.add_option_group(group)
    2462
    2463              group = optparse.OptionGroup(parser, 'Writing Namespace Archives', 'Control the location and content of a namespace archive corresponding to a binding generation.')
    2464              group.add_option('--archive-to-file', metavar="FILE",
    2465                               help=self.__stripSpaces(self.archiveToFile.__doc__))
    2466              group.add_option('--public-namespace', metavar="URI",
    2467                               action='append',
    2468                               help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a public archive member.'))
    2469              group.add_option('--private-namespace', metavar="URI",
    2470                               action='append',
    2471                               help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a private archive member.'))
    2472              group.add_option('--default-namespace-public',
    2473                               action="store_true", dest='default_namespace_public',
    2474                               help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{public} (I{default}).'))
    2475              group.add_option('--default-namespace-private',
    2476                               action="store_false", dest='default_namespace_public',
    2477                               help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{private}.'))
    2478              parser.add_option_group(group)
    2479
    2480              group = optparse.OptionGroup(parser, 'Configuring Binding Code Generation', "Control the style and content of the generated bindings.  This is not well-supported, and you are advised to pretend these options don't exist.")
    2481              group.add_option('--validate-changes',
    2482                                action='store_true', dest='validate_changes',
    2483                                help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns on validation (default).'))
    2484              group.add_option('--no-validate-changes',
    2485                                action='store_false', dest='validate_changes',
    2486                                help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns off validation.'))
    2487              parser.add_option_group(group)
    2488
    2489              group = optparse.OptionGroup(parser, 'Miscellaneous Options', "Anything else.")
    2490              group.add_option('--logging-config-file', metavar="FILE",
    2491                               help=self.__stripSpaces(self.loggingConfigFile.__doc__))
    2492              parser.add_option_group(group)
    2493
    2494              group = optparse.OptionGroup(parser, 'Maintainer Options', "Don't use these.  They don't exist.  If they did, they'd do different things at different times, and if you used them you'd probably be sorry.")
    2495
    2496              group.add_option('--allow-absent-module',
    2497                                action='store_true', dest='allow_absent_module',
    2498                                help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns on the feature.'))
    2499              group.add_option('--no-allow-absent-module',
    2500                               action='store_false', dest='allow_absent_module',
    2501                               help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns off the feature (default).'))
    2502              group.add_option('--allow-builtin-generation',
    2503                               action='store_true', dest='allow_builtin_generation',
    2504                               help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns on the feature.'))
    2505              group.add_option('--no-allow-builtin-generation',
    2506                               action='store_false', dest='allow_builtin_generation',
    2507                               help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns off the feature (default).'))
    2508              parser.add_option_group(group)
    2509
    2510              self.__optionParser = parser
    2511          return self.__optionParser
    2512      __optionParser = None
    2513
    2514 -    def getCommandLineArgs (self):
    2515          """Return a command line option sequence that could be used to
    2516          construct an equivalent configuration.
    2517
    2518          @note: If you extend the option parser, as is done by
    2519          C{pyxbgen}, this may not be able to reconstruct the correct
    2520          command line."""
    2521          opts = []
    2522          module_list = self.moduleList()
    2523          schema_list = self.schemaLocationList()
    2524          while module_list and schema_list:
    2525              ml = module_list.pop(0)
    2526              sl = schema_list.pop(0)
    2527              if isinstance(sl, tuple):
    2528                  sl = sl[0]
    2529              opts.extend(['--schema-location=' + sl, '--module=' + ml])
    2530          for sl in schema_list:
    2531              opts.append('--schema-location=' + sl)
    2532          if self.schemaRoot() is not None:
    2533              opts.append('--schema-root=' + self.schemaRoot())
    2534          if self.schemaStrippedPrefix() is not None:
    2535              opts.append('--schema-stripped-prefix=%s' + self.schemaStrippedPrefix())
    2536          for (pfx, sub) in self.locationPrefixRewriteMap():
    2537              opts.append('--location-prefix-rewrite=%s=%s' % (pfx, sub))
    2538          if self.modulePrefix() is not None:
    2539              opts.append('--module-prefix=' + self.modulePrefix())
    2540          opts.append('--binding-root=' + self.bindingRoot())
    2541          if self.archivePath() is not None:
    2542              opts.append('--archive-path=' + self.archivePath())
    2543          for ns in self.noLoadNamespaces():
    2544              opts.append('--no-load-namespace=' + ns.uri())
    2545          for ns in self.importAugmentableNamespaces():
    2546              opts.append('--import-augmentable-namespace=' + ns.uri())
    2547          if self.archiveToFile() is not None:
    2548              opts.append('--archive-to-file=' + self.archiveToFile())
    2549          for (ns, visibility) in self.namespaceVisibilityMap():
    2550              if visibility:
    2551                  opts.append('--public-namespace=' + ns.uri())
    2552              else:
    2553                  opts.append('--private-namespace=' + ns.uri())
    2554          if self.defaultNamespacePublic():
    2555              opts.append('--default-namespace-public')
    2556          else:
    2557              opts.append('--default-namespace-private')
    2558          for (val, opt) in ( (self.validateChanges(), 'validate-changes'),
    2559                              (self.writeForCustomization(), 'write-for-customization'),
    2560                              (self.allowAbsentModule(), 'allow-absent-module'),
    2561                              (self.allowBuiltinGeneration(), 'allow-builtin-generation') ):
    2562              if val:
    2563                  opts.append('--' + opt)
    2564              else:
    2565                  opts.append('--no-' + opt)
    2566          if self.uriContentArchiveDirectory() is not None:
    2567              opts.append('--uri-content-archive-directory=%s' + self.uriContentArchiveDirectory())
    2568          return opts
    2569
    2570 -    def normalizeSchemaLocation (self, sl):
    2571          ssp = self.schemaStrippedPrefix()
    2572          if ssp and sl.startswith(ssp):
    2573              sl = sl[len(ssp):]
    2574          return pyxb.utils.utility.NormalizeLocation(sl, self.schemaRoot())
    2575
    2576 -    def assignModulePath (self, module_record, module_path=None):
    2577          """Provide a Python module path for the module record.
    2578
    2579          This is the path by which the module bindings associated with
    2580          C{module_record} will be imported.
    2581
    2582          If a path had already been assigned to the module, it is left
    2583          in place.
    2584
    2585          @param module_record: Information about a collection of related bindings
    2586          @type module_record: L{pyxb.namespace.archive.ModuleRecord}
    2587
    2588          @param module_path: Default path to use
    2589          @type module_path: C{str}
    2590
    2591          @return: C{module_record}
    2592          """
    2593          if module_record.modulePath() is not None:
    2594              return module_record
    2595          namespace = module_record.namespace()
    2596          if not namespace.isAbsentNamespace():
    2597              # Use the namespace prefix from a referencing schema if no other clue was given
    2598              if (module_path is None) and not (namespace.prefix() is None):
    2599                  module_path = namespace.prefix()
    2600              # Prefer an existing assignment over a new one
    2601              module_path = self.namespaceModuleMap().get(namespace.uri(), module_path)
    2602          if (module_path is None) and self.generateToFiles():
    2603              module_path = pyxb.utils.utility.MakeUnique('binding', self.__unnamedModulePaths)
    2604          if (module_path is not None) and self.modulePrefix(): # non-empty value
    2605              # Prepend a configured module prefix
    2606              module_path = '.'.join([self.modulePrefix(), module_path])
    2607          module_record.setModulePath(module_path)
    2608          return module_record
    2609
    2610      __didResolveExternalSchema = False
    2611 -    def resolveExternalSchema (self):
    2612          if self.__didResolveExternalSchema:
    2613              return
    2614
    2615          # Locate all relevant archives and the namespaces they
    2616          # provide.
    2617          pyxb.namespace.archive.NamespaceArchive.PreLoadArchives(self.archivePath())
    2618
    2619          # Mark the namespaces we were told not to load.  These may be
    2620          # namespaces for which we already have bindings in the search
    2621          # path, but we want to generate completely new ones.
    2622          for ns in self.noLoadNamespaces():
    2623              assert isinstance(ns, pyxb.namespace.Namespace)
    2624              _log.info("Namespace %s marked not loadable" % (ns,))
    2625              ns.markNotLoadable()
    2626
    2627          # Mark the namespaces that we permit to be extended by import
    2628          # statements.
    2629          for ns in self.importAugmentableNamespaces():
    2630              assert isinstance(ns, pyxb.namespace.Namespace)
    2631              _log.info("Namespace %s marked import-augmentable" % (ns,))
    2632              ns.setImportAugmentable(True)
    2633
    2634          # Read all the schema we were told about.
    2635          while self.__schemaLocationList:
    2636              sl = self.__schemaLocationList.pop(0)
    2637              if isinstance(sl, tuple):
    2638                  (sl, converter) = sl
    2639              else:
    2640                  converter = None
    2641              try:
    2642                  if converter is None:
    2643                      schema = xs.schema.CreateFromLocation(absolute_schema_location=self.normalizeSchemaLocation(sl),
    2644                                                            generation_uid=self.generationUID(),
    2645                                                            uri_content_archive_directory=self.uriContentArchiveDirectory())
    2646                  else:
    2647                      schema = converter(self, sl)
    2648                  self.addSchema(schema)
    2649              except pyxb.SchemaUniquenessError as e:
    2650                  _log.info('Skipped redundant translation of %s defining %s', e.schemaLocation(), e.namespace())
    2651                  self.addSchema(e.existingSchema())
    2652
    2653          # Assign Python modules to hold bindings for the schema we're
    2654          # processing.
    2655          for schema in self.__schemas:
    2656              if isinstance(schema, basestring):
    2657                  schema = xs.schema.CreateFromDocument(schema, generation_uid=self.generationUID())
    2658              origin = schema.originRecord()
    2659              assert origin is not None
    2660              module_path = None
    2661              if self.__moduleList:
    2662                  module_path = self.__moduleList.pop(0)
    2663              self.assignModulePath(origin.moduleRecord(), module_path)
    2664              assert schema.targetNamespace() == origin.moduleRecord().namespace()
    2665              self.addNamespace(schema.targetNamespace())
    2666          self.__didResolveExternalSchema = True
    2667
    2668          # Discard any existing component information
    2669          self.__componentGraph = None
    2670          self.__componentOrder = None
    2671
    2672 -    def __graphFromComponents (self, components, include_lax):
    2673          components = components.copy()
    2674          component_graph = pyxb.utils.utility.Graph()
    2675          need_visit = components.copy()
    2676          bindable_fn = lambda _c: isinstance(_c, xs.structures.ElementDeclaration) or _c.isTypeDefinition()
    2677          while 0 < len(need_visit):
    2678              c = need_visit.pop()
    2679              assert c is not None
    2680              assert bindable_fn(c) or include_lax
    2681              assert c._objectOrigin() is not None, '%s %s has no origin' % (type(c), c)
    2682              component_graph.addNode(c)
    2683              br = c.bindingRequires(reset=True, include_lax=include_lax)
    2684              for cd in br:
    2685                  assert bindable_fn(cd) or include_lax, '%s produced %s in requires' % (type(c), type(cd))
    2686                  if cd._objectOrigin() is None:
    2687                      assert isinstance(cd, (pyxb.xmlschema.structures.Annotation, pyxb.xmlschema.structures.Wildcard))
    2688                      continue
    2689                  if (cd._objectOrigin().moduleRecord() in self.__moduleRecords) and not (cd in components):
    2690                      components.add(cd)
    2691                      need_visit.add(cd)
    2692                  if cd in components:
    2693                      component_graph.addEdge(c, cd)
    2694          return component_graph
    2695
    2696 -    def __resolveComponentDependencies (self):
    2697          self.resolveExternalSchema()
    2698
    2699          bindable_fn = lambda _c: isinstance(_c, xs.structures.ElementDeclaration) or _c.isTypeDefinition()
    2700
    2701          self.__moduleRecords = set()
    2702          all_components = set()
    2703          for origin in self.generationUID().associatedObjects():
    2704              mr = origin.moduleRecord()
    2705              if not (mr in self.__moduleRecords):
    2706                  self.__moduleRecords.add(mr)
    2707                  mr.completeGenerationAssociations()
    2708              all_components.update(origin.originatedObjects())
    2709
    2710          namespaces = set()
    2711          for mr in self.__moduleRecords:
    2712              if mr.namespace().isBuiltinNamespace() and not self.allowBuiltinGeneration():
    2713                  continue
    2714              namespaces.add(mr.namespace())
    2715          pyxb.namespace.resolution.ResolveSiblingNamespaces(namespaces)
    2716
    2717          # Mark module visibility.  Entry-point namespaces default to
    2718          # public.
    2719          for ns in self.namespaces():
    2720              self.__namespaceVisibilityMap.setdefault(ns, True)
    2721
    2722          # Generate the graph from all components and descend into lax
    2723          # requirements; otherwise we might miss anonymous types hidden
    2724          # inside attribute declarations and the like.
    2725          component_graph = self.__graphFromComponents(all_components, True)
    2726
    2727          binding_components = set(filter(bindable_fn, component_graph.nodes()))
    2728          for c in binding_components:
    2729              assert bindable_fn(c), 'Unexpected %s in binding components' % (type(c),)
    2730              c._setBindingNamespace(c._objectOrigin().moduleRecord().namespace())
    2731
    2732          component_order = []
    2733          root_sets = self.__graphFromComponents(binding_components, False).rootSetOrder()
    2734          if root_sets is None:
    2735              raise pyxb.BindingGenerationError('Unable to partial-order named components')
    2736          for rs in root_sets:
    2737              component_order.extend(sorted(rs, key=lambda _c: _c.schemaOrderSortKey()))
    2738
    2739          self.__componentGraph = component_graph
    2740          self.__componentOrder = component_order
    2741
    2742      __moduleRecords = None
    2743      __componentGraph = None
    2744      __componentOrder = None
    2745
    2746 -    def moduleRecords (self):
    2747          """The set of L{pyxb.namespace.archive.ModuleRecord} instances
    2748          associated with schema processed in this generation
    2749          instance.
    2750
    2751          These should be in one-to-one correspondence with the
    2752          namespaces for which bindings are being generated.  Multiple
    2753          input schemas may contribute to a single module record; all
    2754          material in that record is placed in a single binding file.
    2755          """
    2756          if self.__moduleRecords is None:
    2757              self.__resolveComponentDependencies()
    2758          return self.__moduleRecords
    2759
    2760 -    def componentGraph (self):
    2761          if self.__componentGraph is None:
    2762              self.__resolveComponentDependencies()
    2763          return self.__componentGraph
    2764
    2765 -    def componentOrder (self):
    2766          if self.__componentOrder is None:
    2767              self.__resolveComponentDependencies()
    2768          return self.__componentOrder
    2769
    2770 -    def __generateBindings (self):
    2771
    2772          # Note that module graph may have fewer nodes than
    2773          # self.moduleRecords(), if a module has no components that
    2774          # require binding generation.
    2775
    2776          module_graph = pyxb.utils.utility.Graph()
    2777          [ module_graph.addRoot(_mr) for _mr in self.moduleRecords() ]
    2778          for (s, t) in self.componentGraph().edges():
    2779              module_graph.addEdge(s._objectOrigin().moduleRecord(), t._objectOrigin().moduleRecord())
    2780          module_scc_order = module_graph.sccOrder()
    2781
    2782          record_binding_map = {}
    2783          modules = []
    2784          nsvm = self.namespaceVisibilityMap()
    2785          for mr_scc in module_scc_order:
    2786              scc_modules = [ ]
    2787              for mr in mr_scc:
    2788                  mr._setIsPublic(nsvm.get(mr.namespace(), self.defaultNamespacePublic()))
    2789                  self.assignModulePath(mr)
    2790                  if (mr.modulePath() is None) and self.generateToFiles():
    2791                      raise pyxb.BindingGenerationError('No prefix or module name available for %s' % (mr,))
    2792                  if (not mr.isPublic()) and (mr.modulePath() is not None):
    2793                      elts = mr.modulePath().split('.')
    2794                      elts[-1] = '_%s' % (elts[-1],)
    2795                      mr.setModulePath('.'.join(elts))
    2796                  nsm = NamespaceModule(self, mr, mr_scc)
    2797                  record_binding_map[mr] = nsm
    2798                  scc_modules.append(nsm)
    2799
    2800              scc_modules.sort(key=lambda _nm: _nm.namespace().uri())
    2801              modules.extend(scc_modules)
    2802              if 1 < len(mr_scc):
    2803                  ngm = NamespaceGroupModule(self, scc_modules)
    2804                  modules.append(ngm)
    2805                  for nsm in scc_modules:
    2806                      nsm.setNamespaceGroupModule(ngm)
    2807
    2808          element_declarations = []
    2809          type_definitions = []
    2810          for c in self.componentOrder():
    2811              if isinstance(c, xs.structures.ElementDeclaration) and c._scopeIsGlobal():
    2812                  # Only bind elements this pass, so their names get priority in deconfliction
    2813                  nsm = record_binding_map[c._objectOrigin().moduleRecord()]
    2814                  nsm.bindComponent(c)
    2815                  element_declarations.append(c)
    2816              elif c.isTypeDefinition():
    2817                  type_definitions.append(c)
    2818              else:
    2819                  # No binding generation required
    2820                  pass
    2821
    2822          simple_type_definitions = []
    2823          complex_type_definitions = []
    2824          for td in type_definitions:
    2825              nsm = record_binding_map[td._objectOrigin().moduleRecord()]
    2826              assert nsm is not None, 'No namespace module for %s type %s scope %s namespace %s' % (td.expandedName(), type(td), td._scope(), td.bindingNamespace)
    2827              module_context = nsm.bindComponent(td)
    2828              assert isinstance(module_context, _ModuleNaming_mixin), 'Unexpected type %s' % (type(module_context),)
    2829              if isinstance(td, xs.structures.SimpleTypeDefinition):
    2830                  _PrepareSimpleTypeDefinition(td, self, nsm, module_context)
    2831                  simple_type_definitions.append(td)
    2832              elif isinstance(td, xs.structures.ComplexTypeDefinition):
    2833                  _PrepareComplexTypeDefinition(td, self, nsm, module_context)
    2834                  complex_type_definitions.append(td)
    2835              else:
    2836                  assert False, 'Unexpected component type %s' % (type(td),)
    2837
    2838          for ngm in modules:
    2839              if isinstance(ngm, NamespaceGroupModule):
    2840                  for m in ngm.namespaceModules():
    2841                      m.addImportsFrom(ngm)
    2842
    2843          for std in simple_type_definitions:
    2844              GenerateSTD(std, self)
    2845          for ctd in complex_type_definitions:
    2846              GenerateCTD(ctd, self)
    2847          for ed in element_declarations:
    2848              GenerateED(ed, self)
    2849
    2850          self.__bindingModules = modules
    2851
    2852      __bindingModules = None
    2853 -    def bindingModules (self):
    2854          if self.__componentGraph is None:
    2855              self.__resolveComponentDependencies()
    2856          if self.__bindingModules is None:
    2857              self.__generateBindings()
    2858          return self.__bindingModules
    2859
    2860 -    def writeNamespaceArchive (self):
    2861          archive_file = self.archiveToFile()
    2862          if archive_file is not None:
    2863              ns_archive = pyxb.namespace.archive.NamespaceArchive(generation_uid=self.generationUID())
    2864              try:
    2865                  ns_archive.writeNamespaces(pyxb.utils.utility.OpenOrCreate(archive_file))
    2866                  _log.info('Saved parsed schema to %s URI', archive_file)
    2867              except Exception as e:
    2868                  _log.exception('Failure saving preprocessed schema to %s', archive_file)
    2869                  #try:
    2870                  #    os.unlink(component_model_file)
    2871                  #except (OSError, IOError), e:
    2872                  #    pass
    2873                  if isinstance(e, (AssertionError, AttributeError, TypeError)):
    2874                      raise
    2875
    2876 -    def moduleForComponent (self, component):
    2877          return _ModuleNaming_mixin.ComponentBindingModule(component)
    2878