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.items(): 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 'binding_module' : binding_module, 905 'binding_tag' : binding_module.bindingTag(), 906 'pyxbVersion' : pyxb.__version__ }) 907 self.__stringIO = StringIO.StringIO() 908 if self.__bindingFile: 909 self.__bindingFile.write(self.expand('''# %{filePath} 910 # PyXB bindings for %{binding_tag} 911 # Generated %{date} by PyXB version %{pyxbVersion} 912 %{binding_preface}''', binding_preface=binding_module.bindingPreface())) 913 self.__bindingFile.flush()
914
915 - def bindingFile (self):
916 return self.__bindingFile
917
918 - def expand (self, template, **kw):
919 tm = self.__templateMap.copy() 920 tm.update(kw) 921 return templates.replaceInText(template, **tm)
922
923 - def write (self, template, **kw):
924 txt = self.expand(template, **kw) 925 self.__stringIO.write(txt)
926
927 - def bindingModule (self):
928 return self.__bindingModule
929 __bindingModule = None 930
931 - def prolog (self):
932 return self.__prolog
933 - def postscript (self):
934 return self.__postscript
935
936 - def literal (self, *args, **kw):
937 kw.update(self.__templateMap) 938 return pythonLiteral(*args, **kw)
939
940 - def contents (self):
941 rv = self.__prolog 942 rv.append(self.__stringIO.getvalue()) 943 rv.extend(self.__postscript) 944 return ''.join(rv)
945
946 -class _ModuleNaming_mixin (object):
947 __anonSTDIndex = None 948 __anonCTDIndex = None 949 __uniqueInModule = None 950 __uniqueInClass = None 951 952 # @todo: provide a way to reset this, for multiple generations in a single run 953 _UniqueInModule = set([ 'pyxb', 'sys' ]) 954 955 __ComponentBindingModuleMap = {} 956
957 - def generator (self):
958 return self.__generator
959 __generator = None 960
961 - def __init__ (self, generator, *args, **kw):
962 super(_ModuleNaming_mixin, self).__init__(*args, **kw) 963 self.__generator = generator 964 assert isinstance(self.__generator, Generator) 965 self.__anonSTDIndex = 1 966 self.__anonCTDIndex = 1 967 self.__components = [] 968 self.__componentNameMap = {} 969 self.__uniqueInModule = set() 970 self.__bindingIO = None 971 self.__importedModules = [] 972 self.__namespaceDeclarations = [] 973 self.__referencedNamespaces = {} 974 self.__uniqueInClass = {}
975
976 - def _importModule (self, module):
977 assert not isinstance(module, pyxb.namespace.Namespace) 978 assert isinstance(module, (_ModuleNaming_mixin, pyxb.namespace.Namespace, pyxb.namespace.archive.ModuleRecord)), 'Unexpected type %s' % (type(module),) 979 if isinstance(module, NamespaceModule) and (pyxb.namespace.XMLSchema == module.namespace()): 980 return 981 if not (module in self.__importedModules): 982 self.__importedModules.append(module)
983
984 - def uniqueInClass (self, component):
985 rv = self.__uniqueInClass.get(component) 986 if rv is None: 987 rv = set() 988 if isinstance(component, xs.structures.SimpleTypeDefinition): 989 rv.update(basis.simpleTypeDefinition._ReservedSymbols) 990 else: 991 assert isinstance(component, xs.structures.ComplexTypeDefinition) 992 if component._isHierarchyRoot(): 993 rv.update(basis.complexTypeDefinition._ReservedSymbols) 994 else: 995 base_td = component.baseTypeDefinition() 996 base_unique = base_td._templateMap().get('_unique') 997 assert base_unique is not None, 'Base %s of %s has no unique' % (base_td.expandedName(), component.expandedName()) 998 rv.update(base_unique) 999 self.__uniqueInClass[component] = rv 1000 return rv
1001 1002 __referencedNamespaces = None 1003
1004 - def bindingIO (self):
1005 return self.__bindingIO
1006 1007 __moduleUID = None
1008 - def moduleUID (self):
1009 if self.__moduleUID is None: 1010 self.__moduleUID = pyxb.utils.utility.HashForText(self._moduleUID_vx()) 1011 return self.__moduleUID
1012
1013 - def _moduleUID_vx (self):
1014 return str(id(self))
1015
1016 - def bindingTag (self):
1017 """Return a distinct string recorded in the first 4096 bytes of the binding file. 1018 1019 This is used to ensure uniqueness and avoid overwriting data 1020 belonging to a different binding. The return value comprises 1021 the class-specialized L{_bindingTagPrefix_vx} with the 1022 L{moduleUID}. 1023 """ 1024 return '%s:%s' % (self._bindingTagPrefix_vx(), self.moduleUID())
1025
1026 - def _bindingTagPrefix_vx (self):
1027 raise pyxb.LogicError('Subclass %s does not define _bindingTagPrefix_vx' % (type(self),))
1028
1029 - def bindingPreface (self):
1030 """Return a block of binding text (comment or code) serving as a preface. 1031 1032 Normally this should describe the module contents.""" 1033 return self._bindingPreface_vx()
1034 - def _bindingPreface_vx (self):
1035 return ''
1036
1037 - def moduleContents (self):
1038 template_map = {} 1039 aux_imports = [] 1040 for ns in self.__importedModules: 1041 if isinstance(ns, NamespaceModule): 1042 ns = ns.moduleRecord() 1043 module_path = ns.modulePath() 1044 assert module_path is not None, 'No module path for %s type %s' % (ns, type(ns)) 1045 aux_imports.append('import %s' % (module_path,)) 1046 template_map['aux_imports'] = "\n".join(aux_imports) 1047 template_map['namespace_decls'] = "\n".join(self.__namespaceDeclarations) 1048 template_map['module_uid'] = self.moduleUID() 1049 template_map['generation_uid_expr'] = repr(self.generator().generationUID()) 1050 self._finalizeModuleContents_vx(template_map) 1051 return self.__bindingIO.contents()
1052
1053 - def modulePath (self):
1054 return self.__modulePath
1055 - def _setModulePath (self, path_data):
1056 (binding_file_path, binding_file, module_path) = path_data 1057 self.__bindingFilePath = binding_file_path 1058 self.__bindingFile = binding_file 1059 #print 'Set %s binding file %s path %s' % (self, binding_file, binding_file_path) 1060 if module_path is None: 1061 module_path = self.moduleRecord().modulePath() 1062 if module_path is not None: 1063 self.__modulePath = module_path 1064 kw = self._initialBindingTemplateMap() 1065 self.__bindingIO = BindingIO(self, binding_file=binding_file, binding_file_path=binding_file_path, **kw)
1066 __modulePath = None 1067
1068 - def bindingFile (self):
1069 return self.__bindingFile
1070 __bindingFile = None 1071 __bindingFilePath = None 1072
1073 - def _initializeUniqueInModule (self, unique_in_module):
1074 self.__uniqueInModule = set(unique_in_module)
1075
1076 - def uniqueInModule (self):
1077 return self.__uniqueInModule
1078 1079 @classmethod
1080 - def BindComponentInModule (cls, component, module):
1081 cls.__ComponentBindingModuleMap[component] = module 1082 return module
1083 1084 @classmethod
1085 - def ComponentBindingModule (cls, component):
1086 rv = cls.__ComponentBindingModuleMap.get(component) 1087 return cls.__ComponentBindingModuleMap.get(component)
1088 1089 @classmethod
1090 - def _RecordModule (cls, module):
1093 @classmethod
1094 - def _ForRecord (cls, module_record):
1095 return cls.__RecordModuleMap.get(module_record)
1096 __RecordModuleMap = { } 1097
1098 - def _bindComponent (self, component):
1099 kw = {} 1100 rv = component.bestNCName() 1101 if rv is None: 1102 if isinstance(component, xs.structures.ComplexTypeDefinition): 1103 rv = utility.PrepareIdentifier('CTD_ANON', self.uniqueInClass(component), protected=True) 1104 elif isinstance(component, xs.structures.SimpleTypeDefinition): 1105 rv = utility.PrepareIdentifier('STD_ANON', self.uniqueInClass(component), protected=True) 1106 else: 1107 assert False 1108 kw['protected'] = True 1109 rv = utility.PrepareIdentifier(rv, self.__uniqueInModule, kw) 1110 assert not component in self.__componentNameMap 1111 self.__components.append(component) 1112 self.__componentNameMap[component] = rv 1113 return rv
1114 - def nameInModule (self, component):
1115 return self.__componentNameMap.get(component)
1116
1117 - def __componentModule (self, component, module_type):
1118 assert module_type is None 1119 if NamespaceGroupModule == module_type: 1120 pass 1121 elif NamespaceModule == module_type: 1122 pass 1123 else: 1124 assert module_type is None 1125 return component_module
1126
1127 - def referenceSchemaComponent (self, component):
1128 origin = component._objectOrigin() 1129 assert origin is not None 1130 module_record = origin.moduleRecord() 1131 assert module_record is not None 1132 if self.generator().generationUID() != module_record.generationUID(): 1133 self._importModule(module_record) 1134 return '%s.%s' % (module_record.modulePath(), component.nameInBinding()) 1135 component_module = _ModuleNaming_mixin.ComponentBindingModule(component) 1136 assert component_module is not None, 'No binding module for %s from %s in %s as %s' % (component, module_record, self.moduleRecord(), component.nameInBinding()) 1137 name = component_module.__componentNameMap.get(component) 1138 if name is None: 1139 assert isinstance(self, NamespaceModule) and (self.namespace() == component.bindingNamespace()) 1140 name = component.nameInBinding() 1141 if self != component_module: 1142 self._importModule(component_module) 1143 name = '%s.%s' % (component_module.modulePath(), name) 1144 return name
1145
1146 - def _referencedNamespaces (self): return self.__referencedNamespaces
1147
1148 - def defineNamespace (self, namespace, name, require_unique=True, definition=None, **kw):
1149 rv = self.__referencedNamespaces.get(namespace) 1150 assert rv is None, 'Module %s already has reference to %s' % (self, namespace) 1151 if require_unique: 1152 name = utility.PrepareIdentifier(name, self.__uniqueInModule, **kw) 1153 if definition is None: 1154 if namespace.isAbsentNamespace(): 1155 definition = 'pyxb.namespace.CreateAbsentNamespace()' 1156 else: 1157 definition = 'pyxb.namespace.NamespaceForURI(%s, create_if_missing=True)' % (repr(namespace.uri()),) 1158 self.__namespaceDeclarations.append('%s = %s' % (name, definition)) 1159 self.__namespaceDeclarations.append("%s.configureCategories(['typeBinding', 'elementBinding'])" % (name,)) 1160 self.__referencedNamespaces[namespace] = name 1161 return name
1162
1163 - def referenceNamespace (self, namespace):
1164 rv = self.__referencedNamespaces.get(namespace) 1165 if rv is None: 1166 if namespace.isBuiltinNamespace(): 1167 rv = namespace.builtinNamespaceRepresentation() 1168 elif namespace.isUndeclaredNamespace(): 1169 rv = namespace.modulePath() 1170 elif isinstance(self, NamespaceModule): 1171 if (self.namespace() == namespace): 1172 rv = 'Namespace' 1173 else: 1174 rv = 'pyxb.namespace.NamespaceForURI(%s)' % (repr(namespace.uri()),) 1175 ''' 1176 namespace_module = self.ForNamespace(namespace) 1177 if namespace_module is not None: 1178 self._importModule(namespace_module) 1179 rv = '%s.Namespace' % (namespace_module.modulePath(),) 1180 else: 1181 assert False, 'Unexpected reference to %s' % (namespace,) 1182 #rv = 'pyxb.namespace.NamespaceForURI(%s)' % (repr(namespace.uri()),) 1183 ''' 1184 else: 1185 if namespace.prefix(): 1186 nsn = 'Namespace_%s' % (namespace.prefix(),) 1187 else: 1188 nsn = 'Namespace' 1189 for im in self.__importedModules: 1190 if isinstance(im, NamespaceModule) and (im.namespace() == namespace): 1191 rv = '%s.Namespace' % (im.modulePath(),) 1192 break 1193 if isinstance(im, NamespaceGroupModule): 1194 irv = im.__referencedNamespaces.get(namespace) 1195 if irv is not None: 1196 rv = self.defineNamespace(namespace, nsn, '%s.%s' % (im.modulePath(), irv), protected=True) 1197 break 1198 if rv is None: 1199 rv = self.defineNamespace(namespace, nsn, protected=True) 1200 assert 0 < len(self.__namespaceDeclarations) 1201 self.__referencedNamespaces[namespace] = rv 1202 return rv
1203
1204 - def literal (self, *args, **kw):
1205 return self.__bindingIO.literal(*args, **kw)
1206
1207 - def addImportsFrom (self, module):
1208 print 'Importing to %s from %s' % (self, module) 1209 self._importModule(module) 1210 for c in self.__components: 1211 local_name = self.nameInModule(c) 1212 assert local_name is not None 1213 rem_name = module.nameInModule(c) 1214 if rem_name is None: 1215 continue 1216 aux = '' 1217 if local_name != rem_name: 1218 aux = ' as %s' % (local_name,) 1219 self.__bindingIO.write("from %s import %s%s # %s\n" % (module.modulePath(), rem_name, aux, c.expandedName()))
1220
1221 - def writeToModuleFile (self):
1222 if self.bindingFile(): 1223 self.bindingFile().write(self.moduleContents().encode('utf8')) 1224 self.bindingFile().close() 1225 print 'Saved binding source to %s' % (self.__bindingFilePath,) 1226 else: 1227 print 'WARNING: No binding file for %s' % (self,)
1228
1229 1230 -class NamespaceModule (_ModuleNaming_mixin):
1231 """This class represents a Python module that holds all the 1232 declarations belonging to a specific namespace.""" 1233
1234 - def namespace (self):
1235 return self.__namespace
1236 __namespace = None 1237
1238 - def moduleRecord (self):
1239 return self.__moduleRecord
1240 __moduleRecord = None 1241
1242 - def namespaceGroupModule (self):
1243 return self.__namespaceGroupModule
1244 - def setNamespaceGroupModule (self, namespace_group_module):
1245 self.__namespaceGroupModule = namespace_group_module
1246 __namespaceGroupModule = None 1247 1248 _UniqueInModule = _ModuleNaming_mixin._UniqueInModule.copy() 1249 _UniqueInModule.update([ 'Namespace', 'CreateFromDOM', 'CreateFromDocument' ]) 1250
1251 - def namespaceGroupHead (self):
1252 return self.__namespaceGroupHead
1253 __namespaceGroupHead = None 1254 __namespaceGroup = None 1255
1256 - def componentsInNamespace (self):
1257 return self.__components
1258 __components = None 1259 1260 @classmethod
1261 - def ForComponent (cls, component):
1262 return cls.__ComponentModuleMap.get(component)
1263 __ComponentModuleMap = { } 1264
1265 - def _bindingTagPrefix_vx (self):
1266 return 'NM'
1267
1268 - def _bindingPreface_vx (self):
1269 ns = self.namespace() 1270 rvl = ['# Namespace %s' % (ns,)] 1271 if ns.prefix() is not None: 1272 rvl.append(' [xmlns:%s]' % (ns.prefix(),)) 1273 rvl.append('\n') 1274 return ''.join(rvl)
1275
1276 - def _moduleUID_vx (self):
1277 if self.namespace().isAbsentNamespace(): 1278 return 'Absent' 1279 return str(self.namespace())
1280
1281 - def namespaceGroupMulti (self):
1282 return 1 < len(self.__namespaceGroup)
1283
1284 - def __init__ (self, generator, module_record, mr_scc, components=None, **kw):
1285 super(NamespaceModule, self).__init__(generator, **kw) 1286 self._initializeUniqueInModule(self._UniqueInModule) 1287 self.__moduleRecord = module_record 1288 self.__namespace = self.__moduleRecord.namespace() 1289 self.defineNamespace(self.__namespace, 'Namespace', require_unique=False) 1290 #print 'NSM Namespace %s module path %s' % (namespace, namespace.modulePath()) 1291 #self.__namespaceGroup = mr_scc 1292 self._RecordModule(self) 1293 #self.__namespaceGroupHead = self.ForNamespace(ns_scc[0]) 1294 self.__components = components 1295 # wow! fromkeys actually IS useful! 1296 if self.__components is not None: 1297 self.__ComponentModuleMap.update(dict.fromkeys(self.__components, self)) 1298 self.__namespaceBindingNames = {} 1299 self.__componentBindingName = {} 1300 self._setModulePath(generator.modulePathData(self))
1301
1302 - def _initialBindingTemplateMap (self):
1303 kw = { 'moduleType' : 'namespace' 1304 , 'targetNamespace' : repr(self.__namespace.uri()) 1305 , 'namespaceURI' : self.__namespace.uri() 1306 , 'namespaceReference' : self.referenceNamespace(self.__namespace) 1307 } 1308 return kw
1309
1310 - def _finalizeModuleContents_vx (self, template_map):
1311 self.bindingIO().prolog().append(self.bindingIO().expand(''' 1312 import pyxb 1313 import pyxb.binding 1314 import pyxb.binding.saxer 1315 import StringIO 1316 import pyxb.utils.utility 1317 import pyxb.utils.domutils 1318 import sys 1319 1320 # Unique identifier for bindings created at the same time 1321 _GenerationUID = %{generation_uid_expr} 1322 1323 # Import bindings for namespaces imported into schema 1324 %{aux_imports} 1325 1326 %{namespace_decls} 1327 ModuleRecord = Namespace.lookupModuleRecordByUID(_GenerationUID, create_if_missing=True) 1328 ModuleRecord._setModule(sys.modules[__name__]) 1329 1330 def CreateFromDocument (xml_text, default_namespace=None, location_base=None): 1331 """Parse the given XML and use the document element to create a Python instance.""" 1332 if pyxb.XMLStyle_saxer != pyxb._XMLStyle: 1333 dom = pyxb.utils.domutils.StringToDOM(xml_text) 1334 return CreateFromDOM(dom.documentElement) 1335 saxer = pyxb.binding.saxer.make_parser(fallback_namespace=Namespace.fallbackNamespace(), location_base=location_base) 1336 handler = saxer.getContentHandler() 1337 saxer.parse(StringIO.StringIO(xml_text)) 1338 instance = handler.rootObject() 1339 return instance 1340 1341 def CreateFromDOM (node, default_namespace=None): 1342 """Create a Python instance from the given DOM node. 1343 The node tag must correspond to an element declaration in this module. 1344 1345 @deprecated: Forcing use of DOM interface is unnecessary; use L{CreateFromDocument}.""" 1346 if default_namespace is None: 1347 default_namespace = Namespace.fallbackNamespace() 1348 return pyxb.binding.basis.element.AnyCreateFromDOM(node, _fallback_namespace=default_namespace) 1349 1350 ''', **template_map))
1351 1352 __components = None 1353 __componentBindingName = None 1354
1355 - def bindComponent (self, component):
1356 ns_name = self._bindComponent(component) 1357 component.setNameInBinding(ns_name) 1358 #print 'set name %s in %s' % (ns_name, component) 1359 binding_module = self 1360 if self.__namespaceGroupModule: 1361 self.__namespaceGroupModule._bindComponent(component) 1362 binding_module = self.__namespaceGroupModule 1363 return _ModuleNaming_mixin.BindComponentInModule(component, binding_module)
1364
1365 - def __str__ (self):
1366 return 'NM:%s@%s' % (self.namespace(), self.modulePath())
1367
1368 -class NamespaceGroupModule (_ModuleNaming_mixin):
1369 """This class represents a Python module that holds all the 1370 declarations belonging to a set of namespaces which have 1371 interdependencies.""" 1372
1373 - def namespaceModules (self):
1374 return self.__namespaceModules
1375 __namespaceModules = None 1376 1377 __components = None 1378 __componentBindingName = None 1379 __uniqueInModule = None 1380 1381 _UniqueInModule = _ModuleNaming_mixin._UniqueInModule.copy() 1382 1383 __UniqueInGroups = set() 1384 1385 _GroupPrefix = '_group' 1386
1387 - def __init__ (self, generator, namespace_modules, **kw):
1388 super(NamespaceGroupModule, self).__init__(generator, **kw) 1389 assert 1 < len(namespace_modules) 1390 self.__namespaceModules = namespace_modules 1391 self.__namespaceGroupHead = namespace_modules[0].namespaceGroupHead() 1392 self._initializeUniqueInModule(self._UniqueInModule) 1393 self._setModulePath(generator.modulePathData(self))
1394
1395 - def _initialBindingTemplateMap (self):
1396 kw = { 'moduleType' : 'namespaceGroup' } 1397 return kw
1398
1399 - def _bindingTagPrefix_vx (self):
1400 return 'NGM'
1401
1402 - def _bindingPreface_vx (self):
1403 rvl = ['# Group contents:\n' ] 1404 for nsm in self.namespaceModules(): 1405 rvl.append(nsm.bindingPreface()) 1406 rvl.append('\n') 1407 return ''.join(rvl)
1408
1409 - def _finalizeModuleContents_vx (self, template_map):
1410 self.bindingIO().prolog().append(self.bindingIO().expand(''' 1411 import pyxb 1412 import pyxb.binding 1413 import pyxb.utils.utility 1414 1415 # Unique identifier for bindings created at the same time 1416 _GenerationUID = %{generation_uid_expr} 1417 1418 # Import bindings for schemas in group 1419 %{aux_imports} 1420 1421 %{namespace_decls} 1422 ''', **template_map))
1423
1424 - def _moduleUID_vx (self):
1425 nss = [] 1426 for nsm in self.namespaceModules(): 1427 ns = nsm.namespace() 1428 if ns.isAbsentNamespace(): 1429 nss.append('Absent') 1430 else: 1431 nss.append(str(ns)) 1432 nss.sort() 1433 return ';'.join(nss)
1434
1435 - def __str__ (self):
1436 return 'NGM:%s' % (self.modulePath(),)
1437
1438 1439 -def GeneratePython (schema_location=None, 1440 schema_text=None, 1441 namespace=None, 1442 module_prefix_elts=[], 1443 **kw):
1444 1445 generator = Generator(allow_absent_module=True, generate_to_files=False, **kw) 1446 if schema_location is not None: 1447 generator.addSchemaLocation(schema_location) 1448 elif schema_text is not None: 1449 generator.addSchema(schema_text) 1450 modules = generator.bindingModules() 1451 1452 assert 1 == len(modules), '%s produced %d modules: %s' % (namespace, len(modules), " ".join([ str(_m) for _m in modules])) 1453 return modules.pop().moduleContents()
1454 1455 import optparse 1456 import re
1457 1458 -class Generator (object):
1459 """Configuration and data for a single binding-generation action.""" 1460 1461 _DEFAULT_bindingRoot = '.'
1462 - def bindingRoot (self):
1463 """The directory path into which generated bindings will be written. 1464 @rtype: C{str}""" 1465 return self.__bindingRoot
1466 - def setBindingRoot (self, binding_root):
1467 self.__bindingRoot = binding_root 1468 return self
1469 __bindingRoot = None 1470
1471 - def __moduleFilePath (self, module_elts, inhibit_extension=False):
1472 if isinstance(module_elts, basestring): 1473 module_elts = module_elts.split('.') 1474 else: 1475 module_elts = module_elts[:] 1476 assert 0 < len(module_elts) 1477 if not inhibit_extension: 1478 assert not module_elts[-1].endswith('.py') 1479 module_elts[-1] = '%s.py' % (module_elts[-1],) 1480 return os.path.join(self.bindingRoot(), *module_elts)
1481
1482 - def generateToFiles (self):
1483 return self.__generateToFiles
1484 __generateToFiles = None 1485
1486 - def modulePathData (self, module):
1487 # file system path to where the bindings are written 1488 # module path from which the bindings are normally imported 1489 # file object into which bindings are written 1490 1491 module_path = None 1492 if isinstance(module, NamespaceModule): 1493 mr = module.moduleRecord() 1494 if mr is None: 1495 return ('/dev/null', None, None) 1496 if self.generationUID() != mr.generationUID(): 1497 return ('/dev/null', None, None) 1498 if not self.generateToFiles(): 1499 return ('/dev/null', None, None) 1500 if mr.namespace().isBuiltinNamespace() and (not self.allowBuiltinGeneration()): 1501 return ('/dev/null', None, None) 1502 module_path = mr.modulePath() 1503 assert module_path is not None, 'No path specified for module %s' % (mr,) 1504 #if pyxb.namespace.XMLSchema != ns: 1505 # return ('/dev/null', None, None) 1506 #module_path="bogus.xsd" 1507 module_elts = module_path.split('.') 1508 if self.writeForCustomization(): 1509 import_file_path = self.__moduleFilePath(module_elts) 1510 module_elts.insert(-1, 'raw') 1511 if not os.path.exists(import_file_path): 1512 raw_module_path = '.'.join(module_elts) 1513 pyxb.utils.utility.OpenOrCreate(import_file_path).write("from %s import *\n" % (raw_module_path,)) 1514 binding_file_path = self.__moduleFilePath(module_elts) 1515 try: 1516 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID()) 1517 except OSError, e: 1518 if errno.EEXIST == e.errno: 1519 raise pyxb.BindingGenerationError('Target file %s for module %s bindings exists with other content' % (binding_file_path, mr)) 1520 raise 1521 elif isinstance(module, NamespaceGroupModule): 1522 if not self.generateToFiles(): 1523 raise pyxb.BindingGenerationError('Generation of namespace groups requires generate-to-files') 1524 module_elts = [] 1525 if self.modulePrefix(): 1526 module_elts.extend(self.modulePrefix().split('.')) 1527 if self.writeForCustomization(): 1528 module_elts.append('raw') 1529 in_use = set() 1530 while True: 1531 module_elts.append(pyxb.utils.utility.PrepareIdentifier('nsgroup', in_use, protected=True)) 1532 try: 1533 binding_file_path = self.__moduleFilePath(module_elts) 1534 print 'Attempting group %s uid %s at %s' % (module, module.moduleUID(), binding_file_path) 1535 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID()) 1536 break 1537 except OSError, e: 1538 if errno.EEXIST != e.errno: 1539 raise 1540 module_elts.pop() 1541 module_path = '.'.join(module_elts) 1542 else: 1543 assert False 1544 if self.generateToFiles(): 1545 for n in range(len(module_elts)-1): 1546 sub_path = self.__moduleFilePath(module_elts[:1+n], inhibit_extension=True) 1547 init_path = os.path.join(sub_path, '__init__.py') 1548 if not os.path.exists(init_path): 1549 file(init_path, 'w') 1550 return (binding_file_path, binding_file, module_path)
1551
1552 - def schemaRoot (self):
1553 """The directory from which entrypoint schemas specified as 1554 relative file paths will be read.""" 1555 return self.__schemaRoot
1556 - def setSchemaRoot (self, schema_root):
1557 if not schema_root.endswith(os.sep): 1558 schema_root = schema_root + os.sep 1559 self.__schemaRoot = schema_root 1560 return self
1561 __schemaRoot = None 1562
1563 - def schemaStrippedPrefix (self):
1564 """Optional string that is stripped from the beginning of 1565 schemaLocation values before loading from them. 1566 1567 This applies only to the values of schemaLocation attributes 1568 in C{import} and C{include} elements. Its purpose is to 1569 convert absolute schema locations into relative ones to allow 1570 offline processing when all schema are available in a local 1571 directory. See C{schemaRoot}. 1572 """ 1573 return self.__schemaStrippedPrefix
1574 - def setSchemaStrippedPrefix (self, schema_stripped_prefix):
1575 self.__schemaStrippedPrefix = schema_stripped_prefix 1576 return self
1577 __schemaStrippedPrefix = None 1578
1579 - def locationPrefixRewriteMap (self):
1580 """Optional map to rewrite schema locations. 1581 1582 This applies only to the values of schemaLocation attributes 1583 in C{import} and C{include} elements. Its purpose is to 1584 convert remote or absolute schema locations into local or 1585 relative ones to allow offline processing when all schema are 1586 available in a local directory. See C{schemaRoot}. 1587 """ 1588 return self.__locationPrefixRewriteMap
1589 - def setLocationPrefixRewriteMap (self, location_prefix_rewrite_map):
1590 self.__locationPrefixMap.clear() 1591 print 'GOT "%s"' % (location_prefix_rewrite_map,) 1592 self.__locationPrefixMap.update(location_prefix_rewrite_map) 1593 return self
1594 - def addLocationPrefixRewrite (self, prefix, substituent):
1595 """Add a rewrite entry for schema locations. 1596 1597 @param prefix : A text prefix that should be removed from 1598 schema location URIs. 1599 1600 @param substituent : The text prefix that should replace 1601 C{prefix} as a prefix in a schema location URI. 1602 """ 1603 1604 self.__locationPrefixRewriteMap[prefix] = substituent 1605 return self
1606 - def argAddLocationPrefixRewrite (self, prefix_rewrite):
1607 """Add a rewrite entry for schema locations. 1608 1609 Parameter values are strings of the form C{pfx=sub}. The 1610 effect is that a schema location that begins with C{pfx} is 1611 rewritten so that it instead begins with C{sub}.""" 1612 try: 1613 (prefix, substituent) = prefix_rewrite.split('=', 1) 1614 except: 1615 raise 1616 self.addLocationPrefixRewrite(prefix, substituent)
1617 __locationPrefixMap = {} 1618
1619 - def schemaLocationList (self):
1620 """A list of locations from which entrypoint schemas are to be 1621 read. 1622 1623 The values in the list are either URIs, or tuples consisting 1624 of a value and a callable which, when passed the generator 1625 object and the value, will return a 1626 L{pyxb.xmlschema.structures.Schema} instance. See 1627 L{addSchemaLocation}. 1628 1629 See also L{addSchemaLocation} and L{schemas}. 1630 """ 1631 return self.__schemaLocationList
1632 - def setSchemaLocationList (self, schema_location_list):
1633 self.__schemaLocationList[:] = [] 1634 self.__schemaLocationList.extend(schema_location_list) 1635 return self
1636 - def addSchemaLocation (self, schema_location, converter=None):
1637 """Add the location of an entrypoint schema. 1638 1639 @param schema_location: The location of the schema. This 1640 should be a URL; if the schema location does not have a URL 1641 scheme (e.g., C{http:}), it is assumed to be a file, and if it 1642 is not an absolute path is located relative to the 1643 C{schemaRoot}. 1644 1645 @keyword converter: Optional callable that will be invoked 1646 with the generator instance and the schema location, and is 1647 expected to return a L{pyxb.xmlschema.structures.Schema} 1648 instance. If absent, the contents of the location are 1649 converted directly. 1650 1651 @note: The C{converter} argument derives from WSDL support: we 1652 need to add to the sequence of schema locations a URI of 1653 something that will not parse as a schema, but does have inner 1654 material that can if treated properly. "Treated properly" may 1655 include having the archive path and other namespace 1656 manipulations configured before anything is done to it. 1657 """ 1658 self.__schemaLocationList.append( (schema_location, converter) ) 1659 return self
1660 - def argAddSchemaLocation (self, schema_location):
1661 """Add the location of an entrypoint schema. The provided 1662 value should be a URL; if it does not have a URL scheme (e.g., 1663 C{http:}), it is assumed to be a file, and if it is not an 1664 absolute path is located relative to the C{schemaRoot}.""" 1665 self.addSchemaLocation(schema_location)
1666 __schemaLocationList = None 1667
1668 - def schemas (self):
1669 """Schema for which bindings should be generated. 1670 1671 These may be L{Schema<pyxb.xmlschema.structures.Schema>} 1672 instances, or strings; the latter is preferred, and is parsed 1673 into a Schema instance when required. 1674 1675 This is the list of entrypoint schemas for binding generation. 1676 Values in L{schemaLocationList} are read and converted into 1677 schema, then appended to this list. Values from L{moduleList} 1678 are applied starting with the first schema in this list. 1679 """ 1680 return self.__schemas[:]
1681 - def setSchemas (self, schemas):
1682 self.__schemas[:] = [] 1683 self.__schemas.extend(schemas) 1684 return self
1685 - def addSchema (self, schema):
1686 self.__schemas.append(schema) 1687 return self
1688 __schemas = None 1689
1690 - def namespaces (self):
1691 """The set of L{namespaces<pyxb.namespace.Namespace>} for 1692 which bindings will be generated. 1693 1694 This is the set of namespaces read from entrypoint schema, 1695 closed under reference to namespaces defined by schema import. 1696 1697 @rtype: C{set} 1698 """ 1699 return self.__namespaces.copy()
1700 - def setNamespaces (self, namespace_set):
1701 self.__namespaces.clear() 1702 self.__namespaces.update(namespace_set) 1703 return self
1704 - def addNamespace (self, namespace):
1705 self.__namespaces.add(namespace) 1706 return self
1707 __namespaces = None 1708
1709 - def moduleList (self):
1710 """A list of module names to be applied in order to the namespaces of entrypoint schemas""" 1711 return self.__moduleList[:]
1712 - def _setModuleList (self, module_list):
1713 self.__moduleList[:] = [] 1714 self.__moduleList.extend(module_list) 1715 return self
1716
1717 - def addModuleName (self, module_name):
1718 """Add a module name corresponding to an entrypoint schema. 1719 1720 The namespace defined by the corresponding schema will be 1721 written to a binding using the given module name, adjusted by 1722 L{modulePrefix}.""" 1723 self.__moduleList.append(module_name) 1724 return self
1725 __moduleList = None 1726
1727 - def modulePrefix (self):
1728 """The prefix for binding modules. 1729 1730 The base name for the module holding a binding is taken from 1731 the moduleList, moduleMap, or an XMLNS prefix associated with 1732 the namespace in a containing schema. This value, if present, 1733 is used as a prefix to allow a deeper module hierarchy.""" 1734 return self.__modulePrefix
1735 - def setModulePrefix (self, module_prefix):
1736 self.__modulePrefix = module_prefix 1737 return self
1738 __modulePrefix = None 1739
1740 - def namespaceModuleMap (self):
1741 """A map from namespace URIs to the module to be used for the 1742 corresponding generated binding. 1743 1744 Module values are adjusted by L{modulePrefix} if that has been 1745 specified. 1746 1747 An entry in this map for a namespace supersedes the module 1748 specified in moduleList if the namespace is defined by an 1749 entrypoint schema. 1750 1751 @return: A reference to the namespace module map. 1752 """ 1753 return self.__namespaceModuleMap
1754 __namespaceModuleMap = None 1755
1756 - def archivePath (self):
1757 """A colon-separated list of paths from which namespace 1758 archives can be read. 1759 1760 The default path is the contents of the C{PYXB_ARCHIVE_PATH} 1761 environment variable, or the standard path configured at 1762 installation time. Any file with the extension C{.wxs} found 1763 in one of these directories is examined to see whether it is a 1764 namespace archive. 1765 """ 1766 return self.__archivePath
1767 - def setArchivePath (self, archive_path):
1768 self.__archivePath = archive_path 1769 return self
1770 __archivePath = None 1771
1772 - def noLoadNamespaces (self):
1773 """A frozenset of namespaces that many not be loaded from an archive.""" 1774 return frozenset(self.__noLoadNamespaces)
1775 - def _setNoLoadNamespaces (self, namespace_set):
1776 """Record the set of namespaces that should not be loaded from an archive. 1777 1778 The expectation is that any required entities in the namespace 1779 will be defined by loading schema.""" 1780 self.__noLoadNamespaces.clear() 1781 self.__noLoadNamespaces.update([ pyxb.namespace.NamespaceInstance(_ns) for _ns in namespace_set ])
1782 - def addNoLoadNamespace (self, namespace):
1783 """Mark that the specified namespace should not be loaded from an archive. 1784 1785 Use this when you are generating bindings for an application 1786 that has a restricted profile of a namespace that would 1787 otherwise be read from an archive. Be aware that this removes 1788 any knowledge of any archive in which this namespace is 1789 present as a non-private member.""" 1790 self.__noLoadNamespaces.add(pyxb.namespace.NamespaceInstance(namespace))
1791 __noloadNamespaces = None 1792
1793 - def preLoadArchives (self):
1794 """A list of paths to archives that should be loaded, in order, prior to parsing schema.""" 1795 return frozenset(self.__preLoadArchives)
1796 - def addPreLoadArchive (self, archive_file):
1797 """Name of a file containing a stored archive from which 1798 namespaces should be read prior to processing schema. 1799 1800 Files to be pre-loaded are not affected by 1801 C{noLoadNamespace}.""" 1802 self.__preLoadArchives.append(archive_file)
1803 - def _setPreLoadArchives (self, pre_load_archives):
1804 self.__preLoadArchives[:] = pre_load_archives 1805 return self
1806 __preLoadArchives = None 1807
1808 - def archiveToFile (self):
1809 """Optional file into which the archive of namespaces will be written. 1810 1811 Subsequent generation actions can read pre-parsed namespaces 1812 from this file, and therefore reference the bindings that were 1813 built earlier rather than re-generating them. 1814 1815 The file name should normally end with C{.wxs}.""" 1816 return self.__archiveToFile
1817 - def setArchiveToFile (self, archive_to_file):
1818 self.__archiveToFile = archive_to_file 1819 return self
1820 __archiveToFile = None 1821
1822 - def setNamespaceVisibility (self, namespace, visibility):
1826 - def _setNamespaceVisibilities (self, public, private):
1827 if public is None: 1828 public = set() 1829 if private is None: 1830 private = set() 1831 self.__namespaceVisibilityMap.clear() 1832 self.__namespaceVisibilityMap.update(dict.fromkeys(public, True)) 1833 self.__namespaceVisibilityMap.update(dict.fromkeys(private, False))
1834 - def namespaceVisibilityMap (self):
1835 """Indicates, for specific namespaces, whether their 1836 visibility in the archive should be public or private.""" 1837 return self.__namespaceVisibilityMap.copy()
1838 __namespaceVisibilityMap = None 1839
1840 - def defaultNamespacePublic (self):
1841 """Indicates whether unmentioned namespaces will be public or private (default) in the archive. 1842 1843 A namespace is I{mentioned} if it is the target namespace of 1844 an entrypoint schema, or appears in a namespace visibility 1845 specification. I.e., this default applies only to namespaces 1846 that are modified as a result of including some schema, which 1847 is generally a local customization of something. 1848 """ 1849 return self.__defaultNamespacePublic
1850 - def setDefaultNamespacePublic (self, default_namespace_public):
1851 self.__defaultNamespacePublic = default_namespace_public
1852 __defaultNamespacePublic = None 1853
1854 - def validateChanges (self):
1855 """Indicates whether the bindings should validate mutations 1856 against the content model.""" 1857 return self.__validateChanges
1858 - def setValidateChanges (self, validate_changes):
1859 #raise pyxb.IncompleteImplementationError('No support for disabling validation') 1860 self.__validateChanges = validate_changes 1861 return self
1862 __validateChanges = None 1863 1864 _DEFAULT_bindingStyle = basis.CURRENT_BINDING_STYLE
1865 - def bindingStyle (self):
1866 """The style of Python used in generated bindings. 1867 1868 C{accessor} means values are private variables accessed 1869 through inspector and mutator methods. 1870 1871 C{property} means values are private variables accessed 1872 through a Python property. 1873 """ 1874 return self.__bindingStyle
1875 - def setBindingStyle (self, binding_style):
1876 raise pyxb.IncompleteImplementationError('No support for binding style configuration') 1877 self.__bindingStyle = binding_style 1878 return self
1879 __bindingStyle = None 1880
1881 - def writeForCustomization (self):
1882 """Indicates whether the binding Python code should be written into a sub-module for customization. 1883 1884 If enabled, a module C{path.to.namespace} will be written to 1885 the file C{path/to/raw/namespace.py}, so that the file 1886 C{path/to/namespace.py} can import it and override behavior.""" 1887 return self.__writeForCustomization
1888 - def setWriteForCustomization (self, write_for_customization):
1889 self.__writeForCustomization = write_for_customization 1890 return self
1891 __writeForCustomization = None 1892
1893 - def allowAbsentModule (self):
1894 """Indicates whether the code generator is permitted to 1895 process namespace for which no module path can be determined. 1896 1897 Use this only when generating bindings that will not be 1898 referenced by other bindings.""" 1899 return self.__allowAbsentModule
1900 - def setAllowAbsentModule (self, allow_absent_module):
1901 self.__allowAbsentModule = allow_absent_module 1902 return self
1903 __allowAbsentModule = None 1904
1905 - def allowBuiltinGeneration (self):
1906 """Indicates whether bindings will be written for namespaces that are built-in to PyXB. 1907 1908 This must be enabled when building bindings for the XML, 1909 XMLSchema instance, and other built-in namespaces. Normally 1910 generation of these namespaces is inhibited lest it produce 1911 inconsistencies.""" 1912 return self.__allowBuiltinGeneration
1913 - def setAllowBuiltinGeneration (self, allow_builtin_generation):
1914 self.__allowBuiltinGeneration = allow_builtin_generation 1915 return self
1916 __allowBuiltinGeneration = None 1917
1918 - def uriContentArchiveDirectory (self):
1919 """The directory path into which any content retrieved by URI will be written. 1920 1921 This serves as a local cache, and to give you an opportunity 1922 to inspect material retrieved from some other system. 1923 @rtype: C{str}""" 1924 return self.__uriContentArchiveDirectory
1925 - def setUriContentArchiveDirectory (self, ucad):
1927 __uriContentArchiveDirectory = None 1928
1929 - def __init__ (self, *args, **kw):
1930 """Create a configuration to be used for generating bindings. 1931 1932 Arguments are treated as additions to the schema location list 1933 after all keywords have been processed. 1934 1935 @keyword binding_root: Invokes L{setBindingRoot} 1936 @keyword schema_root: Invokes L{setSchemaRoot} 1937 @keyword schema_stripped_prefix: Invokes L{setSchemaStrippedPrefix} 1938 @keyword location_prefix_rewrite_map: Invokes L{setLocationPrefixRewriteMap} 1939 @keyword schema_location_list: Invokes L{setSchemaLocationList} 1940 @keyword module_list: Invokes L{_setModuleList} 1941 @keyword module_prefix: Invokes L{setModulePrefix} 1942 @keyword archive_path: Invokes L{setArchivePath} 1943 @keyword no_load_namespaces: Invokes L{_setNoLoadNamespaces} 1944 @keyword pre_load_archives: Invokes L{_setPreLoadArchives} 1945 @keyword archive_to_file: Invokes L{setArchiveToFile} 1946 @keyword public_namespace: Invokes L{setNamespaceVisibility} 1947 @keyword private_namespace: Invokes L{setNamespaceVisibility} 1948 @keyword default_namespace_public: Invokes L{setDefaultNamespacePublic} 1949 @keyword validate_changes: Invokes L{setValidateChanges} 1950 @keyword binding_style: Invokes L{setBindingStyle} 1951 @keyword namespace_module_map: Initializes L{namespaceModuleMap} 1952 @keyword schemas: Invokes L{setSchemas} 1953 @keyword namespaces: Invokes L{setNamespaces} 1954 @keyword write_for_customization: Invokes L{setWriteForCustomization} 1955 @keyword allow_builtin_generation: Invokes L{setAllowBuiltinGeneration} 1956 @keyword allow_absent_module: Invokes L{setAllowAbsentModule} 1957 @keyword generate_to_files: Sets L{generateToFiles} 1958 @keyword uri_content_archive_directory: Invokes L{setUriContentArchiveDirectory} 1959 """ 1960 argv = kw.get('argv', None) 1961 if argv is not None: 1962 kw = {} 1963 self.__bindingRoot = kw.get('binding_root', self._DEFAULT_bindingRoot) 1964 self.__schemaRoot = kw.get('schema_root', '.') 1965 self.__schemaStrippedPrefix = kw.get('schema_stripped_prefix') 1966 self.__locationPrefixRewriteMap = kw.get('location_prefix_rewrite_map', {}) 1967 self.__schemas = [] 1968 self.__schemaLocationList = kw.get('schema_location_list', [])[:] 1969 self.__moduleList = kw.get('module_list', [])[:] 1970 self.__modulePrefix = kw.get('module_prefix') 1971 self.__archivePath = kw.get('archive_path', pyxb.namespace.archive.GetArchivePath()) 1972 self.__noLoadNamespaces = kw.get('no_load_namespaces', set()).copy() 1973 self.__preLoadArchives = kw.get('pre_load_archives', [])[:] 1974 self.__archiveToFile = kw.get('archive_to_file') 1975 self.__namespaceVisibilityMap = {} 1976 self._setNamespaceVisibilities(kw.get('public_namespaces', set()), kw.get('private_namespaces', set())) 1977 self.__defaultNamespacePublic = kw.get('default_namespace_public', False) 1978 self.__validateChanges = kw.get('validate_changes', True) 1979 self.__bindingStyle = kw.get('binding_style', self._DEFAULT_bindingStyle) 1980 self.__namespaceModuleMap = kw.get('namespace_module_map', {}).copy() 1981 self.__schemas = kw.get('schemas', [])[:] 1982 self.__namespaces = set(kw.get('namespaces', [])) 1983 self.__writeForCustomization = kw.get('write_for_customization', False) 1984 self.__writeForCustomization = kw.get('allow_builtin_generation', False) 1985 self.__allowAbsentModule = kw.get('allow_absent_module', False) 1986 self.__generateToFiles = kw.get('generate_to_files', True) 1987 self.__uriContentArchiveDirectory = kw.get('uri_content_archive_directory') 1988 1989 if argv is not None: 1990 self.applyOptionValues(*self.optionParser().parse_args(argv)) 1991 [ self.addSchemaLocation(_a) for _a in args ] 1992 1993 self.__generationUID = pyxb.utils.utility.UniqueIdentifier() 1994 1995 pyxb.namespace.XML.validateComponentModel()
1996 1997 __stripSpaces_re = re.compile('\s\s\s+')
1998 - def __stripSpaces (self, string):
1999 return self.__stripSpaces_re.sub(' ', string)
2000 2001 __OptionSetters = ( 2002 ('binding_root', setBindingRoot), 2003 ('schema_root', setSchemaRoot), 2004 ('schema_stripped_prefix', setSchemaStrippedPrefix), 2005 ('location_prefix_rewrite', argAddLocationPrefixRewrite), 2006 ('schema_location', setSchemaLocationList), 2007 ('module', _setModuleList), 2008 ('module_prefix', setModulePrefix), 2009 ('archive_path', setArchivePath), 2010 ('no_load_namespace', _setNoLoadNamespaces), 2011 ('pre_load_archive', _setPreLoadArchives), 2012 ('archive_to_file', setArchiveToFile), 2013 ('default_namespace_public', setDefaultNamespacePublic), 2014 ('binding_style', setBindingStyle), 2015 ('validate_changes', setValidateChanges), 2016 ('write_for_customization', setWriteForCustomization), 2017 ('allow_builtin_generation', setAllowBuiltinGeneration), 2018 ('allow_absent_module', setAllowAbsentModule), 2019 ('uri_content_archive_directory', setUriContentArchiveDirectory) 2020 )
2021 - def applyOptionValues (self, options, args=None):
2022 for (tag, method) in self.__OptionSetters: 2023 v = getattr(options, tag) 2024 if v is not None: 2025 method(self, v) 2026 public_namespaces = getattr(options, 'public_namespace') 2027 private_namespaces = getattr(options, 'private_namespace') 2028 self._setNamespaceVisibilities(public_namespaces, private_namespaces) 2029 if args is not None: 2030 self.__schemaLocationList.extend(args) 2031 pyxb.utils.utility.SetLocationPrefixRewriteMap(self.locationPrefixRewriteMap())
2032
2033 - def setFromCommandLine (self, argv=None):
2034 if argv is None: 2035 argv = sys.argv[1:] 2036 (options, args) = self.optionParser().parse_args(argv) 2037 self.applyOptionValues(options, args) 2038 return self
2039
2040 - def generationUID (self):
2041 return self.__generationUID
2042 __generationUID = None 2043
2044 - def optionParser (self, reset=False):
2045 """Return an C{optparse.OptionParser} instance tied to this configuration. 2046 2047 @param reset: If C{False} (default), a parser created in a 2048 previous invocation will be returned. If C{True}, any 2049 previous option parser is discarded and a new one created. 2050 @type reset: C{bool} 2051 """ 2052 if reset or (self.__optionParser is None): 2053 parser = optparse.OptionParser(usage="%prog [options] [more schema locations...]", 2054 version='%%prog from PyXB %s' % (pyxb.__version__,), 2055 description='Generate bindings from a set of XML schemas') 2056 2057 group = optparse.OptionGroup(parser, 'Identifying Schema', 'Specify and locate schema for which bindings should be generated.') 2058 group.add_option('--schema-location', '-u', metavar="FILE_or_URL", 2059 action='append', 2060 help=self.__stripSpaces(self.argAddSchemaLocation.__doc__)) 2061 group.add_option('--schema-root', metavar="DIRECTORY", 2062 help=self.__stripSpaces(self.schemaRoot.__doc__)) 2063 group.add_option('--schema-stripped-prefix', metavar="TEXT", type='string', 2064 help=self.__stripSpaces(self.schemaStrippedPrefix.__doc__)) 2065 group.add_option('--location-prefix-rewrite', metavar="TEXT", type='string', 2066 help=self.__stripSpaces(self.argAddLocationPrefixRewrite.__doc__)) 2067 group.add_option('--uri-content-archive-directory', metavar="DIRECTORY", 2068 help=self.__stripSpaces(self.uriContentArchiveDirectory.__doc__)) 2069 parser.add_option_group(group) 2070 2071 group = optparse.OptionGroup(parser, 'Configuring Bindings', 'Specify where generated bindings should be written, and how they will be accessed from Python.') 2072 group.add_option('--module', '-m', metavar="MODULE", 2073 action='append', 2074 help=self.__stripSpaces(self.addModuleName.__doc__)) 2075 group.add_option('--module-prefix', metavar="MODULE", 2076 help=self.__stripSpaces(self.modulePrefix.__doc__)) 2077 group.add_option('--binding-root', metavar="DIRECTORY", 2078 help=self.__stripSpaces(self.bindingRoot.__doc__)) 2079 group.add_option('-r', '--write-for-customization', 2080 action='store_true', dest='write_for_customization', 2081 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns on the feature.')) 2082 group.add_option('--no-write-for-customization', 2083 action='store_false', dest='write_for_customization', 2084 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns off the feature (I{default}).')) 2085 parser.add_option_group(group) 2086 2087 group = optparse.OptionGroup(parser, 'Reading Namespace Archives', 'Locating and loading (or inhibiting load of) namespace archives.') 2088 group.add_option('--archive-path', metavar="PATH", 2089 help=self.__stripSpaces(self.archivePath.__doc__)) 2090 group.add_option('--pre-load-archive', metavar="FILE", 2091 action='append', 2092 help=self.__stripSpaces(self.addPreLoadArchive.__doc__)) 2093 group.add_option('--no-load-namespace', metavar="URI", 2094 action='append', 2095 help=self.__stripSpaces(self.addNoLoadNamespace.__doc__)) 2096 parser.add_option_group(group) 2097 2098 group = optparse.OptionGroup(parser, 'Writing Namespace Archives', 'Control the location and content of a namespace archive corresponding to a binding generation.') 2099 group.add_option('--archive-to-file', metavar="FILE", 2100 help=self.__stripSpaces(self.archiveToFile.__doc__)) 2101 group.add_option('--public-namespace', metavar="URI", 2102 action='append', 2103 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a public archive member.')) 2104 group.add_option('--private-namespace', metavar="URI", 2105 action='append', 2106 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a private archive member.')) 2107 group.add_option('--default-namespace-public', 2108 action="store_true", dest='default_namespace_public', 2109 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{public} (I{default}).')) 2110 group.add_option('--default-namespace-private', 2111 action="store_false", dest='default_namespace_public', 2112 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{private}.')) 2113 parser.add_option_group(group) 2114 2115 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.") 2116 group.add_option('--binding-style', 2117 type='choice', choices=basis.BINDING_STYLES, 2118 help=self.__stripSpaces(self.bindingStyle.__doc__)) 2119 group.add_option('--validate-changes', 2120 action='store_true', dest='validate_changes', 2121 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns on validation (default).')) 2122 group.add_option('--no-validate-changes', 2123 action='store_false', dest='validate_changes', 2124 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns off validation.')) 2125 parser.add_option_group(group) 2126 2127 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.") 2128 group.add_option('--allow-absent-module', 2129 action='store_true', dest='allow_absent_module', 2130 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns on the feature.')) 2131 group.add_option('--no-allow-absent-module', 2132 action='store_false', dest='allow_absent_module', 2133 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns off the feature (default).')) 2134 group.add_option('--allow-builtin-generation', 2135 action='store_true', dest='allow_builtin_generation', 2136 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns on the feature.')) 2137 group.add_option('--no-allow-builtin-generation', 2138 action='store_false', dest='allow_builtin_generation', 2139 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns off the feature (default).')) 2140 parser.add_option_group(group) 2141 2142 self.__optionParser = parser 2143 return self.__optionParser
2144 __optionParser = None 2145
2146 - def getCommandLineArgs (self):
2147 """Return a command line option sequence that could be used to 2148 construct an equivalent configuration. 2149 2150 @note: If you extend the option parser, as is done by 2151 C{pyxbgen}, this may not be able to reconstruct the correct 2152 command line.""" 2153 opts = [] 2154 module_list = self.moduleList() 2155 schema_list = self.schemaLocationList() 2156 while module_list and schema_list: 2157 ml = module_list.pop(0) 2158 sl = schema_list.pop(0) 2159 if isinstance(sl, tuple): 2160 sl = sl[0] 2161 opts.extend(['--schema-location=' + sl, '--module=' + ml]) 2162 for sl in schema_list: 2163 opts.append('--schema-location=' + sl) 2164 if self.schemaRoot() is not None: 2165 opts.append('--schema-root=' + self.schemaRoot()) 2166 if self.schemaStrippedPrefix() is not None: 2167 opts.append('--schema-stripped-prefix=%s' + self.schemaStrippedPrefix()) 2168 for (pfx, sub) in self.locationPrefixRewriteMap(): 2169 opts.append('--location-prefix-rewrite=%s=%s' % (pfx, sub)) 2170 if self.modulePrefix() is not None: 2171 opts.append('--module-prefix=' + self.modulePrefix()) 2172 opts.append('--binding-root=' + self.bindingRoot()) 2173 if self.archivePath() is not None: 2174 opts.append('--archive-path=' + self.archivePath()) 2175 for ns in self.noLoadNamespaces(): 2176 opts.append('--no-load-namespace=' + ns.uri()) 2177 for fps in self.preLoadArchives(): 2178 opts.append('--pre-load-archive=' + fp) 2179 if self.archiveToFile() is not None: 2180 opts.append('--archive-to-file=' + self.archiveToFile()) 2181 for (ns, visibility) in self._namespaceVisibilityMap(): 2182 if visibility: 2183 opts.append('--public-namespace=' + ns.uri()) 2184 else: 2185 opts.append('--private-namespace=' + ns.uri()) 2186 if self.defaultNamespacePublic(): 2187 opts.append('--default-namespace-public') 2188 else: 2189 opts.append('--default-namespace-private') 2190 for (val, opt) in ( (self.validateChanges(), 'validate-changes'), 2191 (self.writeForCustomization(), 'write-for-customization'), 2192 (self.allowAbsentModule(), 'allow-absent-module'), 2193 (self.allowBuiltinGeneration(), 'allow-builtin-generation') ): 2194 if val: 2195 opts.append('--' + opt) 2196 else: 2197 opts.append('--no-' + opt) 2198 if self.uriContentArchiveDirectory() is not None: 2199 opts.append('--uri-content-archive-directory=%s' + self.uriContentArchiveDirectory()) 2200 return opts
2201
2202 - def normalizeSchemaLocation (self, sl):
2203 ssp = self.schemaStrippedPrefix() 2204 if ssp and sl.startswith(ssp): 2205 sl = sl[len(ssp):] 2206 return pyxb.utils.utility.NormalizeLocation(sl, self.schemaRoot())
2207
2208 - def __assignModulePath (self, module_record, module_path=None):
2209 if module_record.modulePath() is not None: 2210 return module_record 2211 namespace = module_record.namespace() 2212 if not namespace.isAbsentNamespace(): 2213 if (module_path is None) and not (namespace.prefix() is None): 2214 module_path = namespace.prefix() 2215 module_path = self.namespaceModuleMap().get(namespace.uri(), module_path) 2216 if (module_path is not None) and self.modulePrefix(): # non-empty value 2217 module_path = '.'.join([self.modulePrefix(), module_path]) 2218 if (module_path is None) and self.generateToFiles(): 2219 raise pyxb.BindingGenerationError('No prefix or module name available for %s' % (module_record,)) 2220 module_record.setModulePath(module_path) 2221 return module_record
2222 2223 __didResolveExternalSchema = False
2224 - def resolveExternalSchema (self, reset=False):
2225 if self.__didResolveExternalSchema and (not reset): 2226 raise pyxb.PyXBException('Cannot resolve external schema multiple times') 2227 2228 required_archives = pyxb.namespace.archive.NamespaceArchive.PreLoadArchives(self.archivePath(), self.preLoadArchives()) 2229 for nsa in required_archives: 2230 nsa.readNamespaces() 2231 for ns in self.noLoadNamespaces(): 2232 assert isinstance(ns, pyxb.namespace.Namespace) 2233 ns.markNotLoadable() 2234 while self.__schemaLocationList: 2235 sl = self.__schemaLocationList.pop(0) 2236 if isinstance(sl, tuple): 2237 (sl, converter) = sl 2238 else: 2239 converter = None 2240 try: 2241 if converter is None: 2242 schema = xs.schema.CreateFromLocation(absolute_schema_location=self.normalizeSchemaLocation(sl), 2243 generation_uid=self.generationUID(), 2244 uri_content_archive_directory=self.uriContentArchiveDirectory()) 2245 else: 2246 schema = converter(self, sl) 2247 self.addSchema(schema) 2248 except pyxb.SchemaUniquenessError, e: 2249 print 'WARNING: Skipped redundant translation of %s defining %s' % (e.schemaLocation(), e.namespace()) 2250 self.addSchema(e.existingSchema()) 2251 for schema in self.__schemas: 2252 if isinstance(schema, basestring): 2253 schema = xs.schema.CreateFromDocument(schema, generation_uid=self.generationUID()) 2254 origin = schema.originRecord() 2255 assert origin is not None 2256 module_path = None 2257 if self.__moduleList: 2258 module_path = self.__moduleList.pop(0) 2259 self.__assignModulePath(origin.moduleRecord(), module_path) 2260 assert schema.targetNamespace() == origin.moduleRecord().namespace() 2261 self.addNamespace(schema.targetNamespace()) 2262 self.__didResolveExternalSchema = True 2263 self.__bindingModules = None
2264
2265 - def __graphFromComponents (self, components, include_lax):
2266 components = components.copy() 2267 component_graph = pyxb.utils.utility.Graph() 2268 need_visit = components.copy() 2269 bindable_fn = lambda _c: isinstance(_c, xs.structures.ElementDeclaration) or _c.isTypeDefinition() 2270 while 0 < len(need_visit): 2271 c = need_visit.pop() 2272 assert c is not None 2273 assert bindable_fn(c) or include_lax 2274 assert c._objectOrigin() is not None, '%s %s has no origin' % (type(c), c) 2275 component_graph.addNode(c) 2276 br = c.bindingRequires(reset=True, include_lax=include_lax) 2277 #print 'Component %s requires %d bindings' % (c, len(br)) 2278 for cd in br: 2279 assert bindable_fn(cd) or include_lax, '%s produced %s in requires' % (type(c), type(cd)) 2280 #print ' %s in %s' % (cd, cd._objectOrigin()) 2281 if cd._objectOrigin() is None: 2282 assert isinstance(cd, (pyxb.xmlschema.structures.Annotation, pyxb.xmlschema.structures.Wildcard)) 2283 continue 2284 if (cd._objectOrigin().moduleRecord() in self.__moduleRecords) and not (cd in components): 2285 components.add(cd) 2286 need_visit.add(cd) 2287 if cd in components: 2288 component_graph.addEdge(c, cd) 2289 return component_graph
2290
2291 - def __buildBindingModules (self):
2292 named_bindable_fn = lambda _c: (isinstance(_c, xs.structures.ElementDeclaration) and _c._scopeIsGlobal()) or _c.isTypeDefinition() 2293 bindable_fn = lambda _c: isinstance(_c, xs.structures.ElementDeclaration) or _c.isTypeDefinition() 2294 2295 self.__moduleRecords = set() 2296 all_components = set() 2297 for origin in self.generationUID().associatedObjects(): 2298 mr = origin.moduleRecord() 2299 if not (mr in self.__moduleRecords): 2300 # @todo NOTICE 2301 # print 'Entry %s' % (mr,) 2302 self.__moduleRecords.add(mr) 2303 mr.completeGenerationAssociations() 2304 all_components.update(origin.originatedObjects()) 2305 2306 namespaces = set() 2307 for mr in self.__moduleRecords: 2308 if mr.namespace().isBuiltinNamespace() and not self.allowBuiltinGeneration(): 2309 continue 2310 namespaces.add(mr.namespace()) 2311 pyxb.namespace.resolution.ResolveSiblingNamespaces(namespaces) 2312 2313 # Mark module visibility. Entry-point namespaces default to 2314 # public. 2315 for ns in self.namespaces(): 2316 self.__namespaceVisibilityMap.setdefault(ns, True) 2317 2318 # Generate the graph from all components and descend into lax 2319 # requirements; otherwise we might miss anonymous types hidden 2320 # inside attribute declarations and the like. 2321 component_graph = self.__graphFromComponents(all_components, True) 2322 2323 binding_components = set(filter(bindable_fn, component_graph.nodes())) 2324 # @todo NOTICE 2325 #print '%d of %d components need bindings' % (len(binding_components), len(component_graph.nodes())) 2326 2327 module_graph = pyxb.utils.utility.Graph() 2328 [ module_graph.addRoot(_mr) for _mr in self.__moduleRecords ] 2329 for (s, t) in component_graph.edges(): 2330 module_graph.addEdge(s._objectOrigin().moduleRecord(), t._objectOrigin().moduleRecord()) 2331 module_scc_order = module_graph.sccOrder() 2332 2333 # Note that module graph may have fewer nodes than 2334 # self.__moduleRecords, if a module has no components that 2335 # require binding generation. 2336 2337 # @todo NOTICE 2338 #print '%d entry, %d in graph' % (len(self.__moduleRecords), len(module_graph.nodes())) 2339 2340 for c in binding_components: 2341 assert bindable_fn(c), 'Unexpected %s in binding components' % (type(s),) 2342 c._setBindingNamespace(c._objectOrigin().moduleRecord().namespace()) 2343 2344 record_binding_map = {} 2345 unique_in_bindings = set([NamespaceGroupModule._GroupPrefix]) 2346 modules = [] 2347 for mr_scc in module_scc_order: 2348 scc_modules = [ ] 2349 for mr in mr_scc: 2350 # @todo INFO 2351 #print 'Generating %s of %d' % (mr, len(mr_scc)) 2352 mr._setIsPublic(self.__namespaceVisibilityMap.get(mr.namespace(), self.defaultNamespacePublic())) 2353 self.__assignModulePath(mr) 2354 assert not ((mr.modulePath() is None) and self.generateToFiles()), 'No module path defined for %s' % (mr,) 2355 if (not mr.isPublic()) and (mr.modulePath() is not None): 2356 elts = mr.modulePath().split('.') 2357 elts[-1] = '_%s' % (elts[-1],) 2358 mr.setModulePath('.'.join(elts)) 2359 nsm = NamespaceModule(self, mr, mr_scc) 2360 record_binding_map[mr] = nsm 2361 scc_modules.append(nsm) 2362 2363 modules.extend(scc_modules) 2364 if 1 < len(mr_scc): 2365 ngm = NamespaceGroupModule(self, scc_modules) 2366 modules.append(ngm) 2367 for nsm in scc_modules: 2368 nsm.setNamespaceGroupModule(ngm) 2369 2370 component_csets = self.__graphFromComponents(binding_components, False).sccOrder() 2371 bad_order = False 2372 component_order = [] 2373 for cset in component_csets: 2374 if 1 < len(cset): 2375 print "COMPONENT DEPENDENCY LOOP of %d components" % (len(cset),) 2376 cg = pyxb.utils.utility.Graph() 2377 for c in cset: 2378 assert bindable_fn(c), 'Unexpected %s in list' % (type(c),) 2379 print ' %s' % (c.expandedName(),) 2380 cg.addNode(c) 2381 for cd in c.bindingRequires(reset=True, include_lax=False): 2382 #print '%s depends on %s' % (c, cd) 2383 cg.addEdge(c, cd) 2384 #file('deploop.dot', 'w').write(cg._generateDOT('CompDep', lambda _c: _c.bestNCName())) 2385 relaxed_order = cg.sccOrder() 2386 for rcs in relaxed_order: 2387 assert 1 == len(rcs) 2388 rcs = rcs[0] 2389 if rcs in cset: 2390 component_order.append(rcs) 2391 else: 2392 component_order.extend(cset) 2393 2394 #print '%d components in order' % (len(component_order),) 2395 2396 element_declarations = [] 2397 type_definitions = [] 2398 for c in component_order: 2399 if isinstance(c, xs.structures.ElementDeclaration) and c._scopeIsGlobal(): 2400 # Only bind elements this pass, so their names get priority in deconfliction 2401 nsm = record_binding_map[c._objectOrigin().moduleRecord()] 2402 nsm.bindComponent(c) 2403 element_declarations.append(c) 2404 elif c.isTypeDefinition(): 2405 type_definitions.append(c) 2406 else: 2407 # No binding generation required 2408 pass 2409 2410 simple_type_definitions = [] 2411 complex_type_definitions = [] 2412 for td in type_definitions: 2413 nsm = record_binding_map[td._objectOrigin().moduleRecord()] 2414 assert nsm is not None, 'No namespace module for %s type %s scope %s namespace %s' % (td.expandedName(), type(td), td._scope(), td.bindingNamespace) 2415 module_context = nsm.bindComponent(td) 2416 assert isinstance(module_context, _ModuleNaming_mixin), 'Unexpected type %s' % (type(module_context),) 2417 if isinstance(td, xs.structures.SimpleTypeDefinition): 2418 _PrepareSimpleTypeDefinition(td, self, nsm, module_context) 2419 simple_type_definitions.append(td) 2420 elif isinstance(td, xs.structures.ComplexTypeDefinition): 2421 _PrepareComplexTypeDefinition(td, self, nsm, module_context) 2422 complex_type_definitions.append(td) 2423 else: 2424 assert False, 'Unexpected component type %s' % (type(td),) 2425 2426 for ngm in modules: 2427 if isinstance(ngm, NamespaceGroupModule): 2428 for m in ngm.namespaceModules(): 2429 m.addImportsFrom(ngm) 2430 2431 for std in simple_type_definitions: 2432 GenerateSTD(std, self) 2433 for ctd in complex_type_definitions: 2434 GenerateCTD(ctd, self) 2435 for ed in element_declarations: 2436 GenerateED(ed, self) 2437 2438 return modules
2439 2440 __bindingModules = None
2441 - def bindingModules (self, reset=False):
2442 if reset or (not self.__didResolveExternalSchema): 2443 self.resolveExternalSchema(reset) 2444 if reset or (self.__bindingModules is None): 2445 self.__bindingModules = self.__buildBindingModules() 2446 return self.__bindingModules
2447
2448 - def writeNamespaceArchive (self):
2449 archive_file = self.archiveToFile() 2450 if archive_file is not None: 2451 ns_archive = pyxb.namespace.archive.NamespaceArchive(generation_uid=self.generationUID()) 2452 try: 2453 ns_archive.writeNamespaces(pyxb.utils.utility.OpenOrCreate(archive_file)) 2454 print 'Saved parsed schema to %s URI' % (archive_file,) 2455 except Exception, e: 2456 print 'Exception saving preprocessed schema to %s: %s' % (archive_file, e) 2457 traceback.print_exception(*sys.exc_info()) 2458 #try: 2459 # os.unlink(component_model_file) 2460 #except (OSError, IOError), e: 2461 # pass 2462 if isinstance(e, (AssertionError, AttributeError, TypeError)): 2463 raise
2464
2465 - def moduleForComponent (self, component):
2467