1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 fac
27 from pyxb.utils import utility
28 from pyxb.utils import templates
29 from pyxb.binding import basis
30 from pyxb.binding import datatypes
31 from pyxb.binding import facets
32
33 import types
34 import sys
35 import traceback
36 import os.path
37 import logging
38 import logging.config
39
40 _log = logging.getLogger(__name__)
43 if text is None:
44 text = value.__name__
45 if value.__module__ == datatypes.__name__:
46 return 'pyxb.binding.datatypes.%s' % (text,)
47 if value.__module__ == facets.__name__:
48 return 'pyxb.binding.facets.%s' % (text,)
49 raise ValueError('No standard name for module of value', value)
50
52 """Base class for something that requires fairly complex activity
53 in order to generate its literal value."""
54
55
56
57 __ownerClass = None
58
59
60 __literal = None
61
65
69
72
77
93
95 __wildcard = None
96
98 self.__wildcard = wildcard
99 super(ReferenceWildcard, self).__init__(**kw)
100
101 template_map = { }
102 template_map['Wildcard'] = 'pyxb.binding.content.Wildcard'
103 if (xs.structures.Wildcard.NC_any == wildcard.namespaceConstraint()):
104 template_map['nc'] = templates.replaceInText('%{Wildcard}.NC_any', **template_map)
105 elif isinstance(wildcard.namespaceConstraint(), (set, frozenset)):
106 namespaces = []
107 for ns in wildcard.namespaceConstraint():
108 if ns is None:
109 namespaces.append(None)
110 else:
111 namespaces.append(ns.uri())
112 template_map['nc'] = 'set([%s])' % (",".join( [ repr(_ns) for _ns in namespaces ]))
113 else:
114 assert isinstance(wildcard.namespaceConstraint(), tuple)
115 ns = wildcard.namespaceConstraint()[1]
116 if ns is not None:
117 ns = ns.uri()
118 template_map['nc'] = templates.replaceInText('(%{Wildcard}.NC_not, %{namespace})', namespace=repr(ns), **template_map)
119 template_map['pc'] = wildcard.processContents()
120 self.setLiteral(templates.replaceInText('%{Wildcard}(process_contents=%{Wildcard}.PC_%{pc}, namespace_constraint=%{nc})', **template_map))
121
131
141
149
157
197
199
200 if isinstance(value, types.DictionaryType):
201 return ', '.join([ '%s=%s' % (k, pythonLiteral(v, **kw)) for (k, v) in value.items() ])
202
203
204 if isinstance(value, types.ListType):
205 return [ pythonLiteral(_v, **kw) for _v in value ]
206
207
208 if isinstance(value, pyxb.namespace.ExpandedName):
209 return pythonLiteral(ReferenceExpandedName(expanded_name=value, **kw))
210
211
212 if isinstance(value, (types.TupleType, set)):
213 return type(value)(pythonLiteral(list(value), **kw))
214
215
216
217 if isinstance(value, facets._Enumeration_mixin):
218 return pythonLiteral(ReferenceEnumerationMember(enum_value=value, **kw))
219
220
221
222
223 if isinstance(value, basis.simpleTypeDefinition):
224 return PrefixModule(value, value.pythonLiteral())
225
226 if isinstance(value, pyxb.namespace.Namespace):
227 return pythonLiteral(ReferenceNamespace(namespace=value, **kw))
228
229 if isinstance(value, type):
230 if issubclass(value, basis.simpleTypeDefinition):
231 return PrefixModule(value)
232 if issubclass(value, facets.Facet):
233 return PrefixModule(value)
234
235
236 if isinstance(value, types.StringTypes):
237 return utility.QuotedEscaped(value,)
238
239 if isinstance(value, facets.Facet):
240 return pythonLiteral(ReferenceFacet(facet=value, **kw))
241
242
243 if isinstance(value, facets._PatternElement):
244 return pythonLiteral(value.pattern)
245
246
247 if isinstance(value, facets._EnumerationElement):
248 return pythonLiteral(value.value())
249
250
251 if isinstance(value, xs.structures.Wildcard):
252 return pythonLiteral(ReferenceWildcard(value, **kw))
253
254
255 if isinstance(value, xs.structures._SchemaComponent_mixin):
256 return pythonLiteral(ReferenceSchemaComponent(value, **kw))
257
258
259 if isinstance(value, ReferenceLiteral):
260 return value.asLiteral()
261
262
263 if isinstance(value, pyxb.namespace.Namespace):
264 return repr(value.uri())
265
266
267 if isinstance(value, (types.NoneType, types.BooleanType, types.FloatType, types.IntType, types.LongType)):
268 return repr(value)
269
270 raise Exception('Unexpected literal type %s' % (type(value),))
271
288
289 def counterConditionSortKey (cc):
290 return cc.metadata.facStateSortKey()
291
292 def updateInstructionSortKey (ui):
293 return counterConditionSortKey(ui.counterCondition)
294
295 def transitionSortKey (xit):
296
297
298
299 st = xit.consumingState()
300
301
302
303 ssk = None
304 if st is not None:
305 ssk = stateSortKey(st)
306 keys = [ ssk ]
307 keys.extend(map(updateInstructionSortKey, sorted(xit.updateInstructions, key=updateInstructionSortKey)))
308 return tuple(keys)
309
310 au_src.append(' counters = set()')
311 counter_map = {}
312 sorted_counter_conditions = sorted(automaton.counterConditions, key=counterConditionSortKey)
313 for cc in sorted_counter_conditions:
314 cc_id = 'cc_%u' % (len(counter_map),)
315 counter_map[cc] = cc_id
316 au_src.append(' %s = fac.CounterCondition(min=%r, max=%r, metadata=%r)' % (cc_id, cc.min, cc.max, cc.metadata._location()))
317 au_src.append(' counters.add(%s)' % (cc_id,))
318 state_map = {}
319 au_src.append(' states = []')
320 sorted_states = sorted(automaton.states, key=stateSortKey)
321 for st in sorted_states:
322 st_id = 'st_%u' % (len(state_map),)
323 state_map[st] = st_id
324 if st.subAutomata is not None:
325 au_src.append(' sub_automata = []')
326 for sa in st.subAutomata:
327 au_src.append(' sub_automata.append(%s)' % (_GenerateAutomaton(sa, template_map, st_id, lines, **kw),))
328 if st.finalUpdate is None:
329 au_src.append(' final_update = None')
330 else:
331 au_src.append(' final_update = set()')
332 for ui in sorted(st.finalUpdate, key=updateInstructionSortKey):
333 au_src.append(' final_update.add(fac.UpdateInstruction(%s, %r))' % (counter_map[ui.counterCondition], ui.doIncrement))
334 if isinstance(st.symbol, xs.structures.ModelGroup):
335 au_src.append(' symbol = %r' % (st.symbol._location(),))
336 else:
337 (particle, symbol) = st.symbol
338 if isinstance(symbol, xs.structures.Wildcard):
339 au_src.append(templates.replaceInText(' symbol = pyxb.binding.content.WildcardUse(%{wildcard}, %{location})', wildcard=binding_module.literal(symbol, **kw), location=repr(particle._location())))
340 elif isinstance(symbol, xs.structures.ElementDeclaration):
341 binding_module.importForDeclaration(symbol)
342 au_src.append(templates.replaceInText(' symbol = pyxb.binding.content.ElementUse(%{ctd}._UseForTag(%{field_tag}), %{location})', field_tag=binding_module.literal(symbol.expandedName(), **kw), location=repr(particle._location()), **template_map))
343 au_src.append(' %s = fac.State(symbol, is_initial=%r, final_update=final_update, is_unordered_catenation=%r)' % (st_id, st.isInitial, st.isUnorderedCatenation))
344 if st.subAutomata is not None:
345 au_src.append(' %s._set_subAutomata(*sub_automata)' % (st_id,))
346 au_src.append(' states.append(%s)' % (st_id,))
347 for st in sorted_states:
348 au_src.append(' transitions = []')
349 for xit in sorted(st.transitionSet, key=transitionSortKey):
350 au_src.append(' transitions.append(fac.Transition(%s, [' % (state_map[xit.destination],))
351 sorted_ui = sorted(xit.updateInstructions, key=updateInstructionSortKey)
352 au_src.append(' %s ]))' % (',\n '.join(map(lambda _ui: 'fac.UpdateInstruction(%s, %r)' % (counter_map[_ui.counterCondition], _ui.doIncrement), sorted_ui))))
353 au_src.append(' %s._set_transitionSet(transitions)' % (state_map[st],))
354 au_src.append(' return fac.Automaton(states, counters, %r, containing_state=%s)' % (automaton.nullable, containing_state))
355 lines.extend(au_src)
356 return '%s()' % (name,)
357
369
389
391 binding_module = kw['binding_module']
392 outf = binding_module.bindingIO()
393 facet_instances = []
394 gen_enum_tag = _useEnumerationTags(td)
395 for (fc, fi) in td.facets().items():
396
397
398 if (fi is None) and (fc in td.baseTypeDefinition().facets()):
399
400 continue
401 if (fi is not None) and (fi.ownerTypeDefinition() != td):
402
403 continue
404 argset = { }
405 is_collection = issubclass(fc, facets._CollectionFacet_mixin)
406 if issubclass(fc, facets._LateDatatype_mixin):
407 vdt = td
408 if fc.LateDatatypeBindsSuperclass():
409 vdt = vdt.baseTypeDefinition()
410 argset['value_datatype'] = vdt
411 if fi is not None:
412 if not is_collection:
413 argset['value'] = fi.value()
414 if isinstance(fi, facets.CF_enumeration):
415 argset['enum_prefix'] = fi.enumPrefix()
416 facet_var = ReferenceFacetMember(type_definition=td, facet_class=fc, **kw)
417 outf.write("%s = %s(%s)\n" % binding_module.literal( (facet_var, fc, argset ), **kw))
418 facet_instances.append(binding_module.literal(facet_var, **kw))
419 if (fi is not None) and is_collection:
420 for i in fi.items():
421 if isinstance(i, facets._EnumerationElement):
422 enum_config = '%s.addEnumeration(unicode_value=%s, tag=%s)' % binding_module.literal( ( facet_var, i.unicodeValue(), i.tag() ), **kw)
423 if gen_enum_tag and (i.tag() is not None):
424 enum_member = ReferenceEnumerationMember(type_definition=td, facet_instance=fi, enumeration_element=i, **kw)
425 outf.write("%s = %s\n" % (binding_module.literal(enum_member, **kw), enum_config))
426 if fi.enumPrefix() is not None:
427 outf.write("%s_%s = %s\n" % (fi.enumPrefix(), i.tag(), binding_module.literal(enum_member, **kw)))
428 else:
429 outf.write("%s\n" % (enum_config,))
430 if isinstance(i, facets._PatternElement):
431 outf.write("%s.addPattern(pattern=%s)\n" % binding_module.literal( (facet_var, i.pattern ), **kw))
432 if gen_enum_tag and (xs.structures.SimpleTypeDefinition.VARIETY_union == td.variety()):
433
434
435
436 fi = td.facets().get(facets.CF_enumeration)
437 if fi is None:
438
439 for mtd in td.memberTypeDefinitions():
440 if not _useEnumerationTags(mtd):
441 continue
442 fi = mtd.facets().get(facets.CF_enumeration)
443 if fi is None:
444 continue
445 for i in fi.items():
446 assert isinstance(i, facets._EnumerationElement)
447 etd = i.enumeration().ownerTypeDefinition()
448 enum_member = ReferenceEnumerationMember(type_definition=td, facet_instance=fi, enumeration_element=i, **kw)
449 outf.write("%-50s%s\n" % ('%s = %s' % binding_module.literal( (enum_member, i.unicodeValue()) ),
450 '# originally %s.%s' % (binding_module.literal(etd), i.tag())))
451 if 2 <= len(facet_instances):
452 map_args = ",\n ".join(facet_instances)
453 else:
454 map_args = ','.join(facet_instances)
455 outf.write("%s._InitializeFacetMap(%s)\n" % (binding_module.literal(td, **kw), map_args))
456
458 if vc_source.fixed() is not None:
459 aux_init.append('fixed=True')
460 aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.fixed(), **kw),))
461 elif vc_source.default() is not None:
462 aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.default(), **kw),))
463
465
466 binding_module = generator.moduleForComponent(std)
467 outf = binding_module.bindingIO()
468
469 class_keywords = frozenset(basis.simpleTypeDefinition._ReservedSymbols)
470 class_unique = set()
471
472 kw = { }
473 kw['binding_module'] = binding_module
474 kw['class_keywords'] = class_keywords
475 kw['class_unique'] = class_unique
476
477 parent_classes = [ binding_module.literal(std.baseTypeDefinition(), **kw) ]
478 enum_facet = std.facets().get(facets.CF_enumeration)
479 if (enum_facet is not None) and (enum_facet.ownerTypeDefinition() == std):
480 parent_classes.append('pyxb.binding.basis.enumeration_mixin')
481
482 template_map = { }
483 binding_name = template_map['std'] = binding_module.literal(std, **kw)
484 if (std.expandedName() is not None) and (std.expandedName().localName() != binding_name):
485 _log.warning('Simple type %s renamed to %s', std.expandedName(), binding_name)
486
487 template_map['superclasses'] = ''
488 if 0 < len(parent_classes):
489 template_map['superclasses'] = ', '.join(parent_classes)
490 template_map['expanded_name'] = binding_module.literal(std.expandedName(), **kw)
491 if std.expandedName() is not None:
492 template_map['qname'] = unicode(std.expandedName())
493 else:
494 template_map['qname'] = '[anonymous]'
495 template_map['namespaceReference'] = binding_module.literal(std.bindingNamespace(), **kw)
496 template_map['xsd_location'] = repr(std._location())
497 if std.annotation() is not None:
498 template_map['documentation'] = std.annotation().asDocString()
499 template_map['documentation_expr'] = binding_module.literal(std.annotation().text())
500 else:
501 template_map['documentation'] = ''
502 template_map['documentation_expr'] = binding_module.literal(None)
503
504
505
506 common_template = '''
507 """%{documentation}"""
508
509 _ExpandedName = %{expanded_name}
510 _XSDLocation = %{xsd_location}
511 _Documentation = %{documentation_expr}
512 '''
513 if xs.structures.SimpleTypeDefinition.VARIETY_absent == std.variety():
514 template = '''
515 # The ur simple type: %{qname}
516 class %{std} (%{superclasses}):
517 ''' + common_template
518 if not template_map['documentation']:
519 template_map['documentation'] = 'The ur simple type.'
520 elif xs.structures.SimpleTypeDefinition.VARIETY_atomic == std.variety():
521 template = '''
522 # Atomic simple type: %{qname}
523 class %{std} (%{superclasses}):
524 ''' + common_template
525 if not template_map['documentation']:
526 template_map['documentation'] = 'An atomic simple type.'
527 elif xs.structures.SimpleTypeDefinition.VARIETY_list == std.variety():
528 template = '''
529 # List simple type: %{qname}
530 # superclasses %{superclasses}
531 class %{std} (pyxb.binding.basis.STD_list):
532 ''' + common_template + '''
533 _ItemType = %{itemtype}
534 '''
535 template_map['itemtype'] = binding_module.literal(std.itemTypeDefinition(), **kw)
536 if not template_map['documentation']:
537 template_map['documentation'] = templates.replaceInText('Simple type that is a list of %{itemtype}.', **template_map)
538 elif xs.structures.SimpleTypeDefinition.VARIETY_union == std.variety():
539 template = '''
540 # Union simple type: %{qname}
541 # superclasses %{superclasses}
542 class %{std} (pyxb.binding.basis.STD_union):
543 ''' + common_template + '''
544 _MemberTypes = ( %{membertypes}, )
545 '''
546 template_map['membertypes'] = ", ".join( [ binding_module.literal(_mt, **kw) for _mt in std.memberTypeDefinitions() ])
547 if not template_map['documentation']:
548 template_map['documentation'] = templates.replaceInText('Simple type that is a union of %{membertypes}.', **template_map)
549 else:
550 raise pyxb.LogicError("Unhandled STD variety")
551
552 outf.write(templates.replaceInText(template, **template_map))
553
554 generate_facets = False
555 if generate_facets:
556
557 if std.isBuiltin():
558 GenerateFacets(std, generator, **kw)
559 else:
560 GenerateFacets(std, generator, **kw)
561
562 if std.name() is not None:
563 outf.write(templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{std})\n",
564 localName=binding_module.literal(std.name(), **kw), **template_map))
565
567 template_map = { }
568 template_map['qname'] = unicode(ed.expandedName())
569 template_map['decl_location'] = repr(ed._location())
570 template_map['namespaceReference'] = binding_module.literal(ed.bindingNamespace(), **kw)
571 if (ed.SCOPE_global == ed.scope()):
572 binding_name = template_map['class'] = binding_module.literal(ed, **kw)
573 if ed.expandedName().localName() != binding_name:
574 _log.warning('Element %s renamed to %s', ed.expandedName(), binding_name)
575 template_map['localName'] = binding_module.literal(ed.name(), **kw)
576 template_map['map_update'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('elementBinding', %{localName}, %{class})", **template_map)
577 else:
578 template_map['scope'] = binding_module.literal(ed.scope(), **kw)
579 if ed.annotation() is not None:
580 template_map['documentation'] = binding_module.literal(unicode(ed.annotation()))
581 if ed.abstract():
582 template_map['abstract'] = binding_module.literal(ed.abstract(), **kw)
583 if ed.nillable():
584 template_map['nillable'] = binding_module.literal(ed.nillable(), **kw)
585 if ed.default():
586 template_map['defaultValue'] = binding_module.literal(ed.default(), **kw)
587 template_map['typeDefinition'] = binding_module.literal(ed.typeDefinition(), **kw)
588 if ed.substitutionGroupAffiliation():
589 template_map['substitution_group'] = binding_module.literal(ed.substitutionGroupAffiliation(), **kw)
590 aux_init = []
591 for k in ( 'nillable', 'abstract', 'scope', 'documentation' ):
592 if k in template_map:
593 aux_init.append('%s=%s' % (k, template_map[k]))
594 aux_init.append('location=%s' % (template_map['decl_location'],))
595 _VCAppendAuxInit(ed, aux_init, binding_module, kw)
596 template_map['element_aux_init'] = ''
597 if 0 < len(aux_init):
598 template_map['element_aux_init'] = ', ' + ', '.join(aux_init)
599
600 return template_map
601
602 import pyxb.utils.fac
603 import operator
612 """Construct a L{FAC term tree<pyxb.utils.fac.Node>} for a L{particle<xs.structures.Particle>}.
613
614 This translates the XML schema content model of particles, model
615 groups, element declarations, and wildcards into a tree expressing
616 the corresponding content as a regular expression with numerical
617 constraints.
618
619 @param node: An instance of L{xs.structures.Particle}
620
621 @return: An instance of L{pyxb.utils.fac.Node}
622 """
623
624 def _generateTermTree_visitor (node, entered, arg):
625 """Helper for constructing a L{FAC term tree<pyxb.utils.fac.Node>}.
626
627 This is passed to L{xs.structures.Particle.walkParticleTree}.
628
629 @param node: An instance of L{xs.structures._ParticleTree_mixin}
630
631 @param entered: C{True} entering an interior tree node, C{False}
632 leaving an interior tree node, C{None} at a leaf node.
633
634 @param arg: A list of pairs C{(particle, terms)} where C{particle}
635 is the L{xs.structures.Particle} instance containing a list of
636 L{term trees<pyxb.utils.fac.Node>}.
637 """
638
639 if entered is None:
640 (parent_particle, terms) = arg.peekNodeTermPair()
641 assert isinstance(parent_particle, xs.structures.Particle)
642 assert isinstance(node, (xs.structures.ElementDeclaration, xs.structures.Wildcard))
643 node._setFacStateSortKey(arg.nextSequenceNumber())
644 terms.append(pyxb.utils.fac.Symbol((parent_particle, node)))
645 elif entered:
646 node._setFacStateSortKey(arg.nextSequenceNumber())
647 arg.addNode(node)
648 else:
649 (xnode, terms) = arg.popNodeTermPair()
650 assert xnode == node
651 (parent_particle, siblings) = arg.peekNodeTermPair()
652 if 1 == len(terms):
653 term = terms[0]
654
655
656
657
658
659 if isinstance(node, xs.structures.Particle) and ((1 != node.minOccurs()) or (1 != node.maxOccurs())):
660 term = pyxb.utils.fac.NumericalConstraint(term, node.minOccurs(), node.maxOccurs(), metadata=node)
661 else:
662 assert isinstance(parent_particle, xs.structures.Particle), 'unexpected %s' % (parent_particle,)
663 assert isinstance(node, xs.structures.ModelGroup)
664 if node.C_CHOICE == node.compositor():
665 term = pyxb.utils.fac.Choice(*terms, metadata=node)
666 elif node.C_SEQUENCE == node.compositor():
667 term = pyxb.utils.fac.Sequence(*terms, metadata=node)
668 else:
669
670
671
672
673
674
675 assert node.C_ALL == node.compositor()
676 assert reduce(operator.and_, map(lambda _s: isinstance(_s, pyxb.utils.fac.Node), terms), True)
677 term = pyxb.utils.fac.All(*terms, metadata=node)
678 siblings.append(term)
679
680 class TermTreeArg (object):
681 __sequenceNumber = None
682 __termTreeList = None
683 __nodeTermPairs = None
684 def __init__ (self, node):
685 self.__sequenceNumber = 0
686 self.__termTreeList = []
687 self.__nodeTermPairs = [ (node, self.__termTreeList) ]
688
689 def termTree (self):
690 assert 1 == len(self.__nodeTermPairs)
691 assert 1 == len(self.__termTreeList)
692 return self.__termTreeList[0]
693
694 def peekNodeTermPair (self):
695 return self.__nodeTermPairs[-1]
696
697 def popNodeTermPair (self):
698 return self.__nodeTermPairs.pop()
699
700 def addNode (self, node):
701 self.__nodeTermPairs.append((node, []))
702
703 def nextSequenceNumber (self):
704 rv = self.__sequenceNumber
705 self.__sequenceNumber += 1
706 return rv
707
708 assert isinstance(node, xs.structures.Particle)
709 ttarg = TermTreeArg(node)
710 node.walkParticleTree(_generateTermTree_visitor, ttarg)
711 term_tree = ttarg.termTree()
712 return term_tree
713
715 """Walk a term tree to determine which element declarations may
716 appear multiple times.
717
718 The bindings need to use a list for any Python attribute
719 corresponding to an element declaration that can occur multiple
720 times in the content model. The number of occurrences is
721 determined by the occurrence constraints on parent particles and
722 the compositors of containing model groups. All this information
723 is available in the term tree used for the content model
724 automaton.
725
726 @param term_tree: A L{FAC term tree<pyxb.utils.fac.Node>}
727 representing the content model for a complex data type.
728
729 @return: Plurality data, as a pair C{(singles, multiples)} where
730 C{singles} is a set of base L{element
731 declarations<xs.structures.ElementDeclaration>} that are known to
732 occur at least once and at most once in a region of the content,
733 and C{multiples} is a similar set of declarations that are known
734 to potentially occur more than once."""
735
736 def _ttMergeSets (parent, child):
737 (p1, pm) = parent
738 (c1, cm) = child
739
740
741 pm.update(cm)
742
743
744
745 pm.update(c1.intersection(p1))
746
747
748
749 p1.difference_update(pm)
750 c1.difference_update(pm)
751
752
753
754 p1.symmetric_difference_update(c1)
755
756 def _ttPrePluralityWalk (node, pos, arg):
757
758
759 if isinstance(node, pyxb.utils.fac.MultiTermNode):
760 arg.append([])
761
762 def _ttPostPluralityWalk (node, pos, arg):
763
764 singles = set()
765 multiples = set()
766 combined = (singles, multiples)
767 if isinstance(node, pyxb.utils.fac.MultiTermNode):
768
769 term_list = arg.pop()
770 if isinstance(node, pyxb.utils.fac.Choice):
771
772
773 for (t1, tm) in term_list:
774 multiples.update(tm)
775 singles.update(t1)
776 else:
777
778 assert isinstance(node, (pyxb.utils.fac.Sequence, pyxb.utils.fac.All))
779 for tt in term_list:
780 _ttMergeSets(combined, tt)
781 elif isinstance(node, pyxb.utils.fac.Symbol):
782 (particle, term) = node.metadata
783 if isinstance(term, xs.structures.ElementDeclaration):
784
785 singles.add(term.baseDeclaration())
786 elif isinstance(term, xs.structures.Wildcard):
787 pass
788 else:
789 assert isinstance(term, list)
790
791 for tt in term:
792 _ttMergeSets(combined, BuildPluralityData(tt))
793 else:
794 assert isinstance(node, pyxb.utils.fac.NumericalConstraint)
795
796
797 combined = arg[-1].pop()
798 (singles, multiples) = combined
799 if 0 == node.max:
800
801
802 multiples.clear()
803 singles.clear()
804 elif 1 == node.max:
805
806 pass
807 else:
808
809
810 multiples.update(singles)
811 singles.clear()
812 arg[-1].append(combined)
813
814
815
816 arg = [[]]
817 term_tree.walkTermTree(_ttPrePluralityWalk, _ttPostPluralityWalk, arg)
818
819
820 assert 1 == len(arg)
821 arg = arg[0]
822 assert 1 == len(arg)
823 return arg[0]
824
826 """Helper class holding information need in both preparation and generation."""
827
828 contentBasis = None
829 termTree = None
830 edSingles = None
831 edMultiples = None
832 automaton = None
833 ctd = None
834
846
847 @classmethod
850
851 @classmethod
852 - def Get (cls, ctd):
854
856 binding_module = generator.moduleForComponent(ctd)
857 outf = binding_module.bindingIO()
858
859 prolog_template = None
860 template_map = { }
861 binding_name = template_map['ctd'] = binding_module.literal(ctd, **kw)
862 if (ctd.expandedName() is not None) and (ctd.expandedName().localName() != binding_name):
863 _log.warning('Complex type %s renamed to %s', ctd.expandedName(), binding_name)
864
865 base_type = ctd.baseTypeDefinition()
866 content_type_tag = ctd._contentTypeTag()
867
868 template_map['base_type'] = binding_module.literal(base_type, **kw)
869 template_map['namespaceReference'] = binding_module.literal(ctd.bindingNamespace(), **kw)
870 template_map['expanded_name'] = binding_module.literal(ctd.expandedName(), **kw)
871 if ctd.expandedName() is not None:
872 template_map['qname'] = unicode(ctd.expandedName())
873 else:
874 template_map['qname'] = '[anonymous]'
875 template_map['xsd_location'] = repr(ctd._location())
876 template_map['simple_base_type'] = binding_module.literal(None, **kw)
877 template_map['contentTypeTag'] = content_type_tag
878 template_map['is_abstract'] = repr(not not ctd.abstract())
879
880 content_basis = None
881 if (ctd.CT_SIMPLE == content_type_tag):
882 content_basis = ctd.contentType()[1]
883 template_map['simple_base_type'] = binding_module.literal(content_basis, **kw)
884 elif (ctd.CT_MIXED == content_type_tag):
885 content_basis = ctd.contentType()[1]
886 elif (ctd.CT_ELEMENT_ONLY == content_type_tag):
887 content_basis = ctd.contentType()[1]
888
889 if ctd.annotation() is not None:
890 template_map['documentation'] = ctd.annotation().asDocString()
891 elif isinstance(ctd.owner(), xs.structures.ElementDeclaration) \
892 and ctd.owner().annotation() is not None:
893 template_map['documentation'] = ctd.owner().annotation().asDocString()
894 else:
895 template_map['documentation'] = templates.replaceInText("Complex type %{qname} with content type %{contentTypeTag}", **template_map)
896
897 prolog_template = '''
898 # Complex type %{qname} with content type %{contentTypeTag}
899 class %{ctd} (%{superclass}):
900 """%{documentation}"""
901 _TypeDefinition = %{simple_base_type}
902 _ContentTypeTag = pyxb.binding.basis.complexTypeDefinition._CT_%{contentTypeTag}
903 _Abstract = %{is_abstract}
904 _ExpandedName = %{expanded_name}
905 _XSDLocation = %{xsd_location}
906 '''
907
908
909
910
911 inherits_from_base = True
912 template_map['superclass'] = binding_module.literal(base_type, **kw)
913 if ctd._isHierarchyRoot():
914 inherits_from_base = False
915 template_map['superclass'] = 'pyxb.binding.basis.complexTypeDefinition'
916 assert base_type.nameInBinding() is not None
917
918 if inherits_from_base:
919 prolog_template += ''' _ElementMap = %{superclass}._ElementMap.copy()
920 _AttributeMap = %{superclass}._AttributeMap.copy()
921 '''
922 else:
923 prolog_template += ''' _ElementMap = {}
924 _AttributeMap = {}
925 '''
926
927
928 class_keywords = frozenset(basis.complexTypeDefinition._ReservedSymbols)
929 class_unique = set()
930
931
932
933
934
935
936
937 element_uses = []
938
939 definitions = []
940
941 definitions.append('# Base type is %{base_type}')
942
943
944
945
946
947 if isinstance(content_basis, xs.structures.Particle):
948 plurality_data = {}
949 aux = _CTDAuxData.Get(ctd)
950 elements = aux.edSingles.union(aux.edMultiples)
951
952 outf.postscript().append("\n\n")
953 for ed in sorted(elements, key=lambda _c: _c.schemaOrderSortKey()):
954 is_plural = ed in aux.edMultiples
955
956 ef_map = ed._templateMap()
957 if ed.scope() == ctd:
958 ef_map.update(elementDeclarationMap(ed, binding_module, **kw))
959 aux_init = []
960 ef_map['is_plural'] = repr(is_plural)
961 element_uses.append(templates.replaceInText('%{use}.name() : %{use}', **ef_map))
962 if 0 == len(aux_init):
963 ef_map['aux_init'] = ''
964 else:
965 ef_map['aux_init'] = ', ' + ', '.join(aux_init)
966 ef_map['element_binding'] = utility.PrepareIdentifier('%s_elt' % (ef_map['id'],), class_unique, class_keywords, private=True)
967 if ed.annotation() is not None:
968 ef_map['documentation'] = binding_module.literal(unicode(ed.annotation()))
969 else:
970 ef_map['documentation'] = binding_module.literal(None)
971 if ed.scope() != ctd:
972 definitions.append(templates.replaceInText('''
973 # Element %{id} (%{qname}) inherited from %{decl_type_en}''', decl_type_en=unicode(ed.scope().expandedName()), **ef_map))
974 continue
975
976 binding_module.importForDeclaration(ed);
977 if ed.expandedName().localName() != ef_map['id']:
978 _log.warning('Element use %s.%s renamed to %s', ctd.expandedName(), ed.expandedName(), ef_map['id'])
979 definitions.append(templates.replaceInText('''
980 # Element %{qname} uses Python identifier %{id}
981 %{use} = pyxb.binding.content.ElementDeclaration(%{name_expr}, '%{id}', '%{key}', %{is_plural}, %{decl_location}, %{aux_init})
982 ''', name_expr=binding_module.literal(ed.expandedName(), **kw), **ef_map))
983
984 definitions.append(templates.replaceInText('''
985 %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation})
986 ''', **ef_map))
987 outf.postscript().append(templates.replaceInText('''
988 %{ctd}._AddElement(pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init}))
989 ''', name_expr=binding_module.literal(ed.expandedName(), **kw), ctd=template_map['ctd'], **ef_map))
990
991 auto_defn = GenerateAutomaton(ctd, binding_module=binding_module, **kw)
992 if auto_defn is not None:
993 (automaton_ctor, lines) = auto_defn
994 if lines:
995 outf.postscript().append("\n".join(lines))
996 outf.postscript().append("\n")
997 outf.postscript().append(templates.replaceInText('%{ctd}._Automaton = %{automaton_ctor}\n', ctd=template_map['ctd'], automaton_ctor=automaton_ctor))
998 outf.postscript().append("\n")
999
1000
1001 attribute_uses = []
1002
1003
1004
1005
1006
1007
1008
1009
1010 for au in sorted(ctd.attributeUses(), key=lambda _au: _au.attributeDeclaration().schemaOrderSortKey()):
1011 ad = au.attributeDeclaration()
1012 assert isinstance(ad.scope(), xs.structures.ComplexTypeDefinition), 'unexpected scope %s' % (ad.scope(),)
1013 au_map = ad._templateMap()
1014 if ad.scope() != ctd:
1015 definitions.append(templates.replaceInText('''
1016 # Attribute %{id} inherited from %{decl_type_en}''', decl_type_en=unicode(ad.scope().expandedName()), **au_map))
1017 continue
1018 assert isinstance(au_map, dict)
1019 aur = au;
1020 while aur.restrictionOf() is not None:
1021 aur = aur.restrictionOf()
1022 if au != aur:
1023 au_map = aur.attributeDeclaration()._templateMap().copy()
1024 definitions.append(templates.replaceInText('''
1025 # Attribute %{id} is restricted from parent''', **au_map))
1026
1027 assert ad.typeDefinition() is not None
1028 au_map['attr_type'] = binding_module.literal(ad.typeDefinition(), **kw)
1029 au_map['decl_location'] = repr(ad._location())
1030 au_map['use_location'] = repr(au._location())
1031
1032 vc_source = ad
1033 if au.valueConstraint() is not None:
1034 vc_source = au
1035 aux_init = []
1036 _VCAppendAuxInit(vc_source, aux_init, binding_module, kw)
1037 if au.required():
1038 aux_init.append('required=True')
1039 if au.prohibited():
1040 aux_init.append('prohibited=True')
1041 if 0 == len(aux_init):
1042 au_map['aux_init'] = ''
1043 else:
1044 aux_init.insert(0, '')
1045 au_map['aux_init'] = ', '.join(aux_init)
1046 if ad.annotation() is not None:
1047 au_map['documentation'] = binding_module.literal(unicode(ad.annotation()))
1048 else:
1049 au_map['documentation'] = binding_module.literal(None)
1050
1051 binding_module.importForDeclaration(ad);
1052 attribute_uses.append(templates.replaceInText('%{use}.name() : %{use}', **au_map))
1053 if ad.expandedName().localName() != au_map['id']:
1054 _log.warning('Attribute %s.%s renamed to %s', ctd.expandedName(), ad.expandedName(), au_map['id'])
1055 definitions.append(templates.replaceInText('''
1056 # Attribute %{qname} uses Python identifier %{id}
1057 %{use} = pyxb.binding.content.AttributeUse(%{name_expr}, '%{id}', '%{key}', %{attr_type}%{aux_init})
1058 %{use}._DeclarationLocation = %{decl_location}
1059 %{use}._UseLocation = %{use_location}''', name_expr=binding_module.literal(ad.expandedName(), **kw), **au_map))
1060 definitions.append(templates.replaceInText('''
1061 %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation})
1062 ''', ctd=template_map['ctd'], **au_map))
1063
1064 if ctd.attributeWildcard() is not None:
1065 definitions.append('_AttributeWildcard = %s' % (binding_module.literal(ctd.attributeWildcard(), **kw),))
1066 if ctd.hasWildcardElement():
1067 definitions.append('_HasWildcardElement = True')
1068 template_map['attribute_uses'] = ",\n ".join(attribute_uses)
1069 template_map['element_uses'] = ",\n ".join(element_uses)
1070
1071 template_map['registration'] = ''
1072 if ctd.name() is not None:
1073 template_map['registration'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{ctd})",
1074 localName=binding_module.literal(ctd.name(), **kw), **template_map)
1075
1076 template = ''.join([prolog_template,
1077 " ", "\n ".join(definitions), "\n",
1078 ''' _ElementMap.update({
1079 %{element_uses}
1080 })
1081 _AttributeMap.update({
1082 %{attribute_uses}
1083 })
1084 %{registration}
1085
1086 '''])
1087
1088 outf.write(template, **template_map)
1089
1091
1092 assert ed._scopeIsGlobal()
1093
1094 binding_module = generator.moduleForComponent(ed)
1095 outf = binding_module.bindingIO()
1096
1097 template_map = elementDeclarationMap(ed, binding_module, **kw)
1098 template_map.setdefault('scope', binding_module.literal(None, **kw))
1099 template_map.setdefault('map_update', '')
1100
1101 binding_module.importForDeclaration(ed)
1102 outf.write(templates.replaceInText('''
1103 %{class} = pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init})
1104 %{namespaceReference}.addCategoryObject('elementBinding', %{class}.name().localName(), %{class})
1105 ''', name_expr=binding_module.literal(ed.expandedName(), **kw), **template_map))
1106
1107 if ed.substitutionGroupAffiliation() is not None:
1108 outf.postscript().append(templates.replaceInText('''
1109 %{class}._setSubstitutionGroup(%{substitution_group})
1110 ''', **template_map))
1111
1120
1128
1130 use_map = component._templateMap()
1131 class_unique = nsm.uniqueInClass(container)
1132 assert isinstance(component, xs.structures._ScopedDeclaration_mixin)
1133 unique_name = utility.PrepareIdentifier(component.expandedName().localName(), class_unique)
1134 use_map['id'] = unique_name
1135 use_map['inspector'] = unique_name
1136 use_map['mutator'] = utility.PrepareIdentifier('set' + unique_name[0].upper() + unique_name[1:], class_unique)
1137 use_map['use'] = utility.MakeUnique('__' + unique_name.strip('_'), class_unique)
1138 assert component._scope() == container
1139 assert component.nameInBinding() is None, 'Use %s but binding name %s for %s' % (use_map['use'], component.nameInBinding(), component.expandedName())
1140 component.setNameInBinding(use_map['use'])
1141 key_name = u'%s_%s_%s' % (unicode(nsm.namespace()), container.nameInBinding(), component.expandedName())
1142 use_map['key'] = utility.PrepareIdentifier(key_name, class_unique, private=True)
1143 use_map['qname'] = unicode(component.expandedName())
1144 if isinstance(component, xs.structures.ElementDeclaration) and is_plural:
1145 use_map['appender'] = utility.PrepareIdentifier('add' + unique_name[0].upper() + unique_name[1:], class_unique)
1146 return use_map
1147
1209
1211 __anonSTDIndex = None
1212 __anonCTDIndex = None
1213 __uniqueInModule = None
1214 __uniqueInClass = None
1215 __referencedFromClass = None
1216
1217 _UniqueInModule = set([ 'pyxb', 'sys' ])
1218 """Identifiers that are reserved within a module.
1219
1220 Subclasses extend this with the identifiers they add to the
1221 module. Module-level schema-derived identifiers (such as type
1222 definition and element names) are deconflicted from this set and
1223 from each other."""
1224
1225 _ReferencedFromClass = set([ 'pyxb', 'sys' ])
1226 """Identifiers defined in module that are accessed unqualified from class.
1227
1228 These include standard import module names and globals such as
1229 references to namespaces."""
1230
1231 __ComponentBindingModuleMap = {}
1232
1235 __generator = None
1236
1237 - def __init__ (self, generator, *args, **kw):
1252
1254 assert not isinstance(module, pyxb.namespace.Namespace)
1255 assert isinstance(module, (_ModuleNaming_mixin, pyxb.namespace.archive.ModuleRecord)), 'Unexpected type %s' % (type(module),)
1256 if isinstance(module, NamespaceModule):
1257 if pyxb.namespace.XMLSchema == module.namespace():
1258 return
1259 module = module.moduleRecord()
1260 assert isinstance(module, (pyxb.namespace.archive.ModuleRecord, NamespaceGroupModule))
1261 if not (module in self.__importModulePathMap):
1262 module_path = module.modulePath()
1263 if 'pyxb' == module_path.split('.', 2)[0]:
1264 assert 'pyxb' in self.uniqueInModule()
1265 assert 'pyxb' in self.__referencedFromClass
1266 module_path = None
1267 else:
1268 module_path = utility.PrepareIdentifier('ImportedBinding_' + module_path.replace('.', '_'),
1269 self.uniqueInModule(), protected=True)
1270 self.__referencedFromClass.add(module_path)
1271 self.__importModulePathMap[module] = module_path
1272
1291
1292 __referencedNamespaces = None
1293
1295 return self.__bindingIO
1296
1297 __moduleUID = None
1302
1304 return str(id(self))
1305
1307 """Return a distinct string recorded in the first 4096 bytes of the binding file.
1308
1309 This is used to ensure uniqueness and avoid overwriting data
1310 belonging to a different binding. The return value comprises
1311 the class-specialized L{_bindingTagPrefix_vx} with the
1312 L{moduleUID}.
1313 """
1314 return '%s:%s' % (self._bindingTagPrefix_vx(), self.moduleUID())
1315
1317 raise pyxb.LogicError('Subclass %s does not define _bindingTagPrefix_vx' % (type(self),))
1318
1320 """Return a block of binding text (comment or code) serving as a preface.
1321
1322 Normally this should describe the module contents."""
1323 return self._bindingPreface_vx()
1326
1327 - def moduleContents (self):
1328 template_map = {}
1329 import_paths = set()
1330 aux_imports = []
1331 for (mr, as_path) in self.__importModulePathMap.iteritems():
1332 assert self != mr
1333 if as_path is not None:
1334 aux_imports.append('import %s as %s' % (mr.modulePath(), as_path))
1335 else:
1336 aux_imports.append('import %s' % (mr.modulePath(),))
1337 template_map['aux_imports'] = "\n".join(aux_imports)
1338 template_map['namespace_decls'] = "\n".join(self.__namespaceDeclarations)
1339 template_map['module_uid'] = self.moduleUID()
1340 template_map['generation_uid_expr'] = repr(self.generator().generationUID())
1341 self._finalizeModuleContents_vx(template_map)
1342 return self.__bindingIO.contents()
1343
1356 __modulePath = None
1357
1359 """Python code reference to an object in an imported module"""
1360 if isinstance(module, NamespaceModule):
1361 module = module.moduleRecord()
1362 as_path = self.__importModulePathMap[module]
1363 if as_path is None:
1364 as_path = module.modulePath()
1365 return '%s.%s' % (as_path, name)
1366
1369 __bindingFile = None
1370 __bindingFilePath = None
1371
1374
1377
1378 @classmethod
1382
1383 @classmethod
1386
1387 @classmethod
1391 @classmethod
1394 __RecordModuleMap = { }
1395
1413 return self.__componentNameMap.get(component)
1414
1433
1435
1437 rv = self.__referencedNamespaces.get(namespace)
1438 assert rv is None, 'Module %s already has reference to %s' % (self, namespace)
1439
1440
1441
1442
1443 assert name.startswith('Namespace'), 'unexpected %s naming %s' % (name, namespace)
1444 name = utility.PrepareIdentifier(name, self.__uniqueInModule, **kw)
1445 self.__referencedFromClass.add(name)
1446 if definition is None:
1447 if namespace.isAbsentNamespace():
1448 definition = 'pyxb.namespace.CreateAbsentNamespace()'
1449 else:
1450 definition = 'pyxb.namespace.NamespaceForURI(%s, create_if_missing=True)' % (repr(namespace.uri()),)
1451 self.__namespaceDeclarations.append('%s = %s' % (name, definition))
1452 self.__namespaceDeclarations.append("%s.configureCategories(['typeBinding', 'elementBinding'])" % (name,))
1453 self.__referencedNamespaces[namespace] = name
1454 return name
1455
1457 rv = self.__referencedNamespaces.get(namespace)
1458 if rv is None:
1459 assert not (isinstance(self, NamespaceModule) and (self.namespace() == namespace))
1460 assert namespace.isBuiltinNamespace() or not namespace.isUndeclaredNamespace()
1461 if namespace.isBuiltinNamespace():
1462 rv = namespace.builtinNamespaceRepresentation()
1463 if rv is None:
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473 if namespace.prefix():
1474 nsn = 'Namespace_%s' % (namespace.prefix(),)
1475 else:
1476 nsn = 'Namespace'
1477 nsdef = None
1478 for im in self.__importModulePathMap.keys():
1479 if isinstance(im, pyxb.namespace.archive.ModuleRecord):
1480 if im.namespace() == namespace:
1481 nsdef = self.pathFromImport(im, 'Namespace')
1482 break
1483 elif isinstance(im, NamespaceGroupModule):
1484 pass
1485 else:
1486 assert False, 'unexpected import from type %s %s' % (type(im), im,)
1487
1488
1489
1490 if (nsdef is None) and not (isinstance(self, NamespaceGroupModule) and self.moduleForNamespace(namespace) is not None):
1491 raise pyxb.LogicError('MISSING NSDEF: %s cannot be found for %s in imports' % (namespace, nsn))
1492
1493 rv = self.defineNamespace(namespace, nsn, nsdef, protected=True)
1494 assert 0 < len(self.__namespaceDeclarations)
1495 self.__referencedNamespaces[namespace] = rv
1496 return rv
1497
1528
1530 return self.__bindingIO.literal(*args, **kw)
1531
1533 _log.info('Importing to %s from %s', self, module)
1534 self._importModule(module)
1535 for c in self.__components:
1536 local_name = self.nameInModule(c)
1537 assert local_name is not None
1538 rem_name = module.nameInModule(c)
1539 if rem_name is None:
1540 continue
1541 aux = ''
1542 if local_name != rem_name:
1543 aux = ' as %s' % (local_name,)
1544 self.__bindingIO.write("from %s import %s%s # %s\n" % (module.modulePath(), rem_name, aux, c.expandedName()))
1545
1553
1555 """This class represents a Python module that holds all the
1556 declarations belonging to a specific namespace."""
1557
1560 __namespace = None
1561
1564 __moduleRecord = None
1565
1570 __namespaceGroupModule = None
1571
1572 _UniqueInModule = _ModuleNaming_mixin._UniqueInModule.copy()
1573 _UniqueInModule.update([ 'CreateFromDOM', 'CreateFromDocument' ])
1574
1577 __namespaceGroupHead = None
1578 __namespaceGroup = None
1579
1582 __components = None
1583
1584 @classmethod
1587 __ComponentModuleMap = { }
1588
1591
1593 ns = self.namespace()
1594 rvl = ['# Namespace %s' % (ns,)]
1595 if ns.prefix() is not None:
1596 rvl.append(' [xmlns:%s]' % (ns.prefix(),))
1597 rvl.append('\n')
1598 return ''.join(rvl)
1599
1604
1607
1608 - def __init__ (self, generator, module_record, mr_scc, components=None, **kw):
1622
1631
1632 - def _finalizeModuleContents_vx (self, template_map):
1633 self.bindingIO().prolog().append(self.bindingIO().expand('''
1634 import pyxb
1635 import pyxb.binding
1636 import pyxb.binding.saxer
1637 import StringIO
1638 import pyxb.utils.utility
1639 import pyxb.utils.domutils
1640 import sys
1641
1642 # Unique identifier for bindings created at the same time
1643 _GenerationUID = %{generation_uid_expr}
1644
1645 # Version of PyXB used to generate the bindings
1646 _PyXBVersion = %{pyxb_version}
1647 # Generated bindings are not compatible across PyXB versions
1648 if pyxb.__version__ != _PyXBVersion:
1649 raise pyxb.PyXBVersionError(_PyXBVersion)
1650
1651 # Import bindings for namespaces imported into schema
1652 %{aux_imports}
1653
1654 # NOTE: All namespace declarations are reserved within the binding
1655 %{namespace_decls}
1656
1657 def CreateFromDocument (xml_text, default_namespace=None, location_base=None):
1658 """Parse the given XML and use the document element to create a
1659 Python instance.
1660
1661 @kw default_namespace The L{pyxb.Namespace} instance to use as the
1662 default namespace where there is no default namespace in scope.
1663 If unspecified or C{None}, the namespace of the module containing
1664 this function will be used.
1665
1666 @keyword location_base: An object to be recorded as the base of all
1667 L{pyxb.utils.utility.Location} instances associated with events and
1668 objects handled by the parser. You might pass the URI from which
1669 the document was obtained.
1670 """
1671
1672 if pyxb.XMLStyle_saxer != pyxb._XMLStyle:
1673 dom = pyxb.utils.domutils.StringToDOM(xml_text)
1674 return CreateFromDOM(dom.documentElement)
1675 if default_namespace is None:
1676 default_namespace = Namespace.fallbackNamespace()
1677 saxer = pyxb.binding.saxer.make_parser(fallback_namespace=default_namespace, location_base=location_base)
1678 handler = saxer.getContentHandler()
1679 saxer.parse(StringIO.StringIO(xml_text))
1680 instance = handler.rootObject()
1681 return instance
1682
1683 def CreateFromDOM (node, default_namespace=None):
1684 """Create a Python instance from the given DOM node.
1685 The node tag must correspond to an element declaration in this module.
1686
1687 @deprecated: Forcing use of DOM interface is unnecessary; use L{CreateFromDocument}."""
1688 if default_namespace is None:
1689 default_namespace = Namespace.fallbackNamespace()
1690 return pyxb.binding.basis.element.AnyCreateFromDOM(node, default_namespace)
1691
1692 ''', **template_map))
1693
1694 __components = None
1695 __componentBindingName = None
1696
1705
1708
1710 """This class represents a Python module that holds all the
1711 declarations belonging to a set of namespaces which have
1712 interdependencies."""
1713
1716 __namespaceModules = None
1717
1723
1724 __components = None
1725 __componentBindingName = None
1726 __uniqueInModule = None
1727
1728 __UniqueInGroups = set()
1729
1730 _GroupPrefix = '_group'
1731
1732 - def __init__ (self, generator, namespace_modules, **kw):
1739
1741 kw = { 'moduleType' : 'namespaceGroup' }
1742 return kw
1743
1746
1753
1754 - def _finalizeModuleContents_vx (self, template_map):
1755 self.bindingIO().prolog().append(self.bindingIO().expand('''
1756 import pyxb
1757 import pyxb.binding
1758 import pyxb.utils.utility
1759
1760 # Unique identifier for bindings created at the same time
1761 _GenerationUID = %{generation_uid_expr}
1762
1763 # Import bindings for schemas in group
1764 %{aux_imports}
1765
1766 # NOTE: All namespace declarations are reserved within the binding
1767 %{namespace_decls}
1768 ''', **template_map))
1769
1780
1783
1784
1785 -def GeneratePython (schema_location=None,
1786 schema_text=None,
1787 namespace=None,
1788 module_prefix_elts=[],
1789 **kw):
1800
1801 import optparse
1802 import re
1805 """Configuration and data for a single binding-generation action."""
1806
1807 _DEFAULT_bindingRoot = '.'
1809 """The directory path into which generated bindings will be written.
1810 @rtype: C{str}"""
1811 return self.__bindingRoot
1815 __bindingRoot = None
1816
1818 if isinstance(module_elts, basestring):
1819 module_elts = module_elts.split('.')
1820 else:
1821 module_elts = module_elts[:]
1822 assert 0 < len(module_elts)
1823 if not inhibit_extension:
1824 assert not module_elts[-1].endswith('.py')
1825 module_elts[-1] = '%s.py' % (module_elts[-1],)
1826 return os.path.join(self.bindingRoot(), *module_elts)
1827
1830 __generateToFiles = None
1831
1833
1834
1835
1836
1837 module_path = None
1838 if isinstance(module, NamespaceModule):
1839 mr = module.moduleRecord()
1840 if mr is None:
1841 return ('/dev/null', None, None)
1842 if self.generationUID() != mr.generationUID():
1843 return ('/dev/null', None, None)
1844 if not self.generateToFiles():
1845 return ('/dev/null', None, None)
1846 if mr.namespace().isBuiltinNamespace() and (not self.allowBuiltinGeneration()):
1847 return ('/dev/null', None, None)
1848 module_path = mr.modulePath()
1849 assert module_path is not None, 'No path specified for module %s' % (mr,)
1850
1851
1852
1853 module_elts = module_path.split('.')
1854 if self.writeForCustomization():
1855 import_file_path = self.__moduleFilePath(module_elts)
1856 module_elts.insert(-1, 'raw')
1857 if not os.path.exists(import_file_path):
1858 raw_module_path = '.'.join(module_elts)
1859 pyxb.utils.utility.OpenOrCreate(import_file_path).write("from %s import *\n" % (raw_module_path,))
1860 binding_file_path = self.__moduleFilePath(module_elts)
1861 try:
1862 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID())
1863 except OSError as e:
1864 if errno.EEXIST == e.errno:
1865 raise pyxb.BindingGenerationError('Target file %s for module %s bindings exists with other content' % (binding_file_path, mr))
1866 raise
1867 elif isinstance(module, NamespaceGroupModule):
1868 if not self.generateToFiles():
1869 raise pyxb.BindingGenerationError('Generation of namespace groups requires generate-to-files')
1870 module_elts = []
1871 if self.modulePrefix():
1872 module_elts.extend(self.modulePrefix().split('.'))
1873 if self.writeForCustomization():
1874 module_elts.append('raw')
1875 in_use = set()
1876 while True:
1877 module_elts.append(pyxb.utils.utility.PrepareIdentifier('nsgroup', in_use, protected=True))
1878 try:
1879 binding_file_path = self.__moduleFilePath(module_elts)
1880 _log.info('Attempting group %s uid %s at %s', module, module.moduleUID(), binding_file_path)
1881 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID())
1882 break
1883 except OSError as e:
1884 if errno.EEXIST != e.errno:
1885 raise
1886 module_elts.pop()
1887 module_path = '.'.join(module_elts)
1888 else:
1889 assert False
1890 if self.generateToFiles():
1891 for n in range(len(module_elts)-1):
1892 sub_path = self.__moduleFilePath(module_elts[:1+n], inhibit_extension=True)
1893 init_path = os.path.join(sub_path, '__init__.py')
1894 if not os.path.exists(init_path):
1895 file(init_path, 'w')
1896 return (binding_file_path, binding_file, module_path)
1897
1899 """The directory from which entrypoint schemas specified as
1900 relative file paths will be read."""
1901 return self.__schemaRoot
1903 if not schema_root.endswith(os.sep):
1904 schema_root = schema_root + os.sep
1905 self.__schemaRoot = schema_root
1906 return self
1907 __schemaRoot = None
1908
1910 """Optional string that is stripped from the beginning of
1911 schemaLocation values before loading from them.
1912
1913 This applies only to the values of schemaLocation attributes
1914 in C{import} and C{include} elements. Its purpose is to
1915 convert absolute schema locations into relative ones to allow
1916 offline processing when all schema are available in a local
1917 directory. See C{schemaRoot}.
1918 """
1919 return self.__schemaStrippedPrefix
1923 __schemaStrippedPrefix = None
1924
1926 """Optional map to rewrite schema locations.
1927
1928 This applies only to the values of schemaLocation attributes
1929 in C{import} and C{include} elements. Its purpose is to
1930 convert remote or absolute schema locations into local or
1931 relative ones to allow offline processing when all schema are
1932 available in a local directory. See C{schemaRoot}.
1933 """
1934 return self.__locationPrefixRewriteMap
1940 """Add a rewrite entry for schema locations.
1941
1942 @param prefix : A text prefix that should be removed from
1943 schema location URIs.
1944
1945 @param substituent : The text prefix that should replace
1946 C{prefix} as a prefix in a schema location URI.
1947 """
1948
1949 self.__locationPrefixRewriteMap[prefix] = substituent
1950 return self
1952 """Add a rewrite entry for schema locations.
1953
1954 Parameter values are strings of the form C{pfx=sub}. The
1955 effect is that a schema location that begins with C{pfx} is
1956 rewritten so that it instead begins with C{sub}."""
1957 try:
1958 (prefix, substituent) = prefix_rewrite.split('=', 1)
1959 except:
1960 raise
1961 self.addLocationPrefixRewrite(prefix, substituent)
1962 __locationPrefixMap = {}
1963
1965 """A list of locations from which entrypoint schemas are to be
1966 read.
1967
1968 The values in the list are either URIs, or tuples consisting
1969 of a value and a callable which, when passed the generator
1970 object and the value, will return a
1971 L{pyxb.xmlschema.structures.Schema} instance. See
1972 L{addSchemaLocation}.
1973
1974 See also L{addSchemaLocation} and L{schemas}.
1975 """
1976 return self.__schemaLocationList
1982 """Add the location of an entrypoint schema.
1983
1984 @param schema_location: The location of the schema. This
1985 should be a URL; if the schema location does not have a URL
1986 scheme (e.g., C{http:}), it is assumed to be a file, and if it
1987 is not an absolute path is located relative to the
1988 C{schemaRoot}.
1989
1990 @keyword converter: Optional callable that will be invoked
1991 with the generator instance and the schema location, and is
1992 expected to return a L{pyxb.xmlschema.structures.Schema}
1993 instance. If absent, the contents of the location are
1994 converted directly.
1995
1996 @note: The C{converter} argument derives from WSDL support: we
1997 need to add to the sequence of schema locations a URI of
1998 something that will not parse as a schema, but does have inner
1999 material that can if treated properly. "Treated properly" may
2000 include having the archive path and other namespace
2001 manipulations configured before anything is done to it.
2002 """
2003 self.__schemaLocationList.append( (schema_location, converter) )
2004 return self
2006 """Add the location of an entrypoint schema. The provided
2007 value should be a URL; if it does not have a URL scheme (e.g.,
2008 C{http:}), it is assumed to be a file, and if it is not an
2009 absolute path is located relative to the C{schemaRoot}."""
2010 self.addSchemaLocation(schema_location)
2011 __schemaLocationList = None
2012
2014 """Schema for which bindings should be generated.
2015
2016 These may be L{Schema<pyxb.xmlschema.structures.Schema>}
2017 instances, or strings; the latter is preferred, and is parsed
2018 into a Schema instance when required.
2019
2020 This is the list of entrypoint schemas for binding generation.
2021 Values in L{schemaLocationList} are read and converted into
2022 schema, then appended to this list. Values from L{moduleList}
2023 are applied starting with the first schema in this list.
2024 """
2025 return self.__schemas[:]
2033 __schemas = None
2034
2036 """The set of L{namespaces<pyxb.namespace.Namespace>} for
2037 which bindings will be generated.
2038
2039 This is the set of namespaces read from entrypoint schema,
2040 closed under reference to namespaces defined by schema import.
2041
2042 @rtype: C{set}
2043 """
2044 return self.__namespaces.copy()
2052 __namespaces = None
2053
2055 """A list of module names to be applied in order to the namespaces of entrypoint schemas"""
2056 return self.__moduleList[:]
2061
2063 """Add a module name corresponding to an entrypoint schema.
2064
2065 The namespace defined by the corresponding schema will be
2066 written to a binding using the given module name, adjusted by
2067 L{modulePrefix}."""
2068 self.__moduleList.append(module_name)
2069 return self
2070 __moduleList = None
2071
2073 """The prefix for binding modules.
2074
2075 The base name for the module holding a binding is taken from
2076 the moduleList, moduleMap, or an XMLNS prefix associated with
2077 the namespace in a containing schema. This value, if present,
2078 is used as a prefix to allow a deeper module hierarchy."""
2079 return self.__modulePrefix
2083 __modulePrefix = None
2084
2086 """A map from namespace URIs to the module to be used for the
2087 corresponding generated binding.
2088
2089 Module values are adjusted by L{modulePrefix} if that has been
2090 specified.
2091
2092 An entry in this map for a namespace supersedes the module
2093 specified in moduleList if the namespace is defined by an
2094 entrypoint schema.
2095
2096 @return: A reference to the namespace module map.
2097 """
2098 return self.__namespaceModuleMap
2099 __namespaceModuleMap = None
2100
2102 """A colon-separated list of paths from which namespace
2103 archives can be read.
2104
2105 The default path is the contents of the C{PYXB_ARCHIVE_PATH}
2106 environment variable, or the standard path configured at
2107 installation time. Any file with the extension C{.wxs} found
2108 in one of these directories is examined to see whether it is a
2109 namespace archive.
2110 """
2111 return self.__archivePath
2115 __archivePath = None
2116
2118 """A frozenset of namespaces that many not be loaded from an archive."""
2119 return frozenset(self.__noLoadNamespaces)
2121 """Record the set of namespaces that should not be loaded from an archive.
2122
2123 The expectation is that any required entities in the namespace
2124 will be defined by loading schema."""
2125 self.__noLoadNamespaces.clear()
2126 self.__noLoadNamespaces.update([ pyxb.namespace.NamespaceInstance(_ns) for _ns in namespace_set ])
2128 """Mark that the specified namespace should not be loaded from an archive.
2129
2130 Use this when you are generating bindings for an application
2131 that has a restricted profile of a namespace that would
2132 otherwise be read from an archive. Be aware that this removes
2133 any knowledge of any archive in which this namespace is
2134 present as a non-private member."""
2135 self.__noLoadNamespaces.add(pyxb.namespace.NamespaceInstance(namespace))
2136 __noloadNamespaces = None
2137
2139 """A list of paths to archives that should be loaded, in order, prior to parsing schema."""
2140 return frozenset(self.__preLoadArchives)
2142 """Name of a file containing a stored archive from which
2143 namespaces should be read prior to processing schema.
2144
2145 Files to be pre-loaded are not affected by
2146 C{noLoadNamespace}."""
2147 self.__preLoadArchives.append(archive_file)
2151 __preLoadArchives = None
2152
2154 """Optional file into which the archive of namespaces will be written.
2155
2156 Subsequent generation actions can read pre-parsed namespaces
2157 from this file, and therefore reference the bindings that were
2158 built earlier rather than re-generating them.
2159
2160 The file name should normally end with C{.wxs}."""
2161 return self.__archiveToFile
2165 __archiveToFile = None
2166
2180 """Indicates, for specific namespaces, whether their
2181 visibility in the archive should be public or private."""
2182 return self.__namespaceVisibilityMap.copy()
2183 __namespaceVisibilityMap = None
2184
2186 """Indicates whether unmentioned namespaces will be public or private (default) in the archive.
2187
2188 A namespace is I{mentioned} if it is the target namespace of
2189 an entrypoint schema, or appears in a namespace visibility
2190 specification. I.e., this default applies only to namespaces
2191 that are modified as a result of including some schema, which
2192 is generally a local customization of something.
2193 """
2194 return self.__defaultNamespacePublic
2197 __defaultNamespacePublic = None
2198
2200 """Indicates whether the bindings should validate mutations
2201 against the content model."""
2202 return self.__validateChanges
2206 __validateChanges = None
2207
2209 """Indicates whether the binding Python code should be written into a sub-module for customization.
2210
2211 If enabled, a module C{path.to.namespace} will be written to
2212 the file C{path/to/raw/namespace.py}, so that the file
2213 C{path/to/namespace.py} can import it and override behavior."""
2214 return self.__writeForCustomization
2218 __writeForCustomization = None
2219
2221 """Indicates whether the code generator is permitted to
2222 process namespace for which no module path can be determined.
2223
2224 Use this only when generating bindings that will not be
2225 referenced by other bindings."""
2226 return self.__allowAbsentModule
2230 __allowAbsentModule = None
2231
2233 """Indicates whether bindings will be written for namespaces that are built-in to PyXB.
2234
2235 This must be enabled when building bindings for the XML,
2236 XMLSchema instance, and other built-in namespaces. Normally
2237 generation of these namespaces is inhibited lest it produce
2238 inconsistencies."""
2239 return self.__allowBuiltinGeneration
2243 __allowBuiltinGeneration = None
2244
2246 """The directory path into which any content retrieved by URI will be written.
2247
2248 This serves as a local cache, and to give you an opportunity
2249 to inspect material retrieved from some other system.
2250 @rtype: C{str}"""
2251 return self.__uriContentArchiveDirectory
2254 __uriContentArchiveDirectory = None
2255
2257 """A file provided to L{logging.config.fileConfig} to control log messages.
2258
2259 In the absence of other configuration the Python standard logging infrastructure is used in its
2260 default configuration.
2261
2262 @rtype: C{str}"""
2263 return self.__loggingConfigFile
2266 __loggingConfigFile = None
2267
2269 """Create a configuration to be used for generating bindings.
2270
2271 Arguments are treated as additions to the schema location list
2272 after all keywords have been processed.
2273
2274 @keyword binding_root: Invokes L{setBindingRoot}
2275 @keyword schema_root: Invokes L{setSchemaRoot}
2276 @keyword schema_stripped_prefix: Invokes L{setSchemaStrippedPrefix}
2277 @keyword location_prefix_rewrite_map: Invokes L{setLocationPrefixRewriteMap}
2278 @keyword schema_location_list: Invokes L{setSchemaLocationList}
2279 @keyword module_list: Invokes L{_setModuleList}
2280 @keyword module_prefix: Invokes L{setModulePrefix}
2281 @keyword archive_path: Invokes L{setArchivePath}
2282 @keyword no_load_namespaces: Invokes L{_setNoLoadNamespaces}
2283 @keyword pre_load_archives: Invokes L{_setPreLoadArchives}
2284 @keyword archive_to_file: Invokes L{setArchiveToFile}
2285 @keyword public_namespace: Invokes L{setNamespaceVisibility}
2286 @keyword private_namespace: Invokes L{setNamespaceVisibility}
2287 @keyword default_namespace_public: Invokes L{setDefaultNamespacePublic}
2288 @keyword validate_changes: Invokes L{setValidateChanges}
2289 @keyword namespace_module_map: Initializes L{namespaceModuleMap}
2290 @keyword schemas: Invokes L{setSchemas}
2291 @keyword namespaces: Invokes L{setNamespaces}
2292 @keyword write_for_customization: Invokes L{setWriteForCustomization}
2293 @keyword allow_builtin_generation: Invokes L{setAllowBuiltinGeneration}
2294 @keyword allow_absent_module: Invokes L{setAllowAbsentModule}
2295 @keyword generate_to_files: Sets L{generateToFiles}
2296 @keyword uri_content_archive_directory: Invokes L{setUriContentArchiveDirectory}
2297 @keyword logging_config_file: Invokes L{setLoggingConfigFile}
2298 """
2299 argv = kw.get('argv')
2300 if argv is not None:
2301 kw = {}
2302 self.__bindingRoot = kw.get('binding_root', self._DEFAULT_bindingRoot)
2303 self.__schemaRoot = kw.get('schema_root', '.')
2304 self.__schemaStrippedPrefix = kw.get('schema_stripped_prefix')
2305 self.__locationPrefixRewriteMap = kw.get('location_prefix_rewrite_map', {})
2306 self.__schemas = []
2307 self.__schemaLocationList = kw.get('schema_location_list', [])[:]
2308 self.__moduleList = kw.get('module_list', [])[:]
2309 self.__modulePrefix = kw.get('module_prefix')
2310 self.__archivePath = kw.get('archive_path', pyxb.namespace.archive.GetArchivePath())
2311 self.__noLoadNamespaces = kw.get('no_load_namespaces', set()).copy()
2312 self.__preLoadArchives = kw.get('pre_load_archives', [])[:]
2313 self.__archiveToFile = kw.get('archive_to_file')
2314 self.__namespaceVisibilityMap = {}
2315 self._setNamespaceVisibilities(kw.get('public_namespaces', set()), kw.get('private_namespaces', set()))
2316 self.__defaultNamespacePublic = kw.get('default_namespace_public', False)
2317 self.__validateChanges = kw.get('validate_changes', True)
2318 self.__namespaceModuleMap = kw.get('namespace_module_map', {}).copy()
2319 self.__schemas = kw.get('schemas', [])[:]
2320 self.__namespaces = set(kw.get('namespaces', []))
2321 self.__writeForCustomization = kw.get('write_for_customization', False)
2322 self.__allowBuiltinGeneration = kw.get('allow_builtin_generation', False)
2323 self.__allowAbsentModule = kw.get('allow_absent_module', False)
2324 self.__generateToFiles = kw.get('generate_to_files', True)
2325 self.__uriContentArchiveDirectory = kw.get('uri_content_archive_directory')
2326 self.__loggingConfigFile = kw.get('logging_config_file')
2327
2328 if argv is not None:
2329 self.applyOptionValues(*self.optionParser().parse_args(argv))
2330 [ self.addSchemaLocation(_a) for _a in args ]
2331
2332 self.__generationUID = pyxb.utils.utility.UniqueIdentifier()
2333
2334 pyxb.namespace.XML.validateComponentModel()
2335
2336 __stripSpaces_re = re.compile('\s\s\s+')
2339
2340 __OptionSetters = (
2341 ('binding_root', setBindingRoot),
2342 ('schema_root', setSchemaRoot),
2343 ('schema_stripped_prefix', setSchemaStrippedPrefix),
2344 ('location_prefix_rewrite', argAddLocationPrefixRewrite),
2345 ('schema_location', setSchemaLocationList),
2346 ('module', _setModuleList),
2347 ('module_prefix', setModulePrefix),
2348 ('archive_path', setArchivePath),
2349 ('no_load_namespace', _setNoLoadNamespaces),
2350 ('pre_load_archive', _setPreLoadArchives),
2351 ('archive_to_file', setArchiveToFile),
2352 ('default_namespace_public', setDefaultNamespacePublic),
2353 ('validate_changes', setValidateChanges),
2354 ('write_for_customization', setWriteForCustomization),
2355 ('allow_builtin_generation', setAllowBuiltinGeneration),
2356 ('allow_absent_module', setAllowAbsentModule),
2357 ('uri_content_archive_directory', setUriContentArchiveDirectory),
2358 ('logging_config_file', setLoggingConfigFile)
2359 )
2373
2375 if argv is None:
2376 argv = sys.argv[1:]
2377 (options, args) = self.optionParser().parse_args(argv)
2378 self.applyOptionValues(options, args)
2379 return self
2380
2382 """A unique identifier associated with this Generator instance.
2383
2384 This is an instance of L{pyxb.utils.utility.UniqueIdentifier}.
2385 Its associated objects are
2386 L{pyxb.namespace.archive._SchemaOrigin} instances, which
2387 identify schema that contribute to the definition of a
2388 namespace."""
2389 return self.__generationUID
2390 __generationUID = None
2391
2393 """Return an C{optparse.OptionParser} instance tied to this configuration.
2394
2395 @param reset: If C{False} (default), a parser created in a
2396 previous invocation will be returned. If C{True}, any
2397 previous option parser is discarded and a new one created.
2398 @type reset: C{bool}
2399 """
2400 if reset or (self.__optionParser is None):
2401 parser = optparse.OptionParser(usage="%prog [options] [more schema locations...]",
2402 version='%%prog from PyXB %s' % (pyxb.__version__,),
2403 description='Generate bindings from a set of XML schemas')
2404
2405 group = optparse.OptionGroup(parser, 'Identifying Schema', 'Specify and locate schema for which bindings should be generated.')
2406 group.add_option('--schema-location', '-u', metavar="FILE_or_URL",
2407 action='append',
2408 help=self.__stripSpaces(self.argAddSchemaLocation.__doc__))
2409 group.add_option('--schema-root', metavar="DIRECTORY",
2410 help=self.__stripSpaces(self.schemaRoot.__doc__))
2411 group.add_option('--schema-stripped-prefix', metavar="TEXT", type='string',
2412 help=self.__stripSpaces(self.schemaStrippedPrefix.__doc__))
2413 group.add_option('--location-prefix-rewrite', metavar="TEXT", type='string',
2414 help=self.__stripSpaces(self.argAddLocationPrefixRewrite.__doc__))
2415 group.add_option('--uri-content-archive-directory', metavar="DIRECTORY",
2416 help=self.__stripSpaces(self.uriContentArchiveDirectory.__doc__))
2417 parser.add_option_group(group)
2418
2419 group = optparse.OptionGroup(parser, 'Configuring Bindings', 'Specify where generated bindings should be written, and how they will be accessed from Python.')
2420 group.add_option('--module', '-m', metavar="MODULE",
2421 action='append',
2422 help=self.__stripSpaces(self.addModuleName.__doc__))
2423 group.add_option('--module-prefix', metavar="MODULE",
2424 help=self.__stripSpaces(self.modulePrefix.__doc__))
2425 group.add_option('--binding-root', metavar="DIRECTORY",
2426 help=self.__stripSpaces(self.bindingRoot.__doc__))
2427 group.add_option('-r', '--write-for-customization',
2428 action='store_true', dest='write_for_customization',
2429 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns on the feature.'))
2430 group.add_option('--no-write-for-customization',
2431 action='store_false', dest='write_for_customization',
2432 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns off the feature (I{default}).'))
2433 parser.add_option_group(group)
2434
2435 group = optparse.OptionGroup(parser, 'Reading Namespace Archives', 'Locating and loading (or inhibiting load of) namespace archives.')
2436 group.add_option('--archive-path', metavar="PATH",
2437 help=self.__stripSpaces(self.archivePath.__doc__))
2438 group.add_option('--pre-load-archive', metavar="FILE",
2439 action='append',
2440 help=self.__stripSpaces(self.addPreLoadArchive.__doc__))
2441 group.add_option('--no-load-namespace', metavar="URI",
2442 action='append',
2443 help=self.__stripSpaces(self.addNoLoadNamespace.__doc__))
2444 parser.add_option_group(group)
2445
2446 group = optparse.OptionGroup(parser, 'Writing Namespace Archives', 'Control the location and content of a namespace archive corresponding to a binding generation.')
2447 group.add_option('--archive-to-file', metavar="FILE",
2448 help=self.__stripSpaces(self.archiveToFile.__doc__))
2449 group.add_option('--public-namespace', metavar="URI",
2450 action='append',
2451 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a public archive member.'))
2452 group.add_option('--private-namespace', metavar="URI",
2453 action='append',
2454 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a private archive member.'))
2455 group.add_option('--default-namespace-public',
2456 action="store_true", dest='default_namespace_public',
2457 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{public} (I{default}).'))
2458 group.add_option('--default-namespace-private',
2459 action="store_false", dest='default_namespace_public',
2460 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{private}.'))
2461 parser.add_option_group(group)
2462
2463 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.")
2464 group.add_option('--validate-changes',
2465 action='store_true', dest='validate_changes',
2466 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns on validation (default).'))
2467 group.add_option('--no-validate-changes',
2468 action='store_false', dest='validate_changes',
2469 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns off validation.'))
2470 parser.add_option_group(group)
2471
2472 group = optparse.OptionGroup(parser, 'Miscellaneous Options', "Anything else.")
2473 group.add_option('--logging-config-file', metavar="FILE",
2474 help=self.__stripSpaces(self.loggingConfigFile.__doc__))
2475 parser.add_option_group(group)
2476
2477 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.")
2478
2479 group.add_option('--allow-absent-module',
2480 action='store_true', dest='allow_absent_module',
2481 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns on the feature.'))
2482 group.add_option('--no-allow-absent-module',
2483 action='store_false', dest='allow_absent_module',
2484 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns off the feature (default).'))
2485 group.add_option('--allow-builtin-generation',
2486 action='store_true', dest='allow_builtin_generation',
2487 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns on the feature.'))
2488 group.add_option('--no-allow-builtin-generation',
2489 action='store_false', dest='allow_builtin_generation',
2490 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns off the feature (default).'))
2491 parser.add_option_group(group)
2492
2493 self.__optionParser = parser
2494 return self.__optionParser
2495 __optionParser = None
2496
2498 """Return a command line option sequence that could be used to
2499 construct an equivalent configuration.
2500
2501 @note: If you extend the option parser, as is done by
2502 C{pyxbgen}, this may not be able to reconstruct the correct
2503 command line."""
2504 opts = []
2505 module_list = self.moduleList()
2506 schema_list = self.schemaLocationList()
2507 while module_list and schema_list:
2508 ml = module_list.pop(0)
2509 sl = schema_list.pop(0)
2510 if isinstance(sl, tuple):
2511 sl = sl[0]
2512 opts.extend(['--schema-location=' + sl, '--module=' + ml])
2513 for sl in schema_list:
2514 opts.append('--schema-location=' + sl)
2515 if self.schemaRoot() is not None:
2516 opts.append('--schema-root=' + self.schemaRoot())
2517 if self.schemaStrippedPrefix() is not None:
2518 opts.append('--schema-stripped-prefix=%s' + self.schemaStrippedPrefix())
2519 for (pfx, sub) in self.locationPrefixRewriteMap():
2520 opts.append('--location-prefix-rewrite=%s=%s' % (pfx, sub))
2521 if self.modulePrefix() is not None:
2522 opts.append('--module-prefix=' + self.modulePrefix())
2523 opts.append('--binding-root=' + self.bindingRoot())
2524 if self.archivePath() is not None:
2525 opts.append('--archive-path=' + self.archivePath())
2526 for ns in self.noLoadNamespaces():
2527 opts.append('--no-load-namespace=' + ns.uri())
2528 for fps in self.preLoadArchives():
2529 opts.append('--pre-load-archive=' + fps)
2530 if self.archiveToFile() is not None:
2531 opts.append('--archive-to-file=' + self.archiveToFile())
2532 for (ns, visibility) in self.namespaceVisibilityMap():
2533 if visibility:
2534 opts.append('--public-namespace=' + ns.uri())
2535 else:
2536 opts.append('--private-namespace=' + ns.uri())
2537 if self.defaultNamespacePublic():
2538 opts.append('--default-namespace-public')
2539 else:
2540 opts.append('--default-namespace-private')
2541 for (val, opt) in ( (self.validateChanges(), 'validate-changes'),
2542 (self.writeForCustomization(), 'write-for-customization'),
2543 (self.allowAbsentModule(), 'allow-absent-module'),
2544 (self.allowBuiltinGeneration(), 'allow-builtin-generation') ):
2545 if val:
2546 opts.append('--' + opt)
2547 else:
2548 opts.append('--no-' + opt)
2549 if self.uriContentArchiveDirectory() is not None:
2550 opts.append('--uri-content-archive-directory=%s' + self.uriContentArchiveDirectory())
2551 return opts
2552
2558
2560 """Provide a Python module path for the module record.
2561
2562 This is the path by which the module bindings associated with
2563 C{module_record} will be imported.
2564
2565 If a path had already been assigned to the module, it is left
2566 in place.
2567
2568 @param module_record: Information about a collection of related bindings
2569 @type module_record: L{pyxb.namespace.archive.ModuleRecord}
2570
2571 @param module_path: Default path to use
2572 @type module_path: C{str}
2573
2574 @return: C{module_record}
2575 """
2576 if module_record.modulePath() is not None:
2577 return module_record
2578 namespace = module_record.namespace()
2579 if not namespace.isAbsentNamespace():
2580
2581 if (module_path is None) and not (namespace.prefix() is None):
2582 module_path = namespace.prefix()
2583
2584 module_path = self.namespaceModuleMap().get(namespace.uri(), module_path)
2585 if (module_path is not None) and self.modulePrefix():
2586
2587 module_path = '.'.join([self.modulePrefix(), module_path])
2588 module_record.setModulePath(module_path)
2589 return module_record
2590
2591 __didResolveExternalSchema = False
2593 if self.__didResolveExternalSchema and (not reset):
2594 raise pyxb.PyXBException('Cannot resolve external schema multiple times')
2595
2596
2597
2598
2599 required_archives = pyxb.namespace.archive.NamespaceArchive.PreLoadArchives(self.archivePath(), self.preLoadArchives())
2600 for nsa in required_archives:
2601 nsa.readNamespaces()
2602
2603
2604
2605
2606 for ns in self.noLoadNamespaces():
2607 assert isinstance(ns, pyxb.namespace.Namespace)
2608 ns.markNotLoadable()
2609
2610
2611 while self.__schemaLocationList:
2612 sl = self.__schemaLocationList.pop(0)
2613 if isinstance(sl, tuple):
2614 (sl, converter) = sl
2615 else:
2616 converter = None
2617 try:
2618 if converter is None:
2619 schema = xs.schema.CreateFromLocation(absolute_schema_location=self.normalizeSchemaLocation(sl),
2620 generation_uid=self.generationUID(),
2621 uri_content_archive_directory=self.uriContentArchiveDirectory())
2622 else:
2623 schema = converter(self, sl)
2624 self.addSchema(schema)
2625 except pyxb.SchemaUniquenessError as e:
2626 _log.info('Skipped redundant translation of %s defining %s', e.schemaLocation(), e.namespace())
2627 self.addSchema(e.existingSchema())
2628
2629
2630
2631 for schema in self.__schemas:
2632 if isinstance(schema, basestring):
2633 schema = xs.schema.CreateFromDocument(schema, generation_uid=self.generationUID())
2634 origin = schema.originRecord()
2635 assert origin is not None
2636 module_path = None
2637 if self.__moduleList:
2638 module_path = self.__moduleList.pop(0)
2639 self.assignModulePath(origin.moduleRecord(), module_path)
2640 assert schema.targetNamespace() == origin.moduleRecord().namespace()
2641 self.addNamespace(schema.targetNamespace())
2642 self.__didResolveExternalSchema = True
2643
2644
2645 self.__componentGraph = None
2646 self.__componentOrder = None
2647
2671
2718
2719 __moduleRecords = None
2720 __componentGraph = None
2721 __componentOrder = None
2722
2724 """The set of L{pyxb.namespace.archive.ModuleRecord} instances
2725 associated with schema processed in this generation
2726 instance.
2727
2728 These should be in one-to-one correspondence with the
2729 namespaces for which bindings are being generated. Multiple
2730 input schemas may contribute to a single module record; all
2731 material in that record is placed in a single binding file.
2732 """
2733 if self.__moduleRecords is None:
2734 self.__resolveComponentDependencies()
2735 return self.__moduleRecords
2736
2741
2746
2748
2749
2750
2751
2752
2753 module_graph = pyxb.utils.utility.Graph()
2754 [ module_graph.addRoot(_mr) for _mr in self.moduleRecords() ]
2755 for (s, t) in self.componentGraph().edges():
2756 module_graph.addEdge(s._objectOrigin().moduleRecord(), t._objectOrigin().moduleRecord())
2757 module_scc_order = module_graph.sccOrder()
2758
2759 record_binding_map = {}
2760 modules = []
2761 nsvm = self.namespaceVisibilityMap()
2762 for mr_scc in module_scc_order:
2763 scc_modules = [ ]
2764 for mr in mr_scc:
2765 mr._setIsPublic(nsvm.get(mr.namespace(), self.defaultNamespacePublic()))
2766 self.assignModulePath(mr)
2767 if (mr.modulePath() is None) and self.generateToFiles():
2768 raise pyxb.BindingGenerationError('No prefix or module name available for %s' % (mr,))
2769 if (not mr.isPublic()) and (mr.modulePath() is not None):
2770 elts = mr.modulePath().split('.')
2771 elts[-1] = '_%s' % (elts[-1],)
2772 mr.setModulePath('.'.join(elts))
2773 nsm = NamespaceModule(self, mr, mr_scc)
2774 record_binding_map[mr] = nsm
2775 scc_modules.append(nsm)
2776
2777 scc_modules.sort(key=lambda _nm: _nm.namespace().uri())
2778 modules.extend(scc_modules)
2779 if 1 < len(mr_scc):
2780 ngm = NamespaceGroupModule(self, scc_modules)
2781 modules.append(ngm)
2782 for nsm in scc_modules:
2783 nsm.setNamespaceGroupModule(ngm)
2784
2785 element_declarations = []
2786 type_definitions = []
2787 for c in self.componentOrder():
2788 if isinstance(c, xs.structures.ElementDeclaration) and c._scopeIsGlobal():
2789
2790 nsm = record_binding_map[c._objectOrigin().moduleRecord()]
2791 nsm.bindComponent(c)
2792 element_declarations.append(c)
2793 elif c.isTypeDefinition():
2794 type_definitions.append(c)
2795 else:
2796
2797 pass
2798
2799 simple_type_definitions = []
2800 complex_type_definitions = []
2801 for td in type_definitions:
2802 nsm = record_binding_map[td._objectOrigin().moduleRecord()]
2803 assert nsm is not None, 'No namespace module for %s type %s scope %s namespace %s' % (td.expandedName(), type(td), td._scope(), td.bindingNamespace)
2804 module_context = nsm.bindComponent(td)
2805 assert isinstance(module_context, _ModuleNaming_mixin), 'Unexpected type %s' % (type(module_context),)
2806 if isinstance(td, xs.structures.SimpleTypeDefinition):
2807 _PrepareSimpleTypeDefinition(td, self, nsm, module_context)
2808 simple_type_definitions.append(td)
2809 elif isinstance(td, xs.structures.ComplexTypeDefinition):
2810 _PrepareComplexTypeDefinition(td, self, nsm, module_context)
2811 complex_type_definitions.append(td)
2812 else:
2813 assert False, 'Unexpected component type %s' % (type(td),)
2814
2815 for ngm in modules:
2816 if isinstance(ngm, NamespaceGroupModule):
2817 for m in ngm.namespaceModules():
2818 m.addImportsFrom(ngm)
2819
2820 for std in simple_type_definitions:
2821 GenerateSTD(std, self)
2822 for ctd in complex_type_definitions:
2823 GenerateCTD(ctd, self)
2824 for ed in element_declarations:
2825 GenerateED(ed, self)
2826
2827 self.__bindingModules = modules
2828
2829 __bindingModules = None
2836
2852
2855