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