1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """Helper classes that maintain the content model of XMLSchema in the binding
17 classes.
18
19 L{AttributeUse} and L{ElementDeclaration} record information associated with a binding
20 class, for example the types of values, the original XML QName or NCName, and
21 the Python field in which the values are stored. They also provide the
22 low-level interface to set and get the corresponding values in a binding
23 instance.
24
25 L{Wildcard} holds content-related information used in the content model.
26 """
27
28 import logging
29 import xml.dom
30
31 import pyxb
32 import pyxb.namespace
33 import pyxb.utils.fac
34 from pyxb.binding import basis
35 import pyxb.utils.utility
36 from pyxb.utils import six
37
38 _log = logging.getLogger(__name__)
41 """A helper class that encapsulates everything we need to know
42 about the way an attribute is used within a binding class.
43
44 Attributes are stored internally as pairs C{(provided, value)}, where
45 C{provided} is a boolean indicating whether a value for the attribute was
46 provided externally, and C{value} is an instance of the attribute
47 datatype. The C{provided} flag is used to determine whether an XML
48 attribute should be added to a created DOM node when generating the XML
49 corresponding to a binding instance.
50 """
51
52 __name = None
53 """ExpandedName of the attribute"""
54
55 __id = None
56 """Identifier used for this attribute within the owning class"""
57
58 __key = None
59 """Private Python attribute used in instances to hold the attribute value"""
60
61 __dataType = None
62 """The L{pyxb.binding.basis.simpleTypeDefinition} for values of the attribute"""
63
64 __unicodeDefault = None
65 """The default attribute value as a unicode string, or C{None}"""
66
67 __defaultValue = None
68 """The default value as an instance of L{__dataType}, or C{None}"""
69
70 __fixed = False
71 """C{True} if the attribute value cannot be changed"""
72
73 __required = False
74 """C{True} if the attribute must appear in every instance of the type"""
75
76 __prohibited = False
77 """C{True} if the attribute must not appear in any instance of the type"""
78
79 - def __init__ (self, name, id, key, data_type, unicode_default=None, fixed=False, required=False, prohibited=False):
80 """Create an AttributeUse instance.
81
82 @param name: The name by which the attribute is referenced in the XML
83 @type name: L{pyxb.namespace.ExpandedName}
84
85 @param id: The Python identifier for the attribute within the
86 containing L{pyxb.basis.binding.complexTypeDefinition}. This is a
87 public identifier, derived from the local part of the attribute name
88 and modified to be unique, and is usually used as the name of the
89 attribute's inspector method.
90 @type id: C{str}
91
92 @param key: The string used to store the attribute
93 value in the dictionary of the containing
94 L{pyxb.basis.binding.complexTypeDefinition}. This is mangled so
95 that it is unique among and is treated as a Python private member.
96 @type key: C{str}
97
98 @param data_type: The class reference to the subclass of
99 L{pyxb.binding.basis.simpleTypeDefinition} of which the attribute
100 values must be instances.
101 @type data_type: C{type}
102
103 @keyword unicode_default: The default value of the attribute as
104 specified in the schema, or None if there is no default attribute
105 value. The default value (of the keyword) is C{None}.
106 @type unicode_default: C{unicode}
107
108 @keyword fixed: If C{True}, indicates that the attribute, if present,
109 must have the value that was given via C{unicode_default}. The
110 default value is C{False}.
111 @type fixed: C{bool}
112
113 @keyword required: If C{True}, indicates that the attribute must appear
114 in the DOM node used to create an instance of the corresponding
115 L{pyxb.binding.basis.complexTypeDefinition}. The default value is
116 C{False}. No more that one of L{required} and L{prohibited} should be
117 assigned C{True}.
118 @type required: C{bool}
119
120 @keyword prohibited: If C{True}, indicates that the attribute must
121 B{not} appear in the DOM node used to create an instance of the
122 corresponding L{pyxb.binding.basis.complexTypeDefinition}. The
123 default value is C{False}. No more that one of L{required} and
124 L{prohibited} should be assigned C{True}.
125 @type prohibited: C{bool}
126
127 @raise pyxb.SimpleTypeValueError: the L{unicode_default} cannot be used
128 to initialize an instance of L{data_type}
129 """
130
131 self.__name = name
132 self.__id = id
133 self.__key = key
134 self.__dataType = data_type
135 self.__unicodeDefault = unicode_default
136 if self.__unicodeDefault is not None:
137 self.__defaultValue = self.__dataType.Factory(self.__unicodeDefault, _from_xml=True)
138 self.__fixed = fixed
139 self.__required = required
140 self.__prohibited = prohibited
141 super(AttributeUse, self).__init__()
142
144 """The expanded name of the element.
145
146 @rtype: L{pyxb.namespace.ExpandedName}
147 """
148 return self.__name
149
151 """The default value of the attribute."""
152 return self.__defaultValue
153
155 """C{True} iff the value of the attribute cannot be changed."""
156 return self.__fixed
157
159 """C{True} iff the attribute must be assigned a value."""
160 return self.__required
161
163 """C{True} iff the attribute must not be assigned a value."""
164 return self.__prohibited
165
167 """C{True} iff the given instance has been explicitly given a value
168 for the attribute.
169
170 This is used for things like only generating an XML attribute
171 assignment when a value was originally given (even if that value
172 happens to be the default).
173 """
174 return self.__getProvided(ctd_instance)
175
177 """Tag used within Python code for the attribute.
178
179 This is not used directly in the default code generation template."""
180 return self.__id
181
183 """String used as key within object dictionary when storing attribute value."""
184 return self.__key
185
187 """The subclass of L{pyxb.binding.basis.simpleTypeDefinition} of which any attribute value must be an instance."""
188 return self.__dataType
189
191 """Retrieve the value information for this attribute in a binding instance.
192
193 @param ctd_instance: The instance object from which the attribute is to be retrieved.
194 @type ctd_instance: subclass of L{pyxb.binding.basis.complexTypeDefinition}
195 @return: C{(provided, value)} where C{provided} is a C{bool} and
196 C{value} is C{None} or an instance of the attribute's datatype.
197
198 """
199 return getattr(ctd_instance, self.__key, (False, None))
200
203
204 - def value (self, ctd_instance):
209
210 - def __setValue (self, ctd_instance, new_value, provided):
211 return setattr(ctd_instance, self.__key, (provided, new_value))
212
213 - def reset (self, ctd_instance):
214 """Set the value of the attribute in the given instance to be its
215 default value, and mark that it has not been provided."""
216 self.__setValue(ctd_instance, self.__defaultValue, False)
217
224
252
253 - def set (self, ctd_instance, new_value, from_xml=False):
254 """Set the value of the attribute.
255
256 This validates the value against the data type, creating a new instance if necessary.
257
258 @param ctd_instance: The binding instance for which the attribute
259 value is to be set
260 @type ctd_instance: subclass of L{pyxb.binding.basis.complexTypeDefinition}
261 @param new_value: The value for the attribute
262 @type new_value: Any value that is permitted as the input parameter to
263 the C{Factory} method of the attribute's datatype.
264 @param from_xml: Value C{True} iff the new_value is known to be in
265 lexical space and must by converted by the type factory. If C{False}
266 (default) the value is only converted if it is not already an instance
267 of the attribute's underlying type.
268 """
269 provided = True
270 assert not isinstance(new_value, xml.dom.Node)
271 if new_value is None:
272 if self.__required:
273 raise pyxb.MissingAttributeError(type(ctd_instance), self.__name, ctd_instance)
274 provided = False
275 if self.__prohibited:
276 raise pyxb.ProhibitedAttributeError(type(ctd_instance), self.__name, ctd_instance)
277 if (new_value is not None) and (from_xml or not isinstance(new_value, self.__dataType)):
278 new_value = self.__dataType.Factory(new_value, _from_xml=from_xml)
279 if self.__fixed and (new_value != self.__defaultValue):
280 raise pyxb.AttributeChangeError(type(ctd_instance), self.__name, ctd_instance)
281 self.__setValue(ctd_instance, new_value, provided)
282 return new_value
283
284 - def _description (self, name_only=False, user_documentation=True):
285 if name_only:
286 return six.text_type(self.__name)
287 assert issubclass(self.__dataType, basis._TypeBinding_mixin)
288 desc = [ six.text_type(self.__id), ': ', six.text_type(self.__name), ' (', self.__dataType._description(name_only=True, user_documentation=False), '), ' ]
289 if self.__required:
290 desc.append('required')
291 elif self.__prohibited:
292 desc.append('prohibited')
293 else:
294 desc.append('optional')
295 if self.__defaultValue is not None:
296 desc.append(', ')
297 if self.__fixed:
298 desc.append('fixed')
299 else:
300 desc.append('default')
301 desc.extend(['=', self.__unicodeDefault ])
302 return ''.join(desc)
303
305 """State for a L{pyxb.utils.fac.Automaton} monitoring content for an
306 incrementally constructed complex type binding instance.
307
308 @warning: This is not an implementation of
309 L{pyxb.utils.fac.Configuration_ABC} because we need the L{step} function
310 to return a different type of value."""
311
312
313 __instance = None
314
315
316
317
318
319
320 __cfg = None
321
322
323
324
325
326
327
328 __multi = None
329
330 PermittedNondeterminism = 20
331 """The maximum amount of unresolved non-determinism that is acceptable.
332 If the value is exceeded, a L{pyxb.ContentNondeterminismExceededError}
333 exception will be raised."""
334
337
339 """Reset the automaton to its initial state.
340
341 Subsequent transitions are expected based on candidate content to be
342 supplied through the L{step} method."""
343 self.__cfg = self.__instance._Automaton.newConfiguration()
344 self.__multi = None
345
347 """Return the number of pending configurations.
348
349 The automaton is deterministic if exactly one configuration is
350 available."""
351 if self.__cfg is not None:
352 assert self.__multi is None
353 return 1
354 return len(self.__multi)
355
356 - def step (self, value, element_decl):
357 """Attempt a transition from the current state.
358
359 @param value: the content to be supplied. For success the value must
360 be consistent with the recorded symbol (element or wildcard
361 declaration) for a transition from the current automaton state.
362
363 @param element_decl: optional
364 L{pyxb.binding.content.ElementDeclaration} that is the preferred
365 symbol for the transition.
366
367 @return: the cardinal number of successful transitions from the
368 current configuration based on the parameters."""
369
370 sym = (value, element_decl)
371
372
373
374 new_multi = []
375 if self.__multi is None:
376 multi = [ (self.__cfg, ()) ]
377 else:
378 multi = self.__multi[:]
379
380
381 for (cfg, pending) in multi:
382 cand = cfg.candidateTransitions(sym)
383 for transition in cand:
384 clone_map = {}
385 ccfg = cfg.clone(clone_map)
386 new_multi.append( (transition.apply(ccfg, clone_map), pending+(transition.consumedSymbol().consumingClosure(sym),)) )
387 rv = len(new_multi)
388 if 0 == rv:
389
390 return 0
391 if 1 == rv:
392
393
394 self.__multi = None
395 (self.__cfg, actions) = new_multi[0]
396 for fn in actions:
397 fn(self.__instance)
398 else:
399
400 if rv > self.PermittedNondeterminism:
401 raise pyxb.ContentNondeterminismExceededError(self.__instance)
402 self.__cfg = None
403 self.__multi = new_multi
404 return rv
405
407 """Resolve any non-determinism in the automaton state.
408
409 If the automaton has reached a single configuration (was
410 deterministic), this does nothing.
411
412 If multiple candidate configurations are available, the best one is
413 selected and applied, updating the binding instance with the pending
414 content.
415
416 "Best" in this case is determined by optionally eliminating
417 configurations that are not accepting, then selecting the path where
418 the initial transition sorts highest using the binding sort key (based
419 on position in the original schema).
420
421 @keyword prefer_accepting: eliminate non-accepting paths if any
422 accepting path is present."""
423 if self.__multi is None:
424 return
425 assert self.__cfg is None
426 multi = self.__multi
427 if prefer_accepting:
428 multi = list(filter(lambda _ts: _ts[0].isAccepting(), self.__multi))
429 if 0 == len(multi):
430 multi = self.__multi
431
432
433
434 assert 0 < len(multi)
435 if 1 < len(multi):
436 desc = self.__instance._ExpandedName
437 if desc is None:
438 desc = type(self.__instance)
439 _log.warning('Multiple accepting paths for %s', desc)
440 '''
441 for (cfg, actions) in multi:
442 foo = type(self.__instance)()
443 for fn in actions:
444 fn(foo)
445 print '1: %s ; 2 : %s ; wc: %s' % (foo.first, foo.second, foo.wildcardElements())
446 '''
447 (self.__cfg, actions) = multi[0]
448 self.__multi = None
449 for fn in actions:
450 fn(self.__instance)
451
453 """Return the sequence of acceptable symbols at this state.
454
455 The list comprises the L{pyxb.binding.content.ElementUse} and
456 L{pyxb.binding.content.WildcardUse} instances that are used to
457 validate proposed symbols, in preferred order."""
458 rv = []
459 seen = set()
460 multi = self.__multi
461 if multi is None:
462 multi = [ self.__cfg]
463 for cfg in multi:
464 for u in cfg.acceptableSymbols():
465 if not (u in seen):
466 rv.append(u)
467 seen.add(u)
468 return rv
469
480
481 - def _diagnoseIncompleteContent (self, symbols, symbol_set):
482 """Check for incomplete content.
483
484 @raises pyxb.IncompleteElementContentError: if a non-accepting state is found
485 @return: the topmost configuration (if accepting)
486 """
487
488
489 cfg = self.__cfg
490 while cfg.isAccepting() and (cfg.superConfiguration is not None):
491 cfg = cfg.superConfiguration
492 if not cfg.isAccepting():
493 raise pyxb.IncompleteElementContentError(self.__instance, cfg, symbols, symbol_set)
494 return cfg
495
497 """Generate the exception explaining why the content is incomplete."""
498 return self._diagnoseIncompleteContent(None, None)
499
500 __preferredSequenceIndex = 0
501 __preferredPendingSymbol = None
502 __pendingNonElementContent = None
503
515
526
558
560 """Implement L{pyxb.binding.basis.complexTypeDefinition._validatedChildren}.
561
562 Go there for the interface.
563 """
564
565
566
567 self.reset()
568 cfg = self.__cfg
569
570
571 symbols = []
572
573
574 instance = self.__instance
575 vc = instance._validationConfig
576
577
578
579
580 symbol_set = instance._symbolSet()
581
582
583 preferred_sequence = self.__resetPreferredSequence(instance)
584
585
586
587
588
589 nec = self.__pendingNonElementContent
590
591 psym = None
592 while symbol_set:
593
594
595 selected_xit = None
596 psym = None
597 if preferred_sequence is not None:
598 (preferred_sequence, psym) = self.__processPreferredSequence(preferred_sequence, symbol_set, vc)
599 candidates = cfg.candidateTransitions(psym)
600 for xit in candidates:
601 csym = xit.consumedSymbol()
602 if isinstance(csym, ElementUse):
603 ed = csym.elementDeclaration()
604 elif isinstance(csym, WildcardUse):
605 ed = None
606 else:
607 assert False
608
609 matches = symbol_set.get(ed)
610 if matches is None:
611 continue
612 if not csym.match((matches[0], ed)):
613 continue
614
615
616
617 value = matches.pop(0)
618 if (psym is not None) and (nec is not None):
619 symbols.extend(nec)
620 nec[:] = []
621 symbols.append(basis.ElementContent(csym.matchValue( (value, ed) ), ed))
622 selected_xit = xit
623 if 0 == len(matches):
624 del symbol_set[ed]
625 break
626 if selected_xit is None:
627 if psym is not None:
628
629 _log.info('invalid %s in content', psym)
630 if vc.IGNORE_ONCE == vc.invalidElementInContent:
631 continue
632 if vc.GIVE_UP == vc.invalidElementInContent:
633 preferred_sequence = self.__discardPreferredSequence(preferred_sequence)
634 continue
635 raise pyxb.InvalidPreferredElementContentError(self.__instance, cfg, symbols, symbol_set, psym)
636 break
637 cfg = selected_xit.apply(cfg)
638 cfg = self._diagnoseIncompleteContent(symbols, symbol_set)
639 if symbol_set:
640 raise pyxb.UnprocessedElementContentError(self.__instance, cfg, symbols, symbol_set)
641
642
643
644 while preferred_sequence is not None:
645 (preferred_sequence, psym) = self.__processPreferredSequence(preferred_sequence, symbol_set, vc)
646 if psym is not None:
647 if not (vc.orphanElementInContent in ( vc.IGNORE_ONCE, vc.GIVE_UP )):
648 raise pyxb.OrphanElementContentError(self.__instance, psym.value)
649 if nec is not None:
650 symbols.extend(nec)
651 return symbols
652
653 -class _FACSymbol (pyxb.utils.fac.SymbolMatch_mixin):
654 """Base class for L{pyxb.utils.fac.Symbol} instances associated with PyXB content models.
655
656 This holds the location in the schema of the L{ElementUse} or
657 L{WildcardUse} and documents the methods expected of its children."""
658
659 __xsdLocation = None
660
663
665 """Return the value accepted by L{match} for this symbol.
666
667 A match for an element declaration might have resulted in a type
668 change for the value (converting it to an acceptable type). There is
669 no safe place to cache the compatible value calculated in the match
670 while other candidates are being considered, so we need to
671 re-calculate it if the transition is taken.
672
673 If the match could not have changed the value, the value from the
674 symbol may be returned immediately."""
675 raise NotImplementedError('%s._matchValue' % (type(self).__name__,))
676
678 """Create a closure that will apply the value from C{sym} to a to-be-supplied instance.
679
680 This is necessary for non-deterministic automata, where we can't store
681 the value into the instance field until we know that the transition
682 will be taken:
683
684 @return: A closure that takes a L{complexTypeDefinition} instance and
685 stores the value from invoking L{matchValue} on C{sym} into the
686 appropriate slot."""
687 raise NotImplementedError('%s._consumingClosure' % (type(self).__name__,))
688
690 """@param xsd_location: the L{location<pyxb.utils.utility.Location>} of the element use or wildcard declaration."""
691 self.__xsdLocation = xsd_location
692 super(_FACSymbol, self).__init__()
693
695 """Information about a schema element declaration reference.
696
697 This is used by the FAC content model to identify the location
698 within a schema at which an element use appears. The L{ElementDeclaration}
699 is not sufficient since multiple uses in various schema, possibly in
700 different namespaces, may refer to the same declaration but be independent
701 uses.
702 """
703
704 __elementDeclaration = None
705
707 """Return the L{element declaration<pyxb.binding.content.ElementDeclaration>} associated with the use."""
708 return self.__elementDeclaration
709
711 """Return the L{element binding<pyxb.binding.content.ElementDeclaration.elementBinding>} associated with the use.
712
713 Equivalent to L{elementDeclaration}().L{elementBinding()<pyxb.binding.content.ElementDeclaration.elementBinding>}."""
714 return self.__elementDeclaration.elementBinding()
715
717 """Return the element type.
718
719 Equivalent to L{elementDeclaration}().L{elementBinding()<pyxb.binding.content.ElementDeclaration.elementBinding>}.L{typeDefinition()<pyxb.binding.basis.element.typeDefinition>}."""
720 return self.__elementDeclaration.elementBinding().typeDefinition()
721
722 - def __init__ (self, element_declaration, xsd_location):
725
731
736
737 - def match (self, symbol):
738 """Satisfy L{pyxb.utils.fac.SymbolMatch_mixin}.
739
740 Determine whether the proposed content encapsulated in C{symbol} is
741 compatible with the element declaration. If so, the accepted value is
742 cached internally and return C{True}; otherwise return C{False}.
743
744 @param symbol: a pair C{(value, element_decl)}.
745 L{pyxb.binding.content.ElementDeclaration._matches} is used to
746 determine whether the proposed content is compatible with this element
747 declaration."""
748 (value, element_decl) = symbol
749
750
751
752 (rv, value) = self.__elementDeclaration._matches(value, element_decl)
753 return rv
754
757
759 """Information about a schema wildcard element.
760
761 This is functionally parallel to L{ElementUse}, but references a
762 L{Wildcard} that is unique to this instance. That L{Wildcard} is not
763 incorporated into this class is an artifact of the evolution of PyXB."""
764
765 __wildcardDeclaration = None
766
769
773
775 """Create a closure that will apply the value accepted by L{match} to a to-be-supplied instance."""
776 return lambda _inst,_av=self.matchValue(sym): _inst._appendWildcardElement(_av)
777
778 - def match (self, symbol):
779 """Satisfy L{pyxb.utils.fac.SymbolMatch_mixin}.
780
781 Determine whether the proposed content encapsulated in C{symbol} is
782 compatible with the wildcard declaration. If so, the accepted value
783 is cached internally and return C{True}; otherwise return C{False}.
784
785 @param symbol: a pair C{(value, element_decl)}.
786 L{pyxb.binding.content.Wildcard.matches} is used to determine whether
787 the proposed content is compatible with this wildcard.
788 """
789 (value, element_decl) = symbol
790 return self.__wildcardDeclaration.matches(None, value)
791
792 - def __init__ (self, wildcard_declaration, xsd_location):
795
798
799 import collections
800
801
802
803
804
805
806 @pyxb.utils.utility.BackfillComparisons
808 """Helper for element content that supports multiple occurences.
809
810 This is an adapter for Python list. Any operation that can mutate an item
811 in the list ensures the stored value is compatible with the element for
812 which the list holds values."""
813
814 __list = None
815 __elementBinding = None
816
818 element_binding = kw.pop('element_binding', None)
819 if not isinstance(element_binding, basis.element):
820 raise ValueError()
821 self.__elementBinding = element_binding
822 self.__list = []
823 self.extend(args)
824
827
830
833
839
842
845
848
851
852
855
858
861
862 - def index (self, x, i=0, j=-1):
864
867
868 - def pop (self, i=-1):
870
873
876
877 - def sort (self, key=None, reverse=False):
879
882
884 return hash(self.__list__)
885
892
899
901 """Aggregate the information relevant to an element of a complex type.
902
903 This includes the L{original tag name<name>}, the spelling of L{the
904 corresponding object in Python <id>}, an L{indicator<isPlural>} of whether
905 multiple instances might be associated with the field, and other relevant
906 information.
907 """
908
910 """The L{location<pyxb.utils.utility.Location>} in the schema where the
911 element was declared.
912
913 Note that this is not necessarily the same location as its use."""
914 return self.__xsdLocation
915 __xsdLocation = None
916
918 """The expanded name of the element.
919
920 @rtype: L{pyxb.namespace.ExpandedName}
921 """
922 return self.__name
923 __name = None
924
926 """The string name of the binding class field used to hold the element
927 values.
928
929 This is the user-visible name, and excepting disambiguation will be
930 equal to the local name of the element."""
931 return self.__id
932 __id = None
933
934
935
936
937 __key = None
938
940 """The L{basis.element} instance identifying the information
941 associated with the element declaration.
942 """
943 return self.__elementBinding
950 __elementBinding = None
951
953 """True iff the content model indicates that more than one element
954 can legitimately belong to this use.
955
956 This includes elements in particles with maxOccurs greater than one,
957 and when multiple elements with the same NCName are declared in the
958 same type.
959 """
960 return self.__isPlural
961 __isPlural = False
962
963 - def __init__ (self, name, id, key, is_plural, location, element_binding=None):
964 """Create an ElementDeclaration instance.
965
966 @param name: The name by which the element is referenced in the XML
967 @type name: L{pyxb.namespace.ExpandedName}
968
969 @param id: The Python name for the element within the containing
970 L{pyxb.basis.binding.complexTypeDefinition}. This is a public
971 identifier, albeit modified to be unique, and is usually used as the
972 name of the element's inspector method or property.
973 @type id: C{str}
974
975 @param key: The string used to store the element
976 value in the dictionary of the containing
977 L{pyxb.basis.binding.complexTypeDefinition}. This is mangled so
978 that it is unique among and is treated as a Python private member.
979 @type key: C{str}
980
981 @param is_plural: If C{True}, documents for the corresponding type may
982 have multiple instances of this element. As a consequence, the value
983 of the element will be a list. If C{False}, the value will be C{None}
984 if the element is absent, and a reference to an instance of the type
985 identified by L{pyxb.binding.basis.element.typeDefinition} if present.
986 @type is_plural: C{bool}
987
988 @param element_binding: Reference to the class that serves as the
989 binding for the element.
990 """
991 self.__name = name
992 self.__id = id
993 self.__key = key
994 self.__isPlural = is_plural
995 self.__elementBinding = element_binding
996 super(ElementDeclaration, self).__init__()
997
999 """Return the default value for this element.
1000
1001 For plural values, this is an empty collection. For non-plural
1002 values, it is C{None} unless the element has a default value, in which
1003 case it is that value.
1004
1005 @todo: This should recursively support filling in default content, as
1006 when the plural list requires a non-zero minimum number of entries.
1007 """
1008 if self.isPlural():
1009 return _PluralBinding(element_binding=self.__elementBinding)
1010 return self.__elementBinding.defaultValue()
1011
1013 """Return the reset value for this element.
1014
1015 For plural values, this is an empty collection. For non-plural
1016 values, it is C{None}, corresponding to absence of an assigned
1017 element.
1018 """
1019 if self.isPlural():
1020 return _PluralBinding(element_binding=self.__elementBinding)
1021 return None
1022
1023 - def value (self, ctd_instance):
1024 """Return the value for this use within the given instance.
1025
1026 Note that this is the L{resetValue()}, not the L{defaultValue()}, if
1027 the element has not yet been assigned a value."""
1028 return getattr(ctd_instance, self.__key, self.resetValue())
1029
1030 - def reset (self, ctd_instance):
1031 """Set the value for this use in the given element to its default."""
1032 setattr(ctd_instance, self.__key, self.resetValue())
1033 return self
1034
1035 - def set (self, ctd_instance, value):
1047
1049 """Invoke either L{set} or L{append}, depending on whether the element
1050 use is plural."""
1051 if self.isPlural():
1052 return self.append(ctd_instance, value)
1053 return self.set(ctd_instance, value)
1054
1055 - def append (self, ctd_instance, value):
1069
1070 - def toDOM (self, dom_support, parent, value):
1071 """Convert the given value to DOM as an instance of this element.
1072
1073 @param dom_support: Helper for managing DOM properties
1074 @type dom_support: L{pyxb.utils.domutils.BindingDOMSupport}
1075 @param parent: The DOM node within which this element should be generated.
1076 @type parent: C{xml.dom.Element}
1077 @param value: The content for this element. May be text (if the
1078 element allows mixed content), or an instance of
1079 L{basis._TypeBinding_mixin}.
1080
1081 @raise pyxb.AbstractElementError: the binding to be used is abstract
1082 """
1083 if isinstance(value, basis._TypeBinding_mixin):
1084 element_binding = self.__elementBinding
1085 if value._substitutesFor(element_binding):
1086 element_binding = value._element()
1087 assert element_binding is not None
1088 if element_binding.abstract():
1089 raise pyxb.AbstractElementError(self, value)
1090 element = dom_support.createChildElement(element_binding.name(), parent)
1091 elt_type = element_binding.typeDefinition()
1092 val_type = type(value)
1093 if isinstance(value, basis.complexTypeDefinition):
1094 if not (isinstance(value, elt_type) or elt_type._RequireXSIType(val_type)):
1095 raise pyxb.LogicError('toDOM with implicit value type %s unrecoverable from %s' % (type(value), elt_type))
1096 else:
1097 if isinstance(value, basis.STD_union) and isinstance(value, elt_type._MemberTypes):
1098 val_type = elt_type
1099 if dom_support.requireXSIType() or elt_type._RequireXSIType(val_type):
1100 dom_support.addAttribute(element, pyxb.namespace.XMLSchema_instance.createExpandedName('type'), value._ExpandedName)
1101 value._toDOM_csc(dom_support, element)
1102 elif isinstance(value, six.string_types):
1103 element = dom_support.createChildElement(self.name(), parent)
1104 element.appendChild(dom_support.document().createTextNode(value))
1105 elif isinstance(value, _PluralBinding):
1106 for v in value:
1107 self.toDOM(dom_support, parent, v)
1108 else:
1109 raise pyxb.LogicError('toDOM with unrecognized value type %s: %s' % (type(value), value))
1110
1111 - def _description (self, name_only=False, user_documentation=True):
1112 if name_only:
1113 return six.text_type(self.__name)
1114 desc = [ six.text_type(self.__id), ': ']
1115 if self.isPlural():
1116 desc.append('MULTIPLE ')
1117 desc.append(self.elementBinding()._description(user_documentation=user_documentation))
1118 return six.u('').join(desc)
1119
1120 - def _matches (self, value, element_decl):
1143
1145 return 'ED.%s@%x' % (self.__name, id(self))
1146
1149 """Placeholder for wildcard objects."""
1150
1151 NC_any = '##any'
1152 NC_not = '##other'
1153 NC_targetNamespace = '##targetNamespace'
1154 NC_local = '##local'
1155
1156 __namespaceConstraint = None
1158 """A constraint on the namespace for the wildcard.
1159
1160 Valid values are:
1161
1162 - L{Wildcard.NC_any}
1163 - A tuple ( L{Wildcard.NC_not}, a L{namespace<pyxb.namespace.Namespace>} instance )
1164 - set(of L{namespace<pyxb.namespace.Namespace>} instances)
1165
1166 Namespaces are represented by their URIs. Absence is
1167 represented by C{None}, both in the "not" pair and in the set.
1168 """
1169 return self.__namespaceConstraint
1170
1171 PC_skip = 'skip'
1172 """No namespace constraint is applied to the wildcard."""
1173
1174 PC_lax = 'lax'
1175 """Validate against available uniquely determined declaration."""
1176
1177 PC_strict = 'strict'
1178 """Validate against declaration or xsi:type, which must be available."""
1179
1180 __processContents = None
1181 """One of L{PC_skip}, L{PC_lax}, L{PC_strict}."""
1182 - def processContents (self):
1183 """Indicate how this wildcard's contents should be processed."""
1184 return self.__processContents
1185
1187 if nsv is None:
1188 return None
1189 if isinstance(nsv, six.string_types):
1190 nsv = pyxb.namespace.NamespaceForURI(nsv, create_if_missing=True)
1191 assert isinstance(nsv, pyxb.namespace.Namespace), 'unexpected non-namespace %s' % (nsv,)
1192 return nsv
1193
1208
1209 - def matches (self, instance, value):
1241
1242
1243
1244
1245