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

Source Code for Module pyxb.binding.generate

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