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