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.bindingSortKey()
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
304
305
306 assert st is not None, 'Transition with no consuming symbol: is All Group Limited satisfied?'
307 keys = [ stateSortKey(st) ]
308 keys.extend(map(updateInstructionSortKey, sorted(xit.updateInstructions, key=updateInstructionSortKey)))
309 return tuple(keys)
310
311 au_src.append(' counters = set()')
312 counter_map = {}
313 sorted_counter_conditions = sorted(automaton.counterConditions, key=counterConditionSortKey)
314 for cc in sorted_counter_conditions:
315 cc_id = 'cc_%u' % (len(counter_map),)
316 counter_map[cc] = cc_id
317 au_src.append(' %s = fac.CounterCondition(min=%r, max=%r, metadata=%r)' % (cc_id, cc.min, cc.max, cc.metadata._location()))
318 au_src.append(' counters.add(%s)' % (cc_id,))
319 state_map = {}
320 au_src.append(' states = []')
321 sorted_states = sorted(automaton.states, key=stateSortKey)
322 for st in sorted_states:
323 st_id = 'st_%u' % (len(state_map),)
324 state_map[st] = st_id
325 if st.subAutomata is not None:
326 au_src.append(' sub_automata = []')
327 for sa in st.subAutomata:
328 au_src.append(' sub_automata.append(%s)' % (_GenerateAutomaton(sa, template_map, st_id, lines, **kw),))
329 if st.finalUpdate is None:
330 au_src.append(' final_update = None')
331 else:
332 au_src.append(' final_update = set()')
333 for ui in sorted(st.finalUpdate, key=updateInstructionSortKey):
334 au_src.append(' final_update.add(fac.UpdateInstruction(%s, %r))' % (counter_map[ui.counterCondition], ui.doIncrement))
335 if isinstance(st.symbol, xs.structures.ModelGroup):
336 au_src.append(' symbol = %r' % (st.symbol._location(),))
337 else:
338 (particle, symbol) = st.symbol
339 if isinstance(symbol, xs.structures.Wildcard):
340 au_src.append(templates.replaceInText(' symbol = pyxb.binding.content.WildcardUse(%{wildcard}, %{location})', wildcard=binding_module.literal(symbol, **kw), location=repr(particle._location())))
341 elif isinstance(symbol, xs.structures.ElementDeclaration):
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
459 binding_module = generator.moduleForComponent(std)
460 outf = binding_module.bindingIO()
461
462 class_keywords = frozenset(basis.simpleTypeDefinition._ReservedSymbols)
463 class_unique = set()
464
465 kw = { }
466 kw['binding_module'] = binding_module
467 kw['class_keywords'] = class_keywords
468 kw['class_unique'] = class_unique
469
470 parent_classes = [ binding_module.literal(std.baseTypeDefinition(), **kw) ]
471 enum_facet = std.facets().get(facets.CF_enumeration)
472 if (enum_facet is not None) and (enum_facet.ownerTypeDefinition() == std):
473 parent_classes.append('pyxb.binding.basis.enumeration_mixin')
474
475 template_map = { }
476 binding_name = template_map['std'] = binding_module.literal(std, **kw)
477 if (std.expandedName() is not None) and (std.expandedName().localName() != binding_name):
478 _log.warning('Simple type %s renamed to %s', std.expandedName(), binding_name)
479
480 template_map['superclasses'] = ''
481 if 0 < len(parent_classes):
482 template_map['superclasses'] = ', '.join(parent_classes)
483 template_map['expanded_name'] = binding_module.literal(std.expandedName(), **kw)
484 if std.expandedName() is not None:
485 template_map['qname'] = unicode(std.expandedName())
486 else:
487 template_map['qname'] = '[anonymous]'
488 template_map['namespaceReference'] = binding_module.literal(std.bindingNamespace(), **kw)
489 template_map['xsd_location'] = repr(std._location())
490 if std.annotation() is not None:
491 template_map['documentation'] = std.annotation().asDocString()
492 template_map['documentation_expr'] = binding_module.literal(std.annotation().text())
493 else:
494 template_map['documentation'] = ''
495 template_map['documentation_expr'] = binding_module.literal(None)
496
497
498
499 common_template = '''
500 """%{documentation}"""
501
502 _ExpandedName = %{expanded_name}
503 _XSDLocation = %{xsd_location}
504 _Documentation = %{documentation_expr}
505 '''
506 if xs.structures.SimpleTypeDefinition.VARIETY_absent == std.variety():
507 template = '''
508 # The ur simple type: %{qname}
509 class %{std} (%{superclasses}):
510 ''' + common_template
511 if not template_map['documentation']:
512 template_map['documentation'] = 'The ur simple type.'
513 elif xs.structures.SimpleTypeDefinition.VARIETY_atomic == std.variety():
514 template = '''
515 # Atomic simple type: %{qname}
516 class %{std} (%{superclasses}):
517 ''' + common_template
518 if not template_map['documentation']:
519 template_map['documentation'] = 'An atomic simple type.'
520 elif xs.structures.SimpleTypeDefinition.VARIETY_list == std.variety():
521 template = '''
522 # List simple type: %{qname}
523 # superclasses %{superclasses}
524 class %{std} (pyxb.binding.basis.STD_list):
525 ''' + common_template + '''
526 _ItemType = %{itemtype}
527 '''
528 template_map['itemtype'] = binding_module.literal(std.itemTypeDefinition(), **kw)
529 if not template_map['documentation']:
530 template_map['documentation'] = templates.replaceInText('Simple type that is a list of %{itemtype}.', **template_map)
531 elif xs.structures.SimpleTypeDefinition.VARIETY_union == std.variety():
532 template = '''
533 # Union simple type: %{qname}
534 # superclasses %{superclasses}
535 class %{std} (pyxb.binding.basis.STD_union):
536 ''' + common_template + '''
537 _MemberTypes = ( %{membertypes}, )
538 '''
539 template_map['membertypes'] = ", ".join( [ binding_module.literal(_mt, **kw) for _mt in std.memberTypeDefinitions() ])
540 if not template_map['documentation']:
541 template_map['documentation'] = templates.replaceInText('Simple type that is a union of %{membertypes}.', **template_map)
542 else:
543 raise pyxb.LogicError("Unhandled STD variety")
544
545 outf.write(templates.replaceInText(template, **template_map))
546
547 generate_facets = False
548 if generate_facets:
549
550 if std.isBuiltin():
551 GenerateFacets(std, generator, **kw)
552 else:
553 GenerateFacets(std, generator, **kw)
554
555 if std.name() is not None:
556 outf.write(templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{std})\n",
557 localName=binding_module.literal(std.name(), **kw), **template_map))
558
560 template_map = { }
561 template_map['qname'] = unicode(ed.expandedName())
562 template_map['decl_location'] = repr(ed._location())
563 template_map['namespaceReference'] = binding_module.literal(ed.bindingNamespace(), **kw)
564 if (ed.SCOPE_global == ed.scope()):
565 binding_name = template_map['class'] = binding_module.literal(ed, **kw)
566 if ed.expandedName().localName() != binding_name:
567 _log.warning('Element %s renamed to %s', ed.expandedName(), binding_name)
568 template_map['localName'] = binding_module.literal(ed.name(), **kw)
569 template_map['map_update'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('elementBinding', %{localName}, %{class})", **template_map)
570 else:
571 template_map['scope'] = binding_module.literal(ed.scope(), **kw)
572 if ed.annotation() is not None:
573 template_map['documentation'] = binding_module.literal(unicode(ed.annotation()))
574 if ed.abstract():
575 template_map['abstract'] = binding_module.literal(ed.abstract(), **kw)
576 if ed.nillable():
577 template_map['nillable'] = binding_module.literal(ed.nillable(), **kw)
578 if ed.default():
579 template_map['defaultValue'] = binding_module.literal(ed.default(), **kw)
580 template_map['typeDefinition'] = binding_module.literal(ed.typeDefinition(), **kw)
581 if ed.substitutionGroupAffiliation():
582 template_map['substitution_group'] = binding_module.literal(ed.substitutionGroupAffiliation(), **kw)
583 aux_init = []
584 for k in ( 'nillable', 'abstract', 'scope', 'documentation' ):
585 if k in template_map:
586 aux_init.append('%s=%s' % (k, template_map[k]))
587 aux_init.append('location=%s' % (template_map['decl_location'],))
588 template_map['element_aux_init'] = ''
589 if 0 < len(aux_init):
590 template_map['element_aux_init'] = ', ' + ', '.join(aux_init)
591
592 return template_map
593
594 import pyxb.utils.fac
595 import operator
604 """Construct a L{FAC term tree<pyxb.utils.fac.Node>} for a L{particle<xs.structures.Particle>}.
605
606 This translates the XML schema content model of particles, model
607 groups, element declarations, and wildcards into a tree expressing
608 the corresponding content as a regular expression with numerical
609 constraints.
610
611 @param node: An instance of L{xs.structures.Particle}
612
613 @return: An instance of L{pyxb.utils.fac.Node}
614 """
615
616 def _generateTermTree_visitor (node, entered, arg):
617 """Helper for constructing a L{FAC term tree<pyxb.utils.fac.Node>}.
618
619 This is passed to L{xs.structures.Particle.walkParticleTree}.
620
621 @param node: An instance of L{xs.structures._ParticleTree_mixin}
622
623 @param entered: C{True} entering an interior tree node, C{False}
624 leaving an interior tree node, C{None} at a leaf node.
625
626 @param arg: A list of pairs C{(particle, terms)} where C{particle}
627 is the L{xs.structures.Particle} instance containing a list of
628 L{term trees<pyxb.utils.fac.Node>}.
629 """
630
631 if entered is None:
632 (parent_particle, terms) = arg[-1]
633 assert isinstance(parent_particle, xs.structures.Particle)
634 assert isinstance(node, (xs.structures.ElementDeclaration, xs.structures.Wildcard))
635 terms.append(pyxb.utils.fac.Symbol((parent_particle, node)))
636 elif entered:
637 arg.append((node, []))
638 else:
639 (xnode, terms) = arg.pop()
640 assert xnode == node
641 (parent_particle, siblings) = arg[-1]
642 if 1 == len(terms):
643 term = terms[0]
644
645
646
647
648
649 if isinstance(node, xs.structures.Particle) and ((1 != node.minOccurs()) or (1 != node.maxOccurs())):
650 term = pyxb.utils.fac.NumericalConstraint(term, node.minOccurs(), node.maxOccurs(), metadata=node)
651 else:
652 assert isinstance(parent_particle, xs.structures.Particle), 'unexpected %s' % (parent_particle,)
653 assert isinstance(node, xs.structures.ModelGroup)
654 if node.C_CHOICE == node.compositor():
655 term = pyxb.utils.fac.Choice(*terms, metadata=node)
656 elif node.C_SEQUENCE == node.compositor():
657 term = pyxb.utils.fac.Sequence(*terms, metadata=node)
658 else:
659
660
661
662
663
664
665 assert node.C_ALL == node.compositor()
666 assert reduce(operator.and_, map(lambda _s: isinstance(_s, pyxb.utils.fac.Node), terms), True)
667 term = pyxb.utils.fac.All(*terms, metadata=node)
668 siblings.append(term)
669
670 assert isinstance(node, xs.structures.Particle)
671 parent_particles = [node]
672 ttlist = []
673 ttarg = [ (node, ttlist) ]
674 node.walkParticleTree(_generateTermTree_visitor, ttarg)
675 assert 1 == len(ttarg)
676 assert 1 == len(ttlist)
677 term_tree = ttlist[0]
678 return term_tree
679
681 """Walk a term tree to determine which element declarations may
682 appear multiple times.
683
684 The bindings need to use a list for any Python attribute
685 corresponding to an element declaration that can occur multiple
686 times in the content model. The number of occurrences is
687 determined by the occurrence constraints on parent particles and
688 the compositors of containing model groups. All this information
689 is available in the term tree used for the content model
690 automaton.
691
692 @param term_tree: A L{FAC term tree<pyxb.utils.fac.Node>}
693 representing the content model for a complex data type.
694
695 @return: Plurality data, as a pair C{(singles, multiples)} where
696 C{singles} is a set of base L{element
697 declarations<xs.structures.ElementDeclaration>} that are known to
698 occur at least once and at most once in a region of the content,
699 and C{multiples} is a similar set of declarations that are known
700 to potentially occur more than once."""
701
702 def _ttMergeSets (parent, child):
703 (p1, pm) = parent
704 (c1, cm) = child
705
706
707 pm.update(cm)
708
709
710
711 pm.update(c1.intersection(p1))
712
713
714
715 p1.difference_update(pm)
716 c1.difference_update(pm)
717
718
719
720 p1.symmetric_difference_update(c1)
721
722 def _ttPrePluralityWalk (node, pos, arg):
723
724
725 if isinstance(node, pyxb.utils.fac.MultiTermNode):
726 arg.append([])
727
728 def _ttPostPluralityWalk (node, pos, arg):
729
730 singles = set()
731 multiples = set()
732 combined = (singles, multiples)
733 if isinstance(node, pyxb.utils.fac.MultiTermNode):
734
735 term_list = arg.pop()
736 if isinstance(node, pyxb.utils.fac.Choice):
737
738
739 for (t1, tm) in term_list:
740 multiples.update(tm)
741 singles.update(t1)
742 else:
743
744 assert isinstance(node, (pyxb.utils.fac.Sequence, pyxb.utils.fac.All))
745 for tt in term_list:
746 _ttMergeSets(combined, tt)
747 elif isinstance(node, pyxb.utils.fac.Symbol):
748 (particle, term) = node.metadata
749 if isinstance(term, xs.structures.ElementDeclaration):
750
751 singles.add(term.baseDeclaration())
752 elif isinstance(term, xs.structures.Wildcard):
753 pass
754 else:
755 assert isinstance(term, list)
756
757 for tt in term:
758 _ttMergeSets(combined, BuildPluralityData(tt))
759 else:
760 assert isinstance(node, pyxb.utils.fac.NumericalConstraint)
761
762
763 combined = arg[-1].pop()
764 (singles, multiples) = combined
765 if 0 == node.max:
766
767
768 multiples.clear()
769 singles.clear()
770 elif 1 == node.max:
771
772 pass
773 else:
774
775
776 multiples.update(singles)
777 singles.clear()
778 arg[-1].append(combined)
779
780
781
782 arg = [[]]
783 term_tree.walkTermTree(_ttPrePluralityWalk, _ttPostPluralityWalk, arg)
784
785
786 assert 1 == len(arg)
787 arg = arg[0]
788 assert 1 == len(arg)
789 return arg[0]
790
792 """Helper class holding information need in both preparation and generation."""
793
794 contentBasis = None
795 termTree = None
796 edSingles = None
797 edMultiples = None
798 automaton = None
799 ctd = None
800
812
813 @classmethod
816
817 @classmethod
818 - def Get (cls, ctd):
820
822 binding_module = generator.moduleForComponent(ctd)
823 outf = binding_module.bindingIO()
824
825 prolog_template = None
826 template_map = { }
827 binding_name = template_map['ctd'] = binding_module.literal(ctd, **kw)
828 if (ctd.expandedName() is not None) and (ctd.expandedName().localName() != binding_name):
829 _log.warning('Complex type %s renamed to %s', ctd.expandedName(), binding_name)
830
831 base_type = ctd.baseTypeDefinition()
832 content_type_tag = ctd._contentTypeTag()
833
834 template_map['base_type'] = binding_module.literal(base_type, **kw)
835 template_map['namespaceReference'] = binding_module.literal(ctd.bindingNamespace(), **kw)
836 template_map['expanded_name'] = binding_module.literal(ctd.expandedName(), **kw)
837 if ctd.expandedName() is not None:
838 template_map['qname'] = unicode(ctd.expandedName())
839 else:
840 template_map['qname'] = '[anonymous]'
841 template_map['xsd_location'] = repr(ctd._location())
842 template_map['simple_base_type'] = binding_module.literal(None, **kw)
843 template_map['contentTypeTag'] = content_type_tag
844 template_map['is_abstract'] = repr(not not ctd.abstract())
845
846 content_basis = None
847 if (ctd.CT_SIMPLE == content_type_tag):
848 content_basis = ctd.contentType()[1]
849 template_map['simple_base_type'] = binding_module.literal(content_basis, **kw)
850 elif (ctd.CT_MIXED == content_type_tag):
851 content_basis = ctd.contentType()[1]
852 elif (ctd.CT_ELEMENT_ONLY == content_type_tag):
853 content_basis = ctd.contentType()[1]
854
855 if ctd.annotation() is not None:
856 template_map['documentation'] = ctd.annotation().asDocString()
857 elif isinstance(ctd.owner(), xs.structures.ElementDeclaration) \
858 and ctd.owner().annotation() is not None:
859 template_map['documentation'] = ctd.owner().annotation().asDocString()
860 else:
861 template_map['documentation'] = templates.replaceInText("Complex type %{qname} with content type %{contentTypeTag}", **template_map)
862
863 prolog_template = '''
864 # Complex type %{qname} with content type %{contentTypeTag}
865 class %{ctd} (%{superclass}):
866 """%{documentation}"""
867 _TypeDefinition = %{simple_base_type}
868 _ContentTypeTag = pyxb.binding.basis.complexTypeDefinition._CT_%{contentTypeTag}
869 _Abstract = %{is_abstract}
870 _ExpandedName = %{expanded_name}
871 _XSDLocation = %{xsd_location}
872 '''
873
874
875
876
877 inherits_from_base = True
878 template_map['superclass'] = binding_module.literal(base_type, **kw)
879 if ctd._isHierarchyRoot():
880 inherits_from_base = False
881 template_map['superclass'] = 'pyxb.binding.basis.complexTypeDefinition'
882 assert base_type.nameInBinding() is not None
883
884
885 class_keywords = frozenset(basis.complexTypeDefinition._ReservedSymbols)
886 class_unique = set()
887
888
889
890
891
892
893
894 element_uses = []
895
896 definitions = []
897
898 definitions.append('# Base type is %{base_type}')
899
900
901
902
903
904 if isinstance(content_basis, xs.structures.Particle):
905 plurality_data = {}
906 aux = _CTDAuxData.Get(ctd)
907 elements = aux.edSingles.union(aux.edMultiples)
908
909 outf.postscript().append("\n\n")
910 for ed in sorted(elements, key=lambda _c: _c.bindingSortKey()):
911 is_plural = ed in aux.edMultiples
912
913 ef_map = ed._templateMap()
914 if ed.scope() == ctd:
915 ef_map.update(elementDeclarationMap(ed, binding_module, **kw))
916 aux_init = []
917 ef_map['is_plural'] = repr(is_plural)
918 element_uses.append(templates.replaceInText('%{use}.name() : %{use}', **ef_map))
919 if 0 == len(aux_init):
920 ef_map['aux_init'] = ''
921 else:
922 ef_map['aux_init'] = ', ' + ', '.join(aux_init)
923 ef_map['element_binding'] = utility.PrepareIdentifier('%s_elt' % (ef_map['id'],), class_unique, class_keywords, private=True)
924 if ed.annotation() is not None:
925 ef_map['documentation'] = binding_module.literal(unicode(ed.annotation()))
926 else:
927 ef_map['documentation'] = binding_module.literal(None)
928 if ed.scope() != ctd:
929 definitions.append(templates.replaceInText('''
930 # Element %{id} (%{qname}) inherited from %{decl_type_en}''', decl_type_en=unicode(ed.scope().expandedName()), **ef_map))
931 continue
932
933 if ed.expandedName().localName() != ef_map['id']:
934 _log.warning('Element use %s.%s renamed to %s', ctd.expandedName(), ed.expandedName(), ef_map['id'])
935 definitions.append(templates.replaceInText('''
936 # Element %{qname} uses Python identifier %{id}
937 %{use} = pyxb.binding.content.ElementDeclaration(%{name_expr}, '%{id}', '%{key}', %{is_plural}, %{decl_location}, %{aux_init})
938 ''', name_expr=binding_module.literal(ed.expandedName(), **kw), **ef_map))
939
940 definitions.append(templates.replaceInText('''
941 %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation})
942 ''', **ef_map))
943 outf.postscript().append(templates.replaceInText('''
944 %{ctd}._AddElement(pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init}))
945 ''', name_expr=binding_module.literal(ed.expandedName(), **kw), ctd=template_map['ctd'], **ef_map))
946
947 auto_defn = GenerateAutomaton(ctd, binding_module=binding_module, **kw)
948 if auto_defn is not None:
949 (automaton_ctor, lines) = auto_defn
950 if lines:
951 outf.postscript().append("\n".join(lines))
952 outf.postscript().append("\n")
953 outf.postscript().append(templates.replaceInText('%{ctd}._Automaton = %{automaton_ctor}\n', ctd=template_map['ctd'], automaton_ctor=automaton_ctor))
954 outf.postscript().append("\n")
955
956
957 attribute_uses = []
958
959
960
961
962
963
964
965
966 for au in sorted(ctd.attributeUses(), key=lambda _au: _au.attributeDeclaration().bindingSortKey()):
967 ad = au.attributeDeclaration()
968 assert isinstance(ad.scope(), xs.structures.ComplexTypeDefinition), 'unexpected scope %s' % (ad.scope(),)
969 au_map = ad._templateMap()
970 if ad.scope() != ctd:
971 definitions.append(templates.replaceInText('''
972 # Attribute %{id} inherited from %{decl_type_en}''', decl_type_en=unicode(ad.scope().expandedName()), **au_map))
973 continue
974 assert isinstance(au_map, dict)
975 aur = au;
976 while aur.restrictionOf() is not None:
977 aur = aur.restrictionOf()
978 if au != aur:
979 au_map = aur.attributeDeclaration()._templateMap().copy()
980 definitions.append(templates.replaceInText('''
981 # Attribute %{id} is restricted from parent''', **au_map))
982
983 assert ad.typeDefinition() is not None
984 au_map['attr_type'] = binding_module.literal(ad.typeDefinition(), **kw)
985 au_map['decl_location'] = repr(ad._location())
986 au_map['use_location'] = repr(au._location())
987
988 vc_source = ad
989 if au.valueConstraint() is not None:
990 vc_source = au
991 aux_init = []
992 if vc_source.fixed() is not None:
993 aux_init.append('fixed=True')
994 aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.fixed(), **kw),))
995 elif vc_source.default() is not None:
996 aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.default(), **kw),))
997 if au.required():
998 aux_init.append('required=True')
999 if au.prohibited():
1000 aux_init.append('prohibited=True')
1001 if 0 == len(aux_init):
1002 au_map['aux_init'] = ''
1003 else:
1004 aux_init.insert(0, '')
1005 au_map['aux_init'] = ', '.join(aux_init)
1006 if ad.annotation() is not None:
1007 au_map['documentation'] = binding_module.literal(unicode(ad.annotation()))
1008 else:
1009 au_map['documentation'] = binding_module.literal(None)
1010
1011 attribute_uses.append(templates.replaceInText('%{use}.name() : %{use}', **au_map))
1012 if ad.expandedName().localName() != au_map['id']:
1013 _log.warning('Attribute %s.%s renamed to %s', ctd.expandedName(), ad.expandedName(), au_map['id'])
1014 definitions.append(templates.replaceInText('''
1015 # Attribute %{qname} uses Python identifier %{id}
1016 %{use} = pyxb.binding.content.AttributeUse(%{name_expr}, '%{id}', '%{key}', %{attr_type}%{aux_init})
1017 %{use}._DeclarationLocation = %{decl_location}
1018 %{use}._UseLocation = %{use_location}''', name_expr=binding_module.literal(ad.expandedName(), **kw), **au_map))
1019 definitions.append(templates.replaceInText('''
1020 %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation})
1021 ''', ctd=template_map['ctd'], **au_map))
1022
1023 if ctd.attributeWildcard() is not None:
1024 definitions.append('_AttributeWildcard = %s' % (binding_module.literal(ctd.attributeWildcard(), **kw),))
1025 if ctd.hasWildcardElement():
1026 definitions.append('_HasWildcardElement = True')
1027 template_map['attribute_uses'] = ",\n ".join(attribute_uses)
1028 template_map['element_uses'] = ",\n ".join(element_uses)
1029 if inherits_from_base:
1030 map_decl = '''
1031 _ElementMap = %{superclass}._ElementMap.copy()
1032 _ElementMap.update({
1033 %{element_uses}
1034 })
1035 _AttributeMap = %{superclass}._AttributeMap.copy()
1036 _AttributeMap.update({
1037 %{attribute_uses}
1038 })'''
1039 else:
1040 map_decl = '''
1041 _ElementMap = {
1042 %{element_uses}
1043 }
1044 _AttributeMap = {
1045 %{attribute_uses}
1046 }'''
1047
1048 template_map['registration'] = ''
1049 if ctd.name() is not None:
1050 template_map['registration'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{ctd})",
1051 localName=binding_module.literal(ctd.name(), **kw), **template_map)
1052
1053 template = ''.join([prolog_template,
1054 " ", "\n ".join(definitions), "\n",
1055 map_decl, '''
1056 %{registration}
1057
1058 '''])
1059
1060 outf.write(template, **template_map)
1061
1063
1064 assert ed._scopeIsGlobal()
1065
1066 binding_module = generator.moduleForComponent(ed)
1067 outf = binding_module.bindingIO()
1068
1069 template_map = elementDeclarationMap(ed, binding_module, **kw)
1070 template_map.setdefault('scope', binding_module.literal(None, **kw))
1071 template_map.setdefault('map_update', '')
1072
1073 outf.write(templates.replaceInText('''
1074 %{class} = pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init})
1075 %{namespaceReference}.addCategoryObject('elementBinding', %{class}.name().localName(), %{class})
1076 ''', name_expr=binding_module.literal(ed.expandedName(), **kw), **template_map))
1077
1078 if ed.substitutionGroupAffiliation() is not None:
1079 outf.postscript().append(templates.replaceInText('''
1080 %{class}._setSubstitutionGroup(%{substitution_group})
1081 ''', **template_map))
1082
1091
1099
1101 use_map = component._templateMap()
1102 class_unique = nsm.uniqueInClass(container)
1103 assert isinstance(component, xs.structures._ScopedDeclaration_mixin)
1104 unique_name = utility.PrepareIdentifier(component.expandedName().localName(), class_unique)
1105 use_map['id'] = unique_name
1106 use_map['inspector'] = unique_name
1107 use_map['mutator'] = utility.PrepareIdentifier('set' + unique_name[0].upper() + unique_name[1:], class_unique)
1108 use_map['use'] = utility.MakeUnique('__' + unique_name.strip('_'), class_unique)
1109 assert component._scope() == container
1110 assert component.nameInBinding() is None, 'Use %s but binding name %s for %s' % (use_map['use'], component.nameInBinding(), component.expandedName())
1111 component.setNameInBinding(use_map['use'])
1112 key_name = '%s_%s_%s' % (str(nsm.namespace()), container.nameInBinding(), component.expandedName())
1113 use_map['key'] = utility.PrepareIdentifier(key_name, class_unique, private=True)
1114 use_map['qname'] = unicode(component.expandedName())
1115 if isinstance(component, xs.structures.ElementDeclaration) and is_plural:
1116 use_map['appender'] = utility.PrepareIdentifier('add' + unique_name[0].upper() + unique_name[1:], class_unique)
1117 return use_map
1118
1180
1182 __anonSTDIndex = None
1183 __anonCTDIndex = None
1184 __uniqueInModule = None
1185 __uniqueInClass = None
1186
1187 _UniqueInModule = set([ 'pyxb', 'sys' ])
1188 """Identifiers that are reserved within a module.
1189
1190 Subclasses extend this with the identifiers they add to the
1191 module. Module-level schema-derived identifiers (such as type
1192 definition and element names) are deconflicted from this set and
1193 from each other."""
1194
1195 __ComponentBindingModuleMap = {}
1196
1199 __generator = None
1200
1201 - def __init__ (self, generator, *args, **kw):
1215
1223
1241
1242 __referencedNamespaces = None
1243
1245 return self.__bindingIO
1246
1247 __moduleUID = None
1252
1254 return str(id(self))
1255
1257 """Return a distinct string recorded in the first 4096 bytes of the binding file.
1258
1259 This is used to ensure uniqueness and avoid overwriting data
1260 belonging to a different binding. The return value comprises
1261 the class-specialized L{_bindingTagPrefix_vx} with the
1262 L{moduleUID}.
1263 """
1264 return '%s:%s' % (self._bindingTagPrefix_vx(), self.moduleUID())
1265
1267 raise pyxb.LogicError('Subclass %s does not define _bindingTagPrefix_vx' % (type(self),))
1268
1270 """Return a block of binding text (comment or code) serving as a preface.
1271
1272 Normally this should describe the module contents."""
1273 return self._bindingPreface_vx()
1276
1277 - def moduleContents (self):
1278 template_map = {}
1279 aux_imports = []
1280 for ns in self.__importedModules:
1281 if isinstance(ns, NamespaceModule):
1282 ns = ns.moduleRecord()
1283 module_path = ns.modulePath()
1284 assert module_path is not None, 'No module path for %s type %s' % (ns, type(ns))
1285 aux_imports.append('import %s' % (module_path,))
1286 template_map['aux_imports'] = "\n".join(aux_imports)
1287 template_map['namespace_decls'] = "\n".join(self.__namespaceDeclarations)
1288 template_map['module_uid'] = self.moduleUID()
1289 template_map['generation_uid_expr'] = repr(self.generator().generationUID())
1290 self._finalizeModuleContents_vx(template_map)
1291 return self.__bindingIO.contents()
1292
1305 __modulePath = None
1306
1309 __bindingFile = None
1310 __bindingFilePath = None
1311
1314
1317
1318 @classmethod
1322
1323 @classmethod
1326
1327 @classmethod
1331 @classmethod
1334 __RecordModuleMap = { }
1335
1353 return self.__componentNameMap.get(component)
1354
1373
1375
1376 - def defineNamespace (self, namespace, name, require_unique=True, definition=None, **kw):
1390
1392 rv = self.__referencedNamespaces.get(namespace)
1393 if rv is None:
1394 if namespace.isBuiltinNamespace():
1395 rv = namespace.builtinNamespaceRepresentation()
1396 elif namespace.isUndeclaredNamespace():
1397 rv = namespace.modulePath()
1398 elif isinstance(self, NamespaceModule):
1399 if (self.namespace() == namespace):
1400 rv = 'Namespace'
1401 else:
1402 rv = 'pyxb.namespace.NamespaceForURI(%s)' % (repr(namespace.uri()),)
1403 '''
1404 namespace_module = self.ForNamespace(namespace)
1405 if namespace_module is not None:
1406 self._importModule(namespace_module)
1407 rv = '%s.Namespace' % (namespace_module.modulePath(),)
1408 else:
1409 assert False, 'Unexpected reference to %s' % (namespace,)
1410 #rv = 'pyxb.namespace.NamespaceForURI(%s)' % (repr(namespace.uri()),)
1411 '''
1412 else:
1413 if namespace.prefix():
1414 nsn = 'Namespace_%s' % (namespace.prefix(),)
1415 else:
1416 nsn = 'Namespace'
1417 for im in self.__importedModules:
1418 if isinstance(im, NamespaceModule) and (im.namespace() == namespace):
1419 rv = '%s.Namespace' % (im.modulePath(),)
1420 break
1421 if isinstance(im, NamespaceGroupModule):
1422 irv = im.__referencedNamespaces.get(namespace)
1423 if irv is not None:
1424 rv = self.defineNamespace(namespace, nsn, '%s.%s' % (im.modulePath(), irv), protected=True)
1425 break
1426 if rv is None:
1427 rv = self.defineNamespace(namespace, nsn, protected=True)
1428 assert 0 < len(self.__namespaceDeclarations)
1429 self.__referencedNamespaces[namespace] = rv
1430 return rv
1431
1433 return self.__bindingIO.literal(*args, **kw)
1434
1448
1456
1458 """This class represents a Python module that holds all the
1459 declarations belonging to a specific namespace."""
1460
1463 __namespace = None
1464
1467 __moduleRecord = None
1468
1473 __namespaceGroupModule = None
1474
1475 _UniqueInModule = _ModuleNaming_mixin._UniqueInModule.copy()
1476 _UniqueInModule.update([ 'Namespace', 'CreateFromDOM', 'CreateFromDocument' ])
1477
1480 __namespaceGroupHead = None
1481 __namespaceGroup = None
1482
1485 __components = None
1486
1487 @classmethod
1490 __ComponentModuleMap = { }
1491
1494
1496 ns = self.namespace()
1497 rvl = ['# Namespace %s' % (ns,)]
1498 if ns.prefix() is not None:
1499 rvl.append(' [xmlns:%s]' % (ns.prefix(),))
1500 rvl.append('\n')
1501 return ''.join(rvl)
1502
1507
1510
1511 - def __init__ (self, generator, module_record, mr_scc, components=None, **kw):
1525
1533
1534 - def _finalizeModuleContents_vx (self, template_map):
1535 self.bindingIO().prolog().append(self.bindingIO().expand('''
1536 import pyxb
1537 import pyxb.binding
1538 import pyxb.binding.saxer
1539 import StringIO
1540 import pyxb.utils.utility
1541 import pyxb.utils.domutils
1542 import sys
1543
1544 # Unique identifier for bindings created at the same time
1545 _GenerationUID = %{generation_uid_expr}
1546
1547 # Import bindings for namespaces imported into schema
1548 %{aux_imports}
1549
1550 %{namespace_decls}
1551 ModuleRecord = Namespace.lookupModuleRecordByUID(_GenerationUID, create_if_missing=True)
1552 ModuleRecord._setModule(sys.modules[__name__])
1553
1554 def CreateFromDocument (xml_text, default_namespace=None, location_base=None):
1555 """Parse the given XML and use the document element to create a
1556 Python instance.
1557
1558 @kw default_namespace The L{pyxb.Namespace} instance to use as the
1559 default namespace where there is no default namespace in scope.
1560 If unspecified or C{None}, the namespace of the module containing
1561 this function will be used.
1562
1563 @keyword location_base: An object to be recorded as the base of all
1564 L{pyxb.utils.utility.Location} instances associated with events and
1565 objects handled by the parser. You might pass the URI from which
1566 the document was obtained.
1567 """
1568
1569 if pyxb.XMLStyle_saxer != pyxb._XMLStyle:
1570 dom = pyxb.utils.domutils.StringToDOM(xml_text)
1571 return CreateFromDOM(dom.documentElement)
1572 if default_namespace is None:
1573 default_namespace = Namespace.fallbackNamespace()
1574 saxer = pyxb.binding.saxer.make_parser(fallback_namespace=default_namespace, location_base=location_base)
1575 handler = saxer.getContentHandler()
1576 saxer.parse(StringIO.StringIO(xml_text))
1577 instance = handler.rootObject()
1578 return instance
1579
1580 def CreateFromDOM (node, default_namespace=None):
1581 """Create a Python instance from the given DOM node.
1582 The node tag must correspond to an element declaration in this module.
1583
1584 @deprecated: Forcing use of DOM interface is unnecessary; use L{CreateFromDocument}."""
1585 if default_namespace is None:
1586 default_namespace = Namespace.fallbackNamespace()
1587 return pyxb.binding.basis.element.AnyCreateFromDOM(node, default_namespace)
1588
1589 ''', **template_map))
1590
1591 __components = None
1592 __componentBindingName = None
1593
1602
1605
1675
1676
1677 -def GeneratePython (schema_location=None,
1678 schema_text=None,
1679 namespace=None,
1680 module_prefix_elts=[],
1681 **kw):
1692
1693 import optparse
1694 import re
1697 """Configuration and data for a single binding-generation action."""
1698
1699 _DEFAULT_bindingRoot = '.'
1701 """The directory path into which generated bindings will be written.
1702 @rtype: C{str}"""
1703 return self.__bindingRoot
1707 __bindingRoot = None
1708
1710 if isinstance(module_elts, basestring):
1711 module_elts = module_elts.split('.')
1712 else:
1713 module_elts = module_elts[:]
1714 assert 0 < len(module_elts)
1715 if not inhibit_extension:
1716 assert not module_elts[-1].endswith('.py')
1717 module_elts[-1] = '%s.py' % (module_elts[-1],)
1718 return os.path.join(self.bindingRoot(), *module_elts)
1719
1722 __generateToFiles = None
1723
1725
1726
1727
1728
1729 module_path = None
1730 if isinstance(module, NamespaceModule):
1731 mr = module.moduleRecord()
1732 if mr is None:
1733 return ('/dev/null', None, None)
1734 if self.generationUID() != mr.generationUID():
1735 return ('/dev/null', None, None)
1736 if not self.generateToFiles():
1737 return ('/dev/null', None, None)
1738 if mr.namespace().isBuiltinNamespace() and (not self.allowBuiltinGeneration()):
1739 return ('/dev/null', None, None)
1740 module_path = mr.modulePath()
1741 assert module_path is not None, 'No path specified for module %s' % (mr,)
1742
1743
1744
1745 module_elts = module_path.split('.')
1746 if self.writeForCustomization():
1747 import_file_path = self.__moduleFilePath(module_elts)
1748 module_elts.insert(-1, 'raw')
1749 if not os.path.exists(import_file_path):
1750 raw_module_path = '.'.join(module_elts)
1751 pyxb.utils.utility.OpenOrCreate(import_file_path).write("from %s import *\n" % (raw_module_path,))
1752 binding_file_path = self.__moduleFilePath(module_elts)
1753 try:
1754 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID())
1755 except OSError as e:
1756 if errno.EEXIST == e.errno:
1757 raise pyxb.BindingGenerationError('Target file %s for module %s bindings exists with other content' % (binding_file_path, mr))
1758 raise
1759 elif isinstance(module, NamespaceGroupModule):
1760 if not self.generateToFiles():
1761 raise pyxb.BindingGenerationError('Generation of namespace groups requires generate-to-files')
1762 module_elts = []
1763 if self.modulePrefix():
1764 module_elts.extend(self.modulePrefix().split('.'))
1765 if self.writeForCustomization():
1766 module_elts.append('raw')
1767 in_use = set()
1768 while True:
1769 module_elts.append(pyxb.utils.utility.PrepareIdentifier('nsgroup', in_use, protected=True))
1770 try:
1771 binding_file_path = self.__moduleFilePath(module_elts)
1772 _log.info('Attempting group %s uid %s at %s', module, module.moduleUID(), binding_file_path)
1773 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID())
1774 break
1775 except OSError as e:
1776 if errno.EEXIST != e.errno:
1777 raise
1778 module_elts.pop()
1779 module_path = '.'.join(module_elts)
1780 else:
1781 assert False
1782 if self.generateToFiles():
1783 for n in range(len(module_elts)-1):
1784 sub_path = self.__moduleFilePath(module_elts[:1+n], inhibit_extension=True)
1785 init_path = os.path.join(sub_path, '__init__.py')
1786 if not os.path.exists(init_path):
1787 file(init_path, 'w')
1788 return (binding_file_path, binding_file, module_path)
1789
1791 """The directory from which entrypoint schemas specified as
1792 relative file paths will be read."""
1793 return self.__schemaRoot
1795 if not schema_root.endswith(os.sep):
1796 schema_root = schema_root + os.sep
1797 self.__schemaRoot = schema_root
1798 return self
1799 __schemaRoot = None
1800
1802 """Optional string that is stripped from the beginning of
1803 schemaLocation values before loading from them.
1804
1805 This applies only to the values of schemaLocation attributes
1806 in C{import} and C{include} elements. Its purpose is to
1807 convert absolute schema locations into relative ones to allow
1808 offline processing when all schema are available in a local
1809 directory. See C{schemaRoot}.
1810 """
1811 return self.__schemaStrippedPrefix
1815 __schemaStrippedPrefix = None
1816
1818 """Optional map to rewrite schema locations.
1819
1820 This applies only to the values of schemaLocation attributes
1821 in C{import} and C{include} elements. Its purpose is to
1822 convert remote or absolute schema locations into local or
1823 relative ones to allow offline processing when all schema are
1824 available in a local directory. See C{schemaRoot}.
1825 """
1826 return self.__locationPrefixRewriteMap
1832 """Add a rewrite entry for schema locations.
1833
1834 @param prefix : A text prefix that should be removed from
1835 schema location URIs.
1836
1837 @param substituent : The text prefix that should replace
1838 C{prefix} as a prefix in a schema location URI.
1839 """
1840
1841 self.__locationPrefixRewriteMap[prefix] = substituent
1842 return self
1844 """Add a rewrite entry for schema locations.
1845
1846 Parameter values are strings of the form C{pfx=sub}. The
1847 effect is that a schema location that begins with C{pfx} is
1848 rewritten so that it instead begins with C{sub}."""
1849 try:
1850 (prefix, substituent) = prefix_rewrite.split('=', 1)
1851 except:
1852 raise
1853 self.addLocationPrefixRewrite(prefix, substituent)
1854 __locationPrefixMap = {}
1855
1857 """A list of locations from which entrypoint schemas are to be
1858 read.
1859
1860 The values in the list are either URIs, or tuples consisting
1861 of a value and a callable which, when passed the generator
1862 object and the value, will return a
1863 L{pyxb.xmlschema.structures.Schema} instance. See
1864 L{addSchemaLocation}.
1865
1866 See also L{addSchemaLocation} and L{schemas}.
1867 """
1868 return self.__schemaLocationList
1874 """Add the location of an entrypoint schema.
1875
1876 @param schema_location: The location of the schema. This
1877 should be a URL; if the schema location does not have a URL
1878 scheme (e.g., C{http:}), it is assumed to be a file, and if it
1879 is not an absolute path is located relative to the
1880 C{schemaRoot}.
1881
1882 @keyword converter: Optional callable that will be invoked
1883 with the generator instance and the schema location, and is
1884 expected to return a L{pyxb.xmlschema.structures.Schema}
1885 instance. If absent, the contents of the location are
1886 converted directly.
1887
1888 @note: The C{converter} argument derives from WSDL support: we
1889 need to add to the sequence of schema locations a URI of
1890 something that will not parse as a schema, but does have inner
1891 material that can if treated properly. "Treated properly" may
1892 include having the archive path and other namespace
1893 manipulations configured before anything is done to it.
1894 """
1895 self.__schemaLocationList.append( (schema_location, converter) )
1896 return self
1898 """Add the location of an entrypoint schema. The provided
1899 value should be a URL; if it does not have a URL scheme (e.g.,
1900 C{http:}), it is assumed to be a file, and if it is not an
1901 absolute path is located relative to the C{schemaRoot}."""
1902 self.addSchemaLocation(schema_location)
1903 __schemaLocationList = None
1904
1906 """Schema for which bindings should be generated.
1907
1908 These may be L{Schema<pyxb.xmlschema.structures.Schema>}
1909 instances, or strings; the latter is preferred, and is parsed
1910 into a Schema instance when required.
1911
1912 This is the list of entrypoint schemas for binding generation.
1913 Values in L{schemaLocationList} are read and converted into
1914 schema, then appended to this list. Values from L{moduleList}
1915 are applied starting with the first schema in this list.
1916 """
1917 return self.__schemas[:]
1925 __schemas = None
1926
1928 """The set of L{namespaces<pyxb.namespace.Namespace>} for
1929 which bindings will be generated.
1930
1931 This is the set of namespaces read from entrypoint schema,
1932 closed under reference to namespaces defined by schema import.
1933
1934 @rtype: C{set}
1935 """
1936 return self.__namespaces.copy()
1944 __namespaces = None
1945
1947 """A list of module names to be applied in order to the namespaces of entrypoint schemas"""
1948 return self.__moduleList[:]
1953
1955 """Add a module name corresponding to an entrypoint schema.
1956
1957 The namespace defined by the corresponding schema will be
1958 written to a binding using the given module name, adjusted by
1959 L{modulePrefix}."""
1960 self.__moduleList.append(module_name)
1961 return self
1962 __moduleList = None
1963
1965 """The prefix for binding modules.
1966
1967 The base name for the module holding a binding is taken from
1968 the moduleList, moduleMap, or an XMLNS prefix associated with
1969 the namespace in a containing schema. This value, if present,
1970 is used as a prefix to allow a deeper module hierarchy."""
1971 return self.__modulePrefix
1975 __modulePrefix = None
1976
1978 """A map from namespace URIs to the module to be used for the
1979 corresponding generated binding.
1980
1981 Module values are adjusted by L{modulePrefix} if that has been
1982 specified.
1983
1984 An entry in this map for a namespace supersedes the module
1985 specified in moduleList if the namespace is defined by an
1986 entrypoint schema.
1987
1988 @return: A reference to the namespace module map.
1989 """
1990 return self.__namespaceModuleMap
1991 __namespaceModuleMap = None
1992
1994 """A colon-separated list of paths from which namespace
1995 archives can be read.
1996
1997 The default path is the contents of the C{PYXB_ARCHIVE_PATH}
1998 environment variable, or the standard path configured at
1999 installation time. Any file with the extension C{.wxs} found
2000 in one of these directories is examined to see whether it is a
2001 namespace archive.
2002 """
2003 return self.__archivePath
2007 __archivePath = None
2008
2010 """A frozenset of namespaces that many not be loaded from an archive."""
2011 return frozenset(self.__noLoadNamespaces)
2013 """Record the set of namespaces that should not be loaded from an archive.
2014
2015 The expectation is that any required entities in the namespace
2016 will be defined by loading schema."""
2017 self.__noLoadNamespaces.clear()
2018 self.__noLoadNamespaces.update([ pyxb.namespace.NamespaceInstance(_ns) for _ns in namespace_set ])
2020 """Mark that the specified namespace should not be loaded from an archive.
2021
2022 Use this when you are generating bindings for an application
2023 that has a restricted profile of a namespace that would
2024 otherwise be read from an archive. Be aware that this removes
2025 any knowledge of any archive in which this namespace is
2026 present as a non-private member."""
2027 self.__noLoadNamespaces.add(pyxb.namespace.NamespaceInstance(namespace))
2028 __noloadNamespaces = None
2029
2031 """A list of paths to archives that should be loaded, in order, prior to parsing schema."""
2032 return frozenset(self.__preLoadArchives)
2034 """Name of a file containing a stored archive from which
2035 namespaces should be read prior to processing schema.
2036
2037 Files to be pre-loaded are not affected by
2038 C{noLoadNamespace}."""
2039 self.__preLoadArchives.append(archive_file)
2043 __preLoadArchives = None
2044
2046 """Optional file into which the archive of namespaces will be written.
2047
2048 Subsequent generation actions can read pre-parsed namespaces
2049 from this file, and therefore reference the bindings that were
2050 built earlier rather than re-generating them.
2051
2052 The file name should normally end with C{.wxs}."""
2053 return self.__archiveToFile
2057 __archiveToFile = None
2058
2072 """Indicates, for specific namespaces, whether their
2073 visibility in the archive should be public or private."""
2074 return self.__namespaceVisibilityMap.copy()
2075 __namespaceVisibilityMap = None
2076
2078 """Indicates whether unmentioned namespaces will be public or private (default) in the archive.
2079
2080 A namespace is I{mentioned} if it is the target namespace of
2081 an entrypoint schema, or appears in a namespace visibility
2082 specification. I.e., this default applies only to namespaces
2083 that are modified as a result of including some schema, which
2084 is generally a local customization of something.
2085 """
2086 return self.__defaultNamespacePublic
2089 __defaultNamespacePublic = None
2090
2092 """Indicates whether the bindings should validate mutations
2093 against the content model."""
2094 return self.__validateChanges
2098 __validateChanges = None
2099
2101 """Indicates whether the binding Python code should be written into a sub-module for customization.
2102
2103 If enabled, a module C{path.to.namespace} will be written to
2104 the file C{path/to/raw/namespace.py}, so that the file
2105 C{path/to/namespace.py} can import it and override behavior."""
2106 return self.__writeForCustomization
2110 __writeForCustomization = None
2111
2113 """Indicates whether the code generator is permitted to
2114 process namespace for which no module path can be determined.
2115
2116 Use this only when generating bindings that will not be
2117 referenced by other bindings."""
2118 return self.__allowAbsentModule
2122 __allowAbsentModule = None
2123
2125 """Indicates whether bindings will be written for namespaces that are built-in to PyXB.
2126
2127 This must be enabled when building bindings for the XML,
2128 XMLSchema instance, and other built-in namespaces. Normally
2129 generation of these namespaces is inhibited lest it produce
2130 inconsistencies."""
2131 return self.__allowBuiltinGeneration
2135 __allowBuiltinGeneration = None
2136
2138 """The directory path into which any content retrieved by URI will be written.
2139
2140 This serves as a local cache, and to give you an opportunity
2141 to inspect material retrieved from some other system.
2142 @rtype: C{str}"""
2143 return self.__uriContentArchiveDirectory
2146 __uriContentArchiveDirectory = None
2147
2149 """A file provided to L{logging.config.fileConfig} to control log messages.
2150
2151 In the absence of other configuration the Python standard logging infrastructure is used in its
2152 default configuration.
2153
2154 @rtype: C{str}"""
2155 return self.__loggingConfigFile
2158 __loggingConfigFile = None
2159
2161 """Create a configuration to be used for generating bindings.
2162
2163 Arguments are treated as additions to the schema location list
2164 after all keywords have been processed.
2165
2166 @keyword binding_root: Invokes L{setBindingRoot}
2167 @keyword schema_root: Invokes L{setSchemaRoot}
2168 @keyword schema_stripped_prefix: Invokes L{setSchemaStrippedPrefix}
2169 @keyword location_prefix_rewrite_map: Invokes L{setLocationPrefixRewriteMap}
2170 @keyword schema_location_list: Invokes L{setSchemaLocationList}
2171 @keyword module_list: Invokes L{_setModuleList}
2172 @keyword module_prefix: Invokes L{setModulePrefix}
2173 @keyword archive_path: Invokes L{setArchivePath}
2174 @keyword no_load_namespaces: Invokes L{_setNoLoadNamespaces}
2175 @keyword pre_load_archives: Invokes L{_setPreLoadArchives}
2176 @keyword archive_to_file: Invokes L{setArchiveToFile}
2177 @keyword public_namespace: Invokes L{setNamespaceVisibility}
2178 @keyword private_namespace: Invokes L{setNamespaceVisibility}
2179 @keyword default_namespace_public: Invokes L{setDefaultNamespacePublic}
2180 @keyword validate_changes: Invokes L{setValidateChanges}
2181 @keyword namespace_module_map: Initializes L{namespaceModuleMap}
2182 @keyword schemas: Invokes L{setSchemas}
2183 @keyword namespaces: Invokes L{setNamespaces}
2184 @keyword write_for_customization: Invokes L{setWriteForCustomization}
2185 @keyword allow_builtin_generation: Invokes L{setAllowBuiltinGeneration}
2186 @keyword allow_absent_module: Invokes L{setAllowAbsentModule}
2187 @keyword generate_to_files: Sets L{generateToFiles}
2188 @keyword uri_content_archive_directory: Invokes L{setUriContentArchiveDirectory}
2189 @keyword logging_config_file: Invokes L{setLoggingConfigFile}
2190 """
2191 argv = kw.get('argv')
2192 if argv is not None:
2193 kw = {}
2194 self.__bindingRoot = kw.get('binding_root', self._DEFAULT_bindingRoot)
2195 self.__schemaRoot = kw.get('schema_root', '.')
2196 self.__schemaStrippedPrefix = kw.get('schema_stripped_prefix')
2197 self.__locationPrefixRewriteMap = kw.get('location_prefix_rewrite_map', {})
2198 self.__schemas = []
2199 self.__schemaLocationList = kw.get('schema_location_list', [])[:]
2200 self.__moduleList = kw.get('module_list', [])[:]
2201 self.__modulePrefix = kw.get('module_prefix')
2202 self.__archivePath = kw.get('archive_path', pyxb.namespace.archive.GetArchivePath())
2203 self.__noLoadNamespaces = kw.get('no_load_namespaces', set()).copy()
2204 self.__preLoadArchives = kw.get('pre_load_archives', [])[:]
2205 self.__archiveToFile = kw.get('archive_to_file')
2206 self.__namespaceVisibilityMap = {}
2207 self._setNamespaceVisibilities(kw.get('public_namespaces', set()), kw.get('private_namespaces', set()))
2208 self.__defaultNamespacePublic = kw.get('default_namespace_public', False)
2209 self.__validateChanges = kw.get('validate_changes', True)
2210 self.__namespaceModuleMap = kw.get('namespace_module_map', {}).copy()
2211 self.__schemas = kw.get('schemas', [])[:]
2212 self.__namespaces = set(kw.get('namespaces', []))
2213 self.__writeForCustomization = kw.get('write_for_customization', False)
2214 self.__allowBuiltinGeneration = kw.get('allow_builtin_generation', False)
2215 self.__allowAbsentModule = kw.get('allow_absent_module', False)
2216 self.__generateToFiles = kw.get('generate_to_files', True)
2217 self.__uriContentArchiveDirectory = kw.get('uri_content_archive_directory')
2218 self.__loggingConfigFile = kw.get('logging_config_file')
2219
2220 if argv is not None:
2221 self.applyOptionValues(*self.optionParser().parse_args(argv))
2222 [ self.addSchemaLocation(_a) for _a in args ]
2223
2224 self.__generationUID = pyxb.utils.utility.UniqueIdentifier()
2225
2226 pyxb.namespace.XML.validateComponentModel()
2227
2228 __stripSpaces_re = re.compile('\s\s\s+')
2231
2232 __OptionSetters = (
2233 ('binding_root', setBindingRoot),
2234 ('schema_root', setSchemaRoot),
2235 ('schema_stripped_prefix', setSchemaStrippedPrefix),
2236 ('location_prefix_rewrite', argAddLocationPrefixRewrite),
2237 ('schema_location', setSchemaLocationList),
2238 ('module', _setModuleList),
2239 ('module_prefix', setModulePrefix),
2240 ('archive_path', setArchivePath),
2241 ('no_load_namespace', _setNoLoadNamespaces),
2242 ('pre_load_archive', _setPreLoadArchives),
2243 ('archive_to_file', setArchiveToFile),
2244 ('default_namespace_public', setDefaultNamespacePublic),
2245 ('validate_changes', setValidateChanges),
2246 ('write_for_customization', setWriteForCustomization),
2247 ('allow_builtin_generation', setAllowBuiltinGeneration),
2248 ('allow_absent_module', setAllowAbsentModule),
2249 ('uri_content_archive_directory', setUriContentArchiveDirectory),
2250 ('logging_config_file', setLoggingConfigFile)
2251 )
2265
2267 if argv is None:
2268 argv = sys.argv[1:]
2269 (options, args) = self.optionParser().parse_args(argv)
2270 self.applyOptionValues(options, args)
2271 return self
2272
2274 """A unique identifier associated with this Generator instance.
2275
2276 This is an instance of L{pyxb.utils.utility.UniqueIdentifier}.
2277 Its associated objects are
2278 L{pyxb.namespace.archive._SchemaOrigin} instances, which
2279 identify schema that contribute to the definition of a
2280 namespace."""
2281 return self.__generationUID
2282 __generationUID = None
2283
2285 """Return an C{optparse.OptionParser} instance tied to this configuration.
2286
2287 @param reset: If C{False} (default), a parser created in a
2288 previous invocation will be returned. If C{True}, any
2289 previous option parser is discarded and a new one created.
2290 @type reset: C{bool}
2291 """
2292 if reset or (self.__optionParser is None):
2293 parser = optparse.OptionParser(usage="%prog [options] [more schema locations...]",
2294 version='%%prog from PyXB %s' % (pyxb.__version__,),
2295 description='Generate bindings from a set of XML schemas')
2296
2297 group = optparse.OptionGroup(parser, 'Identifying Schema', 'Specify and locate schema for which bindings should be generated.')
2298 group.add_option('--schema-location', '-u', metavar="FILE_or_URL",
2299 action='append',
2300 help=self.__stripSpaces(self.argAddSchemaLocation.__doc__))
2301 group.add_option('--schema-root', metavar="DIRECTORY",
2302 help=self.__stripSpaces(self.schemaRoot.__doc__))
2303 group.add_option('--schema-stripped-prefix', metavar="TEXT", type='string',
2304 help=self.__stripSpaces(self.schemaStrippedPrefix.__doc__))
2305 group.add_option('--location-prefix-rewrite', metavar="TEXT", type='string',
2306 help=self.__stripSpaces(self.argAddLocationPrefixRewrite.__doc__))
2307 group.add_option('--uri-content-archive-directory', metavar="DIRECTORY",
2308 help=self.__stripSpaces(self.uriContentArchiveDirectory.__doc__))
2309 parser.add_option_group(group)
2310
2311 group = optparse.OptionGroup(parser, 'Configuring Bindings', 'Specify where generated bindings should be written, and how they will be accessed from Python.')
2312 group.add_option('--module', '-m', metavar="MODULE",
2313 action='append',
2314 help=self.__stripSpaces(self.addModuleName.__doc__))
2315 group.add_option('--module-prefix', metavar="MODULE",
2316 help=self.__stripSpaces(self.modulePrefix.__doc__))
2317 group.add_option('--binding-root', metavar="DIRECTORY",
2318 help=self.__stripSpaces(self.bindingRoot.__doc__))
2319 group.add_option('-r', '--write-for-customization',
2320 action='store_true', dest='write_for_customization',
2321 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns on the feature.'))
2322 group.add_option('--no-write-for-customization',
2323 action='store_false', dest='write_for_customization',
2324 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns off the feature (I{default}).'))
2325 parser.add_option_group(group)
2326
2327 group = optparse.OptionGroup(parser, 'Reading Namespace Archives', 'Locating and loading (or inhibiting load of) namespace archives.')
2328 group.add_option('--archive-path', metavar="PATH",
2329 help=self.__stripSpaces(self.archivePath.__doc__))
2330 group.add_option('--pre-load-archive', metavar="FILE",
2331 action='append',
2332 help=self.__stripSpaces(self.addPreLoadArchive.__doc__))
2333 group.add_option('--no-load-namespace', metavar="URI",
2334 action='append',
2335 help=self.__stripSpaces(self.addNoLoadNamespace.__doc__))
2336 parser.add_option_group(group)
2337
2338 group = optparse.OptionGroup(parser, 'Writing Namespace Archives', 'Control the location and content of a namespace archive corresponding to a binding generation.')
2339 group.add_option('--archive-to-file', metavar="FILE",
2340 help=self.__stripSpaces(self.archiveToFile.__doc__))
2341 group.add_option('--public-namespace', metavar="URI",
2342 action='append',
2343 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a public archive member.'))
2344 group.add_option('--private-namespace', metavar="URI",
2345 action='append',
2346 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a private archive member.'))
2347 group.add_option('--default-namespace-public',
2348 action="store_true", dest='default_namespace_public',
2349 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{public} (I{default}).'))
2350 group.add_option('--default-namespace-private',
2351 action="store_false", dest='default_namespace_public',
2352 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{private}.'))
2353 parser.add_option_group(group)
2354
2355 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.")
2356 group.add_option('--validate-changes',
2357 action='store_true', dest='validate_changes',
2358 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns on validation (default).'))
2359 group.add_option('--no-validate-changes',
2360 action='store_false', dest='validate_changes',
2361 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns off validation.'))
2362 parser.add_option_group(group)
2363
2364 group = optparse.OptionGroup(parser, 'Miscellaneous Options', "Anything else.")
2365 group.add_option('--logging-config-file', metavar="FILE",
2366 help=self.__stripSpaces(self.loggingConfigFile.__doc__))
2367 parser.add_option_group(group)
2368
2369 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.")
2370
2371 group.add_option('--allow-absent-module',
2372 action='store_true', dest='allow_absent_module',
2373 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns on the feature.'))
2374 group.add_option('--no-allow-absent-module',
2375 action='store_false', dest='allow_absent_module',
2376 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns off the feature (default).'))
2377 group.add_option('--allow-builtin-generation',
2378 action='store_true', dest='allow_builtin_generation',
2379 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns on the feature.'))
2380 group.add_option('--no-allow-builtin-generation',
2381 action='store_false', dest='allow_builtin_generation',
2382 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns off the feature (default).'))
2383 parser.add_option_group(group)
2384
2385 self.__optionParser = parser
2386 return self.__optionParser
2387 __optionParser = None
2388
2390 """Return a command line option sequence that could be used to
2391 construct an equivalent configuration.
2392
2393 @note: If you extend the option parser, as is done by
2394 C{pyxbgen}, this may not be able to reconstruct the correct
2395 command line."""
2396 opts = []
2397 module_list = self.moduleList()
2398 schema_list = self.schemaLocationList()
2399 while module_list and schema_list:
2400 ml = module_list.pop(0)
2401 sl = schema_list.pop(0)
2402 if isinstance(sl, tuple):
2403 sl = sl[0]
2404 opts.extend(['--schema-location=' + sl, '--module=' + ml])
2405 for sl in schema_list:
2406 opts.append('--schema-location=' + sl)
2407 if self.schemaRoot() is not None:
2408 opts.append('--schema-root=' + self.schemaRoot())
2409 if self.schemaStrippedPrefix() is not None:
2410 opts.append('--schema-stripped-prefix=%s' + self.schemaStrippedPrefix())
2411 for (pfx, sub) in self.locationPrefixRewriteMap():
2412 opts.append('--location-prefix-rewrite=%s=%s' % (pfx, sub))
2413 if self.modulePrefix() is not None:
2414 opts.append('--module-prefix=' + self.modulePrefix())
2415 opts.append('--binding-root=' + self.bindingRoot())
2416 if self.archivePath() is not None:
2417 opts.append('--archive-path=' + self.archivePath())
2418 for ns in self.noLoadNamespaces():
2419 opts.append('--no-load-namespace=' + ns.uri())
2420 for fps in self.preLoadArchives():
2421 opts.append('--pre-load-archive=' + fps)
2422 if self.archiveToFile() is not None:
2423 opts.append('--archive-to-file=' + self.archiveToFile())
2424 for (ns, visibility) in self.namespaceVisibilityMap():
2425 if visibility:
2426 opts.append('--public-namespace=' + ns.uri())
2427 else:
2428 opts.append('--private-namespace=' + ns.uri())
2429 if self.defaultNamespacePublic():
2430 opts.append('--default-namespace-public')
2431 else:
2432 opts.append('--default-namespace-private')
2433 for (val, opt) in ( (self.validateChanges(), 'validate-changes'),
2434 (self.writeForCustomization(), 'write-for-customization'),
2435 (self.allowAbsentModule(), 'allow-absent-module'),
2436 (self.allowBuiltinGeneration(), 'allow-builtin-generation') ):
2437 if val:
2438 opts.append('--' + opt)
2439 else:
2440 opts.append('--no-' + opt)
2441 if self.uriContentArchiveDirectory() is not None:
2442 opts.append('--uri-content-archive-directory=%s' + self.uriContentArchiveDirectory())
2443 return opts
2444
2450
2452 """Provide a Python module path for the module record.
2453
2454 This is the path by which the module bindings associated with
2455 C{module_record} will be imported.
2456
2457 If a path had already been assigned to the module, it is left
2458 in place.
2459
2460 @param module_record: Information about a collection of related bindings
2461 @type module_record: L{pyxb.namespace.archive.ModuleRecord}
2462
2463 @param module_path: Default path to use
2464 @type module_path: C{str}
2465
2466 @return: C{module_record}
2467 """
2468 if module_record.modulePath() is not None:
2469 return module_record
2470 namespace = module_record.namespace()
2471 if not namespace.isAbsentNamespace():
2472
2473 if (module_path is None) and not (namespace.prefix() is None):
2474 module_path = namespace.prefix()
2475
2476 module_path = self.namespaceModuleMap().get(namespace.uri(), module_path)
2477 if (module_path is not None) and self.modulePrefix():
2478
2479 module_path = '.'.join([self.modulePrefix(), module_path])
2480 module_record.setModulePath(module_path)
2481 return module_record
2482
2483 __didResolveExternalSchema = False
2485 if self.__didResolveExternalSchema and (not reset):
2486 raise pyxb.PyXBException('Cannot resolve external schema multiple times')
2487
2488
2489
2490
2491 required_archives = pyxb.namespace.archive.NamespaceArchive.PreLoadArchives(self.archivePath(), self.preLoadArchives())
2492 for nsa in required_archives:
2493 nsa.readNamespaces()
2494
2495
2496
2497
2498 for ns in self.noLoadNamespaces():
2499 assert isinstance(ns, pyxb.namespace.Namespace)
2500 ns.markNotLoadable()
2501
2502
2503 while self.__schemaLocationList:
2504 sl = self.__schemaLocationList.pop(0)
2505 if isinstance(sl, tuple):
2506 (sl, converter) = sl
2507 else:
2508 converter = None
2509 try:
2510 if converter is None:
2511 schema = xs.schema.CreateFromLocation(absolute_schema_location=self.normalizeSchemaLocation(sl),
2512 generation_uid=self.generationUID(),
2513 uri_content_archive_directory=self.uriContentArchiveDirectory())
2514 else:
2515 schema = converter(self, sl)
2516 self.addSchema(schema)
2517 except pyxb.SchemaUniquenessError as e:
2518 _log.info('Skipped redundant translation of %s defining %s', e.schemaLocation(), e.namespace())
2519 self.addSchema(e.existingSchema())
2520
2521
2522
2523 for schema in self.__schemas:
2524 if isinstance(schema, basestring):
2525 schema = xs.schema.CreateFromDocument(schema, generation_uid=self.generationUID())
2526 origin = schema.originRecord()
2527 assert origin is not None
2528 module_path = None
2529 if self.__moduleList:
2530 module_path = self.__moduleList.pop(0)
2531 self.assignModulePath(origin.moduleRecord(), module_path)
2532 assert schema.targetNamespace() == origin.moduleRecord().namespace()
2533 self.addNamespace(schema.targetNamespace())
2534 self.__didResolveExternalSchema = True
2535
2536
2537 self.__componentGraph = None
2538 self.__componentOrder = None
2539
2563
2610
2611 __moduleRecords = None
2612 __componentGraph = None
2613 __componentOrder = None
2614
2616 """The set of L{pyxb.namespace.archive.ModuleRecord} instances
2617 associated with schema processed in this generation
2618 instance.
2619
2620 These should be in one-to-one correspondence with the
2621 namespaces for which bindings are being generated. Multiple
2622 input schemas may contribute to a single module record; all
2623 material in that record is placed in a single binding file.
2624 """
2625 if self.__moduleRecords is None:
2626 self.__resolveComponentDependencies()
2627 return self.__moduleRecords
2628
2633
2638
2640
2641
2642
2643
2644
2645 module_graph = pyxb.utils.utility.Graph()
2646 [ module_graph.addRoot(_mr) for _mr in self.moduleRecords() ]
2647 for (s, t) in self.componentGraph().edges():
2648 module_graph.addEdge(s._objectOrigin().moduleRecord(), t._objectOrigin().moduleRecord())
2649 module_scc_order = module_graph.sccOrder()
2650
2651 record_binding_map = {}
2652 modules = []
2653 nsvm = self.namespaceVisibilityMap()
2654 for mr_scc in module_scc_order:
2655 scc_modules = [ ]
2656 for mr in mr_scc:
2657 mr._setIsPublic(nsvm.get(mr.namespace(), self.defaultNamespacePublic()))
2658 self.assignModulePath(mr)
2659 if (mr.modulePath() is None) and self.generateToFiles():
2660 raise pyxb.BindingGenerationError('No prefix or module name available for %s' % (mr,))
2661 if (not mr.isPublic()) and (mr.modulePath() is not None):
2662 elts = mr.modulePath().split('.')
2663 elts[-1] = '_%s' % (elts[-1],)
2664 mr.setModulePath('.'.join(elts))
2665 nsm = NamespaceModule(self, mr, mr_scc)
2666 record_binding_map[mr] = nsm
2667 scc_modules.append(nsm)
2668
2669 scc_modules.sort(key=lambda _nm: _nm.namespace().uri())
2670 modules.extend(scc_modules)
2671 if 1 < len(mr_scc):
2672 ngm = NamespaceGroupModule(self, scc_modules)
2673 modules.append(ngm)
2674 for nsm in scc_modules:
2675 nsm.setNamespaceGroupModule(ngm)
2676
2677 element_declarations = []
2678 type_definitions = []
2679 for c in self.componentOrder():
2680 if isinstance(c, xs.structures.ElementDeclaration) and c._scopeIsGlobal():
2681
2682 nsm = record_binding_map[c._objectOrigin().moduleRecord()]
2683 nsm.bindComponent(c)
2684 element_declarations.append(c)
2685 elif c.isTypeDefinition():
2686 type_definitions.append(c)
2687 else:
2688
2689 pass
2690
2691 simple_type_definitions = []
2692 complex_type_definitions = []
2693 for td in type_definitions:
2694 nsm = record_binding_map[td._objectOrigin().moduleRecord()]
2695 assert nsm is not None, 'No namespace module for %s type %s scope %s namespace %s' % (td.expandedName(), type(td), td._scope(), td.bindingNamespace)
2696 module_context = nsm.bindComponent(td)
2697 assert isinstance(module_context, _ModuleNaming_mixin), 'Unexpected type %s' % (type(module_context),)
2698 if isinstance(td, xs.structures.SimpleTypeDefinition):
2699 _PrepareSimpleTypeDefinition(td, self, nsm, module_context)
2700 simple_type_definitions.append(td)
2701 elif isinstance(td, xs.structures.ComplexTypeDefinition):
2702 _PrepareComplexTypeDefinition(td, self, nsm, module_context)
2703 complex_type_definitions.append(td)
2704 else:
2705 assert False, 'Unexpected component type %s' % (type(td),)
2706
2707 for ngm in modules:
2708 if isinstance(ngm, NamespaceGroupModule):
2709 for m in ngm.namespaceModules():
2710 m.addImportsFrom(ngm)
2711
2712 for std in simple_type_definitions:
2713 GenerateSTD(std, self)
2714 for ctd in complex_type_definitions:
2715 GenerateCTD(ctd, self)
2716 for ed in element_declarations:
2717 GenerateED(ed, self)
2718
2719 self.__bindingModules = modules
2720
2721 __bindingModules = None
2728
2744
2747