1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """The really ugly code that generates the Python bindings. This
16 whole thing is going to be refactored once customized generation makes
17 it to the top of the task queue."""
18
19 import pyxb
20 import pyxb.xmlschema as xs
21 import StringIO
22 import datetime
23 import urlparse
24 import errno
25
26 from pyxb.utils import utility
27 from pyxb.utils import templates
28 from pyxb.utils import domutils
29 import basis
30 import content
31 import datatypes
32 import facets
33
34 import nfa
35
36 import types
37 import sys
38 import traceback
39 import xml.dom
40 import os.path
41 import StringIO
42
43
44
45 UniqueInBinding = set([ 'pyxb', 'sys', 'Namespace', 'ModuleRecord', 'CreateFromDocument', 'CreateFromDOM' ])
55
57 """Base class for something that requires fairly complex activity
58 in order to generate its literal value."""
59
60
61
62 __ownerClass = None
63
64
65 __literal = None
66
70
74
77
82
98
100 __wildcard = None
101
103 self.__wildcard = wildcard
104 super(ReferenceWildcard, self).__init__(**kw)
105
106 template_map = { }
107 template_map['Wildcard'] = 'pyxb.binding.content.Wildcard'
108 if (xs.structures.Wildcard.NC_any == wildcard.namespaceConstraint()):
109 template_map['nc'] = templates.replaceInText('%{Wildcard}.NC_any', **template_map)
110 elif isinstance(wildcard.namespaceConstraint(), (set, frozenset)):
111 namespaces = []
112 for ns in wildcard.namespaceConstraint():
113 if ns is None:
114 namespaces.append(None)
115 else:
116 namespaces.append(ns.uri())
117 template_map['nc'] = 'set(%s)' % (",".join( [ repr(_ns) for _ns in namespaces ]))
118 else:
119 assert isinstance(wildcard.namespaceConstraint(), tuple)
120 ns = wildcard.namespaceConstraint()[1]
121 if ns is not None:
122 ns = ns.uri()
123 template_map['nc'] = templates.replaceInText('(%{Wildcard}.NC_not, %{namespace})', namespace=repr(ns), **template_map)
124 template_map['pc'] = wildcard.processContents()
125 self.setLiteral(templates.replaceInText('%{Wildcard}(process_contents=%{Wildcard}.PC_%{pc}, namespace_constraint=%{nc})', **template_map))
126
136
146
153
161
163 enumerationElement = None
164
166
167
168
169
170
171
172
173
174 value = kw.get('enum_value', None)
175 assert (value is None) or isinstance(value, facets._Enumeration_mixin)
176
177
178
179 facet_instance = kw.get('facet_instance', None)
180 if facet_instance is None:
181 assert isinstance(value, facets._Enumeration_mixin)
182 facet_instance = value._CF_enumeration
183 assert isinstance(facet_instance, facets.CF_enumeration)
184
185
186
187 self.enumerationElement = kw.get('enumeration_element', None)
188 if self.enumerationElement is None:
189 assert value is not None
190 self.enumerationElement = facet_instance.elementForValue(value)
191 assert isinstance(self.enumerationElement, facets._EnumerationElement)
192 if self.enumerationElement.tag() is None:
193 self.enumerationElement._setTag(utility.MakeIdentifier(self.enumerationElement.unicodeValue()))
194 binding_tag = utility.PrepareIdentifier(self.enumerationElement.tag(), kw['class_unique'], kw['class_keywords'])
195 if self.enumerationElement.bindingTag() is None:
196
197
198 self.enumerationElement._setBindingTag(binding_tag)
199
200
201
202 kw.setdefault('type_definition', facet_instance.valueDatatype())
203
204 super(ReferenceEnumerationMember, self).__init__(**kw)
205
206 self.setLiteral(self._addTypePrefix(binding_tag, **kw))
207
209
210 if isinstance(value, types.DictionaryType):
211 return ', '.join([ '%s=%s' % (k, pythonLiteral(v, **kw)) for (k, v) in value.items() ])
212
213
214 if isinstance(value, types.ListType):
215 return [ pythonLiteral(_v, **kw) for _v in value ]
216
217
218 if isinstance(value, pyxb.namespace.ExpandedName):
219 return pythonLiteral(ReferenceExpandedName(expanded_name=value, **kw))
220
221
222 if isinstance(value, (types.TupleType, set)):
223 return type(value)(pythonLiteral(list(value), **kw))
224
225
226
227 if isinstance(value, facets._Enumeration_mixin):
228 return pythonLiteral(ReferenceEnumerationMember(enum_value=value, **kw))
229
230
231
232
233 if isinstance(value, basis.simpleTypeDefinition):
234 return PrefixModule(value, value.pythonLiteral())
235
236 if isinstance(value, pyxb.namespace.Namespace):
237 return pythonLiteral(ReferenceNamespace(namespace=value, **kw))
238
239 if isinstance(value, type):
240 if issubclass(value, basis.simpleTypeDefinition):
241 return PrefixModule(value)
242 if issubclass(value, facets.Facet):
243 return PrefixModule(value)
244
245
246 if isinstance(value, types.StringTypes):
247 return utility.QuotedEscaped(value,)
248
249 if isinstance(value, facets.Facet):
250 return pythonLiteral(ReferenceFacet(facet=value, **kw))
251
252
253 if isinstance(value, facets._PatternElement):
254 return pythonLiteral(value.pattern)
255
256
257 if isinstance(value, facets._EnumerationElement):
258 return pythonLiteral(value.value())
259
260
261 if isinstance(value, xs.structures.Particle):
262 return pythonLiteral(ReferenceParticle(value, **kw))
263
264
265 if isinstance(value, xs.structures.Wildcard):
266 return pythonLiteral(ReferenceWildcard(value, **kw))
267
268
269 if isinstance(value, xs.structures._SchemaComponent_mixin):
270 return pythonLiteral(ReferenceSchemaComponent(value, **kw))
271
272
273 if isinstance(value, ReferenceLiteral):
274 return value.asLiteral()
275
276
277 if isinstance(value, pyxb.namespace.Namespace):
278 return repr(value.uri())
279
280
281 if isinstance(value, (types.NoneType, types.BooleanType, types.FloatType, types.IntType, types.LongType)):
282 return repr(value)
283
284 raise Exception('Unexpected literal type %s' % (type(value),))
285 print 'Unexpected literal type %s' % (type(value),)
286 return str(value)
287
290 mga_tag = '__AModelGroup'
291 template_map['mga_tag'] = mga_tag
292 lines = []
293 lines2 = []
294 for ( dfa, is_required ) in mga.particles():
295 ( dfa_tag, dfa_lines ) = GenerateContentModel(ctd, dfa, binding_module, **kw)
296 lines.extend(dfa_lines)
297 template_map['dfa_tag'] = dfa_tag
298 template_map['is_required'] = binding_module.literal(is_required, **kw)
299 lines2.append(templates.replaceInText(' %{content}.ModelGroupAllAlternative(%{ctd}.%{dfa_tag}, %{is_required}),', **template_map))
300 lines.append(templates.replaceInText('%{mga_tag} = %{content}.ModelGroupAll(alternatives=[', **template_map))
301 lines.extend(lines2)
302 lines.append('])')
303 return (mga_tag, lines)
304
305 -def GenerateContentModel (ctd, automaton, binding_module, **kw):
306 cmi = None
307 template_map = { }
308 template_map['ctd'] = binding_module.literal(ctd, **kw)
309 try:
310 cmi = '_ContentModel_%d' % (ctd.__contentModelIndex,)
311 ctd.__contentModelIndex += 1
312 except AttributeError:
313 cmi = '_ContentModel'
314 ctd.__contentModelIndex = 1
315 template_map['cm_tag'] = cmi
316 template_map['content'] = 'pyxb.binding.content'
317 template_map['state_comma'] = ' '
318 lines = []
319 lines2 = []
320 for (state, transitions) in automaton.items():
321 if automaton.end() == state:
322 continue
323 template_map['state'] = binding_module.literal(state)
324 template_map['is_final'] = binding_module.literal(None in transitions)
325
326 lines2.append(templates.replaceInText('%{state_comma} %{state} : %{content}.ContentModelState(state=%{state}, is_final=%{is_final}, transitions=[', **template_map))
327 template_map['state_comma'] = ','
328 lines3 = []
329 for (key, destinations) in transitions.items():
330 if key is None:
331 continue
332 assert 1 == len(destinations)
333 template_map['next_state'] = binding_module.literal(list(destinations)[0], **kw)
334 if isinstance(key, xs.structures.Wildcard):
335 template_map['kw_key'] = 'term'
336 template_map['kw_val'] = binding_module.literal(key, **kw)
337 elif isinstance(key, nfa.AllWalker):
338 (mga_tag, mga_defns) = GenerateModelGroupAll(ctd, key, binding_module, template_map.copy(), **kw)
339 template_map['kw_key'] = 'term'
340 template_map['kw_val'] = mga_tag
341 lines.extend(mga_defns)
342 else:
343 assert isinstance(key, xs.structures.ElementDeclaration)
344 template_map['kw_key'] = 'element_use'
345 template_map['kw_val'] = templates.replaceInText('%{ctd}._UseForTag(%{field_tag})', field_tag=binding_module.literal(key.expandedName(), **kw), **template_map)
346 lines3.append(templates.replaceInText('%{content}.ContentModelTransition(next_state=%{next_state}, %{kw_key}=%{kw_val}),',
347 **template_map))
348 lines2.extend([ ' '+_l for _l in lines3 ])
349 lines2.append("])")
350
351 lines.append(templates.replaceInText('%{ctd}.%{cm_tag} = %{content}.ContentModel(state_map = {', **template_map))
352 lines.extend([' '+_l for _l in lines2 ])
353 lines.append("})")
354 return (cmi, lines)
355
373
375 binding_module = kw['binding_module']
376 outf = binding_module.bindingIO()
377 facet_instances = []
378 gen_enum_tag = _useEnumerationTags(td)
379 for (fc, fi) in td.facets().items():
380
381
382 if (fi is None) and (fc in td.baseTypeDefinition().facets()):
383
384
385 continue
386 if (fi is not None) and (fi.ownerTypeDefinition() != td):
387
388
389 continue
390 argset = { }
391 is_collection = issubclass(fc, facets._CollectionFacet_mixin)
392 if issubclass(fc, facets._LateDatatype_mixin):
393 vdt = td
394 if fc.LateDatatypeBindsSuperclass():
395 vdt = vdt.baseTypeDefinition()
396 argset['value_datatype'] = vdt
397 if fi is not None:
398 if not is_collection:
399 argset['value'] = fi.value()
400 if isinstance(fi, facets.CF_enumeration):
401 argset['enum_prefix'] = fi.enumPrefix()
402 facet_var = ReferenceFacetMember(type_definition=td, facet_class=fc, **kw)
403 outf.write("%s = %s(%s)\n" % binding_module.literal( (facet_var, fc, argset ), **kw))
404 facet_instances.append(binding_module.literal(facet_var, **kw))
405 if (fi is not None) and is_collection:
406 for i in fi.items():
407 if isinstance(i, facets._EnumerationElement):
408 enum_config = '%s.addEnumeration(unicode_value=%s)' % binding_module.literal( ( facet_var, i.unicodeValue() ), **kw)
409 if gen_enum_tag:
410 enum_member = ReferenceEnumerationMember(type_definition=td, facet_instance=fi, enumeration_element=i, **kw)
411 outf.write("%s = %s\n" % (binding_module.literal(enum_member, **kw), enum_config))
412 if fi.enumPrefix() is not None:
413 outf.write("%s_%s = %s\n" % (fi.enumPrefix(), i.tag(), binding_module.literal(enum_member, **kw)))
414 else:
415 outf.write("%s\n" % (enum_config,))
416 if isinstance(i, facets._PatternElement):
417 outf.write("%s.addPattern(pattern=%s)\n" % binding_module.literal( (facet_var, i.pattern ), **kw))
418 if gen_enum_tag and (xs.structures.SimpleTypeDefinition.VARIETY_union == td.variety()):
419
420
421 fi = td.facets().get(facets.CF_enumeration)
422 if fi is None:
423
424 for mtd in td.memberTypeDefinitions():
425 if not _useEnumerationTags(mtd):
426 continue
427 fi = mtd.facets().get(facets.CF_enumeration)
428 if fi is None:
429 continue
430 for i in fi.items():
431 assert isinstance(i, facets._EnumerationElement)
432 etd = i.enumeration().ownerTypeDefinition()
433 enum_member = ReferenceEnumerationMember(type_definition=td, facet_instance=fi, enumeration_element=i, **kw)
434 outf.write("%-50s%s\n" % ('%s = %s' % binding_module.literal( (enum_member, i.unicodeValue()) ),
435 '# originally %s.%s' % (binding_module.literal(etd), i.bindingTag())))
436 if 2 <= len(facet_instances):
437 map_args = ",\n ".join(facet_instances)
438 else:
439 map_args = ','.join(facet_instances)
440 outf.write("%s._InitializeFacetMap(%s)\n" % (binding_module.literal(td, **kw), map_args))
441
443
444 binding_module = generator.moduleForComponent(std)
445 outf = binding_module.bindingIO()
446
447 class_keywords = frozenset(basis.simpleTypeDefinition._ReservedSymbols)
448 class_unique = set()
449
450 kw = { }
451 kw['binding_module'] = binding_module
452 kw['class_keywords'] = class_keywords
453 kw['class_unique'] = class_unique
454
455 parent_classes = [ binding_module.literal(std.baseTypeDefinition(), **kw) ]
456 enum_facet = std.facets().get(facets.CF_enumeration, None)
457 if (enum_facet is not None) and (enum_facet.ownerTypeDefinition() == std):
458 parent_classes.append('pyxb.binding.basis.enumeration_mixin')
459
460 template_map = { }
461 template_map['std'] = binding_module.literal(std, **kw)
462 template_map['superclasses'] = ''
463 if 0 < len(parent_classes):
464 template_map['superclasses'] = ', '.join(parent_classes)
465 template_map['expanded_name'] = binding_module.literal(std.expandedName(), **kw)
466 template_map['namespaceReference'] = binding_module.literal(std.bindingNamespace(), **kw)
467 if std.annotation() is not None:
468 template_map['documentation'] = std.annotation().asDocString()
469 template_map['documentation_expr'] = binding_module.literal(std.annotation().text())
470 else:
471 template_map['documentation'] = ''
472 template_map['documentation_expr'] = binding_module.literal(None)
473
474
475
476 common_template = '''
477 """%{description}
478 %{documentation}"""
479
480 _ExpandedName = %{expanded_name}
481 _Documentation = %{documentation_expr}
482 '''
483 if xs.structures.SimpleTypeDefinition.VARIETY_absent == std.variety():
484 template = '''
485 # The ur SimpleTypeDefinition
486 class %{std} (%{superclasses}):
487 ''' + common_template
488 template_map['description'] = ''
489 elif xs.structures.SimpleTypeDefinition.VARIETY_atomic == std.variety():
490 template = '''
491 # Atomic SimpleTypeDefinition
492 class %{std} (%{superclasses}):
493 ''' + common_template
494 template_map['description'] = ''
495 elif xs.structures.SimpleTypeDefinition.VARIETY_list == std.variety():
496 template = '''
497 # List SimpleTypeDefinition
498 # superclasses %{superclasses}
499 class %{std} (pyxb.binding.basis.STD_list):
500 ''' + common_template + '''
501 _ItemType = %{itemtype}
502 '''
503 template_map['itemtype'] = binding_module.literal(std.itemTypeDefinition(), **kw)
504 template_map['description'] = templates.replaceInText('Simple type that is a list of %{itemtype}', **template_map)
505 elif xs.structures.SimpleTypeDefinition.VARIETY_union == std.variety():
506 template = '''
507 # Union SimpleTypeDefinition
508 # superclasses %{superclasses}
509 class %{std} (pyxb.binding.basis.STD_union):
510 ''' + common_template + '''
511 _MemberTypes = ( %{membertypes}, )
512 '''
513 template_map['membertypes'] = ", ".join( [ binding_module.literal(_mt, **kw) for _mt in std.memberTypeDefinitions() ])
514 template_map['description'] = templates.replaceInText('Simple type that is a union of %{membertypes}', **template_map)
515
516 if 0 == len(template_map['description']):
517 template_map['description'] = 'No information'
518 outf.write(templates.replaceInText(template, **template_map))
519
520 generate_facets = False
521 if generate_facets:
522
523 if std.isBuiltin():
524 GenerateFacets(std, generator, **kw)
525 else:
526 GenerateFacets(std, generator, **kw)
527
528 if std.name() is not None:
529 outf.write(templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{std})\n",
530 localName=binding_module.literal(std.name(), **kw), **template_map))
531
533 template_map = { }
534 template_map['name'] = unicode(ed.expandedName())
535 template_map['name_expr'] = binding_module.literal(ed.expandedName(), **kw)
536 template_map['namespaceReference'] = binding_module.literal(ed.bindingNamespace(), **kw)
537 if (ed.SCOPE_global == ed.scope()):
538 template_map['class'] = binding_module.literal(ed, **kw)
539 template_map['localName'] = binding_module.literal(ed.name(), **kw)
540 template_map['map_update'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('elementBinding', %{localName}, %{class})", **template_map)
541 else:
542 template_map['scope'] = binding_module.literal(ed.scope(), **kw)
543 if ed.annotation() is not None:
544 template_map['documentation'] = binding_module.literal(unicode(ed.annotation()))
545 if ed.abstract():
546 template_map['abstract'] = binding_module.literal(ed.abstract(), **kw)
547 if ed.nillable():
548 template_map['nillable'] = binding_module.literal(ed.nillable(), **kw)
549 if ed.default():
550 template_map['defaultValue'] = binding_module.literal(ed.default(), **kw)
551 template_map['typeDefinition'] = binding_module.literal(ed.typeDefinition(), **kw)
552 if ed.substitutionGroupAffiliation():
553 template_map['substitution_group'] = binding_module.literal(ed.substitutionGroupAffiliation(), **kw)
554 aux_init = []
555 for k in ( 'nillable', 'abstract', 'scope', 'documentation' ):
556 if k in template_map:
557 aux_init.append('%s=%s' % (k, template_map[k]))
558 template_map['element_aux_init'] = ''
559 if 0 < len(aux_init):
560 template_map['element_aux_init'] = ', ' + ', '.join(aux_init)
561
562 return template_map
563
565 binding_module = generator.moduleForComponent(ctd)
566 outf = binding_module.bindingIO()
567
568 content_type = None
569 prolog_template = None
570 template_map = { }
571 template_map['ctd'] = binding_module.literal(ctd, **kw)
572 base_type = ctd.baseTypeDefinition()
573 content_type_tag = ctd._contentTypeTag()
574
575 template_map['base_type'] = binding_module.literal(base_type, **kw)
576 template_map['namespaceReference'] = binding_module.literal(ctd.bindingNamespace(), **kw)
577 template_map['expanded_name'] = binding_module.literal(ctd.expandedName(), **kw)
578 template_map['simple_base_type'] = binding_module.literal(None, **kw)
579 template_map['contentTypeTag'] = content_type_tag
580 template_map['is_abstract'] = repr(not not ctd.abstract())
581
582 need_content = False
583 content_basis = None
584 if (ctd.CT_SIMPLE == content_type_tag):
585 content_basis = ctd.contentType()[1]
586 template_map['simple_base_type'] = binding_module.literal(content_basis, **kw)
587 elif (ctd.CT_MIXED == content_type_tag):
588 content_basis = ctd.contentType()[1]
589 need_content = True
590 elif (ctd.CT_ELEMENT_ONLY == content_type_tag):
591 content_basis = ctd.contentType()[1]
592 need_content = True
593 need_content = False
594
595 prolog_template = '''
596 # Complex type %{ctd} with content type %{contentTypeTag}
597 class %{ctd} (%{superclass}):
598 _TypeDefinition = %{simple_base_type}
599 _ContentTypeTag = pyxb.binding.basis.complexTypeDefinition._CT_%{contentTypeTag}
600 _Abstract = %{is_abstract}
601 _ExpandedName = %{expanded_name}
602 '''
603
604
605
606
607 inherits_from_base = True
608 template_map['superclass'] = binding_module.literal(base_type, **kw)
609 if ctd._isHierarchyRoot():
610 inherits_from_base = False
611 template_map['superclass'] = 'pyxb.binding.basis.complexTypeDefinition'
612 assert base_type.nameInBinding() is not None
613
614
615 class_keywords = frozenset(basis.complexTypeDefinition._ReservedSymbols)
616 class_unique = set()
617
618
619
620
621
622
623
624 element_name_map = { }
625 element_uses = []
626
627 definitions = []
628
629 definitions.append('# Base type is %{base_type}')
630
631
632
633
634
635 if isinstance(content_basis, xs.structures.Particle):
636 plurality_data = content_basis.pluralityData().combinedPlurality()
637
638 outf.postscript().append("\n\n")
639 for (ed, is_plural) in plurality_data.items():
640
641 ef_map = ed._templateMap()
642 if ed.scope() == ctd:
643 ef_map.update(elementDeclarationMap(ed, binding_module, **kw))
644 aux_init = []
645 ef_map['is_plural'] = repr(is_plural)
646 element_uses.append(templates.replaceInText('%{use}.name() : %{use}', **ef_map))
647 if 0 == len(aux_init):
648 ef_map['aux_init'] = ''
649 else:
650 ef_map['aux_init'] = ', ' + ', '.join(aux_init)
651 ef_map['element_binding'] = utility.PrepareIdentifier('%s_elt' % (ef_map['id'],), class_unique, class_keywords, private=True)
652 if ed.annotation() is not None:
653 ef_map['documentation'] = binding_module.literal(unicode(ed.annotation()))
654 else:
655 ef_map['documentation'] = binding_module.literal(None)
656 if ed.scope() != ctd:
657 definitions.append(templates.replaceInText('''
658 # Element %{id} (%{name}) inherited from %{decl_type_en}''', decl_type_en=unicode(ed.scope().expandedName()), **ef_map))
659 continue
660
661 if ed.expandedName().localName() != ef_map['id']:
662 print 'Element %s.%s renamed to %s' % (ctd.expandedName(), ed.expandedName(), ef_map['id'])
663 definitions.append(templates.replaceInText('''
664 # Element %{name} uses Python identifier %{id}
665 %{use} = pyxb.binding.content.ElementUse(%{name_expr}, '%{id}', '%{key}', %{is_plural}%{aux_init})
666 ''', **ef_map))
667
668 if basis.BINDING_STYLE_ACCESSOR == generator.bindingStyle():
669 definitions.append(templates.replaceInText('''
670 def %{inspector} (self):
671 """Get the value of the %{name} element."""
672 return self.%{use}.value(self)
673 def %{mutator} (self, new_value):
674 """Set the value of the %{name} element. Raises BadValueTypeException
675 if the new value is not consistent with the element's type."""
676 return self.%{use}.set(self, new_value)''', **ef_map))
677 if is_plural:
678 definitions.append(templates.replaceInText('''
679 def %{appender} (self, new_value):
680 """Add the value as another occurrence of the %{name} element. Raises
681 BadValueTypeException if the new value is not consistent with the
682 element's type."""
683 return self.%{use}.append(self, new_value)''', **ef_map))
684 elif basis.BINDING_STYLE_PROPERTY == generator.bindingStyle():
685 definitions.append(templates.replaceInText('''
686 %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation})
687 ''', **ef_map))
688 else:
689 raise pyxb.LogicError('Unexpected binding style %s' % (generator.bindingStyle(),))
690 outf.postscript().append(templates.replaceInText('''
691 %{ctd}._AddElement(pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init}))
692 ''', ctd=template_map['ctd'], **ef_map))
693
694 fa = nfa.Thompson(content_basis).nfa()
695 fa = fa.buildDFA()
696 (cmi, cmi_defn) = GenerateContentModel(ctd=ctd, automaton=fa, binding_module=binding_module, **kw)
697 outf.postscript().append("\n".join(cmi_defn))
698 outf.postscript().append("\n")
699
700 if need_content:
701 PostscriptItems.append(templates.replaceInText('''
702 %{ctd}._Content = %{particle}
703 ''', **template_map))
704
705
706 attribute_uses = []
707
708
709
710
711
712
713
714
715 for au in ctd.attributeUses():
716 ad = au.attributeDeclaration()
717 assert isinstance(ad.scope(), xs.structures.ComplexTypeDefinition), 'unexpected scope %s' % (ad.scope(),)
718 au_map = ad._templateMap()
719 if ad.scope() == ctd:
720 assert isinstance(au_map, dict)
721 if au.restrictionOf() is not None:
722
723 au_map = au.restrictionOf().attributeDeclaration()._templateMap().copy()
724 definitions.append(templates.replaceInText('''
725 # Attribute %{id} is restricted from parent''', **au_map))
726
727 assert ad.typeDefinition() is not None
728 au_map['attr_type'] = binding_module.literal(ad.typeDefinition(), **kw)
729
730 vc_source = ad
731 if au.valueConstraint() is not None:
732 vc_source = au
733 aux_init = []
734 if vc_source.fixed() is not None:
735 aux_init.append('fixed=True')
736 aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.fixed(), **kw),))
737 elif vc_source.default() is not None:
738 aux_init.append('unicode_default=%s' % (binding_module.literal(vc_source.default(), **kw),))
739 if au.required():
740 aux_init.append('required=True')
741 if au.prohibited():
742 aux_init.append('prohibited=True')
743 if 0 == len(aux_init):
744 au_map['aux_init'] = ''
745 else:
746 aux_init.insert(0, '')
747 au_map['aux_init'] = ', '.join(aux_init)
748 if ad.annotation() is not None:
749 au_map['documentation'] = binding_module.literal(unicode(ad.annotation()))
750 else:
751 au_map['documentation'] = binding_module.literal(None)
752 if ad.scope() != ctd:
753 definitions.append(templates.replaceInText('''
754 # Attribute %{id} inherited from %{decl_type_en}''', decl_type_en=unicode(ad.scope().expandedName()), **au_map))
755 continue
756
757 attribute_uses.append(templates.replaceInText('%{use}.name() : %{use}', **au_map))
758 if ad.expandedName().localName() != au_map['id']:
759 print 'Attribute %s.%s renamed to %s' % (ctd.expandedName(), ad.expandedName(), au_map['id'])
760 definitions.append(templates.replaceInText('''
761 # Attribute %{name} uses Python identifier %{id}
762 %{use} = pyxb.binding.content.AttributeUse(%{name_expr}, '%{id}', '%{key}', %{attr_type}%{aux_init})''', **au_map))
763 if au.prohibited():
764 if basis.BINDING_STYLE_ACCESSOR == generator.bindingStyle():
765 definitions.append(templates.replaceInText('''
766 # Attribute %{id} marked prohibited in this type
767 def %{inspector} (self):
768 raise pyxb.ProhibitedAttributeError("Attribute %{name} is prohibited in %{ctd}")
769 def %{mutator} (self, new_value):
770 raise pyxb.ProhibitedAttributeError("Attribute %{name} is prohibited in %{ctd}")
771 ''', ctd=template_map['ctd'], **au_map))
772 elif basis.BINDING_STYLE_PROPERTY == generator.bindingStyle():
773 definitions.append(templates.replaceInText('''
774 %{inspector} = property()
775 ''', ctd=template_map['ctd'], **au_map))
776
777 else:
778 raise pyxb.LogicError('Unexpected binding style %s' % (generator.bindingStyle(),))
779 else:
780 if basis.BINDING_STYLE_ACCESSOR == generator.bindingStyle():
781 definitions.append(templates.replaceInText('''
782 def %{inspector} (self):
783 """Get the attribute value for %{name}."""
784 return self.%{use}.value(self)
785 def %{mutator} (self, new_value):
786 """Set the attribute value for %{name}. Raises BadValueTypeException
787 if the new value is not consistent with the attribute's type."""
788 return self.%{use}.set(self, new_value)''', **au_map))
789 elif basis.BINDING_STYLE_PROPERTY == generator.bindingStyle():
790 definitions.append(templates.replaceInText('''
791 %{inspector} = property(%{use}.value, %{use}.set, None, %{documentation})
792 ''', ctd=template_map['ctd'], **au_map))
793 else:
794 raise pyxb.LogicError('Unexpected binding style %s' % (generator.bindingStyle(),))
795
796 if ctd.attributeWildcard() is not None:
797 definitions.append('_AttributeWildcard = %s' % (binding_module.literal(ctd.attributeWildcard(), **kw),))
798 if ctd.hasWildcardElement():
799 definitions.append('_HasWildcardElement = True')
800 template_map['attribute_uses'] = ",\n ".join(attribute_uses)
801 template_map['element_uses'] = ",\n ".join(element_uses)
802 if inherits_from_base:
803 map_decl = '''
804 _ElementMap = %{superclass}._ElementMap.copy()
805 _ElementMap.update({
806 %{element_uses}
807 })
808 _AttributeMap = %{superclass}._AttributeMap.copy()
809 _AttributeMap.update({
810 %{attribute_uses}
811 })'''
812 else:
813 map_decl = '''
814 _ElementMap = {
815 %{element_uses}
816 }
817 _AttributeMap = {
818 %{attribute_uses}
819 }'''
820
821 template_map['registration'] = ''
822 if ctd.name() is not None:
823 template_map['registration'] = templates.replaceInText("%{namespaceReference}.addCategoryObject('typeBinding', %{localName}, %{ctd})",
824 localName=binding_module.literal(ctd.name(), **kw), **template_map)
825
826 template = ''.join([prolog_template,
827 " ", "\n ".join(definitions), "\n",
828 map_decl, '''
829 %{registration}
830
831 '''])
832
833 outf.write(template, **template_map)
834
836
837 assert ed._scopeIsGlobal()
838
839 binding_module = generator.moduleForComponent(ed)
840 outf = binding_module.bindingIO()
841
842 template_map = elementDeclarationMap(ed, binding_module, **kw)
843 template_map.setdefault('scope', binding_module.literal(None, **kw))
844 template_map.setdefault('map_update', '')
845
846 outf.write(templates.replaceInText('''
847 %{class} = pyxb.binding.basis.element(%{name_expr}, %{typeDefinition}%{element_aux_init})
848 %{namespaceReference}.addCategoryObject('elementBinding', %{class}.name().localName(), %{class})
849 ''', **template_map))
850
851 if ed.substitutionGroupAffiliation() is not None:
852 outf.postscript().append(templates.replaceInText('''
853 %{class}._setSubstitutionGroup(%{substitution_group})
854 ''', **template_map))
855
869
891
893 use_map = component._templateMap()
894 class_unique = nsm.uniqueInClass(container)
895 assert isinstance(component, xs.structures._ScopedDeclaration_mixin)
896 unique_name = utility.PrepareIdentifier(component.expandedName().localName(), class_unique)
897 use_map['id'] = unique_name
898 use_map['inspector'] = unique_name
899 use_map['mutator'] = utility.PrepareIdentifier('set' + unique_name[0].upper() + unique_name[1:], class_unique)
900 use_map['use'] = utility.MakeUnique('__' + unique_name.strip('_'), class_unique)
901 assert component._scope() == container
902 assert component.nameInBinding() is None, 'Use %s but binding name %s for %s' % (use_map['use'], component.nameInBinding(), component.expandedName())
903 component.setNameInBinding(use_map['use'])
904 key_name = '%s_%s_%s' % (str(nsm.namespace()), container.nameInBinding(), component.expandedName())
905 use_map['key'] = utility.PrepareIdentifier(key_name, class_unique, private=True)
906 use_map['name'] = unicode(component.expandedName())
907 use_map['name_expr'] = binding_module.literal(component.expandedName(), **kw)
908 if isinstance(component, xs.structures.ElementDeclaration) and is_plural:
909 use_map['appender'] = utility.PrepareIdentifier('add' + unique_name[0].upper() + unique_name[1:], class_unique)
910 return use_map
911
964
966 __anonSTDIndex = None
967 __anonCTDIndex = None
968 __uniqueInModule = None
969 __uniqueInClass = None
970
971
972 _UniqueInModule = set([ 'pyxb', 'sys' ])
973
974 __ComponentBindingModuleMap = {}
975
978 __generator = None
979
980 - def __init__ (self, generator, *args, **kw):
994
1002
1020
1021 __referencedNamespaces = None
1022
1024 return self.__bindingIO
1025
1026 __moduleUID = None
1031
1033 return str(id(self))
1034
1035 - def moduleContents (self):
1036 template_map = {}
1037 aux_imports = []
1038 for ns in self.__importedModules:
1039 if isinstance(ns, NamespaceModule):
1040 ns = ns.moduleRecord()
1041 module_path = ns.modulePath()
1042 assert module_path is not None, 'No module path for %s type %s' % (ns, type(ns))
1043 aux_imports.append('import %s' % (module_path,))
1044 template_map['aux_imports'] = "\n".join(aux_imports)
1045 template_map['namespace_decls'] = "\n".join(self.__namespaceDeclarations)
1046 template_map['module_uid'] = self.moduleUID()
1047 template_map['generation_uid_expr'] = repr(self.generator().generationUID())
1048 self._finalizeModuleContents_vx(template_map)
1049 return self.__bindingIO.contents()
1050
1064 __modulePath = None
1065
1068 __bindingFile = None
1069 __bindingFilePath = None
1070
1073
1076
1077 @classmethod
1081
1082 @classmethod
1086
1087 @classmethod
1091 @classmethod
1094 __RecordModuleMap = { }
1095
1115 return self.__componentNameMap.get(component)
1116
1118 assert module_type is None
1119 if NamespaceGroupModule == module_type:
1120 pass
1121 elif NamespaceModule == module_type:
1122 pass
1123 else:
1124 assert module_type is None
1125 return component_module
1126
1145
1147
1148 - def defineNamespace (self, namespace, name, require_unique=True, definition=None, **kw):
1162
1164 rv = self.__referencedNamespaces.get(namespace)
1165 if rv is None:
1166 if namespace.isBuiltinNamespace():
1167 rv = namespace.builtinNamespaceRepresentation()
1168 elif namespace.isUndeclaredNamespace():
1169 rv = namespace.modulePath()
1170 elif isinstance(self, NamespaceModule):
1171 if (self.namespace() == namespace):
1172 rv = 'Namespace'
1173 else:
1174 rv = 'pyxb.namespace.NamespaceForURI(%s)' % (repr(namespace.uri()),)
1175 '''
1176 namespace_module = self.ForNamespace(namespace)
1177 if namespace_module is not None:
1178 self._importModule(namespace_module)
1179 rv = '%s.Namespace' % (namespace_module.modulePath(),)
1180 else:
1181 assert False, 'Unexpected reference to %s' % (namespace,)
1182 #rv = 'pyxb.namespace.NamespaceForURI(%s)' % (repr(namespace.uri()),)
1183 '''
1184 else:
1185 if namespace.prefix():
1186 nsn = 'Namespace_%s' % (namespace.prefix(),)
1187 else:
1188 nsn = 'Namespace'
1189 for im in self.__importedModules:
1190 if isinstance(im, NamespaceModule) and (im.namespace() == namespace):
1191 rv = '%s.Namespace' % (im.modulePath(),)
1192 break
1193 if isinstance(im, NamespaceGroupModule):
1194 irv = im.__referencedNamespaces.get(namespace)
1195 if irv is not None:
1196 rv = self.defineNamespace(namespace, nsn, '%s.%s' % (im.modulePath(), irv), protected=True)
1197 break
1198 if rv is None:
1199 rv = self.defineNamespace(namespace, nsn, protected=True)
1200 assert 0 < len(self.__namespaceDeclarations)
1201 self.__referencedNamespaces[namespace] = rv
1202 return rv
1203
1205 return self.__bindingIO.literal(*args, **kw)
1206
1220
1228
1231 """This class represents a Python module that holds all the
1232 declarations belonging to a specific namespace."""
1233
1236 __namespace = None
1237
1240 __moduleRecord = None
1241
1246 __namespaceGroupModule = None
1247
1248 _UniqueInModule = _ModuleNaming_mixin._UniqueInModule.copy()
1249 _UniqueInModule.update([ 'Namespace', 'CreateFromDOM', 'CreateFromDocument' ])
1250
1253 __namespaceGroupHead = None
1254 __namespaceGroup = None
1255
1258 __components = None
1259
1260 @classmethod
1263 __ComponentModuleMap = { }
1264
1269
1272
1273 - def __init__ (self, generator, module_record, mr_scc, components=None, **kw):
1290
1298
1299 - def _finalizeModuleContents_vx (self, template_map):
1300 self.bindingIO().prolog().append(self.bindingIO().expand('''# %{filePath}
1301 # PyXB bindings for NamespaceModule
1302 # NSM:%{module_uid}
1303 # Generated %{date} by PyXB version %{pyxbVersion}
1304 import pyxb
1305 import pyxb.binding
1306 import pyxb.binding.saxer
1307 import StringIO
1308 import pyxb.utils.utility
1309 import pyxb.utils.domutils
1310 import sys
1311
1312 # Unique identifier for bindings created at the same time
1313 _GenerationUID = %{generation_uid_expr}
1314
1315 # Import bindings for namespaces imported into schema
1316 %{aux_imports}
1317
1318 %{namespace_decls}
1319 ModuleRecord = Namespace.lookupModuleRecordByUID(_GenerationUID, create_if_missing=True)
1320 ModuleRecord._setModule(sys.modules[__name__])
1321
1322 def CreateFromDocument (xml_text, default_namespace=None):
1323 """Parse the given XML and use the document element to create a Python instance."""
1324 if pyxb.XMLStyle_saxer != pyxb._XMLStyle:
1325 dom = pyxb.utils.domutils.StringToDOM(xml_text)
1326 return CreateFromDOM(dom.documentElement)
1327 saxer = pyxb.binding.saxer.make_parser(fallback_namespace=Namespace.fallbackNamespace())
1328 handler = saxer.getContentHandler()
1329 saxer.parse(StringIO.StringIO(xml_text))
1330 instance = handler.rootObject()
1331 return instance
1332
1333 def CreateFromDOM (node, default_namespace=None):
1334 """Create a Python instance from the given DOM node.
1335 The node tag must correspond to an element declaration in this module.
1336
1337 @deprecated: Forcing use of DOM interface is unnecessary; use L{CreateFromDocument}."""
1338 if default_namespace is None:
1339 default_namespace = Namespace.fallbackNamespace()
1340 return pyxb.binding.basis.element.AnyCreateFromDOM(node, _fallback_namespace=default_namespace)
1341
1342 ''', **template_map))
1343
1344 __components = None
1345 __componentBindingName = None
1346
1356
1359
1428
1429
1430 -def GeneratePython (schema_location=None,
1431 schema_text=None,
1432 namespace=None,
1433 module_prefix_elts=[],
1434 **kw):
1445
1446 import optparse
1447 import re
1450 """Configuration and data for a single binding-generation action."""
1451
1452 _DEFAULT_bindingRoot = '.'
1454 """The directory path into which generated bindings will be written.
1455 @rtype: C{str}"""
1456 return self.__bindingRoot
1460 __bindingRoot = None
1461
1471
1474 __generateToFiles = None
1475
1477
1478
1479
1480
1481 module_path = None
1482 if isinstance(module, NamespaceModule):
1483 mr = module.moduleRecord()
1484 if mr is None:
1485 return ('/dev/null', None, None)
1486 if self.generationUID() != mr.generationUID():
1487 return ('/dev/null', None, None)
1488 if not self.generateToFiles():
1489 return ('/dev/null', None, None)
1490 if mr.namespace().isBuiltinNamespace() and (not self.allowBuiltinGeneration()):
1491 return ('/dev/null', None, None)
1492 module_path = mr.modulePath()
1493 assert module_path is not None, 'No path specified for module %s' % (mr,)
1494
1495
1496
1497 module_elts = module_path.split('.')
1498 import_file_path = self.__directoryForModulePath(module_elts)
1499 if self.writeForCustomization():
1500 module_elts.insert(-1, 'raw')
1501 if self.writeForCustomization() and (not os.path.exists(import_file_path)):
1502 raw_module_path = '.'.join(module_elts)
1503 pyxb.utils.utility.OpenOrCreate(import_file_path).write("from %s import *\n" % (raw_module_path,))
1504 binding_file_path = self.__directoryForModulePath(module_elts)
1505 try:
1506 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID())
1507 except OSError, e:
1508 if errno.EEXIST == e.errno:
1509 raise pyxb.BindingGenerationError('Target file %s for module %s bindings exists with other content' % (binding_file_path, mr))
1510 raise
1511 elif isinstance(module, NamespaceGroupModule):
1512 if not self.generateToFiles():
1513 raise pyxb.BindingGenerationError('Generation of namespace groups requires generate-to-files')
1514 module_elts = []
1515 if self.modulePrefix():
1516 module_elts.extend(self.modulePrefix().split('.'))
1517 if self.writeForCustomization():
1518 module_elts.append('raw')
1519 in_use = set()
1520 while True:
1521 module_elts.append(pyxb.utils.utility.PrepareIdentifier('nsgroup', in_use, protected=True))
1522 try:
1523 binding_file_path = self.__directoryForModulePath(module_elts)
1524 print 'Attempting group at %s' % (binding_file_path,)
1525 binding_file = pyxb.utils.utility.OpenOrCreate(binding_file_path, tag=module.moduleUID())
1526 break
1527 except OSError, e:
1528 if errno.EEXIST != e.errno:
1529 raise
1530 module_elts.pop()
1531 module_path = '.'.join(module_elts)
1532 else:
1533 assert False
1534 if self.generateToFiles():
1535 for n in range(len(module_elts)-1):
1536 sub_path = os.path.join(*module_elts[:1+n])
1537 init_path = os.path.join(sub_path, '__init__.py')
1538 if not os.path.exists(init_path):
1539 file(init_path, 'w')
1540 return (binding_file_path, binding_file, module_path)
1541
1543 """The directory from which entrypoint schemas specified as
1544 relative file paths will be read."""
1545 return self.__schemaRoot
1547 if not schema_root.endswith(os.sep):
1548 schema_root = schema_root + os.sep
1549 self.__schemaRoot = schema_root
1550 return self
1551 __schemaRoot = None
1552
1554 """Optional string that is stripped from the beginning of
1555 schemaLocation values before loading from them.
1556
1557 This applies only to the values of schemaLocation attributes
1558 in C{import} and C{include} elements. Its purpose is to
1559 convert absolute schema locations into relative ones to allow
1560 offline processing when all schema are available in a local
1561 directory. See C{schemaRoot}.
1562 """
1563 return self.__schemaStrippedPrefix
1567 __schemaStrippedPrefix = None
1568
1570 """A list of locations from which entrypoint schemas are to be
1571 read.
1572
1573 The values in the list are either URIs, or tuples consisting
1574 of a value and a callable which, when passed the generator
1575 object and the value, will return a
1576 L{pyxb.xmlschema.structures.Schema} instance. See
1577 L{addSchemaLocation}.
1578
1579 See also L{addSchemaLocation} and L{schemas}.
1580 """
1581 return self.__schemaLocationList
1587 """Add the location of an entrypoint schema.
1588
1589 @param schema_location: The location of the schema. This
1590 should be a URL; if the schema location does not have a URL
1591 scheme (e.g., C{http:}), it is assumed to be a file, and if it
1592 is not an absolute path is located relative to the
1593 C{schemaRoot}.
1594
1595 @keyword converter: Optional callable that will be invoked
1596 with the generator instance and the schema location, and is
1597 expected to return a L{pyxb.xmlschema.structures.Schema}
1598 instance. If absent, the contents of the location are
1599 converted directly.
1600
1601 @note: The C{converter} argument derives from WSDL support: we
1602 need to add to the sequence of schema locations a URI of
1603 something that will not parse as a schema, but does have inner
1604 material that can if treated properly. "Treated properly" may
1605 include having the archive path and other namespace
1606 manipulations configured before anything is done to it.
1607 """
1608 self.__schemaLocationList.append( (schema_location, converter) )
1609 return self
1611 """Add the location of an entrypoint schema. The provided
1612 value should be a URL; if it does not have a URL scheme (e.g.,
1613 C{http:}), it is assumed to be a file, and if it is not an
1614 absolute path is located relative to the C{schemaRoot}."""
1615 self.addSchemaLocation(schema_location)
1616 __schemaLocationList = None
1617
1619 """Schema for which bindings should be generated.
1620
1621 These may be L{Schema<pyxb.xmlschema.structures.Schema>}
1622 instances, or strings; the latter is preferred, and is parsed
1623 into a Schema instance when required.
1624
1625 This is the list of entrypoint schemas for binding generation.
1626 Values in L{schemaLocationList} are read and converted into
1627 schema, then appended to this list. Values from L{moduleList}
1628 are applied starting with the first schema in this list.
1629 """
1630 return self.__schemas[:]
1638 __schemas = None
1639
1641 """The set of L{namespaces<pyxb.namespace.Namespace>} for
1642 which bindings will be generated.
1643
1644 This is the set of namespaces read from entrypoint schema,
1645 closed under reference to namespaces defined by schema import.
1646
1647 @rtype: C{set}
1648 """
1649 return self.__namespaces.copy()
1657 __namespaces = None
1658
1660 """A list of module names to be applied in order to the namespaces of entrypoint schemas"""
1661 return self.__moduleList[:]
1666
1668 """Add a module name corresponding to an entrypoint schema.
1669
1670 The namespace defined by the corresponding schema will be
1671 written to a binding using the given module name, adjusted by
1672 L{modulePrefix}."""
1673 self.__moduleList.append(module_name)
1674 return self
1675 __moduleList = None
1676
1678 """The prefix for binding modules.
1679
1680 The base name for the module holding a binding is taken from
1681 the moduleList, moduleMap, or an XMLNS prefix associated with
1682 the namespace in a containing schema. This value, if present,
1683 is used as a prefix to allow a deeper module hierarchy."""
1684 return self.__modulePrefix
1688 __modulePrefix = None
1689
1691 """A map from namespace URIs to the module to be used for the
1692 corresponding generated binding.
1693
1694 Module values are adjusted by L{modulePrefix} if that has been
1695 specified.
1696
1697 An entry in this map for a namespace supersedes the module
1698 specified in moduleList if the namespace is defined by an
1699 entrypoint schema.
1700
1701 @return: A reference to the namespace module map.
1702 """
1703 return self.__namespaceModuleMap
1704 __namespaceModuleMap = None
1705
1707 """A colon-separated list of paths from which namespace
1708 archives can be read.
1709
1710 The default path is the contents of the C{PYXB_ARCHIVE_PATH}
1711 environment variable, or the standard path configured at
1712 installation time. Any file with the extension C{.wxs} found
1713 in one of these directories is examined to see whether it is a
1714 namespace archive.
1715 """
1716 return self.__archivePath
1720 __archivePath = None
1721
1723 """A frozenset of namespaces that many not be loaded from an archive."""
1724 return frozenset(self.__noLoadNamespaces)
1726 """Record the set of namespaces that should not be loaded from an archive.
1727
1728 The expectation is that any required entities in the namespace
1729 will be defined by loading schema."""
1730 self.__noLoadNamespaces.clear()
1731 self.__noLoadNamespaces.update([ pyxb.namespace.NamespaceInstance(_ns) for _ns in namespace_set ])
1733 """Mark that the specified namespace should not be loaded from an archive.
1734
1735 Use this when you are generating bindings for an application
1736 that has a restricted profile of a namespace that would
1737 otherwise be read from an archive. Be aware that this removes
1738 any knowledge of any archive in which this namespace is
1739 present as a non-private member."""
1740 self.__noLoadNamespaces.add(pyxb.namespace.NamespaceInstance(namespace))
1741 __noloadNamespaces = None
1742
1744 """A list of paths to archives that should be loaded, in order, prior to parsing schema."""
1745 return frozenset(self.__preLoadArchives)
1747 """Name of a file containing a stored archive from which
1748 namespaces should be read prior to processing schema.
1749
1750 Files to be pre-loaded are not affected by
1751 C{noLoadNamespace}."""
1752 self.__preLoadArchives.append(archive_file)
1756 __preLoadArchives = None
1757
1759 """Optional file into which the archive of namespaces will be written.
1760
1761 Subsequent generation actions can read pre-parsed namespaces
1762 from this file, and therefore reference the bindings that were
1763 built earlier rather than re-generating them.
1764
1765 The file name should normally end with C{.wxs}."""
1766 return self.__archiveToFile
1770 __archiveToFile = None
1771
1785 """Indicates, for specific namespaces, whether their
1786 visibility in the archive should be public or private."""
1787 return self.__namespaceVisibilityMap.copy()
1788 __namespaceVisibilityMap = None
1789
1791 """Indicates whether unmentioned namespaces will be public or private (default) in the archive.
1792
1793 A namespace is I{mentioned} if it is the target namespace of
1794 an entrypoint schema, or appears in a namespace visibility
1795 specification. I.e., this default applies only to namespaces
1796 that are modified as a result of including some schema, which
1797 is generally a local customization of something.
1798 """
1799 return self.__defaultNamespacePublic
1802 __defaultNamespacePublic = None
1803
1805 """Indicates whether the bindings should validate mutations
1806 against the content model."""
1807 return self.__validateChanges
1812 __validateChanges = None
1813
1814 _DEFAULT_bindingStyle = basis.CURRENT_BINDING_STYLE
1816 """The style of Python used in generated bindings.
1817
1818 C{accessor} means values are private variables accessed
1819 through inspector and mutator methods.
1820
1821 C{property} means values are private variables accessed
1822 through a Python property.
1823 """
1824 return self.__bindingStyle
1829 __bindingStyle = None
1830
1832 """Indicates whether the binding Python code should be written into a sub-module for customization.
1833
1834 If enabled, a module C{path.to.namespace} will be written to
1835 the file C{path/to/raw/namespace.py}, so that the file
1836 C{path/to/namespace.py} can import it and override behavior."""
1837 return self.__writeForCustomization
1841 __writeForCustomization = None
1842
1844 """Indicates whether the code generator is permitted to
1845 process namespace for which no module path can be determined.
1846
1847 Use this only when generating bindings that will not be
1848 referenced by other bindings."""
1849 return self.__allowAbsentModule
1853 __allowAbsentModule = None
1854
1856 """Indicates whether bindings will be written for namespaces that are built-in to PyXB.
1857
1858 This must be enabled when building bindings for the XML,
1859 XMLSchema instance, and other built-in namespaces. Normally
1860 generation of these namespaces is inhibited lest it produce
1861 inconsistencies."""
1862 return self.__allowBuiltinGeneration
1866 __allowBuiltinGeneration = None
1867
1869 """The directory path into which any content retrieved by URI will be written.
1870
1871 This serves as a local cache, and to give you an opportunity
1872 to inspect material retrieved from some other system.
1873 @rtype: C{str}"""
1874 return self.__uriContentArchiveDirectory
1877 __uriContentArchiveDirectory = None
1878
1880 """Create a configuration to be used for generating bindings.
1881
1882 Arguments are treated as additions to the schema location list
1883 after all keywords have been processed.
1884
1885 @keyword binding_root: Invokes L{setBindingRoot}
1886 @keyword schema_root: Invokes L{setSchemaRoot}
1887 @keyword schema_stripped_prefix: Invokes L{setSchemaStrippedPrefix}
1888 @keyword schema_location_list: Invokes L{setSchemaLocationList}
1889 @keyword module_list: Invokes L{_setModuleList}
1890 @keyword module_prefix: Invokes L{setModulePrefix}
1891 @keyword archive_path: Invokes L{setArchivePath}
1892 @keyword no_load_namespaces: Invokes L{_setNoLoadNamespaces}
1893 @keyword pre_load_archives: Invokes L{_setPreLoadArchives}
1894 @keyword archive_to_file: Invokes L{setArchiveToFile}
1895 @keyword public_namespace: Invokes L{setNamespaceVisibility}
1896 @keyword private_namespace: Invokes L{setNamespaceVisibility}
1897 @keyword default_namespace_public: Invokes L{setDefaultNamespacePublic}
1898 @keyword validate_changes: Invokes L{setValidateChanges}
1899 @keyword binding_style: Invokes L{setBindingStyle}
1900 @keyword namespace_module_map: Initializes L{namespaceModuleMap}
1901 @keyword schemas: Invokes L{setSchemas}
1902 @keyword namespaces: Invokes L{setNamespaces}
1903 @keyword write_for_customization: Invokes L{setWriteForCustomization}
1904 @keyword allow_builtin_generation: Invokes L{setAllowBuiltinGeneration}
1905 @keyword allow_absent_module: Invokes L{setAllowAbsentModule}
1906 @keyword generate_to_files: Sets L{generateToFiles}
1907 @keyword uri_content_archive_directory: Invokes L{setUriContentArchiveDirectory}
1908 """
1909 argv = kw.get('argv', None)
1910 if argv is not None:
1911 kw = {}
1912 self.__bindingRoot = kw.get('binding_root', self._DEFAULT_bindingRoot)
1913 self.__schemaRoot = kw.get('schema_root', '.')
1914 self.__schemaStrippedPrefix = kw.get('schema_stripped_prefix')
1915 self.__schemas = []
1916 self.__schemaLocationList = kw.get('schema_location_list', [])[:]
1917 self.__moduleList = kw.get('module_list', [])[:]
1918 self.__modulePrefix = kw.get('module_prefix')
1919 self.__archivePath = kw.get('archive_path', pyxb.namespace.archive.GetArchivePath())
1920 self.__noLoadNamespaces = kw.get('no_load_namespaces', set()).copy()
1921 self.__preLoadArchives = kw.get('pre_load_archives', [])[:]
1922 self.__archiveToFile = kw.get('archive_to_file')
1923 self.__namespaceVisibilityMap = {}
1924 self._setNamespaceVisibilities(kw.get('public_namespaces', set()), kw.get('private_namespaces', set()))
1925 self.__defaultNamespacePublic = kw.get('default_namespace_public', False)
1926 self.__validateChanges = kw.get('validate_changes', True)
1927 self.__bindingStyle = kw.get('binding_style', self._DEFAULT_bindingStyle)
1928 self.__namespaceModuleMap = kw.get('namespace_module_map', {}).copy()
1929 self.__schemas = kw.get('schemas', [])[:]
1930 self.__namespaces = set(kw.get('namespaces', []))
1931 self.__writeForCustomization = kw.get('write_for_customization', False)
1932 self.__writeForCustomization = kw.get('allow_builtin_generation', False)
1933 self.__allowAbsentModule = kw.get('allow_absent_module', False)
1934 self.__generateToFiles = kw.get('generate_to_files', True)
1935 self.__uriContentArchiveDirectory = kw.get('uri_content_archive_directory')
1936
1937 if argv is not None:
1938 self.applyOptionValues(*self.optionParser().parse_args(argv))
1939 [ self.addSchemaLocation(_a) for _a in args ]
1940
1941 self.__generationUID = pyxb.utils.utility.UniqueIdentifier()
1942
1943 pyxb.namespace.XML.validateComponentModel()
1944
1945 __stripSpaces_re = re.compile('\s\s\s+')
1948
1949 __OptionSetters = (
1950 ('binding_root', setBindingRoot),
1951 ('schema_root', setSchemaRoot),
1952 ('schema_stripped_prefix', setSchemaStrippedPrefix),
1953 ('schema_location', setSchemaLocationList),
1954 ('module', _setModuleList),
1955 ('module_prefix', setModulePrefix),
1956 ('archive_path', setArchivePath),
1957 ('no_load_namespace', _setNoLoadNamespaces),
1958 ('pre_load_archive', _setPreLoadArchives),
1959 ('archive_to_file', setArchiveToFile),
1960 ('default_namespace_public', setDefaultNamespacePublic),
1961 ('binding_style', setBindingStyle),
1962 ('validate_changes', setValidateChanges),
1963 ('write_for_customization', setWriteForCustomization),
1964 ('allow_builtin_generation', setAllowBuiltinGeneration),
1965 ('allow_absent_module', setAllowAbsentModule),
1966 ('uri_content_archive_directory', setUriContentArchiveDirectory)
1967 )
1969 for (tag, method) in self.__OptionSetters:
1970 v = getattr(options, tag)
1971 if v is not None:
1972 method(self, v)
1973 public_namespaces = getattr(options, 'public_namespace')
1974 private_namespaces = getattr(options, 'private_namespace')
1975 self._setNamespaceVisibilities(public_namespaces, private_namespaces)
1976 if args is not None:
1977 self.__schemaLocationList.extend(args)
1978
1980 if argv is None:
1981 argv = sys.argv[1:]
1982 (options, args) = self.optionParser().parse_args(argv)
1983 self.applyOptionValues(options, args)
1984 return self
1985
1988 __generationUID = None
1989
1991 """Return an C{optparse.OptionParser} instance tied to this configuration.
1992
1993 @param reset: If C{False} (default), a parser created in a
1994 previous invocation will be returned. If C{True}, any
1995 previous option parser is discarded and a new one created.
1996 @type reset: C{bool}
1997 """
1998 if reset or (self.__optionParser is None):
1999 parser = optparse.OptionParser(usage="%prog [options] [more schema locations...]",
2000 version='%%prog from PyXB %s' % (pyxb.__version__,),
2001 description='Generate bindings from a set of XML schemas')
2002
2003 group = optparse.OptionGroup(parser, 'Identifying Schema', 'Specify and locate schema for which bindings should be generated.')
2004 group.add_option('--schema-location', '-u', metavar="FILE_or_URL",
2005 action='append',
2006 help=self.__stripSpaces(self.argAddSchemaLocation.__doc__))
2007 group.add_option('--schema-root', metavar="DIRECTORY",
2008 help=self.__stripSpaces(self.schemaRoot.__doc__))
2009 group.add_option('--schema-stripped-prefix', metavar="TEXT", type='string',
2010 help=self.__stripSpaces(self.schemaStrippedPrefix.__doc__))
2011 group.add_option('--uri-content-archive-directory', metavar="DIRECTORY",
2012 help=self.__stripSpaces(self.uriContentArchiveDirectory.__doc__))
2013 parser.add_option_group(group)
2014
2015 group = optparse.OptionGroup(parser, 'Configuring Bindings', 'Specify where generated bindings should be written, and how they will be accessed from Python.')
2016 group.add_option('--module', '-m', metavar="MODULE",
2017 action='append',
2018 help=self.__stripSpaces(self.addModuleName.__doc__))
2019 group.add_option('--module-prefix', metavar="MODULE",
2020 help=self.__stripSpaces(self.modulePrefix.__doc__))
2021 group.add_option('--binding-root', metavar="DIRECTORY",
2022 help=self.__stripSpaces(self.bindingRoot.__doc__))
2023 group.add_option('-r', '--write-for-customization',
2024 action='store_true', dest='write_for_customization',
2025 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns on the feature.'))
2026 group.add_option('--no-write-for-customization',
2027 action='store_false', dest='write_for_customization',
2028 help=self.__stripSpaces(self.writeForCustomization.__doc__ + ' This option turns off the feature (I{default}).'))
2029 parser.add_option_group(group)
2030
2031 group = optparse.OptionGroup(parser, 'Reading Namespace Archives', 'Locating and loading (or inhibiting load of) namespace archives.')
2032 group.add_option('--archive-path', metavar="PATH",
2033 help=self.__stripSpaces(self.archivePath.__doc__))
2034 group.add_option('--pre-load-archive', metavar="FILE",
2035 action='append',
2036 help=self.__stripSpaces(self.addPreLoadArchive.__doc__))
2037 group.add_option('--no-load-namespace', metavar="URI",
2038 action='append',
2039 help=self.__stripSpaces(self.addNoLoadNamespace.__doc__))
2040 parser.add_option_group(group)
2041
2042 group = optparse.OptionGroup(parser, 'Writing Namespace Archives', 'Control the location and content of a namespace archive corresponding to a binding generation.')
2043 group.add_option('--archive-to-file', metavar="FILE",
2044 help=self.__stripSpaces(self.archiveToFile.__doc__))
2045 group.add_option('--public-namespace', metavar="URI",
2046 action='append',
2047 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a public archive member.'))
2048 group.add_option('--private-namespace', metavar="URI",
2049 action='append',
2050 help=self.__stripSpaces(self.namespaceVisibilityMap.__doc__ + ' This option adds the namespace as a private archive member.'))
2051 group.add_option('--default-namespace-public',
2052 action="store_true", dest='default_namespace_public',
2053 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{public} (I{default}).'))
2054 group.add_option('--default-namespace-private',
2055 action="store_false", dest='default_namespace_public',
2056 help=self.__stripSpaces(self.defaultNamespacePublic.__doc__ + ' This option makes the default C{private}.'))
2057 parser.add_option_group(group)
2058
2059 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.")
2060 group.add_option('--binding-style',
2061 type='choice', choices=basis.BINDING_STYLES,
2062 help=self.__stripSpaces(self.bindingStyle.__doc__))
2063 group.add_option('--validate-changes',
2064 action='store_true', dest='validate_changes',
2065 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns on validation (default).'))
2066 group.add_option('--no-validate-changes',
2067 action='store_false', dest='validate_changes',
2068 help=self.__stripSpaces(self.validateChanges.__doc__ + ' This option turns off validation.'))
2069 parser.add_option_group(group)
2070
2071 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.")
2072 group.add_option('--allow-absent-module',
2073 action='store_true', dest='allow_absent_module',
2074 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns on the feature.'))
2075 group.add_option('--no-allow-absent-module',
2076 action='store_false', dest='allow_absent_module',
2077 help=self.__stripSpaces(self.allowAbsentModule.__doc__ + ' This option turns off the feature (default).'))
2078 group.add_option('--allow-builtin-generation',
2079 action='store_true', dest='allow_builtin_generation',
2080 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns on the feature.'))
2081 group.add_option('--no-allow-builtin-generation',
2082 action='store_false', dest='allow_builtin_generation',
2083 help=self.__stripSpaces(self.allowBuiltinGeneration.__doc__ + ' This option turns off the feature (default).'))
2084 parser.add_option_group(group)
2085
2086 self.__optionParser = parser
2087 return self.__optionParser
2088 __optionParser = None
2089
2091 """Return a command line option sequence that could be used to
2092 construct an equivalent configuration.
2093
2094 @note: If you extend the option parser, as is done by
2095 C{pyxbgen}, this may not be able to reconstruct the correct
2096 command line."""
2097 opts = []
2098 module_list = self.moduleList()
2099 schema_list = self.schemaLocationList()
2100 while module_list and schema_list:
2101 ml = module_list.pop(0)
2102 sl = schema_list.pop(0)
2103 if isinstance(sl, tuple):
2104 sl = sl[0]
2105 opts.extend(['--schema-location=' + sl, '--module=' + ml])
2106 for sl in schema_list:
2107 opts.append('--schema-location=' + sl)
2108 if self.schemaRoot() is not None:
2109 opts.append('--schema-root=' + self.schemaRoot())
2110 if self.schemaStrippedPrefix() is not None:
2111 opts.append('--schema-stripped-prefix=%s' + self.schemaStrippedPrefix())
2112 if self.modulePrefix() is not None:
2113 opts.append('--module-prefix=' + self.modulePrefix())
2114 opts.append('--binding-root=' + self.bindingRoot())
2115 if self.archivePath() is not None:
2116 opts.append('--archive-path=' + self.archivePath())
2117 for ns in self.noLoadNamespaces():
2118 opts.append('--no-load-namespace=' + ns.uri())
2119 for fps in self.preLoadArchives():
2120 opts.append('--pre-load-archive=' + fp)
2121 if self.archiveToFile() is not None:
2122 opts.append('--archive-to-file=' + self.archiveToFile())
2123 for (ns, visibility) in self._namespaceVisibilityMap():
2124 if visibility:
2125 opts.append('--public-namespace=' + ns.uri())
2126 else:
2127 opts.append('--private-namespace=' + ns.uri())
2128 if self.defaultNamespacePublic():
2129 opts.append('--default-namespace-public')
2130 else:
2131 opts.append('--default-namespace-private')
2132 for (val, opt) in ( (self.validateChanges(), 'validate-changes'),
2133 (self.writeForCustomization(), 'write-for-customization'),
2134 (self.allowAbsentModule(), 'allow-absent-module'),
2135 (self.allowBuiltinGeneration(), 'allow-builtin-generation') ):
2136 if val:
2137 opts.append('--' + opt)
2138 else:
2139 opts.append('--no-' + opt)
2140 if self.uriContentArchiveDirectory() is not None:
2141 opts.append('--uri-content-archive-directory=%s' + self.uriContentArchiveDirectory())
2142 return opts
2143
2149
2164
2165 __didResolveExternalSchema = False
2167 if self.__didResolveExternalSchema and (not reset):
2168 raise pyxb.PyXBException('Cannot resolve external schema multiple times')
2169
2170 required_archives = pyxb.namespace.archive.NamespaceArchive.PreLoadArchives(self.archivePath(), self.preLoadArchives())
2171 for nsa in required_archives:
2172 nsa.readNamespaces()
2173 for ns in self.noLoadNamespaces():
2174 assert isinstance(ns, pyxb.namespace.Namespace)
2175 ns.markNotLoadable()
2176 while self.__schemaLocationList:
2177 sl = self.__schemaLocationList.pop(0)
2178 if isinstance(sl, tuple):
2179 (sl, converter) = sl
2180 else:
2181 converter = None
2182 try:
2183 if converter is None:
2184 schema = xs.schema.CreateFromLocation(absolute_schema_location=self.normalizeSchemaLocation(sl), generation_uid=self.generationUID(), uri_content_archive_directory=self.uriContentArchiveDirectory())
2185 else:
2186 schema = converter(self, sl)
2187 self.addSchema(schema)
2188 except pyxb.SchemaUniquenessError, e:
2189 print 'WARNING: Skipped redundant translation of %s defining %s' % (e.schemaLocation(), e.namespace())
2190 self.addSchema(e.existingSchema())
2191 for schema in self.__schemas:
2192 if isinstance(schema, basestring):
2193 schema = xs.schema.CreateFromDocument(schema, generation_uid=self.generationUID())
2194 origin = schema.originRecord()
2195 assert origin is not None
2196 module_path = None
2197 if self.__moduleList:
2198 module_path = self.__moduleList.pop(0)
2199 self.__assignModulePath(origin.moduleRecord(), module_path)
2200 assert schema.targetNamespace() == origin.moduleRecord().namespace()
2201 self.addNamespace(schema.targetNamespace())
2202 self.__didResolveExternalSchema = True
2203 self.__bindingModules = None
2204
2230
2232 named_bindable_fn = lambda _c: (isinstance(_c, xs.structures.ElementDeclaration) and _c._scopeIsGlobal()) or _c.isTypeDefinition()
2233 bindable_fn = lambda _c: isinstance(_c, xs.structures.ElementDeclaration) or _c.isTypeDefinition()
2234
2235 self.__moduleRecords = set()
2236 all_components = set()
2237 for origin in self.generationUID().associatedObjects():
2238 mr = origin.moduleRecord()
2239 if not (mr in self.__moduleRecords):
2240
2241
2242 self.__moduleRecords.add(mr)
2243 mr.completeGenerationAssociations()
2244 all_components.update(origin.originatedObjects())
2245
2246 namespaces = set()
2247 for mr in self.__moduleRecords:
2248 if mr.namespace().isBuiltinNamespace() and not self.allowBuiltinGeneration():
2249 continue
2250 namespaces.add(mr.namespace())
2251 pyxb.namespace.resolution.ResolveSiblingNamespaces(namespaces, self.generationUID())
2252
2253
2254
2255 for ns in self.namespaces():
2256 self.__namespaceVisibilityMap.setdefault(ns, True)
2257
2258
2259
2260
2261 component_graph = self.__graphFromComponents(all_components, True)
2262
2263 binding_components = set(filter(bindable_fn, component_graph.nodes()))
2264
2265
2266
2267 module_graph = pyxb.utils.utility.Graph()
2268 [ module_graph.addRoot(_mr) for _mr in self.__moduleRecords ]
2269 for (s, t) in component_graph.edges():
2270 module_graph.addEdge(s._objectOrigin().moduleRecord(), t._objectOrigin().moduleRecord())
2271 module_scc_order = module_graph.sccOrder()
2272
2273
2274
2275
2276
2277
2278
2279
2280 for c in binding_components:
2281 assert bindable_fn(c), 'Unexpected %s in binding components' % (type(s),)
2282 c._setBindingNamespace(c._objectOrigin().moduleRecord().namespace())
2283
2284 record_binding_map = {}
2285 unique_in_bindings = set([NamespaceGroupModule._GroupPrefix])
2286 modules = []
2287 for mr_scc in module_scc_order:
2288 scc_modules = [ ]
2289 for mr in mr_scc:
2290
2291
2292 mr._setIsPublic(self.__namespaceVisibilityMap.get(mr.namespace(), self.defaultNamespacePublic()))
2293 self.__assignModulePath(mr)
2294 assert not ((mr.modulePath() is None) and self.generateToFiles()), 'No module path defined for %s' % (mr,)
2295 if (not mr.isPublic()) and (mr.modulePath() is not None):
2296 elts = mr.modulePath().split('.')
2297 elts[-1] = '_%s' % (elts[-1],)
2298 mr.setModulePath('.'.join(elts))
2299 nsm = NamespaceModule(self, mr, mr_scc)
2300 record_binding_map[mr] = nsm
2301 scc_modules.append(nsm)
2302
2303 modules.extend(scc_modules)
2304 if 1 < len(mr_scc):
2305 ngm = NamespaceGroupModule(self, scc_modules)
2306 modules.append(ngm)
2307 for nsm in scc_modules:
2308 nsm.setNamespaceGroupModule(ngm)
2309
2310 component_csets = self.__graphFromComponents(binding_components, False).sccOrder()
2311 bad_order = False
2312 component_order = []
2313 for cset in component_csets:
2314 if 1 < len(cset):
2315 print "COMPONENT DEPENDENCY LOOP of %d components" % (len(cset),)
2316 cg = pyxb.utils.utility.Graph()
2317 for c in cset:
2318 assert bindable_fn(c), 'Unexpected %s in list' % (type(c),)
2319 print ' %s' % (c.expandedName(),)
2320 cg.addNode(c)
2321 for cd in c.bindingRequires(reset=True, include_lax=False):
2322
2323 cg.addEdge(c, cd)
2324
2325 relaxed_order = cg.sccOrder()
2326 for rcs in relaxed_order:
2327 assert 1 == len(rcs)
2328 rcs = rcs[0]
2329 if rcs in cset:
2330 component_order.append(rcs)
2331 else:
2332 component_order.extend(cset)
2333
2334
2335
2336 element_declarations = []
2337 type_definitions = []
2338 for c in component_order:
2339 if isinstance(c, xs.structures.ElementDeclaration) and c._scopeIsGlobal():
2340
2341 nsm = record_binding_map[c._objectOrigin().moduleRecord()]
2342 nsm.bindComponent(c)
2343 element_declarations.append(c)
2344 elif c.isTypeDefinition():
2345 type_definitions.append(c)
2346 else:
2347
2348 pass
2349
2350 simple_type_definitions = []
2351 complex_type_definitions = []
2352 for td in type_definitions:
2353 nsm = record_binding_map[td._objectOrigin().moduleRecord()]
2354 assert nsm is not None, 'No namespace module for %s type %s scope %s namespace %s' % (td.expandedName(), type(td), td._scope(), td.bindingNamespace)
2355 module_context = nsm.bindComponent(td)
2356 assert isinstance(module_context, _ModuleNaming_mixin), 'Unexpected type %s' % (type(module_context),)
2357 if isinstance(td, xs.structures.SimpleTypeDefinition):
2358 _PrepareSimpleTypeDefinition(td, self, nsm, module_context)
2359 simple_type_definitions.append(td)
2360 elif isinstance(td, xs.structures.ComplexTypeDefinition):
2361 _PrepareComplexTypeDefinition(td, self, nsm, module_context)
2362 complex_type_definitions.append(td)
2363 else:
2364 assert False, 'Unexpected component type %s' % (type(td),)
2365
2366 for ngm in modules:
2367 if isinstance(ngm, NamespaceGroupModule):
2368 for m in ngm.namespaceModules():
2369 m.addImportsFrom(ngm)
2370
2371 for std in simple_type_definitions:
2372 GenerateSTD(std, self)
2373 for ctd in complex_type_definitions:
2374 GenerateCTD(ctd, self)
2375 for ed in element_declarations:
2376 GenerateED(ed, self)
2377
2378 return modules
2379
2380 __bindingModules = None
2387
2389 archive_file = self.archiveToFile()
2390 if archive_file is not None:
2391 ns_archive = pyxb.namespace.archive.NamespaceArchive(generation_uid=self.generationUID())
2392 try:
2393 ns_archive.writeNamespaces(pyxb.utils.utility.OpenOrCreate(archive_file))
2394 print 'Saved parsed schema to %s URI' % (archive_file,)
2395 except Exception, e:
2396 print 'Exception saving preprocessed schema to %s: %s' % (archive_file, e)
2397 traceback.print_exception(*sys.exc_info())
2398
2399
2400
2401
2402 if isinstance(e, (AssertionError, AttributeError, TypeError)):
2403 raise
2404
2407