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