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

Source Code for Module pyxb.binding.generate

   1  # Copyright 2009, Peter A. Bigot 
   2  # 
   3  # Licensed under the Apache License, Version 2.0 (the "License"); you may 
   4  # not use this file except in compliance with the License. You may obtain a 
   5  # copy of the License at: 
   6  # 
   7  #            http://www.apache.org/licenses/LICENSE-2.0 
   8  # 
   9  # Unless required by applicable law or agreed to in writing, software 
  10  # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
  11  # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
  12  # License for the specific language governing permissions and limitations 
  13  # under the License. 
  14   
  15  """The really ugly code that generates the Python bindings.  This 
  16  whole thing is going to be refactored once customized generation makes 
  17  it to the top of the task queue.""" 
  18   
  19  import pyxb 
  20  import pyxb.xmlschema as xs 
  21  import StringIO 
  22  import datetime 
  23  import urlparse 
  24  import errno 
  25   
  26  from pyxb.utils import utility 
  27  from pyxb.utils import templates 
  28  from pyxb.utils import domutils 
  29  import basis 
  30  import content 
  31  import datatypes 
  32  import facets 
  33   
  34  import nfa 
  35   
  36  import types 
  37  import sys 
  38  import traceback 
  39  import xml.dom 
  40  import os.path 
  41  import StringIO 
  42   
  43  # Initialize UniqueInBinding with the public identifiers we generate, 
  44  # import, or otherwise can't have mucked about with. 
  45  UniqueInBinding = set([ 'pyxb', 'sys', 'Namespace', 'ModuleRecord', 'CreateFromDocument', 'CreateFromDOM' ]) 
