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