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

Source Code for Module pyxb.binding.generate

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