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 self.setLiteral(rv)
145
146 -class ReferenceExpandedName (ReferenceLiteral):
147 __expandedName = None 148
149 - def __init__ (self, **kw):
150 self.__expandedName = kw['expanded_name'] 151 self.setLiteral('pyxb.namespace.ExpandedName(%s, %s)' % (pythonLiteral(self.__expandedName.namespace(), **kw), pythonLiteral(self.__expandedName.localName(), **kw)))
152
153 -class ReferenceFacet (ReferenceLiteral):
154 __facet = None 155
156 - def __init__ (self, **kw):
157 self.__facet = kw['facet'] 158 super(ReferenceFacet, self).__init__(**kw) 159 self.setLiteral('%s._CF_%s' % (pythonLiteral(self.__facet.ownerTypeDefinition(), **kw), self.__facet.Name()))
160
161 -class ReferenceEnumerationMember (ReferenceLiteral):
162 enumerationElement = None 163
164 - def __init__ (self, **kw):
165 # NB: Pre-extended __init__ 166 167 # All we really need is the enumeration element, so we can get 168 # its tag, and a type definition or datatype, so we can create 169 # the proper prefix. 170 171 # See if we were given a value, from which we can extract the 172 # other information. 173 value = kw.get('enum_value', None) 174 assert (value is None) or isinstance(value, facets._Enumeration_mixin) 175 176 # Must provide facet_instance, or a value from which it can be 177 # obtained. 178 facet_instance = kw.get('facet_instance', None) 179 if facet_instance is None: 180 assert isinstance(value, facets._Enumeration_mixin) 181 facet_instance = value._CF_enumeration 182 assert isinstance(facet_instance, facets.CF_enumeration) 183 184 # Must provide the enumeration_element, or a facet_instance 185 # and value from which it can be identified. 186 self.enumerationElement = kw.get('enumeration_element', None) 187 if self.enumerationElement is None: 188 assert value is not None 189 self.enumerationElement = facet_instance.elementForValue(value) 190 assert isinstance(self.enumerationElement, facets._EnumerationElement) 191 if self.enumerationElement.tag() is None: 192 self.enumerationElement._setTag(utility.MakeIdentifier(self.enumerationElement.unicodeValue())) 193 binding_tag = utility.PrepareIdentifier(self.enumerationElement.tag(), kw['class_unique'], kw['class_keywords']) 194 if self.enumerationElement.bindingTag() is None: 195 # Boy I hope this is the first time generating one of 196 # thes, so this is in the owner class 197 self.enumerationElement._setBindingTag(binding_tag) 198 199 # If no type definition was provided, use the value datatype 200 # for the facet. 201 kw.setdefault('type_definition', facet_instance.valueDatatype()) 202 203 super(ReferenceEnumerationMember, self).__init__(**kw) 204 205 self.setLiteral(self._addTypePrefix(binding_tag, **kw))
206
207 -def pythonLiteral (value, **kw):
208 # For dictionaries, apply translation to all values (not keys) 209 if isinstance(value, types.DictionaryType): 210 return ', '.join([ '%s=%s' % (k, pythonLiteral(v, **kw)) for (k, v) in value.items() ]) 211 212 # For lists, apply translation to all members 213 if isinstance(value, types.ListType): 214 return [ pythonLiteral(_v, **kw) for _v in value ] 215 216 # ExpandedName is a tuple, but not here 217 if isinstance(value, pyxb.namespace.ExpandedName): 218 return pythonLiteral(ReferenceExpandedName(expanded_name=value, **kw)) 219 220 # For other collection types, do what you do for list 221 if isinstance(value, (types.TupleType, set)): 222 return type(value)(pythonLiteral(list(value), **kw)) 223 224 # Value is a binding value for which there should be an 225 # enumeration constant. Return that constant. 226 if isinstance(value, facets._Enumeration_mixin): 227 return pythonLiteral(ReferenceEnumerationMember(enum_value=value, **kw)) 228 229 # Value is an instance of a Python binding, e.g. one of the 230 # XMLSchema datatypes. Use its value, applying the proper prefix 231 # for the module. 232 if isinstance(value, basis.simpleTypeDefinition): 233 return PrefixModule(value, value.pythonLiteral()) 234 235 if isinstance(value, pyxb.namespace.Namespace): 236 return pythonLiteral(ReferenceNamespace(namespace=value, **kw)) 237 238 if isinstance(value, type): 239 if issubclass(value, basis.simpleTypeDefinition): 240 return PrefixModule(value) 241 if issubclass(value, facets.Facet): 242 return PrefixModule(value) 243 244 # String instances go out as their representation 245 if isinstance(value, types.StringTypes): 246 return utility.QuotedEscaped(value,) 247 248 if isinstance(value, facets.Facet): 249 return pythonLiteral(ReferenceFacet(facet=value, **kw)) 250 251 # Treat pattern elements as their value 252 if isinstance(value, facets._PatternElement): 253 return pythonLiteral(value.pattern) 254 255 # Treat enumeration elements as their value 256 if isinstance(value, facets._EnumerationElement): 257 return pythonLiteral(value.value()) 258 259 # Particles expand to a pyxb.binding.content.Particle instance 260 if isinstance(value, xs.structures.Particle): 261 return pythonLiteral(ReferenceParticle(value, **kw)) 262 263 # Wildcards expand to a pyxb.binding.content.Wildcard instance 264 if isinstance(value, xs.structures.Wildcard): 265 return pythonLiteral(ReferenceWildcard(value, **kw)) 266 267 # Schema components have a single name through their lifespan 268 if isinstance(value, xs.structures._SchemaComponent_mixin): 269 return pythonLiteral(ReferenceSchemaComponent(value, **kw)) 270 271 # Other special cases 272 if isinstance(value, ReferenceLiteral): 273 return value.asLiteral() 274 275 # Represent namespaces by their URI 276 if isinstance(value, pyxb.namespace.Namespace): 277 return repr(value.uri()) 278 279 # Standard Python types 280 if isinstance(value, (types.NoneType, types.BooleanType, types.FloatType, types.IntType, types.LongType)): 281 return repr(value) 282 283 raise Exception('Unexpected literal type %s' % (type(value),)) 284 print 'Unexpected literal type %s' % (type(value),) 285 return str(value)
286
287 288 -def GenerateModelGroupAll (ctd, mga, binding_module, template_map, **kw):
289 mga_tag = '__AModelGroup' 290 template_map['mga_tag'] = mga_tag 291 lines = [] 292 lines2 = [] 293 for ( dfa, is_required ) in mga.particles(): 294 ( dfa_tag, dfa_lines ) = GenerateContentModel(ctd, dfa, binding_module, **kw) 295 lines.extend(dfa_lines) 296 template_map['dfa_tag'] = dfa_tag 297 template_map['is_required'] = binding_module.literal(is_required, **kw) 298 lines2.append(templates.replaceInText(' %{content}.ModelGroupAllAlternative(%{ctd}.%{dfa_tag}, %{is_required}),', **template_map)) 299 lines.append(templates.replaceInText('%{mga_tag} = %{content}.ModelGroupAll(alternatives=[', **template_map)) 300 lines.extend(lines2) 301 lines.append('])') 302 return (mga_tag, lines)
303
304 -def GenerateContentModel (ctd, automaton, binding_module, **kw):
305 cmi = None 306 template_map = { } 307 template_map['ctd'] = binding_module.literal(ctd, **kw) 308 try: 309 cmi = '_ContentModel_%d' % (ctd.__contentModelIndex,) 310 ctd.__contentModelIndex += 1 311 except AttributeError: 312 cmi = '_ContentModel' 313 ctd.__contentModelIndex = 1 314 template_map['cm_tag'] = cmi 315 template_map['content'] = 'pyxb.binding.content' 316 template_map['state_comma'] = ' ' 317 lines = [] 318 lines2 = [] 319 for (state, transitions) in automaton.items(): 320 if automaton.end() == state: 321 continue 322 template_map['state'] = binding_module.literal(state) 323 template_map['is_final'] = binding_module.literal(None in transitions) 324 325 lines2.append(templates.replaceInText('%{state_comma} %{state} : %{content}.ContentModelState(state=%{state}, is_final=%{is_final}, transitions=[', **template_map)) 326 template_map['state_comma'] = ',' 327 lines3 = [] 328 for (key, destinations) in transitions.items(): 329 if key is None: 330 continue 331 assert 1 == len(destinations) 332 template_map['next_state'] = binding_module.literal(list(destinations)[0], **kw) 333 if isinstance(key, xs.structures.Wildcard): 334 template_map['kw_key'] = 'term' 335 template_map['kw_val'] = binding_module.literal(key, **kw) 336 elif isinstance(key, nfa.AllWalker): 337 (mga_tag, mga_defns) = GenerateModelGroupAll(ctd, key, binding_module, template_map.copy(), **kw) 338 template_map['kw_key'] = 'term' 339 template_map['kw_val'] = mga_tag 340 lines.extend(mga_defns) 341 else: 342 assert isinstance(key, xs.structures.ElementDeclaration) 343 template_map['kw_key'] = 'element_use' 344 template_map['kw_val'] = templates.replaceInText('%{ctd}._UseForTag(%{field_tag})', field_tag=binding_module.literal(key.expandedName(), **kw), **template_map) 345 lines3.append(templates.replaceInText('%{content}.ContentModelTransition(next_state=%{next_state}, %{kw_key}=%{kw_val}),', 346 **template_map)) 347 lines2.extend([ ' '+_l for _l in lines3 ]) 348 lines2.append("])") 349 350 lines.append(templates.replaceInText('%{ctd}.%{cm_tag} = %{content}.ContentModel(state_map = {', **template_map)) 351 lines.extend([' '+_l for _l in lines2 ]) 352 lines.append("})") 353 return (cmi, lines)
354
355 -def _useEnumerationTags (td):
356 assert isinstance(td, xs.structures.SimpleTypeDefinition) 357 ptd = td.baseTypeDefinition() 358 python_support = None 359 # Atomic types that use strings as their representation 360 if (ptd.VARIETY_atomic == ptd.variety()): 361 python_support = ptd.primitiveTypeDefinition().pythonSupport() 362 return issubclass(python_support, basestring) 363 # Derivations from anySimpleType use strings too 364 if (ptd.VARIETY_absent == ptd.variety()): 365 return True 366 # Union types? Yeah, I suppose so. Though this only applies to 367 # members lifted up into the union. 368 if (ptd.VARIETY_union == ptd.variety()): 369 return True 370 # List types have spaces so no tags. 371 return False
372
373 -def GenerateFacets (td, generator, **kw):
374 binding_module = kw['binding_module'] 375 outf = binding_module.bindingIO() 376 facet_instances = [] 377 gen_enum_tag = _useEnumerationTags(td) 378 for (fc, fi) in td.facets().items(): 379 #if (fi is None) or (fi.ownerTypeDefinition() != td): 380 # continue 381 if (fi is None) and (fc in td.baseTypeDefinition().facets()): 382 # Nothing new here 383 #print 'Skipping %s in %s: already registered' % (fc, td) 384 continue 385 if (fi is not None) and (fi.ownerTypeDefinition() != td): 386 # Did this one in an ancestor 387 #print 'Skipping %s in %s: found in ancestor' % (fc, td) 388 continue 389 argset = { } 390 is_collection = issubclass(fc, facets._CollectionFacet_mixin) 391 if issubclass(fc, facets._LateDatatype_mixin): 392 vdt = td 393 if fc.LateDatatypeBindsSuperclass(): 394 vdt = vdt.baseTypeDefinition() 395 argset['value_datatype'] = vdt 396 if fi is not None: 397 if not is_collection: 398 argset['value'] = fi.value() 399 if isinstance(fi, facets.CF_enumeration): 400 argset['enum_prefix'] = fi.enumPrefix() 401 facet_var = ReferenceFacetMember(type_definition=td, facet_class=fc, **kw) 402 outf.write("%s = %s(%s)\n" % binding_module.literal( (facet_var, fc, argset ), **kw)) 403 facet_instances.append(binding_module.literal(facet_var, **kw)) 404 if (fi is not None) and is_collection: 405 for i in fi.items(): 406 if isinstance(i, facets._EnumerationElement): 407 enum_config = '%s.addEnumeration(unicode_value=%s)' % binding_module.literal( ( facet_var, i.unicodeValue() ), **kw) 408 if gen_enum_tag: 409 enum_member = ReferenceEnumerationMember(type_definition=td, facet_instance=fi, enumeration_element=i, **kw) 410 outf.write("%s = %s\n" % (binding_module.literal(enum_member, **kw), enum_config)) 411 if fi.enumPrefix() is not None: 412 outf.write("%s_%s = %s\n" % (fi.enumPrefix(), i.tag(), binding_module.literal(enum_member, **kw))) 413 else: 414 outf.write("%s\n" % (enum_config,)) 415 if isinstance(i, facets._PatternElement): 416 outf.write("%s.addPattern(pattern=%s)\n" % binding_module.literal( (facet_var, i.pattern ), **kw)) 417 if gen_enum_tag and (xs.structures.SimpleTypeDefinition.VARIETY_union == td.variety()): 418 # If the union has enumerations of its own, there's no need to 419 # inherit anything. 420 fi = td.facets().get(facets.CF_enumeration) 421 if fi is None: 422 # Need to expose any enumerations in members up in this class 423 for mtd in td.memberTypeDefinitions(): 424 if not _useEnumerationTags(mtd): 425 continue 426 fi = mtd.facets().get(facets.CF_enumeration) 427 if fi is None: 428 continue 429 for i in fi.items(): 430 assert isinstance(i, facets._EnumerationElement) 431 etd = i.enumeration().ownerTypeDefinition() 432 enum_member = ReferenceEnumerationMember(type_definition=td, facet_instance=fi, enumeration_element=i, **kw) 433 outf.write("%-50s%s\n" % ('%s = %s' % binding_module.literal( (enum_member, i.unicodeValue()) ), 434 '# originally %s.%s' % (binding_module.literal(etd), i.bindingTag()))) 435 if 2 <= len(facet_instances): 436 map_args = ",\n ".join(facet_instances) 437 else: 438 map_args = ','.join(facet_instances) 439 outf.write("%s._InitializeFacetMap(%s)\n" % (binding_module.literal(td, **kw), map_args))
440
441 -def GenerateSTD (std, generator):
442 443 binding_module = generator.moduleForComponent(std) 444 outf = binding_module.bindingIO() 445 446 class_keywords = frozenset(basis.simpleTypeDefinition._ReservedSymbols) 447 class_unique = set() 448 449 kw = { } 450 kw['binding_module'] = binding_module 451 kw['class_keywords'] = class_keywords 452 kw['class_unique'] = class_unique 453 454 parent_classes = [ binding_module.literal(std.baseTypeDefinition(), **kw) ] 455 enum_facet = std.facets().get(facets.CF_enumeration, None) 456 if (enum_facet is not None) and (enum_facet.ownerTypeDefinition() == std): 457 parent_classes.append('pyxb.binding.basis.enumeration_mixin') 458 459 template_map = { } 460 template_map['std'] = binding_module.literal(std, **kw) 461 template_map['superclasses'] = '' 462 if 0 < len(parent_classes): 463 template_map['superclasses'] = ', '.join(parent_classes) 464 template_map['expanded_name'] = binding_module.literal(std.expandedName(), **kw) 465 template_map['namespaceReference'] = binding_module.literal(std.bindingNamespace(), **kw) 466 if std.annotation() is not None: 467 template_map['documentation'] = std.annotation().asDocString() 468 template_map['documentation_expr'] = binding_module.literal(std.annotation().text()) 469 else: 470 template_map['documentation'] = '' 471 template_map['documentation_expr'] = binding_module.literal(None) 472 473 # @todo: Extensions of LIST will be wrong in below 474 475 common_template = ''' 476 """%{documentation}""" 477 478 _ExpandedName = %{expanded_name} 479 _Documentation = %{documentation_expr} 480 ''' 481 if xs.structures.SimpleTypeDefinition.VARIETY_absent == std.variety(): 482 template = ''' 483 # The ur SimpleTypeDefinition 484 class %{std} (%{superclasses}): 485 ''' + common_template 486 if not template_map['documentation']: 487 template_map['documentation'] = 'The ur simple type.' 488 elif xs.structures.SimpleTypeDefinition.VARIETY_atomic == std.variety(): 489 template = ''' 490 # Atomic SimpleTypeDefinition 491 class %{std} (%{superclasses}): 492 ''' + common_template 493 if not template_map['documentation']: 494 template_map['documentation'] = 'An atomic simple type.' 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 if not template_map['documentation']: 505 template_map['documentation'] = templates.replaceInText('Simple type that is a list of %{itemtype}.', **template_map) 506 elif xs.structures.SimpleTypeDefinition.VARIETY_union == std.variety(): 507 template = ''' 508 # Union SimpleTypeDefinition 509 # superclasses %{superclasses} 510 class %{std} (pyxb.binding.basis.STD_union): 511 ''' + common_template + ''' 512 _MemberTypes = ( %{membertypes}, ) 513 ''' 514 template_map['membertypes'] = ", ".join( [ binding_module.literal(_mt, **kw) for _mt in std.memberTypeDefinitions() ]) 515 if not template_map['documentation']: 516 template_map['documentation'] = templates.replaceInText('Simple type that is a union of %{membertypes}.', **template_map) 517 else: 518 raise pyxb.LogicError("Unhandled STD variety") 519 520 outf.write(templates.replaceInText(template, **template_map)) 521 522 generate_facets = False 523 if generate_facets: 524 # If generating datatype_facets, throw away the class garbage 525 if std.isBuiltin(): 526 GenerateFacets(std, generator, **kw) 527 else: 528 GenerateFacets(std, generator, **kw) 529 530 if std.name() is not None: 531 outf.write(templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{std})\n", 532 localName=binding_module.literal(std.name(), **kw), **template_map))
533
534 -def elementDeclarationMap (ed, binding_module, **kw):
535 template_map = { } 536 template_map['name'] = unicode(ed.expandedName()) 537 template_map['namespaceReference'] = binding_module.literal(ed.bindingNamespace(), **kw) 538 if (ed.SCOPE_global == ed.scope()): 539 template_map['class'] = binding_module.literal(ed, **kw) 540 template_map['localName'] = binding_module.literal(ed.name(), **kw) 541 template_map['map_update'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('elementBinding', %{localName}, %{class})", **template_map) 542 else: 543 template_map['scope'] = binding_module.literal(ed.scope(), **kw) 544 if ed.annotation() is not None: 545 template_map['documentation'] = binding_module.literal(unicode(ed.annotation())) 546 if ed.abstract(): 547 template_map['abstract'] = binding_module.literal(ed.abstract(), **kw) 548 if ed.nillable(): 549 template_map['nillable'] = binding_module.literal(ed.nillable(), **kw) 550 if ed.default(): 551 template_map['defaultValue'] = binding_module.literal(ed.default(), **kw) 552 template_map['typeDefinition'] = binding_module.literal(ed.typeDefinition(), **kw) 553 if ed.substitutionGroupAffiliation(): 554 template_map['substitution_group'] = binding_module.literal(ed.substitutionGroupAffiliation(), **kw) 555 aux_init = [] 556 for k in ( 'nillable', 'abstract', 'scope', 'documentation' ): 557 if k in template_map: 558 aux_init.append('%s=%s' % (k, template_map[k])) 559 template_map['element_aux_init'] = '' 560 if 0 < len(aux_init): 561 template_map['element_aux_init'] = ', ' + ', '.join(aux_init) 562 563 return template_map
564
565 -def GenerateCTD (ctd, generator, **kw):
566 binding_module = generator.moduleForComponent(ctd) 567 outf = binding_module.bindingIO() 568 569 content_type = None 570 prolog_template = None 571 template_map = { } 572 template_map['ctd'] = binding_module.literal(ctd, **kw) 573 base_type = ctd.baseTypeDefinition() 574 content_type_tag = ctd._contentTypeTag() 575 576 template_map['base_type'] = binding_module.literal(base_type, **kw) 577 template_map['namespaceReference'] = binding_module.literal(ctd.bindingNamespace(), **kw) 578 template_map['expanded_name'] = binding_module.literal(ctd.expandedName(), **kw) 579 template_map['simple_base_type'] = binding_module.literal(None, **kw) 580 template_map['contentTypeTag'] = content_type_tag 581 template_map['is_abstract'] = repr(not not ctd.abstract()) 582 583 need_content = False 584 content_basis = None 585 if (ctd.CT_SIMPLE == content_type_tag): 586 content_basis = ctd.contentType()[1] 587 template_map['simple_base_type'] = binding_module.literal(content_basis, **kw) 588 elif (ctd.CT_MIXED == content_type_tag): 589 content_basis = ctd.contentType()[1] 590 need_content = True 591 elif (ctd.CT_ELEMENT_ONLY == content_type_tag): 592 content_basis = ctd.contentType()[1] 593 need_content = True 594 need_content = False 595 596 prolog_template = ''' 597 # Complex type %{ctd} with content type %{contentTypeTag} 598 class %{ctd} (%{superclass}): 599 _TypeDefinition = %{simple_base_type} 600 _ContentTypeTag = pyxb.binding.basis.complexTypeDefinition._CT_%{contentTypeTag} 601 _Abstract = %{is_abstract} 602 _ExpandedName = %{expanded_name} 603 ''' 604 605 # Complex types that inherit from non-ur-type complex types should 606 # have their base type as their Python superclass, so pre-existing 607 # elements and attributes can be re-used. 608 inherits_from_base = True 609 template_map['superclass'] = binding_module.literal(base_type, **kw) 610 if ctd._isHierarchyRoot(): 611 inherits_from_base = False 612 template_map['superclass'] = 'pyxb.binding.basis.complexTypeDefinition' 613 assert base_type.nameInBinding() is not None 614 615 # Support for deconflicting attributes, elements, and reserved symbols 616 class_keywords = frozenset(basis.complexTypeDefinition._ReservedSymbols) 617 class_unique = set() 618 619 # Deconflict elements first, attributes are lower priority. 620 # Expectation is that all elements that have the same tag in the 621 # XML are combined into the same instance member, even if they 622 # have different types. Determine what name that should be, and 623 # whether there might be multiple instances of elements of that 624 # name. 625 element_name_map = { } 626 element_uses = [] 627 628 definitions = [] 629 630 definitions.append('# Base type is %{base_type}') 631 632 # Retain in the ctd the information about the element 633 # infrastructure, so it can be inherited where appropriate in 634 # subclasses. 635 636 if isinstance(content_basis, xs.structures.Particle): 637 plurality_data = content_basis.pluralityData().combinedPlurality() 638 639 outf.postscript().append("\n\n") 640 for (ed, is_plural) in plurality_data.items(): 641 # @todo Detect and account for plurality change between this and base 642 ef_map = ed._templateMap() 643 if ed.scope() == ctd: 644 ef_map.update(elementDeclarationMap(ed, binding_module, **kw)) 645 aux_init = [] 646 ef_map['is_plural'] = repr(is_plural) 647 element_uses.append(templates.replaceInText('%{use}.name() : %{use}', **ef_map)) 648 if 0 == len(aux_init): 649 ef_map['aux_init'] = '' 650 else: 651 ef_map['aux_init'] = ', ' + ', '.join(aux_init) 652 ef_map['element_binding'] = utility.PrepareIdentifier('%s_elt' % (ef_map['id'],), class_unique, class_keywords, private=True) 653 if ed.annotation() is not None: 654 ef_map['documentation'] = binding_module.literal(unicode(ed.annotation())) 655 else: 656 ef_map['documentation'] = binding_module.literal(None) 657 if ed.scope() != ctd: 658 definitions.append(templates.replaceInText(''' 659 # Element %{id} (%{name}) inherited from %{decl_type_en}''', decl_type_en=unicode(ed.scope().expandedName()), **ef_map)) 660 continue 661 662 if ed.expandedName().localName() != ef_map['id']: 663 print 'Element %s.%s renamed to %s' % (ctd.expandedName(), ed.expandedName(), ef_map['id']) 664 definitions.append(templates.replaceInText(''' 665 # Element %{name} uses Python identifier %{id} 666 %{use} = pyxb.binding.content.ElementUse(%{name_expr}, '%{id}', '%{key}', %{is_plural}%{aux_init}) 667 ''', name_expr=binding_module.literal(ed.expandedName(), **kw), **ef_map)) 668 669 if basis.BINDING_STYLE_ACCESSOR == generator.bindingStyle(): 670 definitions.append(templates.replaceInText(''' 671 def %{inspector} (self): 672 """Get the value of the %{name} element.""" 673 return self.%{use}.value(self) 674 def %{mutator} (self, new_value): 675 """Set the value of the %{name} element. Raises BadValueTypeException 676 if the new value is not consistent with the element's type.""" 677 return self.%{use}.set(self, new_value)''', **ef_map)) 678 if is_plural: 679 definitions.append(templates.replaceInText(''' 680 def %{appender} (self, new_value): 681 """Add the value as another occurrence of the %{name} element. Raises 682 BadValueTypeException if the new value is not consistent with the 683 element's type.""" 684 return self.%{use}.append(self, new_value)''', **ef_map)) 685 elif basis.BINDING_STYLE_PROPERTY == generator.bindingStyle(): 686 definitions.append(templates.replaceInText(''' 687 %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation}) 688 ''', **ef_map)) 689 else: 690 raise pyxb.LogicError('Unexpected binding style %s' % (generator.bindingStyle(),)) 691 outf.postscript().append(templates.replaceInText(''' 692 %{ctd}._AddElement(pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init})) 693 ''', name_expr=binding_module.literal(ed.expandedName(), **kw), ctd=template_map['ctd'], **ef_map)) 694 695 fa = nfa.Thompson(content_basis).nfa() 696 fa = fa.buildDFA() 697 (cmi, cmi_defn) = GenerateContentModel(ctd=ctd, automaton=fa, binding_module=binding_module, **kw) 698 outf.postscript().append("\n".join(cmi_defn)) 699 outf.postscript().append("\n") 700 701 if need_content: 702 PostscriptItems.append(templates.replaceInText(''' 703 %{ctd}._Content = %{particle} 704 ''', **template_map)) 705 706 # Create definitions for all attributes. 707 attribute_uses = [] 708 709 # name - String value of expanded name of the attribute (attr_tag, attr_ns) 710 # name_expr - Python expression for an expanded name identifying the attribute (attr_tag) 711 # use - Binding variable name holding AttributeUse instance (attr_name) 712 # id - Python identifier for attribute (python_attr_name) 713 # key - String used as dictionary key holding instance value of attribute (value_attr_name) 714 # inspector - Name of the method used for inspection (attr_inspector) 715 # mutator - Name of the method use for mutation (attr_mutator) 716 for au in ctd.attributeUses(): 717 ad = au.attributeDeclaration() 718 assert isinstance(ad.scope(), xs.structures.ComplexTypeDefinition), 'unexpected scope %s' % (ad.scope(),) 719 au_map = ad._templateMap() 720 if ad.scope() == ctd: 721 assert isinstance(au_map, dict) 722 if au.restrictionOf() is not None: 723 #print 'Local %s restriction of %s' % (au_map, au.restrictionOf().attributeDeclaration()._templateMap()) 724 au_map = au.restrictionOf().attributeDeclaration()._templateMap().copy() 725 definitions.append(templates.replaceInText(''' 726 # Attribute %{id} is restricted from parent''', **au_map)) 727 728 assert ad.typeDefinition() is not None 729 au_map['attr_type'] = binding_module.literal(ad.typeDefinition(), **kw) 730 731 vc_source = ad 732 if au.valueConstraint() is not None: 733 vc_source = au 734 aux_init = [] 735 if vc_source.fixed() is not None: 736 aux_init.append('fixed=True') 737 aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.fixed(), **kw),)) 738 elif vc_source.default() is not None: 739 aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.default(), **kw),)) 740 if au.required(): 741 aux_init.append('required=True') 742 if au.prohibited(): 743 aux_init.append('prohibited=True') 744 if 0 == len(aux_init): 745 au_map['aux_init'] = '' 746 else: 747 aux_init.insert(0, '') 748 au_map['aux_init'] = ', '.join(aux_init) 749 if ad.annotation() is not None: 750 au_map['documentation'] = binding_module.literal(unicode(ad.annotation())) 751 else: 752 au_map['documentation'] = binding_module.literal(None) 753 if ad.scope() != ctd: 754 definitions.append(templates.replaceInText(''' 755 # Attribute %{id} inherited from %{decl_type_en}''', decl_type_en=unicode(ad.scope().expandedName()), **au_map)) 756 continue 757 758 attribute_uses.append(templates.replaceInText('%{use}.name() : %{use}', **au_map)) 759 if ad.expandedName().localName() != au_map['id']: 760 print 'Attribute %s.%s renamed to %s' % (ctd.expandedName(), ad.expandedName(), au_map['id']) 761 definitions.append(templates.replaceInText(''' 762 # Attribute %{name} uses Python identifier %{id} 763 %{use} = pyxb.binding.content.AttributeUse(%{name_expr}, '%{id}', '%{key}', %{attr_type}%{aux_init})''', name_expr=binding_module.literal(ad.expandedName(), **kw), **au_map)) 764 if au.prohibited(): 765 if basis.BINDING_STYLE_ACCESSOR == generator.bindingStyle(): 766 definitions.append(templates.replaceInText(''' 767 # Attribute %{id} marked prohibited in this type 768 def %{inspector} (self): 769 raise pyxb.ProhibitedAttributeError("Attribute %{name} is prohibited in %{ctd}") 770 def %{mutator} (self, new_value): 771 raise pyxb.ProhibitedAttributeError("Attribute %{name} is prohibited in %{ctd}") 772 ''', ctd=template_map['ctd'], **au_map)) 773 elif basis.BINDING_STYLE_PROPERTY == generator.bindingStyle(): 774 definitions.append(templates.replaceInText(''' 775 %{inspector} = property() 776 ''', ctd=template_map['ctd'], **au_map)) 777 778 else: 779 raise pyxb.LogicError('Unexpected binding style %s' % (generator.bindingStyle(),)) 780 else: 781 if basis.BINDING_STYLE_ACCESSOR == generator.bindingStyle(): 782 definitions.append(templates.replaceInText(''' 783 def %{inspector} (self): 784 """Get the attribute value for %{name}.""" 785 return self.%{use}.value(self) 786 def %{mutator} (self, new_value): 787 """Set the attribute value for %{name}. Raises BadValueTypeException 788 if the new value is not consistent with the attribute's type.""" 789 return self.%{use}.set(self, new_value)''', **au_map)) 790 elif basis.BINDING_STYLE_PROPERTY == generator.bindingStyle(): 791 definitions.append(templates.replaceInText(''' 792 %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation}) 793 ''', ctd=template_map['ctd'], **au_map)) 794 else: 795 raise pyxb.LogicError('Unexpected binding style %s' % (generator.bindingStyle(),)) 796 797 if ctd.attributeWildcard() is not None: 798 definitions.append('_AttributeWildcard = %s' % (binding_module.literal(ctd.attributeWildcard(), **kw),)) 799 if ctd.hasWildcardElement(): 800 definitions.append('_HasWildcardElement = True') 801 template_map['attribute_uses'] = ",\n ".join(attribute_uses) 802 template_map['element_uses'] = ",\n ".join(element_uses) 803 if inherits_from_base: 804 map_decl = ''' 805 _ElementMap = %{superclass}._ElementMap.copy() 806 _ElementMap.update({ 807 %{element_uses} 808 }) 809 _AttributeMap = %{superclass}._AttributeMap.copy() 810 _AttributeMap.update({ 811 %{attribute_uses} 812 })''' 813 else: 814 map_decl = ''' 815 _ElementMap = { 816 %{element_uses} 817 } 818 _AttributeMap = { 819 %{attribute_uses} 820 }''' 821 822 template_map['registration'] = '' 823 if ctd.name() is not None: 824 template_map['registration'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{ctd})", 825 localName=binding_module.literal(ctd.name(), **kw), **template_map) 826 827 template = ''.join([prolog_template, 828 " ", "\n ".join(definitions), "\n", 829 map_decl, ''' 830 %{registration} 831 832 ''']) 833 834 outf.write(template, **template_map)
835
836 -def GenerateED (ed, generator, **kw):
837 # Unscoped declarations should never be referenced in the binding. 838 assert ed._scopeIsGlobal() 839 840 binding_module = generator.moduleForComponent(ed) 841 outf = binding_module.bindingIO() 842 843 template_map = elementDeclarationMap(ed, binding_module, **kw) 844 template_map.setdefault('scope', binding_module.literal(None, **kw)) 845 template_map.setdefault('map_update', '') 846 847 outf.write(templates.replaceInText(''' 848 %{class} = pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init}) 849 %{namespaceReference}.addCategoryObject('elementBinding', %{class}.name().localName(), %{class}) 850 ''', name_expr=binding_module.literal(ed.expandedName(), **kw), **template_map)) 851 852 if ed.substitutionGroupAffiliation() is not None: 853 outf.postscript().append(templates.replaceInText(''' 854 %{class}._setSubstitutionGroup(%{substitution_group}) 855 ''', **template_map))
856
857 -def _PrepareSimpleTypeDefinition (std, generator, nsm, module_context):
858 ptd = std.primitiveTypeDefinition(throw_if_absent=False) 859 std._templateMap()['_unique'] = nsm.uniqueInClass(std) 860 if (ptd is not None) and ptd.hasPythonSupport(): 861 # Only generate enumeration constants for named simple 862 # type definitions that are fundamentally xsd:string 863 # values. 864 if issubclass(ptd.pythonSupport(), pyxb.binding.datatypes.string): 865 enum_facet = std.facets().get(pyxb.binding.facets.CF_enumeration, None) 866 if (enum_facet is not None) and (std.expandedName() is not None): 867 for ei in enum_facet.items(): 868 assert ei.tag() is None, '%s already has a tag' % (ei,) 869 ei._setTag(utility.PrepareIdentifier(ei.unicodeValue(), nsm.uniqueInClass(std)))
870 #print ' Enum %s represents %s' % (ei.tag(), ei.unicodeValue())
871 #print '%s unique: %s' % (std.expandedName(), nsm.uniqueInClass(std)) 872 873 -def _PrepareComplexTypeDefinition (ctd, generator, nsm, module_context):
874 #print '%s represents %s in %s' % (ctd.nameInBinding(), ctd.expandedName(), nsm.namespace()) 875 content_basis = None 876 content_type_tag = ctd._contentTypeTag() 877 if (ctd.CT_SIMPLE == content_type_tag): 878 content_basis = ctd.contentType()[1] 879 #template_map['simple_base_type'] = binding_module.literal(content_basis, **kw) 880 elif (ctd.CT_MIXED == content_type_tag): 881 content_basis = ctd.contentType()[1] 882 elif (ctd.CT_ELEMENT_ONLY == content_type_tag): 883 content_basis = ctd.contentType()[1] 884 kw = { 'binding_module' : module_context } 885 if isinstance(content_basis, xs.structures.Particle): 886 plurality_map = content_basis.pluralityData().combinedPlurality() 887 else: 888 plurality_map = {} 889 ctd._templateMap()['_unique'] = nsm.uniqueInClass(ctd) 890 for cd in ctd.localScopedDeclarations(): 891 _SetNameWithAccessors(cd, ctd, plurality_map.get(cd, False), module_context, nsm, kw)
892
893 -def _SetNameWithAccessors (component, container, is_plural, binding_module, nsm, kw):
894 use_map = component._templateMap() 895 class_unique = nsm.uniqueInClass(container) 896 assert isinstance(component, xs.structures._ScopedDeclaration_mixin) 897 unique_name = utility.PrepareIdentifier(component.expandedName().localName(), class_unique) 898 use_map['id'] = unique_name 899 use_map['inspector'] = unique_name 900 use_map['mutator'] = utility.PrepareIdentifier('set' + unique_name[0].upper() + unique_name[1:], class_unique) 901 use_map['use'] = utility.MakeUnique('__' + unique_name.strip('_'), class_unique) 902 assert component._scope() == container 903 assert component.nameInBinding() is None, 'Use %s but binding name %s for %s' % (use_map['use'], component.nameInBinding(), component.expandedName()) 904 component.setNameInBinding(use_map['use']) 905 key_name = '%s_%s_%s' % (str(nsm.namespace()), container.nameInBinding(), component.expandedName()) 906 use_map['key'] = utility.PrepareIdentifier(key_name, class_unique, private=True) 907 use_map['name'] = unicode(component.expandedName()) 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, location_base=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(), location_base=location_base) 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 __moduleFilePath (self, module_elts, inhibit_extension=False):
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 if not inhibit_extension: 1469 assert not module_elts[-1].endswith('.py') 1470 module_elts[-1] = '%s.py' % (module_elts[-1],) 1471 return os.path.join(self.bindingRoot(), *module_elts)
1472
1473 - def generateToFiles (self):
1474 return self.__generateToFiles
1475 __generateToFiles = None 1476
1477 - def modulePathData (self, module):
1478 # file system path to where the bindings are written 1479 # module path from which the bindings are normally imported 1480 # file object into which bindings are written 1481 1482 module_path = None 1483 if isinstance(module, NamespaceModule): 1484 mr = module.moduleRecord() 1485 if mr is None: 1486 return ('/dev/null', None, None) 1487 if self.generationUID() != mr.generationUID(): 1488 return ('/dev/null', None, None) 1489 if not self.generateToFiles(): 1490 return ('/dev/null', None, None) 1491 if mr.namespace().isBuiltinNamespace() and (not self.allowBuiltinGeneration()): 1492 return ('/dev/null', None, None) 1493 module_path = mr.modulePath() 1494 assert module_path is not None, 'No path specified for module %s' % (mr,) 1495 #if pyxb.namespace.XMLSchema != ns: 1496 # return ('/dev/null', None, None) 1497 #module_path="bogus.xsd" 1498 module_elts = module_path.split('.') 1499 if self.writeForCustomization(): 1500 import_file_path = self.__moduleFilePath(module_elts) 1501 module_elts.insert(-1, 'raw') 1502 if not os.path.exists(import_file_path): 1503 raw_module_path = '.'.join(module_elts) 1504 pyxb.utils.utility.OpenOrCreate(import_file_path).write("from %s import *\n" % (raw_module_path,)) 1505 binding_file_path = self.__moduleFilePath(module_elts) 1506 try: 1507 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID()) 1508 except OSError, e: 1509 if errno.EEXIST == e.errno: 1510 raise pyxb.BindingGenerationError('Target file %s for module %s bindings exists with other content' % (binding_file_path, mr)) 1511 raise 1512 elif isinstance(module, NamespaceGroupModule): 1513 if not self.generateToFiles(): 1514 raise pyxb.BindingGenerationError('Generation of namespace groups requires generate-to-files') 1515 module_elts = [] 1516 if self.modulePrefix(): 1517 module_elts.extend(self.modulePrefix().split('.')) 1518 if self.writeForCustomization(): 1519 module_elts.append('raw') 1520 in_use = set() 1521 while True: 1522 module_elts.append(pyxb.utils.utility.PrepareIdentifier('nsgroup', in_use, protected=True)) 1523 try: 1524 binding_file_path = self.__moduleFilePath(module_elts) 1525 print 'Attempting group at %s' % (binding_file_path,) 1526 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID()) 1527 break 1528 except OSError, e: 1529 if errno.EEXIST != e.errno: 1530 raise 1531 module_elts.pop() 1532 module_path = '.'.join(module_elts) 1533 else: 1534 assert False 1535 if self.generateToFiles(): 1536 for n in range(len(module_elts)-1): 1537 sub_path = self.__moduleFilePath(module_elts[:1+n], inhibit_extension=True) 1538 init_path = os.path.join(sub_path, '__init__.py') 1539 if not os.path.exists(init_path): 1540 file(init_path, 'w') 1541 return (binding_file_path, binding_file, module_path)
1542
1543 - def schemaRoot (self):
1544 """The directory from which entrypoint schemas specified as 1545 relative file paths will be read.""" 1546 return self.__schemaRoot
1547 - def setSchemaRoot (self, schema_root):
1548 if not schema_root.endswith(os.sep): 1549 schema_root = schema_root + os.sep 1550 self.__schemaRoot = schema_root 1551 return self
1552 __schemaRoot = None 1553
1554 - def schemaStrippedPrefix (self):
1555 """Optional string that is stripped from the beginning of 1556 schemaLocation values before loading from them. 1557 1558 This applies only to the values of schemaLocation attributes 1559 in C{import} and C{include} elements. Its purpose is to 1560 convert absolute schema locations into relative ones to allow 1561 offline processing when all schema are available in a local 1562 directory. See C{schemaRoot}. 1563 """ 1564 return self.__schemaStrippedPrefix
1565 - def setSchemaStrippedPrefix (self, schema_stripped_prefix):
1566 self.__schemaStrippedPrefix = schema_stripped_prefix 1567 return self
1568 __schemaStrippedPrefix = None 1569
1570 - def schemaLocationList (self):
1571 """A list of locations from which entrypoint schemas are to be 1572 read. 1573 1574 The values in the list are either URIs, or tuples consisting 1575 of a value and a callable which, when passed the generator 1576 object and the value, will return a 1577 L{pyxb.xmlschema.structures.Schema} instance. See 1578 L{addSchemaLocation}. 1579 1580 See also L{addSchemaLocation} and L{schemas}. 1581 """ 1582 return self.__schemaLocationList
1583 - def setSchemaLocationList (self, schema_location_list):
1584 self.__schemaLocationList[:] = [] 1585 self.__schemaLocationList.extend(schema_location_list) 1586 return self
1587 - def addSchemaLocation (self, schema_location, converter=None):
1588 """Add the location of an entrypoint schema. 1589 1590 @param schema_location: The location of the schema. This 1591 should be a URL; if the schema location does not have a URL 1592 scheme (e.g., C{http:}), it is assumed to be a file, and if it 1593 is not an absolute path is located relative to the 1594 C{schemaRoot}. 1595 1596 @keyword converter: Optional callable that will be invoked 1597 with the generator instance and the schema location, and is 1598 expected to return a L{pyxb.xmlschema.structures.Schema} 1599 instance. If absent, the contents of the location are 1600 converted directly. 1601 1602 @note: The C{converter} argument derives from WSDL support: we 1603 need to add to the sequence of schema locations a URI of 1604 something that will not parse as a schema, but does have inner 1605 material that can if treated properly. "Treated properly" may 1606 include having the archive path and other namespace 1607 manipulations configured before anything is done to it. 1608 """ 1609 self.__schemaLocationList.append( (schema_location, converter) ) 1610 return self
1611 - def argAddSchemaLocation (self, schema_location):
1612 """Add the location of an entrypoint schema. The provided 1613 value should be a URL; if it does not have a URL scheme (e.g., 1614 C{http:}), it is assumed to be a file, and if it is not an 1615 absolute path is located relative to the C{schemaRoot}.""" 1616 self.addSchemaLocation(schema_location)
1617 __schemaLocationList = None 1618
1619 - def schemas (self):
1620 """Schema for which bindings should be generated. 1621 1622 These may be L{Schema<pyxb.xmlschema.structures.Schema>} 1623 instances, or strings; the latter is preferred, and is parsed 1624 into a Schema instance when required. 1625 1626 This is the list of entrypoint schemas for binding generation. 1627 Values in L{schemaLocationList} are read and converted into 1628 schema, then appended to this list. Values from L{moduleList} 1629 are applied starting with the first schema in this list. 1630 """ 1631 return self.__schemas[:]
1632 - def setSchemas (self, schemas):
1633 self.__schemas[:] = [] 1634 self.__schemas.extend(schemas) 1635 return self
1636 - def addSchema (self, schema):
1637 self.__schemas.append(schema) 1638 return self
1639 __schemas = None 1640
1641 - def namespaces (self):
1642 """The set of L{namespaces<pyxb.namespace.Namespace>} for 1643 which bindings will be generated. 1644 1645 This is the set of namespaces read from entrypoint schema, 1646 closed under reference to namespaces defined by schema import. 1647 1648 @rtype: C{set} 1649 """ 1650 return self.__namespaces.copy()
1651 - def setNamespaces (self, namespace_set):
1652 self.__namespaces.clear() 1653 self.__namespaces.update(namespace_set) 1654 return self
1655 - def addNamespace (self, namespace):
1656 self.__namespaces.add(namespace) 1657 return self
1658 __namespaces = None 1659
1660 - def moduleList (self):
1661 """A list of module names to be applied in order to the namespaces of entrypoint schemas""" 1662 return self.__moduleList[:]
1663 - def _setModuleList (self, module_list):
1664 self.__moduleList[:] = [] 1665 self.__moduleList.extend(module_list) 1666 return self
1667
1668 - def addModuleName (self, module_name):
1669 """Add a module name corresponding to an entrypoint schema. 1670 1671 The namespace defined by the corresponding schema will be 1672 written to a binding using the given module name, adjusted by 1673 L{modulePrefix}.""" 1674 self.__moduleList.append(module_name) 1675 return self
1676 __moduleList = None 1677
1678 - def modulePrefix (self):
1679 """The prefix for binding modules. 1680 1681 The base name for the module holding a binding is taken from 1682 the moduleList, moduleMap, or an XMLNS prefix associated with 1683 the namespace in a containing schema. This value, if present, 1684 is used as a prefix to allow a deeper module hierarchy.""" 1685 return self.__modulePrefix
1686 - def setModulePrefix (self, module_prefix):
1687 self.__modulePrefix = module_prefix 1688 return self
1689 __modulePrefix = None 1690
1691 - def namespaceModuleMap (self):
1692 """A map from namespace URIs to the module to be used for the 1693 corresponding generated binding. 1694 1695 Module values are adjusted by L{modulePrefix} if that has been 1696 specified. 1697 1698 An entry in this map for a namespace supersedes the module 1699 specified in moduleList if the namespace is defined by an 1700 entrypoint schema. 1701 1702 @return: A reference to the namespace module map. 1703 """ 1704 return self.__namespaceModuleMap
1705 __namespaceModuleMap = None 1706
1707 - def archivePath (self):
1708 """A colon-separated list of paths from which namespace 1709 archives can be read. 1710 1711 The default path is the contents of the C{PYXB_ARCHIVE_PATH} 1712 environment variable, or the standard path configured at 1713 installation time. Any file with the extension C{.wxs} found 1714 in one of these directories is examined to see whether it is a 1715 namespace archive. 1716 """ 1717 return self.__archivePath
1718 - def setArchivePath (self, archive_path):
1719 self.__archivePath = archive_path 1720 return self
1721 __archivePath = None 1722
1723 - def noLoadNamespaces (self):
1724 """A frozenset of namespaces that many not be loaded from an archive.""" 1725 return frozenset(self.__noLoadNamespaces)
1726 - def _setNoLoadNamespaces (self, namespace_set):
1727 """Record the set of namespaces that should not be loaded from an archive. 1728 1729 The expectation is that any required entities in the namespace 1730 will be defined by loading schema.""" 1731 self.__noLoadNamespaces.clear() 1732 self.__noLoadNamespaces.update([ pyxb.namespace.NamespaceInstance(_ns) for _ns in namespace_set ])
1733 - def addNoLoadNamespace (self, namespace):
1734 """Mark that the specified namespace should not be loaded from an archive. 1735 1736 Use this when you are generating bindings for an application 1737 that has a restricted profile of a namespace that would 1738 otherwise be read from an archive. Be aware that this removes 1739 any knowledge of any archive in which this namespace is 1740 present as a non-private member.""" 1741 self.__noLoadNamespaces.add(pyxb.namespace.NamespaceInstance(namespace))
1742 __noloadNamespaces = None 1743
1744 - def preLoadArchives (self):
1745 """A list of paths to archives that should be loaded, in order, prior to parsing schema.""" 1746 return frozenset(self.__preLoadArchives)
1747 - def addPreLoadArchive (self, archive_file):
1748 """Name of a file containing a stored archive from which 1749 namespaces should be read prior to processing schema. 1750 1751 Files to be pre-loaded are not affected by 1752 C{noLoadNamespace}.""" 1753 self.__preLoadArchives.append(archive_file)
1754 - def _setPreLoadArchives (self, pre_load_archives):
1755 self.__preLoadArchives[:] = pre_load_archives 1756 return self
1757 __preLoadArchives = None 1758
1759 - def archiveToFile (self):
1760 """Optional file into which the archive of namespaces will be written. 1761 1762 Subsequent generation actions can read pre-parsed namespaces 1763 from this file, and therefore reference the bindings that were 1764 built earlier rather than re-generating them. 1765 1766 The file name should normally end with C{.wxs}.""" 1767 return self.__archiveToFile
1768 - def setArchiveToFile (self, archive_to_file):
1769 self.__archiveToFile = archive_to_file 1770 return self
1771 __archiveToFile = None 1772
1773 - def setNamespaceVisibility (self, namespace, visibility):
1777 - def _setNamespaceVisibilities (self, public, private):
1778 if public is None: 1779 public = set() 1780 if private is None: 1781 private = set() 1782 self.__namespaceVisibilityMap.clear() 1783 self.__namespaceVisibilityMap.update(dict.fromkeys(public, True)) 1784 self.__namespaceVisibilityMap.update(dict.fromkeys(private, False))
1785 - def namespaceVisibilityMap (self):
1786 """Indicates, for specific namespaces, whether their 1787 visibility in the archive should be public or private.""" 1788 return self.__namespaceVisibilityMap.copy()
1789 __namespaceVisibilityMap = None 1790
1791 - def defaultNamespacePublic (self):
1792 """Indicates whether unmentioned namespaces will be public or private (default) in the archive. 1793 1794 A namespace is I{mentioned} if it is the target namespace of 1795 an entrypoint schema, or appears in a namespace visibility 1796 specification. I.e., this default applies only to namespaces 1797 that are modified as a result of including some schema, which 1798 is generally a local customization of something. 1799 """ 1800 return self.__defaultNamespacePublic
1801 - def setDefaultNamespacePublic (self, default_namespace_public):
1802 self.__defaultNamespacePublic = default_namespace_public
1803 __defaultNamespacePublic = None 1804
1805 - def validateChanges (self):
1806 """Indicates whether the bindings should validate mutations 1807 against the content model.""" 1808 return self.__validateChanges
1809 - def setValidateChanges (self, validate_changes):
1810 #raise pyxb.IncompleteImplementationError('No support for disabling validation') 1811 self.__validateChanges = validate_changes 1812 return self
1813 __validateChanges = None 1814 1815 _DEFAULT_bindingStyle = basis.CURRENT_BINDING_STYLE
1816 - def bindingStyle (self):
1817 """The style of Python used in generated bindings. 1818 1819 C{accessor} means values are private variables accessed 1820 through inspector and mutator methods. 1821 1822 C{property} means values are private variables accessed 1823 through a Python property. 1824 """ 1825 return self.__bindingStyle
1826 - def setBindingStyle (self, binding_style):
1827 raise pyxb.IncompleteImplementationError('No support for binding style configuration') 1828 self.__bindingStyle = binding_style 1829 return self
1830 __bindingStyle = None 1831
1832 - def writeForCustomization (self):
1833 """Indicates whether the binding Python code should be written into a sub-module for customization. 1834 1835 If enabled, a module C{path.to.namespace} will be written to 1836 the file C{path/to/raw/namespace.py}, so that the file 1837 C{path/to/namespace.py} can import it and override behavior.""" 1838 return self.__writeForCustomization
1839 - def setWriteForCustomization (self, write_for_customization):
1840 self.__writeForCustomization = write_for_customization 1841 return self
1842 __writeForCustomization = None 1843
1844 - def allowAbsentModule (self):
1845 """Indicates whether the code generator is permitted to 1846 process namespace for which no module path can be determined. 1847 1848 Use this only when generating bindings that will not be 1849 referenced by other bindings.""" 1850 return self.__allowAbsentModule
1851 - def setAllowAbsentModule (self, allow_absent_module):
1852 self.__allowAbsentModule = allow_absent_module 1853 return self
1854 __allowAbsentModule = None 1855
1856 - def allowBuiltinGeneration (self):
1857 """Indicates whether bindings will be written for namespaces that are built-in to PyXB. 1858 1859 This must be enabled when building bindings for the XML, 1860 XMLSchema instance, and other built-in namespaces. Normally 1861 generation of these namespaces is inhibited lest it produce 1862 inconsistencies.""" 1863 return self.__allowBuiltinGeneration
1864 - def setAllowBuiltinGeneration (self, allow_builtin_generation):
1865 self.__allowBuiltinGeneration = allow_builtin_generation 1866 return self
1867 __allowBuiltinGeneration = None 1868
1869 - def uriContentArchiveDirectory (self):
1870 """The directory path into which any content retrieved by URI will be written. 1871 1872 This serves as a local cache, and to give you an opportunity 1873 to inspect material retrieved from some other system. 1874 @rtype: C{str}""" 1875 return self.__uriContentArchiveDirectory
1876 - def setUriContentArchiveDirectory (self, ucad):
1878 __uriContentArchiveDirectory = None 1879
1880 - def __init__ (self, *args, **kw):
1881 """Create a configuration to be used for generating bindings. 1882 1883 Arguments are treated as additions to the schema location list 1884 after all keywords have been processed. 1885 1886 @keyword binding_root: Invokes L{setBindingRoot} 1887 @keyword schema_root: Invokes L{setSchemaRoot} 1888 @keyword schema_stripped_prefix: Invokes L{setSchemaStrippedPrefix} 1889 @keyword schema_location_list: Invokes L{setSchemaLocationList} 1890 @keyword module_list: Invokes L{_setModuleList} 1891 @keyword module_prefix: Invokes L{setModulePrefix} 1892 @keyword archive_path: Invokes L{setArchivePath} 1893 @keyword no_load_namespaces: Invokes L{_setNoLoadNamespaces} 1894 @keyword pre_load_archives: Invokes L{_setPreLoadArchives} 1895 @keyword archive_to_file: Invokes L{setArchiveToFile} 1896 @keyword public_namespace: Invokes L{setNamespaceVisibility} 1897 @keyword private_namespace: Invokes L{setNamespaceVisibility} 1898 @keyword default_namespace_public: Invokes L{setDefaultNamespacePublic} 1899 @keyword validate_changes: Invokes L{setValidateChanges} 1900 @keyword binding_style: Invokes L{setBindingStyle} 1901 @keyword namespace_module_map: Initializes L{namespaceModuleMap} 1902 @keyword schemas: Invokes L{setSchemas} 1903 @keyword namespaces: Invokes L{setNamespaces} 1904 @keyword write_for_customization: Invokes L{setWriteForCustomization} 1905 @keyword allow_builtin_generation: Invokes L{setAllowBuiltinGeneration} 1906 @keyword allow_absent_module: Invokes L{setAllowAbsentModule} 1907 @keyword generate_to_files: Sets L{generateToFiles} 1908 @keyword uri_content_archive_directory: Invokes L{setUriContentArchiveDirectory} 1909 """ 1910 argv = kw.get('argv', None) 1911 if argv is not None: 1912 kw = {} 1913 self.__bindingRoot = kw.get('binding_root', self._DEFAULT_bindingRoot) 1914 self.__schemaRoot = kw.get('schema_root', '.') 1915 self.__schemaStrippedPrefix = kw.get('schema_stripped_prefix') 1916 self.__schemas = [] 1917 self.__schemaLocationList = kw.get('schema_location_list', [])[:] 1918 self.__moduleList = kw.get('module_list', [])[:] 1919 self.__modulePrefix = kw.get('module_prefix') 1920 self.__archivePath = kw.get('archive_path', pyxb.namespace.archive.GetArchivePath()) 1921 self.__noLoadNamespaces = kw.get('no_load_namespaces', set()).copy() 1922 self.__preLoadArchives = kw.get('pre_load_archives', [])[:] 1923 self.__archiveToFile = kw.get('archive_to_file') 1924 self.__namespaceVisibilityMap = {} 1925 self._setNamespaceVisibilities(kw.get('public_namespaces', set()), kw.get('private_namespaces', set())) 1926 self.__defaultNamespacePublic = kw.get('default_namespace_public', False) 1927 self.__validateChanges = kw.get('validate_changes', True) 1928 self.__bindingStyle = kw.get('binding_style', self._DEFAULT_bindingStyle) 1929 self.__namespaceModuleMap = kw.get('namespace_module_map', {}).copy() 1930 self.__schemas = kw.get('schemas', [])[:] 1931 self.__namespaces = set(kw.get('namespaces', [])) 1932 self.__writeForCustomization = kw.get('write_for_customization', False) 1933 self.__writeForCustomization = kw.get('allow_builtin_generation', False) 1934 self.__allowAbsentModule = kw.get('allow_absent_module', False) 1935 self.__generateToFiles = kw.get('generate_to_files', True) 1936 self.__uriContentArchiveDirectory = kw.get('uri_content_archive_directory') 1937 1938 if argv is not None: 1939 self.applyOptionValues(*self.optionParser().parse_args(argv)) 1940 [ self.addSchemaLocation(_a) for _a in args ] 1941 1942 self.__generationUID = pyxb.utils.utility.UniqueIdentifier() 1943 1944 pyxb.namespace.XML.validateComponentModel()
1945 1946 __stripSpaces_re = re.compile('\s\s\s+')
1947 - def __stripSpaces (self, string):
1948 return self.__stripSpaces_re.sub(' ', string)
1949 1950 __OptionSetters = ( 1951 ('binding_root', setBindingRoot), 1952 ('schema_root', setSchemaRoot), 1953 ('schema_stripped_prefix', setSchemaStrippedPrefix), 1954 ('schema_location', setSchemaLocationList), 1955 ('module', _setModuleList), 1956 ('module_prefix', setModulePrefix), 1957 ('archive_path', setArchivePath), 1958 ('no_load_namespace', _setNoLoadNamespaces), 1959 ('pre_load_archive', _setPreLoadArchives), 1960 ('archive_to_file', setArchiveToFile), 1961 ('default_namespace_public', setDefaultNamespacePublic), 1962 ('binding_style', setBindingStyle), 1963 ('validate_changes', setValidateChanges), 1964 ('write_for_customization', setWriteForCustomization), 1965 ('allow_builtin_generation', setAllowBuiltinGeneration), 1966 ('allow_absent_module', setAllowAbsentModule), 1967 ('uri_content_archive_directory', setUriContentArchiveDirectory) 1968 )
1969 - def applyOptionValues (self, options, args=None):
1970 for (tag, method) in self.__OptionSetters: 1971 v = getattr(options, tag) 1972 if v is not None: 1973 method(self, v) 1974 public_namespaces = getattr(options, 'public_namespace') 1975 private_namespaces = getattr(options, 'private_namespace') 1976 self._setNamespaceVisibilities(public_namespaces, private_namespaces) 1977 if args is not None: 1978 self.__schemaLocationList.extend(args)
1979
1980 - def setFromCommandLine (self, argv=None):
1981 if argv is None: 1982 argv = sys.argv[1:] 1983 (options, args) = self.optionParser().parse_args(argv) 1984 self.applyOptionValues(options, args) 1985 return self
1986
1987 - def generationUID (self):
1988 return self.__generationUID
1989 __generationUID = None 1990
1991 - def optionParser (self, reset=False):
1992 """Return an C{optparse.OptionParser} instance tied to this configuration. 1993 1994 @param reset: If C{False} (default), a parser created in a 1995 previous invocation will be returned. If C{True}, any 1996 previous option parser is discarded and a new one created. 1997 @type reset: C{bool} 1998 """ 1999 if reset or (self.__optionParser is None): 2000 parser = optparse.OptionParser(usage="%prog [options] [more schema locations...]", 2001 version='%%prog from PyXB %s' % (pyxb.__version__,), 2002 description='Generate bindings from a set of XML schemas') 2003 2004 group = optparse.OptionGroup(parser, 'Identifying Schema', 'Specify and locate schema for which bindings should be generated.') 2005 group.add_option('--schema-location', '-u', metavar="FILE_or_URL", 2006 action='append', 2007 help=self.__stripSpaces(self.argAddSchemaLocation.__doc__)) 2008 group.add_option('--schema-root', metavar="DIRECTORY", 2009 help=self.__stripSpaces(self.schemaRoot.__doc__)) 2010 group.add_option('--schema-stripped-prefix', metavar="TEXT", type='string', 2011 help=self.__stripSpaces(self.schemaStrippedPrefix.__doc__)) 2012 group.add_option('--uri-content-archive-directory', metavar="DIRECTORY", 2013 help=self.__stripSpaces(self.uriContentArchiveDirectory.__doc__)) 2014 parser.add_option_group(group) 2015 2016 group = optparse.OptionGroup(parser, 'Configuring Bindings', 'Specify where generated bindings should be written, and how they will be accessed from Python.') 2017 group.add_option('--module', '-m', metavar="MODULE", 2018 action='append', 2019 help=self.__stripSpaces(self.addModuleName.__doc__)) 2020 group.add_option('--module-prefix', metavar="MODULE", 2021 help=self.__stripSpaces(self.modulePrefix.__doc__)) 2022 group.add_option('--binding-root', metavar="DIRECTORY", 2023 help=self.__stripSpaces(self.bindingRoot.__doc__)) 2024 group.add_option('-r', '--write-for-customization', 2025 action='store_true', dest='write_for_customization', 2026 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns on the feature.')) 2027 group.add_option('--no-write-for-customization', 2028 action='store_false', dest='write_for_customization', 2029 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns off the feature (I{default}).')) 2030 parser.add_option_group(group) 2031 2032 group = optparse.OptionGroup(parser, 'Reading Namespace Archives', 'Locating and loading (or inhibiting load of) namespace archives.') 2033 group.add_option('--archive-path', metavar="PATH", 2034 help=self.__stripSpaces(self.archivePath.__doc__)) 2035 group.add_option('--pre-load-archive', metavar="FILE", 2036 action='append', 2037 help=self.__stripSpaces(self.addPreLoadArchive.__doc__)) 2038 group.add_option('--no-load-namespace', metavar="URI", 2039 action='append', 2040 help=self.__stripSpaces(self.addNoLoadNamespace.__doc__)) 2041 parser.add_option_group(group) 2042 2043 group = optparse.OptionGroup(parser, 'Writing Namespace Archives', 'Control the location and content of a namespace archive corresponding to a binding generation.') 2044 group.add_option('--archive-to-file', metavar="FILE", 2045 help=self.__stripSpaces(self.archiveToFile.__doc__)) 2046 group.add_option('--public-namespace', metavar="URI", 2047 action='append', 2048 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a public archive member.')) 2049 group.add_option('--private-namespace', metavar="URI", 2050 action='append', 2051 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a private archive member.')) 2052 group.add_option('--default-namespace-public', 2053 action="store_true", dest='default_namespace_public', 2054 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{public} (I{default}).')) 2055 group.add_option('--default-namespace-private', 2056 action="store_false", dest='default_namespace_public', 2057 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{private}.')) 2058 parser.add_option_group(group) 2059 2060 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.") 2061 group.add_option('--binding-style', 2062 type='choice', choices=basis.BINDING_STYLES, 2063 help=self.__stripSpaces(self.bindingStyle.__doc__)) 2064 group.add_option('--validate-changes', 2065 action='store_true', dest='validate_changes', 2066 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns on validation (default).')) 2067 group.add_option('--no-validate-changes', 2068 action='store_false', dest='validate_changes', 2069 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns off validation.')) 2070 parser.add_option_group(group) 2071 2072 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.") 2073 group.add_option('--allow-absent-module', 2074 action='store_true', dest='allow_absent_module', 2075 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns on the feature.')) 2076 group.add_option('--no-allow-absent-module', 2077 action='store_false', dest='allow_absent_module', 2078 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns off the feature (default).')) 2079 group.add_option('--allow-builtin-generation', 2080 action='store_true', dest='allow_builtin_generation', 2081 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns on the feature.')) 2082 group.add_option('--no-allow-builtin-generation', 2083 action='store_false', dest='allow_builtin_generation', 2084 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns off the feature (default).')) 2085 parser.add_option_group(group) 2086 2087 self.__optionParser = parser 2088 return self.__optionParser
2089 __optionParser = None 2090
2091 - def getCommandLineArgs (self):
2092 """Return a command line option sequence that could be used to 2093 construct an equivalent configuration. 2094 2095 @note: If you extend the option parser, as is done by 2096 C{pyxbgen}, this may not be able to reconstruct the correct 2097 command line.""" 2098 opts = [] 2099 module_list = self.moduleList() 2100 schema_list = self.schemaLocationList() 2101 while module_list and schema_list: 2102 ml = module_list.pop(0) 2103 sl = schema_list.pop(0) 2104 if isinstance(sl, tuple): 2105 sl = sl[0] 2106 opts.extend(['--schema-location=' + sl, '--module=' + ml]) 2107 for sl in schema_list: 2108 opts.append('--schema-location=' + sl) 2109 if self.schemaRoot() is not None: 2110 opts.append('--schema-root=' + self.schemaRoot()) 2111 if self.schemaStrippedPrefix() is not None: 2112 opts.append('--schema-stripped-prefix=%s' + self.schemaStrippedPrefix()) 2113 if self.modulePrefix() is not None: 2114 opts.append('--module-prefix=' + self.modulePrefix()) 2115 opts.append('--binding-root=' + self.bindingRoot()) 2116 if self.archivePath() is not None: 2117 opts.append('--archive-path=' + self.archivePath()) 2118 for ns in self.noLoadNamespaces(): 2119 opts.append('--no-load-namespace=' + ns.uri()) 2120 for fps in self.preLoadArchives(): 2121 opts.append('--pre-load-archive=' + fp) 2122 if self.archiveToFile() is not None: 2123 opts.append('--archive-to-file=' + self.archiveToFile()) 2124 for (ns, visibility) in self._namespaceVisibilityMap(): 2125 if visibility: 2126 opts.append('--public-namespace=' + ns.uri()) 2127 else: 2128 opts.append('--private-namespace=' + ns.uri()) 2129 if self.defaultNamespacePublic(): 2130 opts.append('--default-namespace-public') 2131 else: 2132 opts.append('--default-namespace-private') 2133 for (val, opt) in ( (self.validateChanges(), 'validate-changes'), 2134 (self.writeForCustomization(), 'write-for-customization'), 2135 (self.allowAbsentModule(), 'allow-absent-module'), 2136 (self.allowBuiltinGeneration(), 'allow-builtin-generation') ): 2137 if val: 2138 opts.append('--' + opt) 2139 else: 2140 opts.append('--no-' + opt) 2141 if self.uriContentArchiveDirectory() is not None: 2142 opts.append('--uri-content-archive-directory=%s' + self.uriContentArchiveDirectory()) 2143 return opts
2144
2145 - def normalizeSchemaLocation (self, sl):
2146 ssp = self.schemaStrippedPrefix() 2147 if ssp and sl.startswith(ssp): 2148 sl = sl[len(ssp):] 2149 return pyxb.utils.utility.NormalizeLocation(sl, self.schemaRoot())
2150
2151 - def __assignModulePath (self, module_record, module_path=None):
2152 if module_record.modulePath() is not None: 2153 return module_record 2154 namespace = module_record.namespace() 2155 if not namespace.isAbsentNamespace(): 2156 if (module_path is None) and not (namespace.prefix() is None): 2157 module_path = namespace.prefix() 2158 module_path = self.namespaceModuleMap().get(namespace.uri(), module_path) 2159 if (module_path is not None) and self.modulePrefix(): # non-empty value 2160 module_path = '.'.join([self.modulePrefix(), module_path]) 2161 if (module_path is None) and self.generateToFiles(): 2162 raise pyxb.BindingGenerationError('No prefix or module name available for %s' % (module_record,)) 2163 module_record.setModulePath(module_path) 2164 return module_record
2165 2166 __didResolveExternalSchema = False
2167 - def resolveExternalSchema (self, reset=False):
2168 if self.__didResolveExternalSchema and (not reset): 2169 raise pyxb.PyXBException('Cannot resolve external schema multiple times') 2170 2171 required_archives = pyxb.namespace.archive.NamespaceArchive.PreLoadArchives(self.archivePath(), self.preLoadArchives()) 2172 for nsa in required_archives: 2173 nsa.readNamespaces() 2174 for ns in self.noLoadNamespaces(): 2175 assert isinstance(ns, pyxb.namespace.Namespace) 2176 ns.markNotLoadable() 2177 while self.__schemaLocationList: 2178 sl = self.__schemaLocationList.pop(0) 2179 if isinstance(sl, tuple): 2180 (sl, converter) = sl 2181 else: 2182 converter = None 2183 try: 2184 if converter is None: 2185 schema = xs.schema.CreateFromLocation(absolute_schema_location=self.normalizeSchemaLocation(sl), generation_uid=self.generationUID(), uri_content_archive_directory=self.uriContentArchiveDirectory()) 2186 else: 2187 schema = converter(self, sl) 2188 self.addSchema(schema) 2189 except pyxb.SchemaUniquenessError, e: 2190 print 'WARNING: Skipped redundant translation of %s defining %s' % (e.schemaLocation(), e.namespace()) 2191 self.addSchema(e.existingSchema()) 2192 for schema in self.__schemas: 2193 if isinstance(schema, basestring): 2194 schema = xs.schema.CreateFromDocument(schema, generation_uid=self.generationUID()) 2195 origin = schema.originRecord() 2196 assert origin is not None 2197 module_path = None 2198 if self.__moduleList: 2199 module_path = self.__moduleList.pop(0) 2200 self.__assignModulePath(origin.moduleRecord(), module_path) 2201 assert schema.targetNamespace() == origin.moduleRecord().namespace() 2202 self.addNamespace(schema.targetNamespace()) 2203 self.__didResolveExternalSchema = True 2204 self.__bindingModules = None
2205
2206 - def __graphFromComponents (self, components, include_lax):
2207 components = components.copy() 2208 component_graph = pyxb.utils.utility.Graph() 2209 need_visit = components.copy() 2210 bindable_fn = lambda _c: isinstance(_c, xs.structures.ElementDeclaration) or _c.isTypeDefinition() 2211 while 0 < len(need_visit): 2212 c = need_visit.pop() 2213 assert c is not None 2214 assert bindable_fn(c) or include_lax 2215 assert c._objectOrigin() is not None, '%s %s has no origin' % (type(c), c) 2216 component_graph.addNode(c) 2217 br = c.bindingRequires(reset=True, include_lax=include_lax) 2218 #print 'Component %s requires %d bindings' % (c, len(br)) 2219 for cd in br: 2220 assert bindable_fn(cd) or include_lax, '%s produced %s in requires' % (type(c), type(cd)) 2221 #print ' %s in %s' % (cd, cd._objectOrigin()) 2222 if cd._objectOrigin() is None: 2223 assert isinstance(cd, (pyxb.xmlschema.structures.Annotation, pyxb.xmlschema.structures.Wildcard)) 2224 continue 2225 if (cd._objectOrigin().moduleRecord() in self.__moduleRecords) and not (cd in components): 2226 components.add(cd) 2227 need_visit.add(cd) 2228 if cd in components: 2229 component_graph.addEdge(c, cd) 2230 return component_graph
2231
2232 - def __buildBindingModules (self):
2233 named_bindable_fn = lambda _c: (isinstance(_c, xs.structures.ElementDeclaration) and _c._scopeIsGlobal()) or _c.isTypeDefinition() 2234 bindable_fn = lambda _c: isinstance(_c, xs.structures.ElementDeclaration) or _c.isTypeDefinition() 2235 2236 self.__moduleRecords = set() 2237 all_components = set() 2238 for origin in self.generationUID().associatedObjects(): 2239 mr = origin.moduleRecord() 2240 if not (mr in self.__moduleRecords): 2241 # @todo NOTICE 2242 # print 'Entry %s' % (mr,) 2243 self.__moduleRecords.add(mr) 2244 mr.completeGenerationAssociations() 2245 all_components.update(origin.originatedObjects()) 2246 2247 namespaces = set() 2248 for mr in self.__moduleRecords: 2249 if mr.namespace().isBuiltinNamespace() and not self.allowBuiltinGeneration(): 2250 continue 2251 namespaces.add(mr.namespace()) 2252 pyxb.namespace.resolution.ResolveSiblingNamespaces(namespaces, self.generationUID()) 2253 2254 # Mark module visibility. Entry-point namespaces default to 2255 # public. 2256 for ns in self.namespaces(): 2257 self.__namespaceVisibilityMap.setdefault(ns, True) 2258 2259 # Generate the graph from all components and descend into lax 2260 # requirements; otherwise we might miss anonymous types hidden 2261 # inside attribute declarations and the like. 2262 component_graph = self.__graphFromComponents(all_components, True) 2263 2264 binding_components = set(filter(bindable_fn, component_graph.nodes())) 2265 # @todo NOTICE 2266 #print '%d of %d components need bindings' % (len(binding_components), len(component_graph.nodes())) 2267 2268 module_graph = pyxb.utils.utility.Graph() 2269 [ module_graph.addRoot(_mr) for _mr in self.__moduleRecords ] 2270 for (s, t) in component_graph.edges(): 2271 module_graph.addEdge(s._objectOrigin().moduleRecord(), t._objectOrigin().moduleRecord()) 2272 module_scc_order = module_graph.sccOrder() 2273 2274 # Note that module graph may have fewer nodes than 2275 # self.__moduleRecords, if a module has no components that 2276 # require binding generation. 2277 2278 # @todo NOTICE 2279 #print '%d entry, %d in graph' % (len(self.__moduleRecords), len(module_graph.nodes())) 2280 2281 for c in binding_components: 2282 assert bindable_fn(c), 'Unexpected %s in binding components' % (type(s),) 2283 c._setBindingNamespace(c._objectOrigin().moduleRecord().namespace()) 2284 2285 record_binding_map = {} 2286 unique_in_bindings = set([NamespaceGroupModule._GroupPrefix]) 2287 modules = [] 2288 for mr_scc in module_scc_order: 2289 scc_modules = [ ] 2290 for mr in mr_scc: 2291 # @todo INFO 2292 #print 'Generating %s of %d' % (mr, len(mr_scc)) 2293 mr._setIsPublic(self.__namespaceVisibilityMap.get(mr.namespace(), self.defaultNamespacePublic())) 2294 self.__assignModulePath(mr) 2295 assert not ((mr.modulePath() is None) and self.generateToFiles()), 'No module path defined for %s' % (mr,) 2296 if (not mr.isPublic()) and (mr.modulePath() is not None): 2297 elts = mr.modulePath().split('.') 2298 elts[-1] = '_%s' % (elts[-1],) 2299 mr.setModulePath('.'.join(elts)) 2300 nsm = NamespaceModule(self, mr, mr_scc) 2301 record_binding_map[mr] = nsm 2302 scc_modules.append(nsm) 2303 2304 modules.extend(scc_modules) 2305 if 1 < len(mr_scc): 2306 ngm = NamespaceGroupModule(self, scc_modules) 2307 modules.append(ngm) 2308 for nsm in scc_modules: 2309 nsm.setNamespaceGroupModule(ngm) 2310 2311 component_csets = self.__graphFromComponents(binding_components, False).sccOrder() 2312 bad_order = False 2313 component_order = [] 2314 for cset in component_csets: 2315 if 1 < len(cset): 2316 print "COMPONENT DEPENDENCY LOOP of %d components" % (len(cset),) 2317 cg = pyxb.utils.utility.Graph() 2318 for c in cset: 2319 assert bindable_fn(c), 'Unexpected %s in list' % (type(c),) 2320 print ' %s' % (c.expandedName(),) 2321 cg.addNode(c) 2322 for cd in c.bindingRequires(reset=True, include_lax=False): 2323 #print '%s depends on %s' % (c, cd) 2324 cg.addEdge(c, cd) 2325 #file('deploop.dot', 'w').write(cg._generateDOT('CompDep', lambda _c: _c.bestNCName())) 2326 relaxed_order = cg.sccOrder() 2327 for rcs in relaxed_order: 2328 assert 1 == len(rcs) 2329 rcs = rcs[0] 2330 if rcs in cset: 2331 component_order.append(rcs) 2332 else: 2333 component_order.extend(cset) 2334 2335 #print '%d components in order' % (len(component_order),) 2336 2337 element_declarations = [] 2338 type_definitions = [] 2339 for c in component_order: 2340 if isinstance(c, xs.structures.ElementDeclaration) and c._scopeIsGlobal(): 2341 # Only bind elements this pass, so their names get priority in deconfliction 2342 nsm = record_binding_map[c._objectOrigin().moduleRecord()] 2343 nsm.bindComponent(c) 2344 element_declarations.append(c) 2345 elif c.isTypeDefinition(): 2346 type_definitions.append(c) 2347 else: 2348 # No binding generation required 2349 pass 2350 2351 simple_type_definitions = [] 2352 complex_type_definitions = [] 2353 for td in type_definitions: 2354 nsm = record_binding_map[td._objectOrigin().moduleRecord()] 2355 assert nsm is not None, 'No namespace module for %s type %s scope %s namespace %s' % (td.expandedName(), type(td), td._scope(), td.bindingNamespace) 2356 module_context = nsm.bindComponent(td) 2357 assert isinstance(module_context, _ModuleNaming_mixin), 'Unexpected type %s' % (type(module_context),) 2358 if isinstance(td, xs.structures.SimpleTypeDefinition): 2359 _PrepareSimpleTypeDefinition(td, self, nsm, module_context) 2360 simple_type_definitions.append(td) 2361 elif isinstance(td, xs.structures.ComplexTypeDefinition): 2362 _PrepareComplexTypeDefinition(td, self, nsm, module_context) 2363 complex_type_definitions.append(td) 2364 else: 2365 assert False, 'Unexpected component type %s' % (type(td),) 2366 2367 for ngm in modules: 2368 if isinstance(ngm, NamespaceGroupModule): 2369 for m in ngm.namespaceModules(): 2370 m.addImportsFrom(ngm) 2371 2372 for std in simple_type_definitions: 2373 GenerateSTD(std, self) 2374 for ctd in complex_type_definitions: 2375 GenerateCTD(ctd, self) 2376 for ed in element_declarations: 2377 GenerateED(ed, self) 2378 2379 return modules
2380 2381 __bindingModules = None
2382 - def bindingModules (self, reset=False):
2383 if reset or (not self.__didResolveExternalSchema): 2384 self.resolveExternalSchema(reset) 2385 if reset or (self.__bindingModules is None): 2386 self.__bindingModules = self.__buildBindingModules() 2387 return self.__bindingModules
2388
2389 - def writeNamespaceArchive (self):
2390 archive_file = self.archiveToFile() 2391 if archive_file is not None: 2392 ns_archive = pyxb.namespace.archive.NamespaceArchive(generation_uid=self.generationUID()) 2393 try: 2394 ns_archive.writeNamespaces(pyxb.utils.utility.OpenOrCreate(archive_file)) 2395 print 'Saved parsed schema to %s URI' % (archive_file,) 2396 except Exception, e: 2397 print 'Exception saving preprocessed schema to %s: %s' % (archive_file, e) 2398 traceback.print_exception(*sys.exc_info()) 2399 #try: 2400 # os.unlink(component_model_file) 2401 #except (OSError, IOError), e: 2402 # pass 2403 if isinstance(e, (AssertionError, AttributeError, TypeError)): 2404 raise
2405
2406 - def moduleForComponent (self, component):
2408