1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """Classes supporting U{XMLSchema Part 2: Datatypes<http://www.w3.org/TR/xmlschema-2/>}.
17
18 Each L{simple type definition<pyxb.xmlschema.structures.SimpleTypeDefinition>} component
19 instance is paired with at most one L{basis.simpleTypeDefinition}
20 class, which is a subclass of a Python type augmented with facets and
21 other constraining information. This file contains the definitions of
22 these types.
23
24 We want the simple datatypes to be efficient Python values, but to
25 also hold specific constraints that don't apply to the Python types.
26 To do this, we subclass each PST. Primitive PSTs inherit from the
27 Python type that represents them, and from a
28 pyxb.binding.basis.simpleTypeDefinition class which adds in the
29 constraint infrastructure. Derived PSTs inherit from the parent PST.
30
31 There is an exception to this when the Python type best suited for a
32 derived SimpleTypeDefinition differs from the type associated with its
33 parent STD: for example, L{xsd:integer<integer>} has a value range
34 that requires it be represented by a Python C{long}, but
35 L{xsd:int<int>} allows representation by a Python C{int}. In this
36 case, the derived PST class is structured like a primitive type, but
37 the PST associated with the STD superclass is recorded in a class
38 variable C{_XsdBaseType}.
39
40 Note the strict terminology: "datatype" refers to a class which is a
41 subclass of a Python type, while "type definition" refers to an
42 instance of either SimpleTypeDefinition or ComplexTypeDefinition.
43
44 """
45
46 import logging
47 import re
48 import binascii
49 import base64
50 import math
51 import decimal as python_decimal
52 from pyxb.exceptions_ import *
53 import pyxb.namespace
54 import pyxb.utils.unicode
55 from pyxb.utils import six
56 from . import basis
57
58 _log = logging.getLogger(__name__)
59
60 _PrimitiveDatatypes = []
61 _DerivedDatatypes = []
62 _ListDatatypes = []
63
64
65
66
67 -class anySimpleType (basis.simpleTypeDefinition, six.text_type):
75
76
77
78 -class string (basis.simpleTypeDefinition, six.text_type):
91
92 _PrimitiveDatatypes.append(string)
93
94
95
96 @six.python_2_unicode_compatible
97 -class boolean (basis.simpleTypeDefinition, six.int_type):
98 """XMLSchema datatype U{boolean<http://www.w3.org/TR/xmlschema-2/#boolean>}."""
99 _XsdBaseType = anySimpleType
100 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('boolean')
101
102 @classmethod
104 if value:
105 return 'true'
106 return 'false'
107
109 if self:
110 return six.u('true')
111 return six.u('false')
112
114 args = cls._ConvertArguments(args, kw)
115 if 0 < len(args):
116 value = args[0]
117 args = args[1:]
118 if value in (1, 0, '1', '0', 'true', 'false'):
119 if value in (1, '1', 'true'):
120 iv = True
121 else:
122 iv = False
123 return super(boolean, cls).__new__(cls, iv, *args, **kw)
124 raise SimpleTypeValueError(cls, value)
125 return super(boolean, cls).__new__(cls, *args, **kw)
126
127 _PrimitiveDatatypes.append(boolean)
128
129 -class decimal (basis.simpleTypeDefinition, python_decimal.Decimal, basis._RepresentAsXsdLiteral_mixin):
130 """XMLSchema datatype U{decimal<http://www.w3.org/TR/xmlschema-2/#decimal>}.
131
132 This class uses Python's L{decimal.Decimal} class to support (by
133 default) 28 significant digits. Only normal and zero values are
134 valid; this means C{NaN} and C{Infinity} may be created during
135 calculations, but cannot be expressed in XML documents.
136 """
137 _XsdBaseType = anySimpleType
138 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('decimal')
139
141 args = cls._ConvertArguments(args, kw)
142
143 if (1 <= len(args)) and isinstance(args[0], six.float_type):
144 args = (str(args[0]),) + args[1:]
145 try:
146 rv = super(decimal, cls).__new__(cls, *args, **kw)
147 except python_decimal.DecimalException:
148 raise SimpleTypeValueError(cls, *args)
149 cls._CheckValidValue(rv)
150 return rv
151
152 @classmethod
157
158 @classmethod
160 (sign, digits, exponent) = value.normalize().as_tuple()
161 if (0 < len(digits)) and (0 == digits[0]):
162 digits = ()
163 rchars = []
164 if sign:
165 rchars.append('-')
166 digits_before = len(digits) + exponent
167 if 0 < digits_before:
168 rchars.extend(map(str, digits[:digits_before]))
169 digits = digits[digits_before:]
170 if (0 == len(digits)) and (0 < exponent):
171 rchars.extend(['0'] * exponent)
172 exponent = 0
173 else:
174 rchars.append('0')
175 rchars.append('.')
176 digits_after = -exponent
177 assert(0 <= digits_after)
178 if 0 < digits_after:
179 rchars.extend(['0'] * (digits_after - len(digits)))
180 rchars.extend(map(str, digits))
181 else:
182 rchars.append('0')
183 return six.u('').join(rchars)
184
185 _PrimitiveDatatypes.append(decimal)
186
187 -class _fp (basis.simpleTypeDefinition, six.float_type):
199
203
204 _PrimitiveDatatypes.append(float)
209
210 _PrimitiveDatatypes.append(double)
211
212 import datetime
213
214 -class duration (basis.simpleTypeDefinition, datetime.timedelta, basis._RepresentAsXsdLiteral_mixin):
215 """XMLSchema datatype U{duration<http://www.w3.org/TR/xmlschema-2/#duration>}.
216
217 This class uses the Python C{datetime.timedelta} class as its
218 underlying representation. This works fine as long as no months
219 or years are involved, and no negative durations are involved.
220 Because the XML Schema value space is so much larger, it is kept
221 distinct from the Python value space, which reduces to integral
222 days, seconds, and microseconds.
223
224 In other words, the implementation of this type is a little
225 shakey.
226
227 """
228
229 _XsdBaseType = anySimpleType
230 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('duration')
231
232 __Lexical_re = re.compile('^(?P<neg>-?)P((?P<years>\d+)Y)?((?P<months>\d+)M)?((?P<days>\d+)D)?(?P<Time>T((?P<hours>\d+)H)?((?P<minutes>\d+)M)?(((?P<seconds>\d+)(?P<fracsec>\.\d+)?)S)?)?$')
233
234
235 __XSDFields = ( 'years', 'months', 'days', 'hours', 'minutes', 'seconds' )
236 __PythonFields = ( 'days', 'seconds', 'microseconds', 'minutes', 'hours' )
237
240 __negativeDuration = None
241
244 __durationData = None
245
247 args = cls._ConvertArguments(args, kw)
248 have_kw_update = False
249 if not kw.get('_nil'):
250 if 0 == len(args):
251 raise SimpleTypeValueError(cls, args)
252 text = args[0]
253 if kw.get('_nil'):
254 data = dict(zip(cls.__PythonFields, len(cls.__PythonFields) * [0,]))
255 negative_duration = False
256 elif isinstance(text, six.string_types):
257 match = cls.__Lexical_re.match(text)
258 if match is None:
259 raise SimpleTypeValueError(cls, text)
260 match_map = match.groupdict()
261 if 'T' == match_map.get('Time'):
262
263 raise SimpleTypeValueError(cls, text)
264
265 negative_duration = ('-' == match_map.get('neg'))
266
267 fractional_seconds = 0.0
268 if match_map.get('fracsec') is not None:
269 fractional_seconds = six.float_type('0%s' % (match_map['fracsec'],))
270 usec = six.int_type(1000000 * fractional_seconds)
271 if negative_duration:
272 kw['microseconds'] = - usec
273 else:
274 kw['microseconds'] = usec
275 else:
276
277 kw.pop('microsecond', None)
278
279 data = { }
280 for fn in cls.__XSDFields:
281 v = match_map.get(fn, 0)
282 if v is None:
283 v = 0
284 data[fn] = six.int_type(v)
285 if fn in cls.__PythonFields:
286 if negative_duration:
287 kw[fn] = - data[fn]
288 else:
289 kw[fn] = data[fn]
290 data['seconds'] += fractional_seconds
291 have_kw_update = True
292 elif isinstance(text, cls):
293 data = text.durationData().copy()
294 negative_duration = text.negativeDuration()
295 elif isinstance(text, datetime.timedelta):
296 data = { 'days' : text.days,
297 'seconds' : text.seconds + (text.microseconds / 1000000.0) }
298 negative_duration = (0 > data['days'])
299 if negative_duration:
300 if 0.0 == data['seconds']:
301 data['days'] = - data['days']
302 else:
303 data['days'] = 1 - data['days']
304 data['seconds'] = 24 * 60 * 60.0 - data['seconds']
305 data['minutes'] = 0
306 data['hours'] = 0
307 elif isinstance(text, six.integer_types) and (1 < len(args)):
308
309 data = dict(zip(cls.__PythonFields[:len(args)], args))
310 negative_duration = False
311 else:
312 raise SimpleTypeValueError(cls, text)
313 if not have_kw_update:
314 rem_time = data.pop('seconds', 0)
315 if (0 != (rem_time % 1)):
316 data['microseconds'] = data.pop('microseconds', 0) + six.int_type(1000000 * (rem_time % 1))
317 rem_time = rem_time // 1
318 data['seconds'] = rem_time % 60
319 rem_time = data.pop('minutes', 0) + (rem_time // 60)
320 data['minutes'] = rem_time % 60
321 rem_time = data.pop('hours', 0) + (rem_time // 60)
322 data['hours'] = rem_time % 24
323 data['days'] += (rem_time // 24)
324 for fn in cls.__PythonFields:
325 if fn in data:
326 if negative_duration:
327 kw[fn] = - data[fn]
328 else:
329 kw[fn] = data[fn]
330 else:
331 kw.pop(fn, None)
332 kw['microseconds'] = data.pop('microseconds', 0)
333 data['seconds'] += kw['microseconds'] / 1000000.0
334
335 rv = super(duration, cls).__new__(cls, **kw)
336 rv.__durationData = data
337 rv.__negativeDuration = negative_duration
338 return rv
339
340 @classmethod
365
366 _PrimitiveDatatypes.append(duration)
367
368 -class _PyXBDateTime_base (basis.simpleTypeDefinition, basis._RepresentAsXsdLiteral_mixin):
369
370 _Lexical_fmt = None
371 """Format for the lexical representation of a date-related instance, excluding timezone.
372
373 Subclasses must define this."""
374
375
376
377
378 __PatternMap = { '%Y' : '(?P<negYear>-?)(?P<year>\d{4,})'
379 , '%m' : '(?P<month>\d{2})'
380 , '%d' : '(?P<day>\d{2})'
381 , '%H' : '(?P<hour>\d{2})'
382 , '%M' : '(?P<minute>\d{2})'
383 , '%S' : '(?P<second>\d{2})(?P<fracsec>\.\d+)?'
384 , '%Z' : '(?P<tzinfo>Z|[-+]\d\d:\d\d)' }
385
386
387
388 __LexicalREMap = { }
389
390
391 __LexicalIntegerFields = ( 'year', 'month', 'day', 'hour', 'minute', 'second' )
392
393 _UTCTimeZone = pyxb.utils.utility.UTCOffsetTimeZone(0)
394 """A L{datetime.tzinfo} instance representing UTC."""
395
396 _LocalTimeZone = pyxb.utils.utility.LocalTimeZone()
397 """A L{datetime.tzinfo} instance representing the local time zone."""
398
399 _DefaultYear = 1900
400 _DefaultMonth = 1
401 _DefaultDay = 1
402
403 @classmethod
432
433 @classmethod
435 for f in fields:
436 kw[f] = getattr(python_value, f)
437 return getattr(super(_PyXBDateTime_base, cls), '_SetKeysFromPython_csc', lambda *a,**kw: None)(python_value, kw, fields)
438
439 @classmethod
442
443
444
445
448
449 @classmethod
451 """Update datetime keywords to account for timezone effects.
452
453 All XML schema timezoned times are in UTC, with the time "in
454 its timezone". If the keywords indicate a non-UTC timezone is
455 in force, and L{pyxb.PreserveInputTimeZone()} has not been
456 set, adjust the values to account for the zone by subtracting
457 the corresponding UTC offset and mark explicitly that the time
458 is in UTC by leaving a C{tzinfo} attribute identifying the UTC
459 time zone.
460
461 @param kw: A dictionary of keywords relevant for a date or
462 time instance. The dictionary is updated by this call.
463 """
464 if pyxb.PreserveInputTimeZone():
465 return
466 tzoffs = kw.pop('tzinfo', None)
467 if tzoffs is not None:
468 use_kw = kw.copy()
469
470 use_kw.setdefault('year', cls._DefaultYear)
471 use_kw.setdefault('month', cls._DefaultMonth)
472 use_kw.setdefault('day', cls._DefaultDay)
473 dt = datetime.datetime(tzinfo=tzoffs, **use_kw)
474 dt -= tzoffs.utcoffset(dt)
475 for k in six.iterkeys(kw):
476 kw[k] = getattr(dt, k)
477 kw['tzinfo'] = cls._UTCTimeZone
478
479 @classmethod
481 iso = value.replace(tzinfo=None).isoformat()
482 if 0 <= iso.find('.'):
483 iso = iso.rstrip('0')
484 if value.tzinfo is not None:
485 iso += value.tzinfo.tzname(value)
486 return iso
487
488 -class dateTime (_PyXBDateTime_base, datetime.datetime):
489 """XMLSchema datatype U{dateTime<http://www.w3.org/TR/xmlschema-2/#dateTime>}.
490
491 This class uses the Python C{datetime.datetime} class as its
492 underlying representation. Unless L{pyxb.PreserveInputTimeZone()}
493 is used, all timezoned dateTime objects are in UTC. Presence of
494 time zone information in the lexical space is preserved by a
495 non-empty tzinfo field, which should always be zero minutes offset
496 from UTC unless the input time zone was preserved.
497
498 @warning: The value space of Python's C{datetime.datetime} class
499 is more restricted than that of C{xs:datetime}. As a specific
500 example, Python does not support negative years or years with more
501 than four digits. For now, the convenience of having an object
502 that is compatible with Python is more important than supporting
503 the full value space. In the future, the choice may be left up to
504 the developer.
505 """
506
507 _XsdBaseType = anySimpleType
508 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('dateTime')
509
510 _Lexical_fmt = '%Y-%m-%dT%H:%M:%S'
511 __CtorFields = ( 'year', 'month', 'day', 'hour', 'minute', 'second', 'microsecond', 'tzinfo' )
512
514 args = cls._ConvertArguments(args, kw)
515
516 ctor_kw = { }
517 if kw.get('_nil'):
518 ctor_kw = { 'year': 1900, 'month': 1, 'day': 1 }
519 elif 1 == len(args):
520 value = args[0]
521 if isinstance(value, six.string_types):
522 ctor_kw.update(cls._LexicalToKeywords(value))
523 elif isinstance(value, datetime.datetime):
524 cls._SetKeysFromPython(value, ctor_kw, cls.__CtorFields)
525 elif isinstance(value, six.integer_types):
526 raise TypeError('function takes at least 3 arguments (%d given)' % (len(args),))
527 else:
528 raise SimpleTypeValueError(cls, value)
529 elif 3 <= len(args):
530 for fi in range(len(cls.__CtorFields)):
531 fn = cls.__CtorFields[fi]
532 if fi < len(args):
533 ctor_kw[fn] = args[fi]
534 elif fn in kw:
535 ctor_kw[fn] = kw[fn]
536 kw.pop(fn, None)
537 else:
538 raise TypeError('function takes at least 3 arguments (%d given)' % (len(args),))
539
540 cls._AdjustForTimezone(ctor_kw)
541 kw.update(ctor_kw)
542 year = kw.pop('year')
543 month = kw.pop('month')
544 day = kw.pop('day')
545 rv = super(dateTime, cls).__new__(cls, year, month, day, **kw)
546 return rv
547
548 @classmethod
550 """Return today.
551
552 Just like datetime.datetime.today(), except this one sets a
553 tzinfo field so it's clear the value is UTC."""
554 return cls(datetime.datetime.now(cls._UTCTimeZone))
555
557 """Returns a C{datetime.datetime} instance denoting the same
558 time as this instance but adjusted to be in the local time
559 zone.
560
561 @rtype: C{datetime.datetime} (B{NOT} C{xsd.dateTime})
562 """
563 dt = self
564 if dt.tzinfo is None:
565 dt = dt.replace(tzinfo=self._UTCTimeZone)
566 return dt.astimezone(self._LocalTimeZone)
567
568 _PrimitiveDatatypes.append(dateTime)
569
570 -class time (_PyXBDateTime_base, datetime.time):
571 """XMLSchema datatype U{time<http://www.w3.org/TR/xmlschema-2/#time>}.
572
573 This class uses the Python C{datetime.time} class as its
574 underlying representation. Note that per the XMLSchema spec, all
575 dateTime objects are in UTC, and that timezone information in the
576 string representation in XML is an indication of the local time
577 zone's offset from UTC. Presence of time zone information in the
578 lexical space is indicated by the tzinfo field.
579
580 @note: C{pyxb.PreserveInputTimeZone()} can be used to bypass the
581 normalization to UTC.
582 """
583
584 _XsdBaseType = anySimpleType
585 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('time')
586
587 _Lexical_fmt = '%H:%M:%S'
588 __CtorFields = ( 'hour', 'minute', 'second', 'microsecond', 'tzinfo' )
589
591 args = cls._ConvertArguments(args, kw)
592 ctor_kw = { }
593 if 1 <= len(args):
594 value = args[0]
595 if isinstance(value, six.string_types):
596 ctor_kw.update(cls._LexicalToKeywords(value))
597 elif isinstance(value, (datetime.time, datetime.datetime)):
598 cls._SetKeysFromPython(value, ctor_kw, cls.__CtorFields)
599 elif isinstance(value, six.integer_types):
600 for fi in range(len(cls.__CtorFields)):
601 fn = cls.__CtorFields[fi]
602 if fi < len(args):
603 ctor_kw[fn] = args[fi]
604 elif fn in kw:
605 ctor_kw[fn] = kw[fn]
606 kw.pop(fn, None)
607 else:
608 raise SimpleTypeValueError(cls, value)
609
610 cls._AdjustForTimezone(ctor_kw)
611 kw.update(ctor_kw)
612 return super(time, cls).__new__(cls, **kw)
613
614 _PrimitiveDatatypes.append(time)
617 _XsdBaseType = anySimpleType
618
619 _ValidFields = ( 'year', 'month', 'day' )
620
622 args = cls._ConvertArguments(args, kw)
623 ctor_kw = { }
624 ctor_kw['year'] = cls._DefaultYear
625 ctor_kw['month'] = cls._DefaultMonth
626 ctor_kw['day'] = cls._DefaultDay
627 ctor_kw['hour'] = 0
628 ctor_kw['minute'] = 0
629 ctor_kw['second'] = 0
630 if kw.get('_nil'):
631 pass
632 elif 1 <= len(args):
633 value = args[0]
634 if isinstance(value, six.string_types):
635 if 1 != len(args):
636 raise TypeError('construction from string requires exactly 1 argument')
637 ctor_kw.update(cls._LexicalToKeywords(value))
638 elif isinstance(value, (datetime.date, datetime.datetime)):
639 if 1 != len(args):
640 raise TypeError('construction from instance requires exactly 1 argument')
641 cls._SetKeysFromPython(value, ctor_kw, cls._ValidFields)
642 try:
643 tzinfo = value.tzinfo
644 if tzinfo is not None:
645 ctor_kw['tzinfo'] = tzinfo
646 except AttributeError:
647 pass
648 else:
649 fi = 0
650 while fi < len(cls._ValidFields):
651 fn = cls._ValidFields[fi]
652 if fi < len(args):
653 ctor_kw[fn] = args[fi]
654 elif fn in kw:
655 ctor_kw[fn] = kw[fn]
656 kw.pop(fn, None)
657 fi += 1
658 if fi < len(args):
659 ctor_kw['tzinfo'] = args[fi]
660 fi += 1
661 if fi != len(args):
662 raise TypeError('function takes %d arguments plus optional tzinfo (%d given)' % (len(cls._ValidFields), len(args)))
663 else:
664 raise TypeError('function takes %d arguments plus optional tzinfo' % (len(cls._ValidFields),))
665
666
667
668
669
670 kw.update(ctor_kw)
671 argv = []
672 argv.append(kw.pop('year'))
673 argv.append(kw.pop('month'))
674 argv.append(kw.pop('day'))
675 return super(_PyXBDateOnly_base, cls).__new__(cls, *argv, **kw)
676
677 @classmethod
687
688 -class date (_PyXBDateOnly_base):
689 """XMLSchema datatype U{date<http://www.w3.org/TR/xmlschema-2/#date>}.
690
691 This class uses the Python C{datetime.datetime} class as its
692 underlying representation; fields not relevant to this type are
693 derived from 1900-01-01T00:00:00.
694
695 @note: Unlike L{dateTime}, timezoned date values are not converted
696 to UTC. The provided timezone information is retained along with
697 the instance; however, the lexical representation generated for
698 output is canonicalized (timezones no more than 12 hours off UTC).
699 """
700
701 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('date')
702 _Lexical_fmt = '%Y-%m-%d'
703 _Fields = ( 'year', 'month', 'day' )
704
705 __SecondsPerMinute = 60
706 __MinutesPerHalfDay = 12 * 60
707 __MinutesPerDay = 24 * 60
709 """Return the recoverable tzinfo for the date.
710
711 Return a L{pyxb.utils.utility.UTCOffsetTimeZone} instance
712 reflecting the timezone associated with the date, or C{None}
713 if the date is not timezoned.
714
715 @note: This is not the recoverable timezone, because timezones are
716 represented as timedeltas which get normalized in ways that
717 don't match what we expect for a tzinfo.
718 """
719 if self.tzinfo is None:
720 return None
721 sdt = self.replace(hour=0, minute=0, second=0, tzinfo=self._UTCTimeZone)
722 utc_offset = (sdt - self).seconds // self.__SecondsPerMinute
723 if utc_offset > self.__MinutesPerHalfDay:
724 utc_offset -= self.__MinutesPerDay
725 return pyxb.utils.utility.UTCOffsetTimeZone(utc_offset)
726
727 @classmethod
745
746 _PrimitiveDatatypes.append(date)
749 """XMLSchema datatype U{gYearMonth<http://www.w3.org/TR/xmlschema-2/#gYearMonth>}.
750
751 This class uses the Python C{datetime.datetime} class as its
752 underlying representation; fields not relevant to this type are
753 derived from 1900-01-01T00:00:00.
754 """
755 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gYearMonth')
756 _Lexical_fmt = '%Y-%m'
757 _ValidFields = ( 'year', 'month' )
758
759 _PrimitiveDatatypes.append(gYearMonth)
760
761 -class gYear (_PyXBDateOnly_base):
762 """XMLSchema datatype U{gYear<http://www.w3.org/TR/xmlschema-2/#gYear>}.
763
764 This class uses the Python C{datetime.datetime} class as its
765 underlying representation; fields not relevant to this type are
766 derived from 1900-01-01T00:00:00.
767 """
768 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gYear')
769 _Lexical_fmt = '%Y'
770 _ValidFields = ( 'year', )
771 _PrimitiveDatatypes.append(gYear)
774 """XMLSchema datatype U{gMonthDay<http://www.w3.org/TR/xmlschema-2/#gMonthDay>}.
775
776 This class uses the Python C{datetime.datetime} class as its
777 underlying representation; fields not relevant to this type are
778 derived from 1900-01-01T00:00:00.
779 """
780 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gMonthDay')
781 _Lexical_fmt = '--%m-%d'
782 _ValidFields = ( 'month', 'day' )
783 _PrimitiveDatatypes.append(gMonthDay)
784
785 -class gDay (_PyXBDateOnly_base):
786 """XMLSchema datatype U{gDay<http://www.w3.org/TR/xmlschema-2/#gDay>}.
787
788 This class uses the Python C{datetime.datetime} class as its
789 underlying representation; fields not relevant to this type are
790 derived from 1900-01-01T00:00:00.
791 """
792 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gDay')
793 _Lexical_fmt = '---%d'
794 _ValidFields = ( 'day', )
795 _PrimitiveDatatypes.append(gDay)
796
797 -class gMonth (_PyXBDateOnly_base):
798 """XMLSchema datatype U{gMonth<http://www.w3.org/TR/xmlschema-2/#gMonth>}.
799
800 This class uses the Python C{datetime.datetime} class as its
801 underlying representation; fields not relevant to this type are
802 derived from 1900-01-01T00:00:00.
803 """
804 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gMonth')
805 _Lexical_fmt = '--%m'
806 _ValidFields = ( 'month', )
807 _PrimitiveDatatypes.append(gMonth)
808
809 -class hexBinary (basis.simpleTypeDefinition, six.binary_type):
810 """XMLSchema datatype U{hexBinary<http://www.w3.org/TR/xmlschema-2/#hexBinary>}."""
811 _XsdBaseType = anySimpleType
812 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('hexBinary')
813
814 @classmethod
816 if (1 <= len(args)) and kw.get('_from_xml', False):
817 xmlt = args[0]
818 try:
819 xmld = xmlt.encode('utf-8')
820 arg0 = binascii.unhexlify(xmld)
821 args = (arg0,) + args[1:]
822 except (TypeError, binascii.Error):
823 raise SimpleTypeValueError(cls, args[0])
824 return args
825
826 @classmethod
828 if isinstance(value, six.text_type):
829 value = value.encode('utf-8')
830 rvd = binascii.hexlify(value)
831 rvt = rvd.decode('utf-8')
832 return rvt.upper()
833
834 @classmethod
837
838 _PrimitiveDatatypes.append(hexBinary)
839
840 -class base64Binary (basis.simpleTypeDefinition, six.binary_type):
841 """XMLSchema datatype U{base64Binary<http://www.w3.org/TR/xmlschema-2/#base64Binary>}.
842
843 See also U{RFC2045<http://tools.ietf.org/html/rfc2045>} and U{RFC4648<http://tools.ietf.org/html/rfc4648>}.
844 """
845 _XsdBaseType = anySimpleType
846 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('base64Binary')
847
848
849
850
851
852 _B04 = '[AQgw]'
853 _B04S = '(%s ?)' % (_B04,)
854 _B16 = '[AEIMQUYcgkosw048]'
855 _B16S = '(%s ?)' % (_B16,)
856 _B64 = '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/]'
857 _B64S = '(%s ?)' % (_B64,)
858
859 __Pattern = '^((' + _B64S + '{4})*((' + _B64S + '{3}' + _B64 + ')|(' + _B64S + '{2}' + _B16S + '=)|(' + _B64S + _B04S + '= ?=)))?$'
860 __Lexical_re = re.compile(__Pattern)
861
862 __ValidateLength = None
863
864 @classmethod
866 """Control the maximum encoded size that is checked for XML literal validity.
867
868 Python's base64 module allows some literals that are invalid
869 according to XML rules. PyXB verifies the validity using a
870 regular expression, which is costly for something that is
871 unlikely to occur. Use this function to inhibit checks for
872 validity based on the length of the XML literal.
873
874 @param length: C{None} (default) to check all literals,
875 otherwise the maximum length literal that will be checked.
876 Pass C{-1} to disable the validity check.
877
878 @return: the previous validation length
879
880 """
881 rv = cls.__ValidateLength
882 if (length is None) or isinstance(length, six.integer_types):
883 cls.__ValidateLength = length
884 return rv
885 raise TypeError('must provide None or integer length')
886
887 @classmethod
902
903 @classmethod
905 if isinstance(value, six.text_type):
906 value = value.encode('utf-8')
907 rvd = base64.standard_b64encode(value)
908 rvt = rvd.decode('utf-8')
909 return rvt
910
911 @classmethod
914
915 _PrimitiveDatatypes.append(base64Binary)
916
917 -class anyURI (basis.simpleTypeDefinition, six.text_type):
929
930 _PrimitiveDatatypes.append(anyURI)
931
932 -class QName (basis.simpleTypeDefinition, pyxb.namespace.ExpandedName):
933 """XMLSchema datatype U{QName<http://www.w3.org/TR/xmlschema-2/#QName>}."""
934 _XsdBaseType = anySimpleType
935 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('QName')
936
937 @classmethod
939 """Section 4.3.1.3: Legacy length return None to indicate no check"""
940 return None
941
942 @classmethod
944 if isinstance(value, pyxb.namespace.ExpandedName):
945 assert 0 > value.localName().find(':')
946 return value
947 if not isinstance(value, six.string_types):
948 raise SimpleTypeValueError(cls, value)
949 if 0 <= value.find(':'):
950 (prefix, local) = value.split(':', 1)
951 if (NCName._ValidRE.match(prefix) is None) or (NCName._ValidRE.match(local) is None):
952 raise SimpleTypeValueError(cls, value)
953 if xmlns_context is None:
954 raise pyxb.QNameResolutionError('QName resolution requires namespace context', value, xmlns_context)
955 return xmlns_context.interpretQName(value, default_no_namespace=True)
956 if NCName._ValidRE.match(value) is None:
957 raise SimpleTypeValueError(cls, value)
958 if xmlns_context is not None:
959 return xmlns_context.interpretQName(value, default_no_namespace=True)
960 return pyxb.namespace.ExpandedName(value)
961
962 @classmethod
964 if 1 == len(args):
965 xmlns_context = kw.pop('_xmlns_context', pyxb.namespace.NamespaceContext.Current())
966 args = (cls._ConvertIf(args[0], xmlns_context),)
967 super_fn = getattr(super(QName, cls), '_ConvertArguments_vx', lambda *a,**kw: args)
968 return super_fn(args, kw)
969
970 @classmethod
972
973
974
975
976
977 raise pyxb.UsageError('Cannot represent QName without namespace declaration')
978
979 @classmethod
983
984
985 _PrimitiveDatatypes.append(QName)
986
987 -class NOTATION (basis.simpleTypeDefinition):
996
997 _PrimitiveDatatypes.append(NOTATION)
1000 """XMLSchema datatype U{normalizedString<http:///www.w3.org/TR/xmlschema-2/#normalizedString>}.
1001
1002 Normalized strings can't have carriage returns, linefeeds, or
1003 tabs in them."""
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('normalizedString')
1015
1016
1017
1018
1019 __BadChars = re.compile("[\r\n\t]")
1020
1021 _ValidRE = None
1022 _InvalidRE = None
1023
1024 @classmethod
1040
1041 @classmethod
1043 """Post-extended method to validate that a string matches a given pattern.
1044
1045 If you can express the valid strings as a compiled regular
1046 expression in the class variable _ValidRE, or the invalid
1047 strings as a compiled regular expression in the class variable
1048 _InvalidRE, you can just use those. If the acceptable matches
1049 are any trickier, you should invoke the superclass
1050 implementation, and if it returns True then perform additional
1051 tests."""
1052 super_fn = getattr(super(normalizedString, cls), '_ValidateString_va', lambda *a,**kw: True)
1053 if not super_fn(value):
1054 return False
1055 return cls.__ValidateString(value)
1056
1057 @classmethod
1065
1066 _DerivedDatatypes.append(normalizedString)
1067 assert normalizedString.XsdSuperType() == string
1068
1069 -class token (normalizedString):
1070 """XMLSchema datatype U{token<http:///www.w3.org/TR/xmlschema-2/#token>}.
1071
1072 Tokens cannot leading or trailing space characters; any
1073 carriage return, line feed, or tab characters; nor any occurrence
1074 of two or more consecutive space characters."""
1075
1076 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('token')
1077
1078 @classmethod
1080 super_fn = getattr(super(token, cls), '_ValidateString_va', lambda *a,**kw: True)
1081 if not super_fn(value):
1082 return False
1083 if value.startswith(" ") \
1084 or value.endswith(" ") \
1085 or (0 <= value.find(' ')):
1086 raise SimpleTypeValueError(cls, value)
1087 return True
1088 _DerivedDatatypes.append(token)
1094 _DerivedDatatypes.append(language)
1105 _DerivedDatatypes.append(NMTOKEN)
1109 _ListDatatypes.append(NMTOKENS)
1110
1111 -class Name (token):
1117 _DerivedDatatypes.append(Name)
1125 _DerivedDatatypes.append(NCName)
1126
1127 -class ID (NCName):
1132 _DerivedDatatypes.append(ID)
1133
1134 -class IDREF (NCName):
1139 _DerivedDatatypes.append(IDREF)
1140
1141 -class IDREFS (basis.STD_list):
1145 _ListDatatypes.append(IDREFS)
1157 _DerivedDatatypes.append(ENTITY)
1163 _ListDatatypes.append(ENTITIES)
1164
1165 -class integer (basis.simpleTypeDefinition, six.long_type):
1173
1174 _DerivedDatatypes.append(integer)
1179 _DerivedDatatypes.append(nonPositiveInteger)
1184 _DerivedDatatypes.append(negativeInteger)
1185
1186 -class long (integer):
1189 _DerivedDatatypes.append(long)
1190
1191 -class int (basis.simpleTypeDefinition, six.int_type):
1201 _DerivedDatatypes.append(int)
1206 _DerivedDatatypes.append(short)
1207
1208 -class byte (short):
1211 _DerivedDatatypes.append(byte)
1216 _DerivedDatatypes.append(nonNegativeInteger)
1221 _DerivedDatatypes.append(unsignedLong)
1226 _DerivedDatatypes.append(unsignedInt)
1231 _DerivedDatatypes.append(unsignedShort)
1236 _DerivedDatatypes.append(unsignedByte)
1241 _DerivedDatatypes.append(positiveInteger)
1242
1243 from . import content
1244
1245 -class anyType (basis.complexTypeDefinition):
1253
1255
1256 global _BuildAutomaton
1257 del _BuildAutomaton
1258 import pyxb.utils.fac as fac
1259
1260 counters = set()
1261 cc_0 = fac.CounterCondition(min=0, max=None, metadata=pyxb.utils.utility.Location('http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/#key-urType', 1, 1))
1262 counters.add(cc_0)
1263 states = set()
1264 final_update = set()
1265 final_update.add(fac.UpdateInstruction(cc_0, False))
1266 symbol = content.WildcardUse(content.Wildcard(process_contents=content.Wildcard.PC_lax, namespace_constraint=content.Wildcard.NC_any), None)
1267 st_0 = fac.State(symbol, is_initial=True, final_update=final_update, is_unordered_catenation=False)
1268 states.add(st_0)
1269 transitions = set()
1270 transitions.add(fac.Transition(st_0, [
1271 fac.UpdateInstruction(cc_0, True) ]))
1272 st_0._set_transitionSet(transitions)
1273 return fac.Automaton(states, counters, True, containing_state=None)
1274 anyType._Automaton = _BuildAutomaton()
1275
1276
1277
1278
1279 anyType._IsUrType = classmethod(lambda _c: _c == anyType)
1280