46 47 -def PrefixModule (value, text=None):
48 if text is None: 49 text = value.__name__ 50 if value.__module__ == datatypes.__name__: 51 return 'pyxb.binding.datatypes.%s' % (text,) 52 if value.__module__ == facets.__name__: 53 return 'pyxb.binding.facets.%s' % (text,) 54 raise pyxb.IncompleteImplementationError('PrefixModule needs support for non-builtin instances')
55
56 -class ReferenceLiteral (object):
57 """Base class for something that requires fairly complex activity 58 in order to generate its literal value.""" 59 60 # Either a STD or a subclass of _Enumeration_mixin, this is the 61 # class in which the referenced object is a member. 62 __ownerClass = None 63 64 # The value to be used as a literal for this object 65 __literal = None 66
67 - def __init__ (self, **kw):
68 # NB: Pre-extend __init__ 69 self.__ownerClass = kw.get('type_definition', None)
70
71 - def setLiteral (self, literal):
72 self.__literal = literal 73 return literal
74
75 - def asLiteral (self):
76 return self.__literal
77
78 - def _addTypePrefix (self, text, **kw):
79 if self.__ownerClass is not None: 80 text = '%s.%s' % (pythonLiteral(self.__ownerClass, **kw), text) 81 return text
82
83 -class ReferenceFacetMember (ReferenceLiteral):
84 __facetClass = None 85
86 - def __init__ (self, **kw):
87 variable = kw.get('variable', None) 88 assert (variable is None) or isinstance(variable, facets.Facet) 89 90 if variable is not None: 91 kw.setdefault('type_definition', variable.ownerTypeDefinition()) 92 self.__facetClass = type(variable) 93 self.__facetClass = kw.get('facet_class', self.__facetClass) 94 95 super(ReferenceFacetMember, self).__init__(**kw) 96 97 self.setLiteral(self._addTypePrefix('_CF_%s' % (self.__facetClass.Name(),), **kw))
98
99 -class ReferenceWildcard (ReferenceLiteral):
100 __wildcard = None 101
102 - def __init__ (self, wildcard, **kw):
103 self.__wildcard = wildcard 104 super(ReferenceWildcard, self).__init__(**kw) 105 106 template_map = { } 107 template_map['Wildcard'] = 'pyxb.binding.content.Wildcard' 108 if (xs.structures.Wildcard.NC_any == wildcard.namespaceConstraint()): 109 template_map['nc'] = templates.replaceInText('%{Wildcard}.NC_any', **template_map) 110 elif isinstance(wildcard.namespaceConstraint(), (set, frozenset)): 111 namespaces = [] 112 for ns in wildcard.namespaceConstraint(): 113 if ns is None: 114 namespaces.append(None) 115 else: 116 namespaces.append(ns.uri()) 117 template_map['nc'] = 'set(%s)' % (",".join( [ repr(_ns) for _ns in namespaces ])) 118 else: 119 assert isinstance(wildcard.namespaceConstraint(), tuple) 120 ns = wildcard.namespaceConstraint()[1] 121 if ns is not None: 122 ns = ns.uri() 123 template_map['nc'] = templates.replaceInText('(%{Wildcard}.NC_not, %{namespace})', namespace=repr(ns), **template_map) 124 template_map['pc'] = wildcard.processContents() 125 self.setLiteral(templates.replaceInText('%{Wildcard}(process_contents=%{Wildcard}.PC_%{pc}, namespace_constraint=%{nc})', **template_map))
126
127 -class ReferenceSchemaComponent (ReferenceLiteral):
128 __component = None 129
130 - def __init__ (self, component, **kw):
131 self.__component = component 132 binding_module = kw['binding_module'] 133 rv = binding_module.referenceSchemaComponent(component) 134 #print '%s in %s is %s' % (component.expandedName(), binding_module, rv) 135 self.setLiteral(rv)
136
137 -class ReferenceNamespace (ReferenceLiteral):
138 __namespace = None 139
140 - def __init__ (self, **kw):
141 self.__namespace = kw['namespace'] 142 binding_module = kw['binding_module'] 143 rv = binding_module.referenceNamespace(self.__namespace) 144 #print '%s in %s is %s' % (self.__namespace, binding_module, rv) 145 self.setLiteral(rv)
146
147 -class ReferenceExpandedName (ReferenceLiteral):
148 __expandedName = None 149
150 - def __init__ (self, **kw):
151 self.__expandedName = kw['expanded_name'] 152 self.setLiteral('pyxb.namespace.ExpandedName(%s, %s)' % (pythonLiteral(self.__expandedName.namespace(), **kw), pythonLiteral(self.__expandedName.localName(), **kw)))
153
154 -class ReferenceFacet (ReferenceLiteral):
155 __facet = None 156
157 - def __init__ (self, **kw):
158 self.__facet = kw['facet'] 159 super(ReferenceFacet, self).__init__(**kw) 160 self.setLiteral('%s._CF_%s' % (pythonLiteral(self.__facet.ownerTypeDefinition(), **kw), self.__facet.Name()))
161
162 -class ReferenceEnumerationMember (ReferenceLiteral):
163 enumerationElement = None 164
165 - def __init__ (self, **kw):
166 # NB: Pre-extended __init__ 167 168 # All we really need is the enumeration element, so we can get 169 # its tag, and a type definition or datatype, so we can create 170 # the proper prefix. 171 172 # See if we were given a value, from which we can extract the 173 # other information. 174 value = kw.get('enum_value', None) 175 assert (value is None) or isinstance(value, facets._Enumeration_mixin) 176 177 # Must provide facet_instance, or a value from which it can be 178 # obtained. 179 facet_instance = kw.get('facet_instance', None) 180 if facet_instance is None: 181 assert isinstance(value, facets._Enumeration_mixin) 182 facet_instance = value._CF_enumeration 183 assert isinstance(facet_instance, facets.CF_enumeration) 184 185 # Must provide the enumeration_element, or a facet_instance 186 # and value from which it can be identified. 187 self.enumerationElement = kw.get('enumeration_element', None) 188 if self.enumerationElement is None: 189 assert value is not None 190 self.enumerationElement = facet_instance.elementForValue(value) 191 assert isinstance(self.enumerationElement, facets._EnumerationElement) 192 if self.enumerationElement.tag() is None: 193 self.enumerationElement._setTag(utility.MakeIdentifier(self.enumerationElement.unicodeValue())) 194 binding_tag = utility.PrepareIdentifier(self.enumerationElement.tag(), kw['class_unique'], kw['class_keywords']) 195 if self.enumerationElement.bindingTag() is None: 196 # Boy I hope this is the first time generating one of 197 # thes, so this is in the owner class 198 self.enumerationElement._setBindingTag(binding_tag) 199 200 # If no type definition was provided, use the value datatype 201 # for the facet. 202 kw.setdefault('type_definition', facet_instance.valueDatatype()) 203 204 super(ReferenceEnumerationMember, self).__init__(**kw) 205 206 self.setLiteral(self._addTypePrefix(binding_tag, **kw))
207
208 -def pythonLiteral (value, **kw):
209 # For dictionaries, apply translation to all values (not keys) 210 if isinstance(value, types.DictionaryType): 211 return ', '.join([ '%s=%s' % (k, pythonLiteral(v, **kw)) for (k, v) in value.items() ]) 212 213 # For lists, apply translation to all members 214 if isinstance(value, types.ListType): 215 return [ pythonLiteral(_v, **kw) for _v in value ] 216 217 # ExpandedName is a tuple, but not here 218 if isinstance(value, pyxb.namespace.ExpandedName): 219 return pythonLiteral(ReferenceExpandedName(expanded_name=value, **kw)) 220 221 # For other collection types, do what you do for list 222 if isinstance(value, (types.TupleType, set)): 223 return type(value)(pythonLiteral(list(value), **kw)) 224 225 # Value is a binding value for which there should be an 226 # enumeration constant. Return that constant. 227 if isinstance(value, facets._Enumeration_mixin): 228 return pythonLiteral(ReferenceEnumerationMember(enum_value=value, **kw)) 229 230 # Value is an instance of a Python binding, e.g. one of the 231 # XMLSchema datatypes. Use its value, applying the proper prefix 232 # for the module. 233 if isinstance(value, basis.simpleTypeDefinition): 234 return PrefixModule(value, value.pythonLiteral()) 235 236 if isinstance(value, pyxb.namespace.Namespace): 237 return pythonLiteral(ReferenceNamespace(namespace=value, **kw)) 238 239 if isinstance(value, type): 240 if issubclass(value, basis.simpleTypeDefinition): 241 return PrefixModule(value) 242 if issubclass(value, facets.Facet): 243 return PrefixModule(value) 244 245 # String instances go out as their representation 246 if isinstance(value, types.StringTypes): 247 return utility.QuotedEscaped(value,) 248 249 if isinstance(value, facets.Facet): 250 return pythonLiteral(ReferenceFacet(facet=value, **kw)) 251 252 # Treat pattern elements as their value 253 if isinstance(value, facets._PatternElement): 254 return pythonLiteral(value.pattern) 255 256 # Treat enumeration elements as their value 257 if isinstance(value, facets._EnumerationElement): 258 return pythonLiteral(value.value()) 259 260 # Particles expand to a pyxb.binding.content.Particle instance 261 if isinstance(value, xs.structures.Particle): 262 return pythonLiteral(ReferenceParticle(value, **kw)) 263 264 # Wildcards expand to a pyxb.binding.content.Wildcard instance 265 if isinstance(value, xs.structures.Wildcard): 266 return pythonLiteral(ReferenceWildcard(value, **kw)) 267 268 # Schema components have a single name through their lifespan 269 if isinstance(value, xs.structures._SchemaComponent_mixin): 270 return pythonLiteral(ReferenceSchemaComponent(value, **kw)) 271 272 # Other special cases 273 if isinstance(value, ReferenceLiteral): 274 return value.asLiteral() 275 276 # Represent namespaces by their URI 277 if isinstance(value, pyxb.namespace.Namespace): 278 return repr(value.uri()) 279 280 # Standard Python types 281 if isinstance(value, (types.NoneType, types.BooleanType, types.FloatType, types.IntType, types.LongType)): 282 return repr(value) 283 284 raise Exception('Unexpected literal type %s' % (type(value),)) 285 print 'Unexpected literal type %s' % (type(value),) 286 return str(value)
287
288 289 -def GenerateModelGroupAll (ctd, mga, binding_module, template_map, **kw):
290 mga_tag = '__AModelGroup' 291 template_map['mga_tag'] = mga_tag 292 lines = [] 293 lines2 = [] 294 for ( dfa, is_required ) in mga.particles(): 295 ( dfa_tag, dfa_lines ) = GenerateContentModel(ctd, dfa, binding_module, **kw) 296 lines.extend(dfa_lines) 297 template_map['dfa_tag'] = dfa_tag 298 template_map['is_required'] = binding_module.literal(is_required, **kw) 299 lines2.append(templates.replaceInText(' %{content}.ModelGroupAllAlternative(%{ctd}.%{dfa_tag}, %{is_required}),', **template_map)) 300 lines.append(templates.replaceInText('%{mga_tag} = %{content}.ModelGroupAll(alternatives=[', **template_map)) 301 lines.extend(lines2) 302 lines.append('])') 303 return (mga_tag, lines)
304
305 -def GenerateContentModel (ctd, automaton, binding_module, **kw):
306 cmi = None 307 template_map = { } 308 template_map['ctd'] = binding_module.literal(ctd, **kw) 309 try: 310 cmi = '_ContentModel_%d' % (ctd.__contentModelIndex,) 311 ctd.__contentModelIndex += 1 312 except AttributeError: 313 cmi = '_ContentModel' 314 ctd.__contentModelIndex = 1 315 template_map['cm_tag'] = cmi 316 template_map['content'] = 'pyxb.binding.content' 317 template_map['state_comma'] = ' ' 318 lines = [] 319 lines2 = [] 320 for (state, transitions) in automaton.items(): 321 if automaton.end() == state: 322 continue 323 template_map['state'] = binding_module.literal(state) 324 template_map['is_final'] = binding_module.literal(None in transitions) 325 326 lines2.append(templates.replaceInText('%{state_comma} %{state} : %{content}.ContentModelState(state=%{state}, is_final=%{is_final}, transitions=[', **template_map)) 327 template_map['state_comma'] = ',' 328 lines3 = [] 329 for (key, destinations) in transitions.items(): 330 if key is None: 331 continue 332 assert 1 == len(destinations) 333 template_map['next_state'] = binding_module.literal(list(destinations)[0], **kw) 334 if isinstance(key, xs.structures.Wildcard): 335 template_map['kw_key'] = 'term' 336 template_map['kw_val'] = binding_module.literal(key, **kw) 337 elif isinstance(key, nfa.AllWalker): 338 (mga_tag, mga_defns) = GenerateModelGroupAll(ctd, key, binding_module, template_map.copy(), **kw) 339 template_map['kw_key'] = 'term' 340 template_map['kw_val'] = mga_tag 341 lines.extend(mga_defns) 342 else: 343 assert isinstance(key, xs.structures.ElementDeclaration) 344 template_map['kw_key'] = 'element_use' 345 template_map['kw_val'] = templates.replaceInText('%{ctd}._UseForTag(%{field_tag})', field_tag=binding_module.literal(key.expandedName(), **kw), **template_map) 346 lines3.append(templates.replaceInText('%{content}.ContentModelTransition(next_state=%{next_state}, %{kw_key}=%{kw_val}),', 347 **template_map)) 348 lines2.extend([ ' '+_l for _l in lines3 ]) 349 lines2.append("])") 350 351 lines.append(templates.replaceInText('%{ctd}.%{cm_tag} = %{content}.ContentModel(state_map = {', **template_map)) 352 lines.extend([' '+_l for _l in lines2 ]) 353 lines.append("})") 354 return (cmi, lines)
355
356 -def _useEnumerationTags (td):
357 assert isinstance(td, xs.structures.SimpleTypeDefinition) 358 ptd = td.baseTypeDefinition() 359 python_support = None 360 # Atomic types that use strings as their representation 361 if (ptd.VARIETY_atomic == ptd.variety()): 362 python_support = ptd.primitiveTypeDefinition().pythonSupport() 363 return issubclass(python_support, basestring) 364 # Derivations from anySimpleType use strings too 365 if (ptd.VARIETY_absent == ptd.variety()): 366 return True 367 # Union types? Yeah, I suppose so. Though this only applies to 368 # members lifted up into the union. 369 if (ptd.VARIETY_union == ptd.variety()): 370 return True 371 # List types have spaces so no tags. 372 return False
373
374 -def GenerateFacets (td, generator, **kw):
375 binding_module = kw['binding_module'] 376 outf = binding_module.bindingIO() 377 facet_instances = [] 378 gen_enum_tag = _useEnumerationTags(td) 379 for (fc, fi) in td.facets().items(): 380 #if (fi is None) or (fi.ownerTypeDefinition() != td): 381 # continue 382 if (fi is None) and (fc in td.baseTypeDefinition().facets()): 383 # Nothing new here 384 #print 'Skipping %s in %s: already registered' % (fc, td) 385 continue 386 if (fi is not None) and (fi.ownerTypeDefinition() != td): 387 # Did this one in an ancestor 388 #print 'Skipping %s in %s: found in ancestor' % (fc, td) 389 continue 390 argset = { } 391 is_collection = issubclass(fc, facets._CollectionFacet_mixin) 392 if issubclass(fc, facets._LateDatatype_mixin): 393 vdt = td 394 if fc.LateDatatypeBindsSuperclass(): 395 vdt = vdt.baseTypeDefinition() 396 argset['value_datatype'] = vdt 397 if fi is not None: 398 if not is_collection: 399 argset['value'] = fi.value() 400 if isinstance(fi, facets.CF_enumeration): 401 argset['enum_prefix'] = fi.enumPrefix() 402 facet_var = ReferenceFacetMember(type_definition=td, facet_class=fc, **kw) 403 outf.write("%s = %s(%s)\n" % binding_module.literal( (facet_var, fc, argset ), **kw)) 404 facet_instances.append(binding_module.literal(facet_var, **kw)) 405 if (fi is not None) and is_collection: 406 for i in fi.items(): 407 if isinstance(i, facets._EnumerationElement): 408 enum_config = '%s.addEnumeration(unicode_value=%s)' % binding_module.literal( ( facet_var, i.unicodeValue() ), **kw) 409 if gen_enum_tag: 410 enum_member = ReferenceEnumerationMember(type_definition=td, facet_instance=fi, enumeration_element=i, **kw) 411 outf.write("%s = %s\n" % (binding_module.literal(enum_member, **kw), enum_config)) 412 if fi.enumPrefix() is not None: 413 outf.write("%s_%s = %s\n" % (fi.enumPrefix(), i.tag(), binding_module.literal(enum_member, **kw))) 414 else: 415 outf.write("%s\n" % (enum_config,)) 416 if isinstance(i, facets._PatternElement): 417 outf.write("%s.addPattern(pattern=%s)\n" % binding_module.literal( (facet_var, i.pattern ), **kw)) 418 if gen_enum_tag and (xs.structures.SimpleTypeDefinition.VARIETY_union == td.variety()): 419 # If the union has enumerations of its own, there's no need to 420 # inherit anything. 421 fi = td.facets().get(facets.CF_enumeration) 422 if fi is None: 423 # Need to expose any enumerations in members up in this class 424 for mtd in td.memberTypeDefinitions(): 425 if not _useEnumerationTags(mtd): 426 continue 427 fi = mtd.facets().get(facets.CF_enumeration) 428 if fi is None: 429 continue 430 for i in fi.items(): 431 assert isinstance(i, facets._EnumerationElement) 432 etd = i.enumeration().ownerTypeDefinition() 433 enum_member = ReferenceEnumerationMember(type_definition=td, facet_instance=fi, enumeration_element=i, **kw) 434 outf.write("%-50s%s\n" % ('%s = %s' % binding_module.literal( (enum_member, i.unicodeValue()) ), 435 '# originally %s.%s' % (binding_module.literal(etd), i.bindingTag()))) 436 if 2 <= len(facet_instances): 437 map_args = ",\n ".join(facet_instances) 438 else: 439 map_args = ','.join(facet_instances) 440 outf.write("%s._InitializeFacetMap(%s)\n" % (binding_module.literal(td, **kw), map_args))
441
442 -def GenerateSTD (std, generator):
443 444 binding_module = generator.moduleForComponent(std) 445 outf = binding_module.bindingIO() 446 447 class_keywords = frozenset(basis.simpleTypeDefinition._ReservedSymbols) 448 class_unique = set() 449 450 kw = { } 451 kw['binding_module'] = binding_module 452 kw['class_keywords'] = class_keywords 453 kw['class_unique'] = class_unique 454 455 parent_classes = [ binding_module.literal(std.baseTypeDefinition(), **kw) ] 456 enum_facet = std.facets().get(facets.CF_enumeration, None) 457 if (enum_facet is not None) and (enum_facet.ownerTypeDefinition() == std): 458 parent_classes.append('pyxb.binding.basis.enumeration_mixin') 459 460 template_map = { } 461 template_map['std'] = binding_module.literal(std, **kw) 462 template_map['superclasses'] = '' 463 if 0 < len(parent_classes): 464 template_map['superclasses'] = ', '.join(parent_classes) 465 template_map['expanded_name'] = binding_module.literal(std.expandedName(), **kw) 466 template_map['namespaceReference'] = binding_module.literal(std.bindingNamespace(), **kw) 467 if std.annotation() is not None: 468 template_map['documentation'] = std.annotation().asDocString() 469 template_map['documentation_expr'] = binding_module.literal(std.annotation().text()) 470 else: 471 template_map['documentation'] = '' 472 template_map['documentation_expr'] = binding_module.literal(None) 473 474 # @todo: Extensions of LIST will be wrong in below 475 476 common_template = ''' 477 """%{description} 478 %{documentation}""" 479 480 _ExpandedName = %{expanded_name} 481 _Documentation = %{documentation_expr} 482 ''' 483 if xs.structures.SimpleTypeDefinition.VARIETY_absent == std.variety(): 484 template = ''' 485 # The ur SimpleTypeDefinition 486 class %{std} (%{superclasses}): 487 ''' + common_template 488 template_map['description'] = '' 489 elif xs.structures.SimpleTypeDefinition.VARIETY_atomic == std.variety(): 490 template = ''' 491 # Atomic SimpleTypeDefinition 492 class %{std} (%{superclasses}): 493 ''' + common_template 494 template_map['description'] = '' 495 elif xs.structures.SimpleTypeDefinition.VARIETY_list == std.variety(): 496 template = ''' 497 # List SimpleTypeDefinition 498 # superclasses %{superclasses} 499 class %{std} (pyxb.binding.basis.STD_list): 500 ''' + common_template + ''' 501 _ItemType = %{itemtype} 502 ''' 503 template_map['itemtype'] = binding_module.literal(std.itemTypeDefinition(), **kw) 504 template_map['description'] = templates.replaceInText('Simple type that is a list of %{itemtype}', **template_map) 505 elif xs.structures.SimpleTypeDefinition.VARIETY_union == std.variety(): 506 template = ''' 507 # Union SimpleTypeDefinition 508 # superclasses %{superclasses} 509 class %{std} (pyxb.binding.basis.STD_union): 510 ''' + common_template + ''' 511 _MemberTypes = ( %{membertypes}, ) 512 ''' 513 template_map['membertypes'] = ", ".join( [ binding_module.literal(_mt, **kw) for _mt in std.memberTypeDefinitions() ]) 514 template_map['description'] = templates.replaceInText('Simple type that is a union of %{membertypes}', **template_map) 515 516 if 0 == len(template_map['description']): 517 template_map['description'] = 'No information' 518 outf.write(templates.replaceInText(template, **template_map)) 519 520 generate_facets = False 521 if generate_facets: 522 # If generating datatype_facets, throw away the class garbage 523 if std.isBuiltin(): 524 GenerateFacets(std, generator, **kw) 525 else: 526 GenerateFacets(std, generator, **kw) 527 528 if std.name() is not None: 529 outf.write(templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{std})\n", 530 localName=binding_module.literal(std.name(), **kw), **template_map))
531
532 -def elementDeclarationMap (ed, binding_module, **kw):
533 template_map = { } 534 template_map['name'] = unicode(ed.expandedName()) 535 template_map['name_expr'] = binding_module.literal(ed.expandedName(), **kw) 536 template_map['namespaceReference'] = binding_module.literal(ed.bindingNamespace(), **kw) 537 if (ed.SCOPE_global == ed.scope()): 538 template_map['class'] = binding_module.literal(ed, **kw) 539 template_map['localName'] = binding_module.literal(ed.name(), **kw) 540 template_map['map_update'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('elementBinding', %{localName}, %{class})", **template_map) 541 else: 542 template_map['scope'] = binding_module.literal(ed.scope(), **kw) 543 if ed.annotation() is not None: 544 template_map['documentation'] = binding_module.literal(unicode(ed.annotation())) 545 if ed.abstract(): 546 template_map['abstract'] = binding_module.literal(ed.abstract(), **kw) 547 if ed.nillable(): 548 template_map['nillable'] = binding_module.literal(ed.nillable(), **kw) 549 if ed.default(): 550 template_map['defaultValue'] = binding_module.literal(ed.default(), **kw) 551 template_map['typeDefinition'] = binding_module.literal(ed.typeDefinition(), **kw) 552 if ed.substitutionGroupAffiliation(): 553 template_map['substitution_group'] = binding_module.literal(ed.substitutionGroupAffiliation(), **kw) 554 aux_init = [] 555 for k in ( 'nillable', 'abstract', 'scope', 'documentation' ): 556 if k in template_map: 557 aux_init.append('%s=%s' % (k, template_map[k])) 558 template_map['element_aux_init'] = '' 559 if 0 < len(aux_init): 560 template_map['element_aux_init'] = ', ' + ', '.join(aux_init) 561 562 return template_map
563
564 -def GenerateCTD (ctd, generator, **kw):
565 binding_module = generator.moduleForComponent(ctd) 566 outf = binding_module.bindingIO() 567 568 content_type = None 569 prolog_template = None 570 template_map = { } 571 template_map['ctd'] = binding_module.literal(ctd, **kw) 572 base_type = ctd.baseTypeDefinition() 573 content_type_tag = ctd._contentTypeTag() 574 575 template_map['base_type'] = binding_module.literal(base_type, **kw) 576 template_map['namespaceReference'] = binding_module.literal(ctd.bindingNamespace(), **kw) 577 template_map['expanded_name'] = binding_module.literal(ctd.expandedName(), **kw) 578 template_map['simple_base_type'] = binding_module.literal(None, **kw) 579 template_map['contentTypeTag'] = content_type_tag 580 template_map['is_abstract'] = repr(not not ctd.abstract()) 581 582 need_content = False 583 content_basis = None 584 if (ctd.CT_SIMPLE == content_type_tag): 585 content_basis = ctd.contentType()[1] 586 template_map['simple_base_type'] = binding_module.literal(content_basis, **kw) 587 elif (ctd.CT_MIXED == content_type_tag): 588 content_basis = ctd.contentType()[1] 589 need_content = True 590 elif (ctd.CT_ELEMENT_ONLY == content_type_tag): 591 content_basis = ctd.contentType()[1] 592 need_content = True 593 need_content = False 594 595 prolog_template = ''' 596 # Complex type %{ctd} with content type %{contentTypeTag} 597 class %{ctd} (%{superclass}): 598 _TypeDefinition = %{simple_base_type} 599 _ContentTypeTag = pyxb.binding.basis.complexTypeDefinition._CT_%{contentTypeTag} 600 _Abstract = %{is_abstract} 601 _ExpandedName = %{expanded_name} 602 ''' 603 604 # Complex types that inherit from non-ur-type complex types should 605 # have their base type as their Python superclass, so pre-existing 606 # elements and attributes can be re-used. 607 inherits_from_base = True 608 template_map['superclass'] = binding_module.literal(base_type, **kw) 609 if ctd._isHierarchyRoot(): 610 inherits_from_base = False 611 template_map['superclass'] = 'pyxb.binding.basis.complexTypeDefinition' 612 assert base_type.nameInBinding() is not None 613 614 # Support for deconflicting attributes, elements, and reserved symbols 615 class_keywords = frozenset(basis.complexTypeDefinition._ReservedSymbols) 616 class_unique = set() 617 618 # Deconflict elements first, attributes are lower priority. 619 # Expectation is that all elements that have the same tag in the 620 # XML are combined into the same instance member, even if they 621 # have different types. Determine what name that should be, and 622 # whether there might be multiple instances of elements of that 623 # name. 624 element_name_map = { } 625 element_uses = [] 626 627 definitions = [] 628 629 definitions.append('# Base type is %{base_type}') 630 631 # Retain in the ctd the information about the element 632 # infrastructure, so it can be inherited where appropriate in 633 # subclasses. 634 635 if isinstance(content_basis, xs.structures.Particle): 636 plurality_data = content_basis.pluralityData().combinedPlurality() 637 638 outf.postscript().append("\n\n") 639 for (ed, is_plural) in plurality_data.items(): 640 # @todo Detect and account for plurality change between this and base 641 ef_map = ed._templateMap() 642 if ed.scope() == ctd: 643 ef_map.update(elementDeclarationMap(ed, binding_module, **kw)) 644 aux_init = [] 645 ef_map['is_plural'] = repr(is_plural) 646 element_uses.append(templates.replaceInText('%{use}.name() : %{use}', **ef_map)) 647 if 0 == len(aux_init): 648 ef_map['aux_init'] = '' 649 else: 650 ef_map['aux_init'] = ', ' + ', '.join(aux_init) 651 ef_map['element_binding'] = utility.PrepareIdentifier('%s_elt' % (ef_map['id'],), class_unique, class_keywords, private=True) 652 if ed.annotation() is not None: 653 ef_map['documentation'] = binding_module.literal(unicode(ed.annotation())) 654 else: 655 ef_map['documentation'] = binding_module.literal(None) 656 if ed.scope() != ctd: 657 definitions.append(templates.replaceInText(''' 658 # Element %{id} (%{name}) inherited from %{decl_type_en}''', decl_type_en=unicode(ed.scope().expandedName()), **ef_map)) 659 continue 660 661 if ed.expandedName().localName() != ef_map['id']: 662 print 'Element %s.%s renamed to %s' % (ctd.expandedName(), ed.expandedName(), ef_map['id']) 663 definitions.append(templates.replaceInText(''' 664 # Element %{name} uses Python identifier %{id} 665 %{use} = pyxb.binding.content.ElementUse(%{name_expr}, '%{id}', '%{key}', %{is_plural}%{aux_init}) 666 ''', **ef_map)) 667 668 if basis.BINDING_STYLE_ACCESSOR == generator.bindingStyle(): 669 definitions.append(templates.replaceInText(''' 670 def %{inspector} (self): 671 """Get the value of the %{name} element.""" 672 return self.%{use}.value(self) 673 def %{mutator} (self, new_value): 674 """Set the value of the %{name} element. Raises BadValueTypeException 675 if the new value is not consistent with the element's type.""" 676 return self.%{use}.set(self, new_value)''', **ef_map)) 677 if is_plural: 678 definitions.append(templates.replaceInText(''' 679 def %{appender} (self, new_value): 680 """Add the value as another occurrence of the %{name} element. Raises 681 BadValueTypeException if the new value is not consistent with the 682 element's type.""" 683 return self.%{use}.append(self, new_value)''', **ef_map)) 684 elif basis.BINDING_STYLE_PROPERTY == generator.bindingStyle(): 685 definitions.append(templates.replaceInText(''' 686 %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation}) 687 ''', **ef_map)) 688 else: 689 raise pyxb.LogicError('Unexpected binding style %s' % (generator.bindingStyle(),)) 690 outf.postscript().append(templates.replaceInText(''' 691 %{ctd}._AddElement(pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init})) 692 ''', ctd=template_map['ctd'], **ef_map)) 693 694 fa = nfa.Thompson(content_basis).nfa() 695 fa = fa.buildDFA() 696 (cmi, cmi_defn) = GenerateContentModel(ctd=ctd, automaton=fa, binding_module=binding_module, **kw) 697 outf.postscript().append("\n".join(cmi_defn)) 698 outf.postscript().append("\n") 699 700 if need_content: 701 PostscriptItems.append(templates.replaceInText(''' 702 %{ctd}._Content = %{particle} 703 ''', **template_map)) 704 705 # Create definitions for all attributes. 706 attribute_uses = [] 707 708 # name - String value of expanded name of the attribute (attr_tag, attr_ns) 709 # name_expr - Python expression for an expanded name identifying the attribute (attr_tag) 710 # use - Binding variable name holding AttributeUse instance (attr_name) 711 # id - Python identifier for attribute (python_attr_name) 712 # key - String used as dictionary key holding instance value of attribute (value_attr_name) 713 # inspector - Name of the method used for inspection (attr_inspector) 714 # mutator - Name of the method use for mutation (attr_mutator) 715 for au in ctd.attributeUses(): 716 ad = au.attributeDeclaration() 717 assert isinstance(ad.scope(), xs.structures.ComplexTypeDefinition), 'unexpected scope %s' % (ad.scope(),) 718 au_map = ad._templateMap() 719 if ad.scope() == ctd: 720 assert isinstance(au_map, dict) 721 if au.restrictionOf() is not None: 722 #print 'Local %s restriction of %s' % (au_map, au.restrictionOf().attributeDeclaration()._templateMap()) 723 au_map = au.restrictionOf().attributeDeclaration()._templateMap().copy() 724 definitions.append(templates.replaceInText(''' 725 # Attribute %{id} is restricted from parent''', **au_map)) 726 727 assert ad.typeDefinition() is not None 728 au_map['attr_type'] = binding_module.literal(ad.typeDefinition(), **kw) 729 730 vc_source = ad 731 if au.valueConstraint() is not None: 732 vc_source = au 733 aux_init = [] 734 if vc_source.fixed() is not None: 735 aux_init.append('fixed=True') 736 aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.fixed(), **kw),)) 737 elif vc_source.default() is not None: 738 aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.default(), **kw),)) 739 if au.required(): 740 aux_init.append('required=True') 741 if au.prohibited(): 742 aux_init.append('prohibited=True') 743 if 0 == len(aux_init): 744 au_map['aux_init'] = '' 745 else: 746 aux_init.insert(0, '') 747 au_map['aux_init'] = ', '.join(aux_init) 748 if ad.annotation() is not None: 749 au_map['documentation'] = binding_module.literal(unicode(ad.annotation())) 750 else: 751 au_map['documentation'] = binding_module.literal(None) 752 if ad.scope() != ctd: 753 definitions.append(templates.replaceInText(''' 754 # Attribute %{id} inherited from %{decl_type_en}''', decl_type_en=unicode(ad.scope().expandedName()), **au_map)) 755 continue 756 757 attribute_uses.append(templates.replaceInText('%{use}.name() : %{use}', **au_map)) 758 if ad.expandedName().localName() != au_map['id']: 759 print 'Attribute %s.%s renamed to %s' % (ctd.expandedName(), ad.expandedName(), au_map['id']) 760 definitions.append(templates.replaceInText(''' 761 # Attribute %{name} uses Python identifier %{id} 762 %{use} = pyxb.binding.content.AttributeUse(%{name_expr}, '%{id}', '%{key}', %{attr_type}%{aux_init})''', **au_map)) 763 if au.prohibited(): 764 if basis.BINDING_STYLE_ACCESSOR == generator.bindingStyle(): 765 definitions.append(templates.replaceInText(''' 766 # Attribute %{id} marked prohibited in this type 767 def %{inspector} (self): 768 raise pyxb.ProhibitedAttributeError("Attribute %{name} is prohibited in %{ctd}") 769 def %{mutator} (self, new_value): 770 raise pyxb.ProhibitedAttributeError("Attribute %{name} is prohibited in %{ctd}") 771 ''', ctd=template_map['ctd'], **au_map)) 772 elif basis.BINDING_STYLE_PROPERTY == generator.bindingStyle(): 773 definitions.append(templates.replaceInText(''' 774 %{inspector} = property() 775 ''', ctd=template_map['ctd'], **au_map)) 776 777 else: 778 raise pyxb.LogicError('Unexpected binding style %s' % (generator.bindingStyle(),)) 779 else: 780 if basis.BINDING_STYLE_ACCESSOR == generator.bindingStyle(): 781 definitions.append(templates.replaceInText(''' 782 def %{inspector} (self): 783 """Get the attribute value for %{name}.""" 784 return self.%{use}.value(self) 785 def %{mutator} (self, new_value): 786 """Set the attribute value for %{name}. Raises BadValueTypeException 787 if the new value is not consistent with the attribute's type.""" 788 return self.%{use}.set(self, new_value)''', **au_map)) 789 elif basis.BINDING_STYLE_PROPERTY == generator.bindingStyle(): 790 definitions.append(templates.replaceInText(''' 791 %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation}) 792 ''', ctd=template_map['ctd'], **au_map)) 793 else: 794 raise pyxb.LogicError('Unexpected binding style %s' % (generator.bindingStyle(),)) 795 796 if ctd.attributeWildcard() is not None: 797 definitions.append('_AttributeWildcard = %s' % (binding_module.literal(ctd.attributeWildcard(), **kw),)) 798 if ctd.hasWildcardElement(): 799 definitions.append('_HasWildcardElement = True') 800 template_map['attribute_uses'] = ",\n ".join(attribute_uses) 801 template_map['element_uses'] = ",\n ".join(element_uses) 802 if inherits_from_base: 803 map_decl = ''' 804 _ElementMap = %{superclass}._ElementMap.copy() 805 _ElementMap.update({ 806 %{element_uses} 807 }) 808 _AttributeMap = %{superclass}._AttributeMap.copy() 809 _AttributeMap.update({ 810 %{attribute_uses} 811 })''' 812 else: 813 map_decl = ''' 814 _ElementMap = { 815 %{element_uses} 816 } 817 _AttributeMap = { 818 %{attribute_uses} 819 }''' 820 821 template_map['registration'] = '' 822 if ctd.name() is not None: 823 template_map['registration'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{ctd})", 824 localName=binding_module.literal(ctd.name(), **kw), **template_map) 825 826 template = ''.join([prolog_template, 827 " ", "\n ".join(definitions), "\n", 828 map_decl, ''' 829 %{registration} 830 831 ''']) 832 833 outf.write(template, **template_map)
834
835 -def GenerateED (ed, generator, **kw):
836 # Unscoped declarations should never be referenced in the binding. 837 assert ed._scopeIsGlobal() 838 839 binding_module = generator.moduleForComponent(ed) 840 outf = binding_module.bindingIO() 841 842 template_map = elementDeclarationMap(ed, binding_module, **kw) 843 template_map.setdefault('scope', binding_module.literal(None, **kw)) 844 template_map.setdefault('map_update', '') 845 846 outf.write(templates.replaceInText(''' 847 %{class} = pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init}) 848 %{namespaceReference}.addCategoryObject('elementBinding', %{class}.name().localName(), %{class}) 849 ''', **template_map)) 850 851 if ed.substitutionGroupAffiliation() is not None: 852 outf.postscript().append(templates.replaceInText(''' 853 %{class}._setSubstitutionGroup(%{substitution_group}) 854 ''', **template_map))
855
856 -def _PrepareSimpleTypeDefinition (std, generator, nsm, module_context):
857 ptd = std.primitiveTypeDefinition(throw_if_absent=False) 858 std._templateMap()['_unique'] = nsm.uniqueInClass(std) 859 if (ptd is not None) and ptd.hasPythonSupport(): 860 # Only generate enumeration constants for named simple 861 # type definitions that are fundamentally xsd:string 862 # values. 863 if issubclass(ptd.pythonSupport(), pyxb.binding.datatypes.string): 864 enum_facet = std.facets().get(pyxb.binding.facets.CF_enumeration, None) 865 if (enum_facet is not None) and (std.expandedName() is not None): 866 for ei in enum_facet.items(): 867 assert ei.tag() is None, '%s already has a tag' % (ei,) 868 ei._setTag(utility.PrepareIdentifier(ei.unicodeValue(), nsm.uniqueInClass(std)))
869 #print ' Enum %s represents %s' % (ei.tag(), ei.unicodeValue())
870 #print '%s unique: %s' % (std.expandedName(), nsm.uniqueInClass(std)) 871 872 -def _PrepareComplexTypeDefinition (ctd, generator, nsm, module_context):
873 #print '%s represents %s in %s' % (ctd.nameInBinding(), ctd.expandedName(), nsm.namespace()) 874 content_basis = None 875 content_type_tag = ctd._contentTypeTag() 876 if (ctd.CT_SIMPLE == content_type_tag): 877 content_basis = ctd.contentType()[1] 878 #template_map['simple_base_type'] = binding_module.literal(content_basis, **kw) 879 elif (ctd.CT_MIXED == content_type_tag): 880 content_basis = ctd.contentType()[1] 881 elif (ctd.CT_ELEMENT_ONLY == content_type_tag): 882 content_basis = ctd.contentType()[1] 883 kw = { 'binding_module' : module_context } 884 if isinstance(content_basis, xs.structures.Particle): 885 plurality_map = content_basis.pluralityData().combinedPlurality() 886 else: 887 plurality_map = {} 888 ctd._templateMap()['_unique'] = nsm.uniqueInClass(ctd) 889 for cd in ctd.localScopedDeclarations(): 890 _SetNameWithAccessors(cd, ctd, plurality_map.get(cd, False), module_context, nsm, kw)
891
892 -def _SetNameWithAccessors (component, container, is_plural, binding_module, nsm, kw):
893 use_map = component._templateMap() 894 class_unique = nsm.uniqueInClass(container) 895 assert isinstance(component, xs.structures._ScopedDeclaration_mixin) 896 unique_name = utility.PrepareIdentifier(component.expandedName().localName(), class_unique) 897 use_map['id'] = unique_name 898 use_map['inspector'] = unique_name 899 use_map['mutator'] = utility.PrepareIdentifier('set' + unique_name[0].upper() + unique_name[1:], class_unique) 900 use_map['use'] = utility.MakeUnique('__' + unique_name.strip('_'), class_unique) 901 assert component._scope() == container 902 assert component.nameInBinding() is None, 'Use %s but binding name %s for %s' % (use_map['use'], component.nameInBinding(), component.expandedName()) 903 component.setNameInBinding(use_map['use']) 904 key_name = '%s_%s_%s' % (str(nsm.namespace()), container.nameInBinding(), component.expandedName()) 905 use_map['key'] = utility.PrepareIdentifier(key_name, class_unique, private=True) 906 use_map['name'] = unicode(component.expandedName()) 907 use_map['name_expr'] = binding_module.literal(component.expandedName(), **kw) 908 if isinstance(component, xs.structures.ElementDeclaration) and is_plural: 909 use_map['appender'] = utility.PrepareIdentifier('add' + unique_name[0].upper() + unique_name[1:], class_unique) 910 return use_map
911
912 -class BindingIO (object):
913 __prolog = None 914 __postscript = None 915 __templateMap = None 916 __stringIO = None 917 __bindingFilePath = None 918 __bindingFile = None 919
920 - def __init__ (self, binding_module, **kw):
921 super(BindingIO, self).__init__() 922 self.__bindingModule = binding_module 923 self.__bindingFilePath = kw['binding_file_path'] 924 self.__bindingFile = kw['binding_file'] 925 self.__prolog = [] 926 self.__postscript = [] 927 self.__templateMap = kw.copy() 928 self.__templateMap.update({ 'date' : str(datetime.datetime.now()), 929 'filePath' : self.__bindingFilePath, 930 'binding_module' : binding_module, 931 'pyxbVersion' : pyxb.__version__ }) 932 self.__stringIO = StringIO.StringIO()
933
934 - def bindingFile (self):
935 return self.__bindingFile
936
937 - def expand (self, template, **kw):
938 tm = self.__templateMap.copy() 939 tm.update(kw) 940 return templates.replaceInText(template, **tm)
941
942 - def write (self, template, **kw):
943 txt = self.expand(template, **kw) 944 self.__stringIO.write(txt)
945
946 - def bindingModule (self):
947 return self.__bindingModule
948 __bindingModule = None 949
950 - def prolog (self):
951 return self.__prolog
952 - def postscript (self):
953 return self.__postscript
954
955 - def literal (self, *args, **kw):
956 kw.update(self.__templateMap) 957 return pythonLiteral(*args, **kw)
958
959 - def contents (self):
960 rv = self.__prolog 961 rv.append(self.__stringIO.getvalue()) 962 rv.extend(self.__postscript) 963 return ''.join(rv)
964
965 -class _ModuleNaming_mixin (object):
966 __anonSTDIndex = None 967 __anonCTDIndex = None 968 __uniqueInModule = None 969 __uniqueInClass = None 970 971 # @todo: provide a way to reset this, for multiple generations in a single run 972 _UniqueInModule = set([ 'pyxb', 'sys' ]) 973 974 __ComponentBindingModuleMap = {} 975
976 - def generator (self):
977 return self.__generator
978 __generator = None 979
980 - def __init__ (self, generator, *args, **kw):
981 super(_ModuleNaming_mixin, self).__init__(*args, **kw) 982 self.__generator = generator 983 assert isinstance(self.__generator, Generator) 984 self.__anonSTDIndex = 1 985 self.__anonCTDIndex = 1 986 self.__components = [] 987 self.__componentNameMap = {} 988 self.__uniqueInModule = set() 989 self.__bindingIO = None 990 self.__importedModules = [] 991 self.__namespaceDeclarations = [] 992 self.__referencedNamespaces = {} 993 self.__uniqueInClass = {}
994
995 - def _importModule (self, module):
996 assert not isinstance(module, pyxb.namespace.Namespace) 997 assert isinstance(module, (_ModuleNaming_mixin, pyxb.namespace.Namespace, pyxb.namespace.archive.ModuleRecord)), 'Unexpected type %s' % (type(module),) 998 if isinstance(module, NamespaceModule) and (pyxb.namespace.XMLSchema == module.namespace()): 999 return 1000 if not (module in self.__importedModules): 1001 self.__importedModules.append(module)
1002
1003 - def uniqueInClass (self, component):
1004 rv = self.__uniqueInClass.get(component) 1005 if rv is None: 1006 rv = set() 1007 if isinstance(component, xs.structures.SimpleTypeDefinition): 1008 rv.update(basis.simpleTypeDefinition._ReservedSymbols) 1009 else: 1010 assert isinstance(component, xs.structures.ComplexTypeDefinition) 1011 if component._isHierarchyRoot(): 1012 rv.update(basis.complexTypeDefinition._ReservedSymbols) 1013 else: 1014 base_td = component.baseTypeDefinition() 1015 base_unique = base_td._templateMap().get('_unique') 1016 assert base_unique is not None, 'Base %s of %s has no unique' % (base_td.expandedName(), component.expandedName()) 1017 rv.update(base_unique) 1018 self.__uniqueInClass[component] = rv 1019 return rv
1020 1021 __referencedNamespaces = None 1022
1023 - def bindingIO (self):
1024 return self.__bindingIO
1025 1026 __moduleUID = None
1027 - def moduleUID (self):
1028 if self.__moduleUID is None: 1029 self.__moduleUID = pyxb.utils.utility.HashForText(self._moduleUID_vx()) 1030 return self.__moduleUID
1031
1032 - def _moduleUID_vx (self):
1033 return str(id(self))
1034
1035 - def moduleContents (self):
1036 template_map = {} 1037 aux_imports = [] 1038 for ns in self.__importedModules: 1039 if isinstance(ns, NamespaceModule): 1040 ns = ns.moduleRecord() 1041 module_path = ns.modulePath() 1042 assert module_path is not None, 'No module path for %s type %s' % (ns, type(ns)) 1043 aux_imports.append('import %s' % (module_path,)) 1044 template_map['aux_imports'] = "\n".join(aux_imports) 1045 template_map['namespace_decls'] = "\n".join(self.__namespaceDeclarations) 1046 template_map['module_uid'] = self.moduleUID() 1047 template_map['generation_uid_expr'] = repr(self.generator().generationUID()) 1048 self._finalizeModuleContents_vx(template_map) 1049 return self.__bindingIO.contents()
1050
1051 - def modulePath (self):
1052 return self.__modulePath
1053 - def _setModulePath (self, path_data):
1054 (binding_file_path, binding_file, module_path) = path_data 1055 self.__bindingFilePath = binding_file_path 1056 self.__bindingFile = binding_file 1057 #print 'Set %s binding file %s path %s' % (self, binding_file, binding_file_path) 1058 if module_path is None: 1059 module_path = self.moduleRecord().modulePath() 1060 if module_path is not None: 1061 self.__modulePath = module_path 1062 kw = self._initialBindingTemplateMap() 1063 self.__bindingIO = BindingIO(self, binding_file=binding_file, binding_file_path=binding_file_path, **kw)
1064 __modulePath = None 1065
1066 - def bindingFile (self):
1067 return self.__bindingFile
1068 __bindingFile = None 1069 __bindingFilePath = None 1070
1071 - def _initializeUniqueInModule (self, unique_in_module):
1072 self.__uniqueInModule = set(unique_in_module)
1073
1074 - def uniqueInModule (self):
1075 return self.__uniqueInModule
1076 1077 @classmethod
1078 - def BindComponentInModule (cls, component, module):
1079 cls.__ComponentBindingModuleMap[component] = module 1080 return module
1081 1082 @classmethod
1083 - def ComponentBindingModule (cls, component):
1084 rv = cls.__ComponentBindingModuleMap.get(component) 1085 return cls.__ComponentBindingModuleMap.get(component)
1086 1087 @classmethod
1088 - def _RecordModule (cls, module):
1091 @classmethod
1092 - def _ForRecord (cls, module_record):
1093 return cls.__RecordModuleMap.get(module_record)
1094 __RecordModuleMap = { } 1095
1096 - def _bindComponent (self, component):
1097 kw = {} 1098 rv = component.bestNCName() 1099 if rv is None: 1100 if isinstance(component, xs.structures.ComplexTypeDefinition): 1101 rv = '_CTD_ANON_%d' % (self.__anonCTDIndex,) 1102 self.__anonCTDIndex += 1 1103 elif isinstance(component, xs.structures.SimpleTypeDefinition): 1104 rv = '_STD_ANON_%d' % (self.__anonSTDIndex,) 1105 self.__anonSTDIndex += 1 1106 else: 1107 assert False 1108 kw['protected'] = True 1109 rv = utility.PrepareIdentifier(rv, self.__uniqueInModule, kw) 1110 assert not component in self.__componentNameMap 1111 self.__components.append(component) 1112 self.__componentNameMap[component] = rv 1113 return rv
1114 - def nameInModule (self, component):
1115 return self.__componentNameMap.get(component)
1116
1117 - def __componentModule (self, component, module_type):
1118 assert module_type is None 1119 if NamespaceGroupModule == module_type: 1120 pass 1121 elif NamespaceModule == module_type: 1122 pass 1123 else: 1124 assert module_type is None 1125 return component_module
1126
1127 - def referenceSchemaComponent (self, component):
1128 origin = component._objectOrigin() 1129 assert origin is not None 1130 module_record = origin.moduleRecord() 1131 assert module_record is not None 1132 if self.generator().generationUID() != module_record.generationUID(): 1133 self._importModule(module_record) 1134 return '%s.%s' % (module_record.modulePath(), component.nameInBinding()) 1135 component_module = _ModuleNaming_mixin.ComponentBindingModule(component) 1136 assert component_module is not None, 'No binding module for %s from %s in %s as %s' % (component, module_record, self.moduleRecord(), component.nameInBinding()) 1137 name = component_module.__componentNameMap.get(component) 1138 if name is None: 1139 assert isinstance(self, NamespaceModule) and (self.namespace() == component.bindingNamespace()) 1140 name = component.nameInBinding() 1141 if self != component_module: 1142 self._importModule(component_module) 1143 name = '%s.%s' % (component_module.modulePath(), name) 1144 return name
1145
1146 - def _referencedNamespaces (self): return self.__referencedNamespaces
1147
1148 - def defineNamespace (self, namespace, name, require_unique=True, definition=None, **kw):
1149 rv = self.__referencedNamespaces.get(namespace) 1150 assert rv is None, 'Module %s already has reference to %s' % (self, namespace) 1151 if require_unique: 1152 name = utility.PrepareIdentifier(name, self.__uniqueInModule, **kw) 1153 if definition is None: 1154 if namespace.isAbsentNamespace(): 1155 definition = 'pyxb.namespace.CreateAbsentNamespace()' 1156 else: 1157 definition = 'pyxb.namespace.NamespaceForURI(%s, create_if_missing=True)' % (repr(namespace.uri()),) 1158 self.__namespaceDeclarations.append('%s = %s' % (name, definition)) 1159 self.__namespaceDeclarations.append("%s.configureCategories(['typeBinding', 'elementBinding'])" % (name,)) 1160 self.__referencedNamespaces[namespace] = name 1161 return name
1162
1163 - def referenceNamespace (self, namespace):
1164 rv = self.__referencedNamespaces.get(namespace) 1165 if rv is None: 1166 if namespace.isBuiltinNamespace(): 1167 rv = namespace.builtinNamespaceRepresentation() 1168 elif namespace.isUndeclaredNamespace(): 1169 rv = namespace.modulePath() 1170 elif isinstance(self, NamespaceModule): 1171 if (self.namespace() == namespace): 1172 rv = 'Namespace' 1173 else: 1174 rv = 'pyxb.namespace.NamespaceForURI(%s)' % (repr(namespace.uri()),) 1175 ''' 1176 namespace_module = self.ForNamespace(namespace) 1177 if namespace_module is not None: 1178 self._importModule(namespace_module) 1179 rv = '%s.Namespace' % (namespace_module.modulePath(),) 1180 else: 1181 assert False, 'Unexpected reference to %s' % (namespace,) 1182 #rv = 'pyxb.namespace.NamespaceForURI(%s)' % (repr(namespace.uri()),) 1183 ''' 1184 else: 1185 if namespace.prefix(): 1186 nsn = 'Namespace_%s' % (namespace.prefix(),) 1187 else: 1188 nsn = 'Namespace' 1189 for im in self.__importedModules: 1190 if isinstance(im, NamespaceModule) and (im.namespace() == namespace): 1191 rv = '%s.Namespace' % (im.modulePath(),) 1192 break 1193 if isinstance(im, NamespaceGroupModule): 1194 irv = im.__referencedNamespaces.get(namespace) 1195 if irv is not None: 1196 rv = self.defineNamespace(namespace, nsn, '%s.%s' % (im.modulePath(), irv), protected=True) 1197 break 1198 if rv is None: 1199 rv = self.defineNamespace(namespace, nsn, protected=True) 1200 assert 0 < len(self.__namespaceDeclarations) 1201 self.__referencedNamespaces[namespace] = rv 1202 return rv
1203
1204 - def literal (self, *args, **kw):
1205 return self.__bindingIO.literal(*args, **kw)
1206
1207 - def addImportsFrom (self, module):
1208 print 'Importing to %s from %s' % (self, module) 1209 self._importModule(module) 1210 for c in self.__components: 1211 local_name = self.nameInModule(c) 1212 assert local_name is not None 1213 rem_name = module.nameInModule(c) 1214 if rem_name is None: 1215 continue 1216 aux = '' 1217 if local_name != rem_name: 1218 aux = ' as %s' % (local_name,) 1219 self.__bindingIO.write("from %s import %s%s # %s\n" % (module.modulePath(), rem_name, aux, c.expandedName()))
1220
1221 - def writeToModuleFile (self):
1222 if self.bindingFile(): 1223 self.bindingFile().write(self.moduleContents().encode('utf8')) 1224 self.bindingFile().close() 1225 print 'Saved binding source to %s' % (self.__bindingFilePath,) 1226 else: 1227 print 'WARNING: No binding file for %s' % (self,)
1228
1229 1230 -class NamespaceModule (_ModuleNaming_mixin):
1231 """This class represents a Python module that holds all the 1232 declarations belonging to a specific namespace.""" 1233
1234 - def namespace (self):
1235 return self.__namespace
1236 __namespace = None 1237
1238 - def moduleRecord (self):
1239 return self.__moduleRecord
1240 __moduleRecord = None 1241
1242 - def namespaceGroupModule (self):
1243 return self.__namespaceGroupModule
1244 - def setNamespaceGroupModule (self, namespace_group_module):
1245 self.__namespaceGroupModule = namespace_group_module
1246 __namespaceGroupModule = None 1247 1248 _UniqueInModule = _ModuleNaming_mixin._UniqueInModule.copy() 1249 _UniqueInModule.update([ 'Namespace', 'CreateFromDOM', 'CreateFromDocument' ]) 1250
1251 - def namespaceGroupHead (self):
1252 return self.__namespaceGroupHead
1253 __namespaceGroupHead = None 1254 __namespaceGroup = None 1255
1256 - def componentsInNamespace (self):
1257 return self.__components
1258 __components = None 1259 1260 @classmethod
1261 - def ForComponent (cls, component):
1262 return cls.__ComponentModuleMap.get(component)
1263 __ComponentModuleMap = { } 1264
1265 - def _moduleUID_vx (self):
1266 if self.namespace().isAbsentNamespace(): 1267 return 'Absent' 1268 return str(self.namespace())
1269
1270 - def namespaceGroupMulti (self):
1271 return 1 < len(self.__namespaceGroup)
1272
1273 - def __init__ (self, generator, module_record, mr_scc, components=None, **kw):
1274 super(NamespaceModule, self).__init__(generator, **kw) 1275 self._initializeUniqueInModule(self._UniqueInModule) 1276 self.__moduleRecord = module_record 1277 self.__namespace = self.__moduleRecord.namespace() 1278 self.defineNamespace(self.__namespace, 'Namespace', require_unique=False) 1279 #print 'NSM Namespace %s module path %s' % (namespace, namespace.modulePath()) 1280 #self.__namespaceGroup = mr_scc 1281 self._RecordModule(self) 1282 #self.__namespaceGroupHead = self.ForNamespace(ns_scc[0]) 1283 self.__components = components 1284 # wow! fromkeys actually IS useful! 1285 if self.__components is not None: 1286 self.__ComponentModuleMap.update(dict.fromkeys(self.__components, self)) 1287 self.__namespaceBindingNames = {} 1288 self.__componentBindingName = {} 1289 self._setModulePath(generator.modulePathData(self))
1290
1291 - def _initialBindingTemplateMap (self):
1292 kw = { 'moduleType' : 'namespace' 1293 , 'targetNamespace' : repr(self.__namespace.uri()) 1294 , 'namespaceURI' : self.__namespace.uri() 1295 , 'namespaceReference' : self.referenceNamespace(self.__namespace) 1296 } 1297 return kw
1298
1299 - def _finalizeModuleContents_vx (self, template_map):
1300 self.bindingIO().prolog().append(self.bindingIO().expand('''# %{filePath} 1301 # PyXB bindings for NamespaceModule 1302 # NSM:%{module_uid} 1303 # Generated %{date} by PyXB version %{pyxbVersion} 1304 import pyxb 1305 import pyxb.binding 1306 import pyxb.binding.saxer 1307 import StringIO 1308 import pyxb.utils.utility 1309 import pyxb.utils.domutils 1310 import sys 1311 1312 # Unique identifier for bindings created at the same time 1313 _GenerationUID = %{generation_uid_expr} 1314 1315 # Import bindings for namespaces imported into schema 1316 %{aux_imports} 1317 1318 %{namespace_decls} 1319 ModuleRecord = Namespace.lookupModuleRecordByUID(_GenerationUID, create_if_missing=True) 1320 ModuleRecord._setModule(sys.modules[__name__]) 1321 1322 def CreateFromDocument (xml_text, default_namespace=None): 1323 """Parse the given XML and use the document element to create a Python instance.""" 1324 if pyxb.XMLStyle_saxer != pyxb._XMLStyle: 1325 dom = pyxb.utils.domutils.StringToDOM(xml_text) 1326 return CreateFromDOM(dom.documentElement) 1327 saxer = pyxb.binding.saxer.make_parser(fallback_namespace=Namespace.fallbackNamespace()) 1328 handler = saxer.getContentHandler() 1329 saxer.parse(StringIO.StringIO(xml_text)) 1330 instance = handler.rootObject() 1331 return instance 1332 1333 def CreateFromDOM (node, default_namespace=None): 1334 """Create a Python instance from the given DOM node. 1335 The node tag must correspond to an element declaration in this module. 1336 1337 @deprecated: Forcing use of DOM interface is unnecessary; use L{CreateFromDocument}.""" 1338 if default_namespace is None: 1339 default_namespace = Namespace.fallbackNamespace() 1340 return pyxb.binding.basis.element.AnyCreateFromDOM(node, _fallback_namespace=default_namespace) 1341 1342 ''', **template_map))
1343 1344 __components = None 1345 __componentBindingName = None 1346
1347 - def bindComponent (self, component):
1348 ns_name = self._bindComponent(component) 1349 component.setNameInBinding(ns_name) 1350 #print 'set name %s in %s' % (ns_name, component) 1351 binding_module = self 1352 if self.__namespaceGroupModule: 1353 self.__namespaceGroupModule._bindComponent(component) 1354 binding_module = self.__namespaceGroupModule 1355 return _ModuleNaming_mixin.BindComponentInModule(component, binding_module)
1356
1357 - def __str__ (self):
1358 return 'NM:%s@%s' % (self.namespace(), self.modulePath())
1359
1360 -class NamespaceGroupModule (_ModuleNaming_mixin):
1361 """This class represents a Python module that holds all the 1362 declarations belonging to a set of namespaces which have 1363 interdependencies.""" 1364
1365 - def namespaceModules (self):
1366 return self.__namespaceModules
1367 __namespaceModules = None 1368 1369 __components = None 1370 __componentBindingName = None 1371 __uniqueInModule = None 1372 1373 _UniqueInModule = _ModuleNaming_mixin._UniqueInModule.copy() 1374 1375 __UniqueInGroups = set() 1376 1377 _GroupPrefix = '_group' 1378
1379 - def __init__ (self, generator, namespace_modules, **kw):
1380 super(NamespaceGroupModule, self).__init__(generator, **kw) 1381 assert 1 < len(namespace_modules) 1382 self.__namespaceModules = namespace_modules 1383 self.__namespaceGroupHead = namespace_modules[0].namespaceGroupHead() 1384 self._initializeUniqueInModule(self._UniqueInModule) 1385 self._setModulePath(generator.modulePathData(self))
1386
1387 - def _initialBindingTemplateMap (self):
1388 kw = { 'moduleType' : 'namespaceGroup' } 1389 return kw
1390
1391 - def _finalizeModuleContents_vx (self, template_map):
1392 text = [] 1393 for nsm in self.namespaceModules(): 1394 text.append('# %s %s' % (nsm.namespace(), nsm.namespace().prefix())) 1395 template_map['namespace_comment'] = "\n".join(text) 1396 self.bindingIO().prolog().append(self.bindingIO().expand('''# %{filePath} 1397 # PyXB bindings for NamespaceGroupModule 1398 # NGM:%{module_uid} 1399 # Incorporated namespaces: 1400 %{namespace_comment} 1401 1402 import pyxb 1403 import pyxb.binding 1404 import pyxb.utils.utility 1405 1406 # Unique identifier for bindings created at the same time 1407 _GenerationUID = %{generation_uid_expr} 1408 1409 # Import bindings for schemas in group 1410 %{aux_imports} 1411 1412 %{namespace_decls} 1413 ''', **template_map))
1414
1415 - def _moduleUID_vx (self):
1416 nss = [] 1417 for nsm in self.namespaceModules(): 1418 ns = nsm.namespace() 1419 if ns.isAbsentNamespace(): 1420 nss.append('Absent') 1421 else: 1422 nss.append(str(ns)) 1423 nss.sort() 1424 return ';'.join(nss)
1425
1426 - def __str__ (self):
1427 return 'NGM:%s' % (self.modulePath(),)
1428
1429 1430 -def GeneratePython (schema_location=None, 1431 schema_text=None, 1432 namespace=None, 1433 module_prefix_elts=[], 1434 **kw):
1435 1436 generator = Generator(allow_absent_module=True, generate_to_files=False, **kw) 1437 if schema_location is not None: 1438 generator.addSchemaLocation(schema_location) 1439 elif schema_text is not None: 1440 generator.addSchema(schema_text) 1441 modules = generator.bindingModules() 1442 1443 assert 1 == len(modules), '%s produced %d modules: %s' % (namespace, len(modules), " ".join([ str(_m) for _m in modules])) 1444 return modules.pop().moduleContents()
1445 1446 import optparse 1447 import re
1448 1449 -class Generator (object):
1450 """Configuration and data for a single binding-generation action.""" 1451 1452 _DEFAULT_bindingRoot = '.'
1453 - def bindingRoot (self):
1454 """The directory path into which generated bindings will be written. 1455 @rtype: C{str}""" 1456 return self.__bindingRoot
1457 - def setBindingRoot (self, binding_root):
1458 self.__bindingRoot = binding_root 1459 return self
1460 __bindingRoot = None 1461
1462 - def __directoryForModulePath (self, module_elts):
1463 if isinstance(module_elts, basestring): 1464 module_elts = module_elts.split('.') 1465 else: 1466 module_elts = module_elts[:] 1467 assert 0 < len(module_elts) 1468 assert not module_elts[-1].endswith('.py') 1469 module_elts[-1] = '%s.py' % (module_elts[-1],) 1470 return os.path.join(self.bindingRoot(), *module_elts)
1471
1472 - def generateToFiles (self):
1473 return self.__generateToFiles
1474 __generateToFiles = None 1475
1476 - def modulePathData (self, module):
1477 # file system path to where the bindings are written 1478 # module path from which the bindings are normally imported 1479 # file object into which bindings are written 1480 1481 module_path = None 1482 if isinstance(module, NamespaceModule): 1483 mr = module.moduleRecord() 1484 if mr is None: 1485 return ('/dev/null', None, None) 1486 if self.generationUID() != mr.generationUID(): 1487 return ('/dev/null', None, None) 1488 if not self.generateToFiles(): 1489 return ('/dev/null', None, None) 1490 if mr.namespace().isBuiltinNamespace() and (not self.allowBuiltinGeneration()): 1491 return ('/dev/null', None, None) 1492 module_path = mr.modulePath() 1493 assert module_path is not None, 'No path specified for module %s' % (mr,) 1494 #if pyxb.namespace.XMLSchema != ns: 1495 # return ('/dev/null', None, None) 1496 #module_path="bogus.xsd" 1497 module_elts = module_path.split('.') 1498 import_file_path = self.__directoryForModulePath(module_elts) 1499 if self.writeForCustomization(): 1500 module_elts.insert(-1, 'raw') 1501 if self.writeForCustomization() and (not os.path.exists(import_file_path)): 1502 raw_module_path = '.'.join(module_elts) 1503 pyxb.utils.utility.OpenOrCreate(import_file_path).write("from %s import *\n" % (raw_module_path,)) 1504 binding_file_path = self.__directoryForModulePath(module_elts) 1505 try: 1506 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID()) 1507 except OSError, e: 1508 if errno.EEXIST == e.errno: 1509 raise pyxb.BindingGenerationError('Target file %s for module %s bindings exists with other content' % (binding_file_path, mr)) 1510 raise 1511 elif isinstance(module, NamespaceGroupModule): 1512 if not self.generateToFiles(): 1513 raise pyxb.BindingGenerationError('Generation of namespace groups requires generate-to-files') 1514 module_elts = [] 1515 if self.modulePrefix(): 1516 module_elts.extend(self.modulePrefix().split('.')) 1517 if self.writeForCustomization(): 1518 module_elts.append('raw') 1519 in_use = set() 1520 while True: 1521 module_elts.append(pyxb.utils.utility.PrepareIdentifier('nsgroup', in_use, protected=True)) 1522 try: 1523 binding_file_path = self.__directoryForModulePath(module_elts) 1524 print 'Attempting group at %s' % (binding_file_path,) 1525 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID()) 1526 break 1527 except OSError, e: 1528 if errno.EEXIST != e.errno: 1529 raise 1530 module_elts.pop() 1531 module_path = '.'.join(module_elts) 1532 else: 1533 assert False 1534 if self.generateToFiles(): 1535 for n in range(len(module_elts)-1): 1536 sub_path = os.path.join(*module_elts[:1+n]) 1537 init_path = os.path.join(sub_path, '__init__.py') 1538 if not os.path.exists(init_path): 1539 file(init_path, 'w') 1540 return (binding_file_path, binding_file, module_path)
1541
1542 - def schemaRoot (self):
1543 """The directory from which entrypoint schemas specified as 1544 relative file paths will be read.""" 1545 return self.__schemaRoot
1546 - def setSchemaRoot (self, schema_root):
1547 if not schema_root.endswith(os.sep): 1548 schema_root = schema_root + os.sep 1549 self.__schemaRoot = schema_root 1550 return self
1551 __schemaRoot = None 1552
1553 - def schemaStrippedPrefix (self):
1554 """Optional string that is stripped from the beginning of 1555 schemaLocation values before loading from them. 1556 1557 This applies only to the values of schemaLocation attributes 1558 in C{import} and C{include} elements. Its purpose is to 1559 convert absolute schema locations into relative ones to allow 1560 offline processing when all schema are available in a local 1561 directory. See C{schemaRoot}. 1562 """ 1563 return self.__schemaStrippedPrefix
1564 - def setSchemaStrippedPrefix (self, schema_stripped_prefix):
1565 self.__schemaStrippedPrefix = schema_stripped_prefix 1566 return self
1567 __schemaStrippedPrefix = None 1568
1569 - def schemaLocationList (self):
1570 """A list of locations from which entrypoint schemas are to be 1571 read. 1572 1573 The values in the list are either URIs, or tuples consisting 1574 of a value and a callable which, when passed the generator 1575 object and the value, will return a 1576 L{pyxb.xmlschema.structures.Schema} instance. See 1577 L{addSchemaLocation}. 1578 1579 See also L{addSchemaLocation} and L{schemas}. 1580 """ 1581 return self.__schemaLocationList
1582 - def setSchemaLocationList (self, schema_location_list):
1583 self.__schemaLocationList[:] = [] 1584 self.__schemaLocationList.extend(schema_location_list) 1585 return self
1586 - def addSchemaLocation (self, schema_location, converter=None):
1587 """Add the location of an entrypoint schema. 1588 1589 @param schema_location: The location of the schema. This 1590 should be a URL; if the schema location does not have a URL 1591 scheme (e.g., C{http:}), it is assumed to be a file, and if it 1592 is not an absolute path is located relative to the 1593 C{schemaRoot}. 1594 1595 @keyword converter: Optional callable that will be invoked 1596 with the generator instance and the schema location, and is 1597 expected to return a L{pyxb.xmlschema.structures.Schema} 1598 instance. If absent, the contents of the location are 1599 converted directly. 1600 1601 @note: The C{converter} argument derives from WSDL support: we 1602 need to add to the sequence of schema locations a URI of 1603 something that will not parse as a schema, but does have inner 1604 material that can if treated properly. "Treated properly" may 1605 include having the archive path and other namespace 1606 manipulations configured before anything is done to it. 1607 """ 1608 self.__schemaLocationList.append( (schema_location, converter) ) 1609 return self
1610 - def argAddSchemaLocation (self, schema_location):
1611 """Add the location of an entrypoint schema. The provided 1612 value should be a URL; if it does not have a URL scheme (e.g., 1613 C{http:}), it is assumed to be a file, and if it is not an 1614 absolute path is located relative to the C{schemaRoot}.""" 1615 self.addSchemaLocation(schema_location)
1616 __schemaLocationList = None 1617
1618 - def schemas (self):
1619 """Schema for which bindings should be generated. 1620 1621 These may be L{Schema<pyxb.xmlschema.structures.Schema>} 1622 instances, or strings; the latter is preferred, and is parsed 1623 into a Schema instance when required. 1624 1625 This is the list of entrypoint schemas for binding generation. 1626 Values in L{schemaLocationList} are read and converted into 1627 schema, then appended to this list. Values from L{moduleList} 1628 are applied starting with the first schema in this list. 1629 """ 1630 return self.__schemas[:]
1631 - def setSchemas (self, schemas):
1632 self.__schemas[:] = [] 1633 self.__schemas.extend(schemas) 1634 return self
1635 - def addSchema (self, schema):
1636 self.__schemas.append(schema) 1637 return self
1638 __schemas = None 1639
1640 - def namespaces (self):
1641 """The set of L{namespaces<pyxb.namespace.Namespace>} for 1642 which bindings will be generated. 1643 1644 This is the set of namespaces read from entrypoint schema, 1645 closed under reference to namespaces defined by schema import. 1646 1647 @rtype: C{set} 1648 """ 1649 return self.__namespaces.copy()
1650 - def setNamespaces (self, namespace_set):
1651 self.__namespaces.clear() 1652 self.__namespaces.update(namespace_set) 1653 return self
1654 - def addNamespace (self, namespace):
1655 self.__namespaces.add(namespace) 1656 return self
1657 __namespaces = None 1658
1659 - def moduleList (self):
1660 """A list of module names to be applied in order to the namespaces of entrypoint schemas""" 1661 return self.__moduleList[:]
1662 - def _setModuleList (self, module_list):
1663 self.__moduleList[:] = [] 1664 self.__moduleList.extend(module_list) 1665 return self
1666
1667 - def addModuleName (self, module_name):
1668 """Add a module name corresponding to an entrypoint schema. 1669 1670 The namespace defined by the corresponding schema will be 1671 written to a binding using the given module name, adjusted by 1672 L{modulePrefix}.""" 1673 self.__moduleList.append(module_name) 1674 return self
1675 __moduleList = None 1676
1677 - def modulePrefix (self):
1678 """The prefix for binding modules. 1679 1680 The base name for the module holding a binding is taken from 1681 the moduleList, moduleMap, or an XMLNS prefix associated with 1682 the namespace in a containing schema. This value, if present, 1683 is used as a prefix to allow a deeper module hierarchy.""" 1684 return self.__modulePrefix
1685 - def setModulePrefix (self, module_prefix):
1686 self.__modulePrefix = module_prefix 1687 return self
1688 __modulePrefix = None 1689
1690 - def namespaceModuleMap (self):
1691 """A map from namespace URIs to the module to be used for the 1692 corresponding generated binding. 1693 1694 Module values are adjusted by L{modulePrefix} if that has been 1695 specified. 1696 1697 An entry in this map for a namespace supersedes the module 1698 specified in moduleList if the namespace is defined by an 1699 entrypoint schema. 1700 1701 @return: A reference to the namespace module map. 1702 """ 1703 return self.__namespaceModuleMap
1704 __namespaceModuleMap = None 1705
1706 - def archivePath (self):
1707 """A colon-separated list of paths from which namespace 1708 archives can be read. 1709 1710 The default path is the contents of the C{PYXB_ARCHIVE_PATH} 1711 environment variable, or the standard path configured at 1712 installation time. Any file with the extension C{.wxs} found 1713 in one of these directories is examined to see whether it is a 1714 namespace archive. 1715 """ 1716 return self.__archivePath
1717 - def setArchivePath (self, archive_path):
1718 self.__archivePath = archive_path 1719 return self
1720 __archivePath = None 1721
1722 - def noLoadNamespaces (self):
1723 """A frozenset of namespaces that many not be loaded from an archive.""" 1724 return frozenset(self.__noLoadNamespaces)
1725 - def _setNoLoadNamespaces (self, namespace_set):
1726 """Record the set of namespaces that should not be loaded from an archive. 1727 1728 The expectation is that any required entities in the namespace 1729 will be defined by loading schema.""" 1730 self.__noLoadNamespaces.clear() 1731 self.__noLoadNamespaces.update([ pyxb.namespace.NamespaceInstance(_ns) for _ns in namespace_set ])
1732 - def addNoLoadNamespace (self, namespace):
1733 """Mark that the specified namespace should not be loaded from an archive. 1734 1735 Use this when you are generating bindings for an application 1736 that has a restricted profile of a namespace that would 1737 otherwise be read from an archive. Be aware that this removes 1738 any knowledge of any archive in which this namespace is 1739 present as a non-private member.""" 1740 self.__noLoadNamespaces.add(pyxb.namespace.NamespaceInstance(namespace))
1741 __noloadNamespaces = None 1742
1743 - def preLoadArchives (self):
1744 """A list of paths to archives that should be loaded, in order, prior to parsing schema.""" 1745 return frozenset(self.__preLoadArchives)
1746 - def addPreLoadArchive (self, archive_file):
1747 """Name of a file containing a stored archive from which 1748 namespaces should be read prior to processing schema. 1749 1750 Files to be pre-loaded are not affected by 1751 C{noLoadNamespace}.""" 1752 self.__preLoadArchives.append(archive_file)
1753 - def _setPreLoadArchives (self, pre_load_archives):
1754 self.__preLoadArchives[:] = pre_load_archives 1755 return self
1756 __preLoadArchives = None 1757
1758 - def archiveToFile (self):
1759 """Optional file into which the archive of namespaces will be written. 1760 1761 Subsequent generation actions can read pre-parsed namespaces 1762 from this file, and therefore reference the bindings that were 1763 built earlier rather than re-generating them. 1764 1765 The file name should normally end with C{.wxs}.""" 1766 return self.__archiveToFile
1767 - def setArchiveToFile (self, archive_to_file):
1768 self.__archiveToFile = archive_to_file 1769 return self
1770 __archiveToFile = None 1771
1772 - def setNamespaceVisibility (self, namespace, visibility):
1776 - def _setNamespaceVisibilities (self, public, private):
1777 if public is None: 1778 public = set() 1779 if private is None: 1780 private = set() 1781 self.__namespaceVisibilityMap.clear() 1782 self.__namespaceVisibilityMap.update(dict.fromkeys(public, True)) 1783 self.__namespaceVisibilityMap.update(dict.fromkeys(private, False))
1784 - def namespaceVisibilityMap (self):
1785 """Indicates, for specific namespaces, whether their 1786 visibility in the archive should be public or private.""" 1787 return self.__namespaceVisibilityMap.copy()
1788 __namespaceVisibilityMap = None 1789
1790 - def defaultNamespacePublic (self):
1791 """Indicates whether unmentioned namespaces will be public or private (default) in the archive. 1792 1793 A namespace is I{mentioned} if it is the target namespace of 1794 an entrypoint schema, or appears in a namespace visibility 1795 specification. I.e., this default applies only to namespaces 1796 that are modified as a result of including some schema, which 1797 is generally a local customization of something. 1798 """ 1799 return self.__defaultNamespacePublic
1800 - def setDefaultNamespacePublic (self, default_namespace_public):
1801 self.__defaultNamespacePublic = default_namespace_public
1802 __defaultNamespacePublic = None 1803
1804 - def validateChanges (self):
1805 """Indicates whether the bindings should validate mutations 1806 against the content model.""" 1807 return self.__validateChanges
1808 - def setValidateChanges (self, validate_changes):
1809 #raise pyxb.IncompleteImplementationError('No support for disabling validation') 1810 self.__validateChanges = validate_changes 1811 return self
1812 __validateChanges = None 1813 1814 _DEFAULT_bindingStyle = basis.CURRENT_BINDING_STYLE
1815 - def bindingStyle (self):
1816 """The style of Python used in generated bindings. 1817 1818 C{accessor} means values are private variables accessed 1819 through inspector and mutator methods. 1820 1821 C{property} means values are private variables accessed 1822 through a Python property. 1823 """ 1824 return self.__bindingStyle
1825 - def setBindingStyle (self, binding_style):
1826 raise pyxb.IncompleteImplementationError('No support for binding style configuration') 1827 self.__bindingStyle = binding_style 1828 return self
1829 __bindingStyle = None 1830
1831 - def writeForCustomization (self):
1832 """Indicates whether the binding Python code should be written into a sub-module for customization. 1833 1834 If enabled, a module C{path.to.namespace} will be written to 1835 the file C{path/to/raw/namespace.py}, so that the file 1836 C{path/to/namespace.py} can import it and override behavior.""" 1837 return self.__writeForCustomization
1838 - def setWriteForCustomization (self, write_for_customization):
1839 self.__writeForCustomization = write_for_customization 1840 return self
1841 __writeForCustomization = None 1842
1843 - def allowAbsentModule (self):
1844 """Indicates whether the code generator is permitted to 1845 process namespace for which no module path can be determined. 1846 1847 Use this only when generating bindings that will not be 1848 referenced by other bindings.""" 1849 return self.__allowAbsentModule
1850 - def setAllowAbsentModule (self, allow_absent_module):
1851 self.__allowAbsentModule = allow_absent_module 1852 return self
1853 __allowAbsentModule = None 1854
1855 - def allowBuiltinGeneration (self):
1856 """Indicates whether bindings will be written for namespaces that are built-in to PyXB. 1857 1858 This must be enabled when building bindings for the XML, 1859 XMLSchema instance, and other built-in namespaces. Normally 1860 generation of these namespaces is inhibited lest it produce 1861 inconsistencies.""" 1862 return self.__allowBuiltinGeneration
1863 - def setAllowBuiltinGeneration (self, allow_builtin_generation):
1864 self.__allowBuiltinGeneration = allow_builtin_generation 1865 return self
1866 __allowBuiltinGeneration = None 1867
1868 - def uriContentArchiveDirectory (self):
1869 """The directory path into which any content retrieved by URI will be written. 1870 1871 This serves as a local cache, and to give you an opportunity 1872 to inspect material retrieved from some other system. 1873 @rtype: C{str}""" 1874 return self.__uriContentArchiveDirectory
1875 - def setUriContentArchiveDirectory (self, ucad):
1877 __uriContentArchiveDirectory = None 1878
1879 - def __init__ (self, *args, **kw):
1880 """Create a configuration to be used for generating bindings. 1881 1882 Arguments are treated as additions to the schema location list 1883 after all keywords have been processed. 1884 1885 @keyword binding_root: Invokes L{setBindingRoot} 1886 @keyword schema_root: Invokes L{setSchemaRoot} 1887 @keyword schema_stripped_prefix: Invokes L{setSchemaStrippedPrefix} 1888 @keyword schema_location_list: Invokes L{setSchemaLocationList} 1889 @keyword module_list: Invokes L{_setModuleList} 1890 @keyword module_prefix: Invokes L{setModulePrefix} 1891 @keyword archive_path: Invokes L{setArchivePath} 1892 @keyword no_load_namespaces: Invokes L{_setNoLoadNamespaces} 1893 @keyword pre_load_archives: Invokes L{_setPreLoadArchives} 1894 @keyword archive_to_file: Invokes L{setArchiveToFile} 1895 @keyword public_namespace: Invokes L{setNamespaceVisibility} 1896 @keyword private_namespace: Invokes L{setNamespaceVisibility} 1897 @keyword default_namespace_public: Invokes L{setDefaultNamespacePublic} 1898 @keyword validate_changes: Invokes L{setValidateChanges} 1899 @keyword binding_style: Invokes L{setBindingStyle} 1900 @keyword namespace_module_map: Initializes L{namespaceModuleMap} 1901 @keyword schemas: Invokes L{setSchemas} 1902 @keyword namespaces: Invokes L{setNamespaces} 1903 @keyword write_for_customization: Invokes L{setWriteForCustomization} 1904 @keyword allow_builtin_generation: Invokes L{setAllowBuiltinGeneration} 1905 @keyword allow_absent_module: Invokes L{setAllowAbsentModule} 1906 @keyword generate_to_files: Sets L{generateToFiles} 1907 @keyword uri_content_archive_directory: Invokes L{setUriContentArchiveDirectory} 1908 """ 1909 argv = kw.get('argv', None) 1910 if argv is not None: 1911 kw = {} 1912 self.__bindingRoot = kw.get('binding_root', self._DEFAULT_bindingRoot) 1913 self.__schemaRoot = kw.get('schema_root', '.') 1914 self.__schemaStrippedPrefix = kw.get('schema_stripped_prefix') 1915 self.__schemas = [] 1916 self.__schemaLocationList = kw.get('schema_location_list', [])[:] 1917 self.__moduleList = kw.get('module_list', [])[:] 1918 self.__modulePrefix = kw.get('module_prefix') 1919 self.__archivePath = kw.get('archive_path', pyxb.namespace.archive.GetArchivePath()) 1920 self.__noLoadNamespaces = kw.get('no_load_namespaces', set()).copy() 1921 self.__preLoadArchives = kw.get('pre_load_archives', [])[:] 1922 self.__archiveToFile = kw.get('archive_to_file') 1923 self.__namespaceVisibilityMap = {} 1924 self._setNamespaceVisibilities(kw.get('public_namespaces', set()), kw.get('private_namespaces', set())) 1925 self.__defaultNamespacePublic = kw.get('default_namespace_public', False) 1926 self.__validateChanges = kw.get('validate_changes', True) 1927 self.__bindingStyle = kw.get('binding_style', self._DEFAULT_bindingStyle) 1928 self.__namespaceModuleMap = kw.get('namespace_module_map', {}).copy() 1929 self.__schemas = kw.get('schemas', [])[:] 1930 self.__namespaces = set(kw.get('namespaces', [])) 1931 self.__writeForCustomization = kw.get('write_for_customization', False) 1932 self.__writeForCustomization = kw.get('allow_builtin_generation', False) 1933 self.__allowAbsentModule = kw.get('allow_absent_module', False) 1934 self.__generateToFiles = kw.get('generate_to_files', True) 1935 self.__uriContentArchiveDirectory = kw.get('uri_content_archive_directory') 1936 1937 if argv is not None: 1938 self.applyOptionValues(*self.optionParser().parse_args(argv)) 1939 [ self.addSchemaLocation(_a) for _a in args ] 1940 1941 self.__generationUID = pyxb.utils.utility.UniqueIdentifier() 1942 1943 pyxb.namespace.XML.validateComponentModel()
1944 1945 __stripSpaces_re = re.compile('\s\s\s+')
1946 - def __stripSpaces (self, string):
1947 return self.__stripSpaces_re.sub(' ', string)
1948 1949 __OptionSetters = ( 1950 ('binding_root', setBindingRoot), 1951 ('schema_root', setSchemaRoot), 1952 ('schema_stripped_prefix', setSchemaStrippedPrefix), 1953 ('schema_location', setSchemaLocationList), 1954 ('module', _setModuleList), 1955 ('module_prefix', setModulePrefix), 1956 ('archive_path', setArchivePath), 1957 ('no_load_namespace', _setNoLoadNamespaces), 1958 ('pre_load_archive', _setPreLoadArchives), 1959 ('archive_to_file', setArchiveToFile), 1960 ('default_namespace_public', setDefaultNamespacePublic), 1961 ('binding_style', setBindingStyle), 1962 ('validate_changes', setValidateChanges), 1963 ('write_for_customization', setWriteForCustomization), 1964 ('allow_builtin_generation', setAllowBuiltinGeneration), 1965 ('allow_absent_module', setAllowAbsentModule), 1966 ('uri_content_archive_directory', setUriContentArchiveDirectory) 1967 )
1968 - def applyOptionValues (self, options, args=None):
1969 for (tag, method) in self.__OptionSetters: 1970 v = getattr(options, tag) 1971 if v is not None: 1972 method(self, v) 1973 public_namespaces = getattr(options, 'public_namespace') 1974 private_namespaces = getattr(options, 'private_namespace') 1975 self._setNamespaceVisibilities(public_namespaces, private_namespaces) 1976 if args is not None: 1977 self.__schemaLocationList.extend(args)
1978
1979 - def setFromCommandLine (self, argv=None):
1980 if argv is None: 1981 argv = sys.argv[1:] 1982 (options, args) = self.optionParser().parse_args(argv) 1983 self.applyOptionValues(options, args) 1984 return self
1985
1986 - def generationUID (self):
1987 return self.__generationUID
1988 __generationUID = None 1989
1990 - def optionParser (self, reset=False):
1991 """Return an C{optparse.OptionParser} instance tied to this configuration. 1992 1993 @param reset: If C{False} (default), a parser created in a 1994 previous invocation will be returned. If C{True}, any 1995 previous option parser is discarded and a new one created. 1996 @type reset: C{bool} 1997 """ 1998 if reset or (self.__optionParser is None): 1999 parser = optparse.OptionParser(usage="%prog [options] [more schema locations...]", 2000 version='%%prog from PyXB %s' % (pyxb.__version__,), 2001 description='Generate bindings from a set of XML schemas') 2002 2003 group = optparse.OptionGroup(parser, 'Identifying Schema', 'Specify and locate schema for which bindings should be generated.') 2004 group.add_option('--schema-location', '-u', metavar="FILE_or_URL", 2005 action='append', 2006 help=self.__stripSpaces(self.argAddSchemaLocation.__doc__)) 2007 group.add_option('--schema-root', metavar="DIRECTORY", 2008 help=self.__stripSpaces(self.schemaRoot.__doc__)) 2009 group.add_option('--schema-stripped-prefix', metavar="TEXT", type='string', 2010 help=self.__stripSpaces(self.schemaStrippedPrefix.__doc__)) 2011 group.add_option('--uri-content-archive-directory', metavar="DIRECTORY", 2012 help=self.__stripSpaces(self.uriContentArchiveDirectory.__doc__)) 2013 parser.add_option_group(group) 2014 2015 group = optparse.OptionGroup(parser, 'Configuring Bindings', 'Specify where generated bindings should be written, and how they will be accessed from Python.') 2016 group.add_option('--module', '-m', metavar="MODULE", 2017 action='append', 2018 help=self.__stripSpaces(self.addModuleName.__doc__)) 2019 group.add_option('--module-prefix', metavar="MODULE", 2020 help=self.__stripSpaces(self.modulePrefix.__doc__)) 2021 group.add_option('--binding-root', metavar="DIRECTORY", 2022 help=self.__stripSpaces(self.bindingRoot.__doc__)) 2023 group.add_option('-r', '--write-for-customization', 2024 action='store_true', dest='write_for_customization', 2025 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns on the feature.')) 2026 group.add_option('--no-write-for-customization', 2027 action='store_false', dest='write_for_customization', 2028 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns off the feature (I{default}).')) 2029 parser.add_option_group(group) 2030 2031 group = optparse.OptionGroup(parser, 'Reading Namespace Archives', 'Locating and loading (or inhibiting load of) namespace archives.') 2032 group.add_option('--archive-path', metavar="PATH", 2033 help=self.__stripSpaces(self.archivePath.__doc__)) 2034 group.add_option('--pre-load-archive', metavar="FILE", 2035 action='append', 2036 help=self.__stripSpaces(self.addPreLoadArchive.__doc__)) 2037 group.add_option('--no-load-namespace', metavar="URI", 2038 action='append', 2039 help=self.__stripSpaces(self.addNoLoadNamespace.__doc__)) 2040 parser.add_option_group(group) 2041 2042 group = optparse.OptionGroup(parser, 'Writing Namespace Archives', 'Control the location and content of a namespace archive corresponding to a binding generation.') 2043 group.add_option('--archive-to-file', metavar="FILE", 2044 help=self.__stripSpaces(self.archiveToFile.__doc__)) 2045 group.add_option('--public-namespace', metavar="URI", 2046 action='append', 2047 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a public archive member.')) 2048 group.add_option('--private-namespace', metavar="URI", 2049 action='append', 2050 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a private archive member.')) 2051 group.add_option('--default-namespace-public', 2052 action="store_true", dest='default_namespace_public', 2053 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{public} (I{default}).')) 2054 group.add_option('--default-namespace-private', 2055 action="store_false", dest='default_namespace_public', 2056 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{private}.')) 2057 parser.add_option_group(group) 2058 2059 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.") 2060 group.add_option('--binding-style', 2061 type='choice', choices=basis.BINDING_STYLES, 2062 help=self.__stripSpaces(self.bindingStyle.__doc__)) 2063 group.add_option('--validate-changes', 2064 action='store_true', dest='validate_changes', 2065 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns on validation (default).')) 2066 group.add_option('--no-validate-changes', 2067 action='store_false', dest='validate_changes', 2068 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns off validation.')) 2069 parser.add_option_group(group) 2070 2071 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.") 2072 group.add_option('--allow-absent-module', 2073 action='store_true', dest='allow_absent_module', 2074 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns on the feature.')) 2075 group.add_option('--no-allow-absent-module', 2076 action='store_false', dest='allow_absent_module', 2077 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns off the feature (default).')) 2078 group.add_option('--allow-builtin-generation', 2079 action='store_true', dest='allow_builtin_generation', 2080 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns on the feature.')) 2081 group.add_option('--no-allow-builtin-generation', 2082 action='store_false', dest='allow_builtin_generation', 2083 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns off the feature (default).')) 2084 parser.add_option_group(group) 2085 2086 self.__optionParser = parser 2087 return self.__optionParser
2088 __optionParser = None 2089
2090 - def getCommandLineArgs (self):
2091 """Return a command line option sequence that could be used to 2092 construct an equivalent configuration. 2093 2094 @note: If you extend the option parser, as is done by 2095 C{pyxbgen}, this may not be able to reconstruct the correct 2096 command line.""" 2097 opts = [] 2098 module_list = self.moduleList() 2099 schema_list = self.schemaLocationList() 2100 while module_list and schema_list: 2101 ml = module_list.pop(0) 2102 sl = schema_list.pop(0) 2103 if isinstance(sl, tuple): 2104 sl = sl[0] 2105 opts.extend(['--schema-location=' + sl, '--module=' + ml]) 2106 for sl in schema_list: 2107 opts.append('--schema-location=' + sl) 2108 if self.schemaRoot() is not None: 2109 opts.append('--schema-root=' + self.schemaRoot()) 2110 if self.schemaStrippedPrefix() is not None: 2111 opts.append('--schema-stripped-prefix=%s' + self.schemaStrippedPrefix()) 2112 if self.modulePrefix() is not None: 2113 opts.append('--module-prefix=' + self.modulePrefix()) 2114 opts.append('--binding-root=' + self.bindingRoot()) 2115 if self.archivePath() is not None: 2116 opts.append('--archive-path=' + self.archivePath()) 2117 for ns in self.noLoadNamespaces(): 2118 opts.append('--no-load-namespace=' + ns.uri()) 2119 for fps in self.preLoadArchives(): 2120 opts.append('--pre-load-archive=' + fp) 2121 if self.archiveToFile() is not None: 2122 opts.append('--archive-to-file=' + self.archiveToFile()) 2123 for (ns, visibility) in self._namespaceVisibilityMap(): 2124 if visibility: 2125 opts.append('--public-namespace=' + ns.uri()) 2126 else: 2127 opts.append('--private-namespace=' + ns.uri()) 2128 if self.defaultNamespacePublic(): 2129 opts.append('--default-namespace-public') 2130 else: 2131 opts.append('--default-namespace-private') 2132 for (val, opt) in ( (self.validateChanges(), 'validate-changes'), 2133 (self.writeForCustomization(), 'write-for-customization'), 2134 (self.allowAbsentModule(), 'allow-absent-module'), 2135 (self.allowBuiltinGeneration(), 'allow-builtin-generation') ): 2136 if val: 2137 opts.append('--' + opt) 2138 else: 2139 opts.append('--no-' + opt) 2140 if self.uriContentArchiveDirectory() is not None: 2141 opts.append('--uri-content-archive-directory=%s' + self.uriContentArchiveDirectory()) 2142 return opts
2143
2144 - def normalizeSchemaLocation (self, sl):
2145 ssp = self.schemaStrippedPrefix() 2146 if ssp and sl.startswith(ssp): 2147 sl = sl[len(ssp):] 2148 return pyxb.utils.utility.NormalizeLocation(sl, self.schemaRoot())
2149
2150 - def __assignModulePath (self, module_record, module_path=None):
2151 if module_record.modulePath() is not None: 2152 return module_record 2153 namespace = module_record.namespace() 2154 if not namespace.isAbsentNamespace(): 2155 if (module_path is None) and not (namespace.prefix() is None): 2156 module_path = namespace.prefix() 2157 module_path = self.namespaceModuleMap().get(namespace.uri(), module_path) 2158 if (module_path is not None) and self.modulePrefix(): # non-empty value 2159 module_path = '.'.join([self.modulePrefix(), module_path]) 2160 if (module_path is None) and self.generateToFiles(): 2161 raise pyxb.BindingGenerationError('No prefix or module name available for %s' % (module_record,)) 2162 module_record.setModulePath(module_path) 2163 return module_record
2164 2165 __didResolveExternalSchema = False
2166 - def resolveExternalSchema (self, reset=False):
2167 if self.__didResolveExternalSchema and (not reset): 2168 raise pyxb.PyXBException('Cannot resolve external schema multiple times') 2169 2170 required_archives = pyxb.namespace.archive.NamespaceArchive.PreLoadArchives(self.archivePath(), self.preLoadArchives()) 2171 for nsa in required_archives: 2172 nsa.readNamespaces() 2173 for ns in self.noLoadNamespaces(): 2174 assert isinstance(ns, pyxb.namespace.Namespace) 2175 ns.markNotLoadable() 2176 while self.__schemaLocationList: 2177 sl = self.__schemaLocationList.pop(0) 2178 if isinstance(sl, tuple): 2179 (sl, converter) = sl 2180 else: 2181 converter = None 2182 try: 2183 if converter is None: 2184 schema = xs.schema.CreateFromLocation(absolute_schema_location=self.normalizeSchemaLocation(sl), generation_uid=self.generationUID(), uri_content_archive_directory=self.uriContentArchiveDirectory()) 2185 else: 2186 schema = converter(self, sl) 2187 self.addSchema(schema) 2188 except pyxb.SchemaUniquenessError, e: 2189 print 'WARNING: Skipped redundant translation of %s defining %s' % (e.schemaLocation(), e.namespace()) 2190 self.addSchema(e.existingSchema()) 2191 for schema in self.__schemas: 2192 if isinstance(schema, basestring): 2193 schema = xs.schema.CreateFromDocument(schema, generation_uid=self.generationUID()) 2194 origin = schema.originRecord() 2195 assert origin is not None 2196 module_path = None 2197 if self.__moduleList: 2198 module_path = self.__moduleList.pop(0) 2199 self.__assignModulePath(origin.moduleRecord(), module_path) 2200 assert schema.targetNamespace() == origin.moduleRecord().namespace() 2201 self.addNamespace(schema.targetNamespace()) 2202 self.__didResolveExternalSchema = True 2203 self.__bindingModules = None
2204
2205 - def __graphFromComponents (self, components, include_lax):
2206 components = components.copy() 2207 component_graph = pyxb.utils.utility.Graph() 2208 need_visit = components.copy() 2209 bindable_fn = lambda _c: isinstance(_c, xs.structures.ElementDeclaration) or _c.isTypeDefinition() 2210 while 0 < len(need_visit): 2211 c = need_visit.pop() 2212 assert c is not None 2213 assert bindable_fn(c) or include_lax 2214 assert c._objectOrigin() is not None, '%s %s has no origin' % (type(c), c) 2215 component_graph.addNode(c) 2216 br = c.bindingRequires(reset=True, include_lax=include_lax) 2217 #print 'Component %s requires %d bindings' % (c, len(br)) 2218 for cd in br: 2219 assert bindable_fn(cd) or include_lax, '%s produced %s in requires' % (type(c), type(cd)) 2220 #print ' %s in %s' % (cd, cd._objectOrigin()) 2221 if cd._objectOrigin() is None: 2222 assert isinstance(cd, (pyxb.xmlschema.structures.Annotation, pyxb.xmlschema.structures.Wildcard)) 2223 continue 2224 if (cd._objectOrigin().moduleRecord() in self.__moduleRecords) and not (cd in components): 2225 components.add(cd) 2226 need_visit.add(cd) 2227 if cd in components: 2228 component_graph.addEdge(c, cd) 2229 return component_graph
2230
2231 - def __buildBindingModules (self):
2232 named_bindable_fn = lambda _c: (isinstance(_c, xs.structures.ElementDeclaration) and _c._scopeIsGlobal()) or _c.isTypeDefinition() 2233 bindable_fn = lambda _c: isinstance(_c, xs.structures.ElementDeclaration) or _c.isTypeDefinition() 2234 2235 self.__moduleRecords = set() 2236 all_components = set() 2237 for origin in self.generationUID().associatedObjects(): 2238 mr = origin.moduleRecord() 2239 if not (mr in self.__moduleRecords): 2240 # @todo NOTICE 2241 # print 'Entry %s' % (mr,) 2242 self.__moduleRecords.add(mr) 2243 mr.completeGenerationAssociations() 2244 all_components.update(origin.originatedObjects()) 2245 2246 namespaces = set() 2247 for mr in self.__moduleRecords: 2248 if mr.namespace().isBuiltinNamespace() and not self.allowBuiltinGeneration(): 2249 continue 2250 namespaces.add(mr.namespace()) 2251 pyxb.namespace.resolution.ResolveSiblingNamespaces(namespaces, self.generationUID()) 2252 2253 # Mark module visibility. Entry-point namespaces default to 2254 # public. 2255 for ns in self.namespaces(): 2256 self.__namespaceVisibilityMap.setdefault(ns, True) 2257 2258 # Generate the graph from all components and descend into lax 2259 # requirements; otherwise we might miss anonymous types hidden 2260 # inside attribute declarations and the like. 2261 component_graph = self.__graphFromComponents(all_components, True) 2262 2263 binding_components = set(filter(bindable_fn, component_graph.nodes())) 2264 # @todo NOTICE 2265 #print '%d of %d components need bindings' % (len(binding_components), len(component_graph.nodes())) 2266 2267 module_graph = pyxb.utils.utility.Graph() 2268 [ module_graph.addRoot(_mr) for _mr in self.__moduleRecords ] 2269 for (s, t) in component_graph.edges(): 2270 module_graph.addEdge(s._objectOrigin().moduleRecord(), t._objectOrigin().moduleRecord()) 2271 module_scc_order = module_graph.sccOrder() 2272 2273 # Note that module graph may have fewer nodes than 2274 # self.__moduleRecords, if a module has no components that 2275 # require binding generation. 2276 2277 # @todo NOTICE 2278 #print '%d entry, %d in graph' % (len(self.__moduleRecords), len(module_graph.nodes())) 2279 2280 for c in binding_components: 2281 assert bindable_fn(c), 'Unexpected %s in binding components' % (type(s),) 2282 c._setBindingNamespace(c._objectOrigin().moduleRecord().namespace()) 2283 2284 record_binding_map = {} 2285 unique_in_bindings = set([NamespaceGroupModule._GroupPrefix]) 2286 modules = [] 2287 for mr_scc in module_scc_order: 2288 scc_modules = [ ] 2289 for mr in mr_scc: 2290 # @todo INFO 2291 #print 'Generating %s of %d' % (mr, len(mr_scc)) 2292 mr._setIsPublic(self.__namespaceVisibilityMap.get(mr.namespace(), self.defaultNamespacePublic())) 2293 self.__assignModulePath(mr) 2294 assert not ((mr.modulePath() is None) and self.generateToFiles()), 'No module path defined for %s' % (mr,) 2295 if (not mr.isPublic()) and (mr.modulePath() is not None): 2296 elts = mr.modulePath().split('.') 2297 elts[-1] = '_%s' % (elts[-1],) 2298 mr.setModulePath('.'.join(elts)) 2299 nsm = NamespaceModule(self, mr, mr_scc) 2300 record_binding_map[mr] = nsm 2301 scc_modules.append(nsm) 2302 2303 modules.extend(scc_modules) 2304 if 1 < len(mr_scc): 2305 ngm = NamespaceGroupModule(self, scc_modules) 2306 modules.append(ngm) 2307 for nsm in scc_modules: 2308 nsm.setNamespaceGroupModule(ngm) 2309 2310 component_csets = self.__graphFromComponents(binding_components, False).sccOrder() 2311 bad_order = False 2312 component_order = [] 2313 for cset in component_csets: 2314 if 1 < len(cset): 2315 print "COMPONENT DEPENDENCY LOOP of %d components" % (len(cset),) 2316 cg = pyxb.utils.utility.Graph() 2317 for c in cset: 2318 assert bindable_fn(c), 'Unexpected %s in list' % (type(c),) 2319 print ' %s' % (c.expandedName(),) 2320 cg.addNode(c) 2321 for cd in c.bindingRequires(reset=True, include_lax=False): 2322 #print '%s depends on %s' % (c, cd) 2323 cg.addEdge(c, cd) 2324 #file('deploop.dot', 'w').write(cg._generateDOT('CompDep', lambda _c: _c.bestNCName())) 2325 relaxed_order = cg.sccOrder() 2326 for rcs in relaxed_order: 2327 assert 1 == len(rcs) 2328 rcs = rcs[0] 2329 if rcs in cset: 2330 component_order.append(rcs) 2331 else: 2332 component_order.extend(cset) 2333 2334 #print '%d components in order' % (len(component_order),) 2335 2336 element_declarations = [] 2337 type_definitions = [] 2338 for c in component_order: 2339 if isinstance(c, xs.structures.ElementDeclaration) and c._scopeIsGlobal(): 2340 # Only bind elements this pass, so their names get priority in deconfliction 2341 nsm = record_binding_map[c._objectOrigin().moduleRecord()] 2342 nsm.bindComponent(c) 2343 element_declarations.append(c) 2344 elif c.isTypeDefinition(): 2345 type_definitions.append(c) 2346 else: 2347 # No binding generation required 2348 pass 2349 2350 simple_type_definitions = [] 2351 complex_type_definitions = [] 2352 for td in type_definitions: 2353 nsm = record_binding_map[td._objectOrigin().moduleRecord()] 2354 assert nsm is not None, 'No namespace module for %s type %s scope %s namespace %s' % (td.expandedName(), type(td), td._scope(), td.bindingNamespace) 2355 module_context = nsm.bindComponent(td) 2356 assert isinstance(module_context, _ModuleNaming_mixin), 'Unexpected type %s' % (type(module_context),) 2357 if isinstance(td, xs.structures.SimpleTypeDefinition): 2358 _PrepareSimpleTypeDefinition(td, self, nsm, module_context) 2359 simple_type_definitions.append(td) 2360 elif isinstance(td, xs.structures.ComplexTypeDefinition): 2361 _PrepareComplexTypeDefinition(td, self, nsm, module_context) 2362 complex_type_definitions.append(td) 2363 else: 2364 assert False, 'Unexpected component type %s' % (type(td),) 2365 2366 for ngm in modules: 2367 if isinstance(ngm, NamespaceGroupModule): 2368 for m in ngm.namespaceModules(): 2369 m.addImportsFrom(ngm) 2370 2371 for std in simple_type_definitions: 2372 GenerateSTD(std, self) 2373 for ctd in complex_type_definitions: 2374 GenerateCTD(ctd, self) 2375 for ed in element_declarations: 2376 GenerateED(ed, self) 2377 2378 return modules
2379 2380 __bindingModules = None
2381 - def bindingModules (self, reset=False):
2382 if reset or (not self.__didResolveExternalSchema): 2383 self.resolveExternalSchema(reset) 2384 if reset or (self.__bindingModules is None): 2385 self.__bindingModules = self.__buildBindingModules() 2386 return self.__bindingModules
2387
2388 - def writeNamespaceArchive (self):
2389 archive_file = self.archiveToFile() 2390 if archive_file is not None: 2391 ns_archive = pyxb.namespace.archive.NamespaceArchive(generation_uid=self.generationUID()) 2392 try: 2393 ns_archive.writeNamespaces(pyxb.utils.utility.OpenOrCreate(archive_file)) 2394 print 'Saved parsed schema to %s URI' % (archive_file,) 2395 except Exception, e: 2396 print 'Exception saving preprocessed schema to %s: %s' % (archive_file, e) 2397 traceback.print_exception(*sys.exc_info()) 2398 #try: 2399 # os.unlink(component_model_file) 2400 #except (OSError, IOError), e: 2401 # pass 2402 if isinstance(e, (AssertionError, AttributeError, TypeError)): 2403 raise
2404
2405 - def moduleForComponent (self, component):
2407