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