1# -*- coding: utf-8 -*-
2# Copyright 2009-2013, Peter A. Bigot
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain a
6# copy of the License at:
7#
8#            http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""Classes supporting U{XMLSchema Part 2: Datatypes<http://www.w3.org/TR/xmlschema-2/>}.
17
18Each L{simple type definition<pyxb.xmlschema.structures.SimpleTypeDefinition>} component
19instance is paired with at most one L{basis.simpleTypeDefinition}
20class, which is a subclass of a Python type augmented with facets and
21other constraining information.  This file contains the definitions of
22these types.
23
24We want the simple datatypes to be efficient Python values, but to
25also hold specific constraints that don't apply to the Python types.
26To do this, we subclass each PST.  Primitive PSTs inherit from the
27Python type that represents them, and from a
28pyxb.binding.basis.simpleTypeDefinition class which adds in the
29constraint infrastructure.  Derived PSTs inherit from the parent PST.
30
31There is an exception to this when the Python type best suited for a
32derived SimpleTypeDefinition differs from the type associated with its
33parent STD: for example, L{xsd:integer<integer>} has a value range
34that requires it be represented by a Python C{long}, but
35L{xsd:int<int>} allows representation by a Python C{int}.  In this
36case, the derived PST class is structured like a primitive type, but
37the PST associated with the STD superclass is recorded in a class
38variable C{_XsdBaseType}.
39
40Note the strict terminology: "datatype" refers to a class which is a
41subclass of a Python type, while "type definition" refers to an
42instance of either SimpleTypeDefinition or ComplexTypeDefinition.
43
44"""
45
46import logging
47import re
48import binascii
49import base64
50import math
51import decimal as python_decimal
52from pyxb.exceptions_ import *
53import pyxb.namespace
54import pyxb.utils.unicode
55from pyxb.utils import six
56from . import basis
57
58_log = logging.getLogger(__name__)
59
60_PrimitiveDatatypes = []
61_DerivedDatatypes = []
62_ListDatatypes = []
63
64# We use unicode as the Python type for anything that isn't a normal
65# primitive type.  Presumably, only enumeration and pattern facets
66# will be applied.
67class anySimpleType (basis.simpleTypeDefinition, six.text_type):
68    """XMLSchema datatype U{anySimpleType<http://www.w3.org/TR/xmlschema-2/#dt-anySimpleType>}."""
69    _XsdBaseType = None
70    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('anySimpleType')
71
72    @classmethod
73    def XsdLiteral (cls, value):
74        return value
75# anySimpleType is not treated as a primitive, because its variety
76# must be absent (not atomic).
77
78class string (basis.simpleTypeDefinition, six.text_type):
79    """XMLSchema datatype U{string<http://www.w3.org/TR/xmlschema-2/#string>}."""
80    _XsdBaseType = anySimpleType
81    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('string')
82
83    @classmethod
84    def XsdLiteral (cls, value):
85        assert isinstance(value, cls)
86        return value
87
88    @classmethod
89    def XsdValueLength (cls, value):
90        return len(value)
91
92_PrimitiveDatatypes.append(string)
93
94# It is illegal to subclass the bool type in Python, so we subclass
95# int instead.
96@six.python_2_unicode_compatible
97class boolean (basis.simpleTypeDefinition, six.int_type, basis._NoNullaryNonNillableNew_mixin):
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
103    def XsdLiteral (cls, value):
104        if value:
105            return 'true'
106        return 'false'
107
108    def __str__ (self):
109        if self:
110            return six.u('true')
111        return six.u('false')
112
113    def __new__ (cls, *args, **kw):
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
129class decimal (basis.simpleTypeDefinition, python_decimal.Decimal, basis._RepresentAsXsdLiteral_mixin, basis._NoNullaryNonNillableNew_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
140    def __new__ (cls, *args, **kw):
141        args = cls._ConvertArguments(args, kw)
142        # Pre Python 2.7 can't construct from float values
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
153    def _CheckValidValue (cls, value):
154        if not (value.is_normal() or value.is_zero()):
155            raise SimpleTypeValueError(cls, value)
156        return super(decimal, cls)._CheckValidValue(value)
157
158    @classmethod
159    def XsdLiteral (cls, value):
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
187class _fp (basis.simpleTypeDefinition, six.float_type, basis._NoNullaryNonNillableNew_mixin):
188    _XsdBaseType = anySimpleType
189
190    @classmethod
191    def XsdLiteral (cls, value):
192        if math.isinf(value):
193            if (0 > value):
194                return '-INF'
195            return 'INF'
196        if math.isnan(value):
197            return 'NaN'
198        return '%s' % (value,)
199
200class float (_fp):
201    """XMLSchema datatype U{float<http://www.w3.org/TR/xmlschema-2/#float>}."""
202    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('float')
203
204_PrimitiveDatatypes.append(float)
205
206class double (_fp):
207    """XMLSchema datatype U{double<http://www.w3.org/TR/xmlschema-2/#double>}."""
208    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('double')
209
210_PrimitiveDatatypes.append(double)
211
212import datetime
213
214class 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    # We do not use weeks
235    __XSDFields = ( 'years', 'months', 'days', 'hours', 'minutes', 'seconds' )
236    __PythonFields = ( 'days', 'seconds', 'microseconds', 'minutes', 'hours' )
237
238    def negativeDuration (self):
239        return self.__negativeDuration
240    __negativeDuration = None
241
242    def durationData (self):
243        return self.__durationData
244    __durationData = None
245
246    def __new__ (cls, *args, **kw):
247        args = cls._ConvertArguments(args, kw)
248        have_kw_update = False
249        negative_duration = False
250        if kw.get('_nil'):
251            data = dict(zip(cls.__PythonFields, len(cls.__PythonFields) * [0,]))
252        elif 0 == len(args):
253            if kw.get('_from_xml'):
254                raise SimpleTypeValueError(cls, args)
255            data = dict(zip(cls.__PythonFields, len(cls.__PythonFields) * [0,]))
256        elif 1 < len(args):
257            if kw.get('_from_xml'):
258                raise SimpleTypeValueError(cls, args)
259            # Apply the arguments as in the underlying Python constructor
260            data = dict(zip(cls.__PythonFields[:len(args)], args))
261        else:
262            text = args[0];
263            if isinstance(text, six.string_types):
264                match = cls.__Lexical_re.match(text)
265                if match is None:
266                    raise SimpleTypeValueError(cls, text)
267                match_map = match.groupdict()
268                if 'T' == match_map.get('Time'):
269                    # Can't have T without additional time information
270                    raise SimpleTypeValueError(cls, text)
271
272                negative_duration = ('-' == match_map.get('neg'))
273
274                fractional_seconds = 0.0
275                if match_map.get('fracsec') is not None:
276                    fractional_seconds = six.float_type('0%s' % (match_map['fracsec'],))
277                    usec = six.int_type(1000000 * fractional_seconds)
278                    if negative_duration:
279                        kw['microseconds'] = - usec
280                    else:
281                        kw['microseconds'] = usec
282                else:
283                    # Discard any bogosity passed in by the caller
284                    kw.pop('microsecond', None)
285
286                data = { }
287                for fn in cls.__XSDFields:
288                    v = match_map.get(fn, 0)
289                    if v is None:
290                        v = 0
291                    data[fn] = six.int_type(v)
292                    if fn in cls.__PythonFields:
293                        if negative_duration:
294                            kw[fn] = - data[fn]
295                        else:
296                            kw[fn] = data[fn]
297                data['seconds'] += fractional_seconds
298                have_kw_update = True
299            elif kw.get('_from_xml'):
300                raise SimpleTypeValueError(cls, args)
301            elif isinstance(text, cls):
302                data = text.durationData().copy()
303                negative_duration = text.negativeDuration()
304            elif isinstance(text, datetime.timedelta):
305                data = { 'days' : text.days,
306                         'seconds' : text.seconds + (text.microseconds / 1000000.0) }
307                negative_duration = (0 > data['days'])
308                if negative_duration:
309                    if 0.0 == data['seconds']:
310                        data['days'] = - data['days']
311                    else:
312                        data['days'] = 1 - data['days']
313                        data['seconds'] = 24 * 60 * 60.0 - data['seconds']
314                data['minutes'] = 0
315                data['hours'] = 0
316            elif isinstance(text, six.integer_types):
317                # Apply the arguments as in the underlying Python constructor
318                data = dict(zip(cls.__PythonFields[:len(args)], args))
319                negative_duration = False
320            else:
321                raise SimpleTypeValueError(cls, text)
322        if not have_kw_update:
323            rem_time = data.pop('seconds', 0)
324            if (0 != (rem_time % 1)):
325                data['microseconds'] = data.pop('microseconds', 0) + six.int_type(1000000 * (rem_time % 1))
326                rem_time = rem_time // 1
327            data['seconds'] = rem_time % 60
328            rem_time = data.pop('minutes', 0) + (rem_time // 60)
329            data['minutes'] = rem_time % 60
330            rem_time = data.pop('hours', 0) + (rem_time // 60)
331            data['hours'] = rem_time % 24
332            data['days'] += (rem_time // 24)
333            for fn in cls.__PythonFields:
334                if fn in data:
335                    if negative_duration:
336                        kw[fn] = - data[fn]
337                    else:
338                        kw[fn] = data[fn]
339                else:
340                    kw.pop(fn, None)
341            kw['microseconds'] = data.pop('microseconds', 0)
342            data['seconds'] += kw['microseconds'] / 1000000.0
343
344        rv = super(duration, cls).__new__(cls, **kw)
345        rv.__durationData = data
346        rv.__negativeDuration = negative_duration
347        return rv
348
349    @classmethod
350    def XsdLiteral (cls, value):
351        elts = []
352        if value.negativeDuration():
353            elts.append('-')
354        elts.append('P')
355        for k in ( 'years', 'months', 'days' ):
356            v = value.__durationData.get(k, 0)
357            if 0 != v:
358                elts.append('%d%s' % (v, k[0].upper()))
359        time_elts = []
360        for k in ( 'hours', 'minutes' ):
361            v = value.__durationData.get(k, 0)
362            if 0 != v:
363                time_elts.append('%d%s' % (v, k[0].upper()))
364        v = value.__durationData.get('seconds', 0)
365        if 0 != v:
366            time_elts.append(('%f' % (v,)).rstrip('0').rstrip('.') + 'S')
367        if 0 < len(time_elts):
368            elts.append('T')
369            elts.extend(time_elts)
370        if 1 == len(elts):
371            # Value must have zero duration.  Pick something short.
372            elts.append('0D')
373        return ''.join(elts)
374
375_PrimitiveDatatypes.append(duration)
376
377class _PyXBDateTime_base (basis.simpleTypeDefinition, basis._RepresentAsXsdLiteral_mixin):
378
379    _Lexical_fmt = None
380    """Format for the lexical representation of a date-related instance, excluding timezone.
381
382    Subclasses must define this."""
383
384    # Map from strptime/strftime formats to the regular expressions we
385    # use to extract them.  We're more strict than strptime, so not
386    # trying to use that.
387    __PatternMap = { '%Y' : '(?P<negYear>-?)(?P<year>\d{4,})'
388                   , '%m' : '(?P<month>\d{2})'
389                   , '%d' : '(?P<day>\d{2})'
390                   , '%H' : '(?P<hour>\d{2})'
391                   , '%M' : '(?P<minute>\d{2})'
392                   , '%S' : '(?P<second>\d{2})(?P<fracsec>\.\d+)?'
393                   , '%Z' : '(?P<tzinfo>Z|[-+]\d\d:\d\d)' }
394
395    # Cache of compiled regular expressions to parse lexical space of
396    # a subclass.
397    __LexicalREMap = { }
398
399    # Fields extracted by parsing that have an integer value
400    __LexicalIntegerFields = ( 'year', 'month', 'day', 'hour', 'minute', 'second' )
401
402    _UTCTimeZone = pyxb.utils.utility.UTCOffsetTimeZone(0)
403    """A L{datetime.tzinfo} instance representing UTC."""
404
405    _LocalTimeZone = pyxb.utils.utility.LocalTimeZone()
406    """A L{datetime.tzinfo} instance representing the local time zone."""
407
408    _DefaultYear = 1900
409    _DefaultMonth = 1
410    _DefaultDay = 1
411
412    @classmethod
413    def _LexicalToKeywords (cls, text):
414        lexical_re = cls.__LexicalREMap.get(cls)
415        if lexical_re is None:
416            pattern = '^' + cls._Lexical_fmt + '%Z?$'
417            for (k, v) in six.iteritems(cls.__PatternMap):
418                pattern = pattern.replace(k, v)
419            lexical_re = re.compile(pattern)
420            cls.__LexicalREMap[cls] = lexical_re
421        match = lexical_re.match(text)
422        if match is None:
423            raise SimpleTypeValueError(cls, text)
424        match_map = match.groupdict()
425        kw = { }
426        for (k, v) in six.iteritems(match_map):
427            if (k in cls.__LexicalIntegerFields) and (v is not None):
428                kw[k] = six.int_type(v)
429        if '-' == match_map.get('negYear'):
430            kw['year'] = - kw['year']
431        if match_map.get('fracsec') is not None:
432            kw['microsecond'] = six.int_type(round(1000000 * six.float_type('0%s' % (match_map['fracsec'],))))
433        else:
434            # Discard any bogosity passed in by the caller
435            kw.pop('microsecond', None)
436        if match_map.get('tzinfo') is not None:
437            kw['tzinfo'] = pyxb.utils.utility.UTCOffsetTimeZone(match_map['tzinfo'])
438        else:
439            kw.pop('tzinfo', None)
440        return kw
441
442    @classmethod
443    def _SetKeysFromPython_csc (cls, python_value, kw, fields):
444        for f in fields:
445            kw[f] = getattr(python_value, f)
446        return getattr(super(_PyXBDateTime_base, cls), '_SetKeysFromPython_csc', lambda *a,**kw: None)(python_value, kw, fields)
447
448    @classmethod
449    def _SetKeysFromPython (cls, python_value, kw, fields):
450        return cls._SetKeysFromPython_csc(python_value, kw, fields)
451
452    # Several datetime classes are extension classes, and the PyXB
453    # subclasses won't recognize the packed values.  Use the lexical
454    # representation instead.
455    def __reduce__ (self):
456        return (self.__class__, (self.xsdLiteral(),))
457
458    # In Python 3.6 datetime started using __reduce_ex__ which is
459    # higher priority.  Override it too.
460    def __reduce_ex__ (self, protocol):
461        return (self.__class__, (self.xsdLiteral(),))
462
463    @classmethod
464    def _AdjustForTimezone (cls, kw):
465        """Update datetime keywords to account for timezone effects.
466
467        All XML schema timezoned times are in UTC, with the time "in
468        its timezone".  If the keywords indicate a non-UTC timezone is
469        in force, and L{pyxb.PreserveInputTimeZone()} has not been
470        set, adjust the values to account for the zone by subtracting
471        the corresponding UTC offset and mark explicitly that the time
472        is in UTC by leaving a C{tzinfo} attribute identifying the UTC
473        time zone.
474
475        @param kw: A dictionary of keywords relevant for a date or
476        time instance.  The dictionary is updated by this call.
477        """
478        if pyxb.PreserveInputTimeZone():
479            return
480        tzoffs = kw.pop('tzinfo', None)
481        if tzoffs is not None:
482            use_kw = kw.copy()
483            # Ensure ctor requirements of datetime.datetime are met
484            use_kw.setdefault('year', cls._DefaultYear)
485            use_kw.setdefault('month', cls._DefaultMonth)
486            use_kw.setdefault('day', cls._DefaultDay)
487            dt = datetime.datetime(tzinfo=tzoffs, **use_kw)
488            dt -= tzoffs.utcoffset(dt)
489            for k in six.iterkeys(kw):
490                kw[k] = getattr(dt, k)
491            kw['tzinfo'] = cls._UTCTimeZone
492
493    @classmethod
494    def XsdLiteral (cls, value):
495        iso = value.replace(tzinfo=None).isoformat()
496        if 0 <= iso.find('.'):
497            iso = iso.rstrip('0')
498        if value.tzinfo is not None:
499            iso += value.tzinfo.tzname(value)
500        return iso
501
502class dateTime (_PyXBDateTime_base, datetime.datetime):
503    """XMLSchema datatype U{dateTime<http://www.w3.org/TR/xmlschema-2/#dateTime>}.
504
505    This class uses the Python C{datetime.datetime} class as its
506    underlying representation.  Unless L{pyxb.PreserveInputTimeZone()}
507    is used, all timezoned dateTime objects are in UTC.  Presence of
508    time zone information in the lexical space is preserved by a
509    non-empty tzinfo field, which should always be zero minutes offset
510    from UTC unless the input time zone was preserved.
511
512    @warning: The value space of Python's C{datetime.datetime} class
513    is more restricted than that of C{xs:datetime}.  As a specific
514    example, Python does not support negative years or years with more
515    than four digits.  For now, the convenience of having an object
516    that is compatible with Python is more important than supporting
517    the full value space.  In the future, the choice may be left up to
518    the developer.
519    """
520
521    _XsdBaseType = anySimpleType
522    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('dateTime')
523
524    _Lexical_fmt = '%Y-%m-%dT%H:%M:%S'
525    __CtorFields = ( 'year', 'month', 'day', 'hour', 'minute', 'second', 'microsecond', 'tzinfo' )
526
527    def __new__ (cls, *args, **kw):
528        args = cls._ConvertArguments(args, kw)
529
530        ctor_kw = { }
531        if kw.get('_nil'):
532            ctor_kw = { 'year': 1900, 'month': 1, 'day': 1 }
533        elif 0 == len(args):
534            if kw.get('_from_xml'):
535                raise SimpleTypeValueError(cls, args)
536            ctor_kw = { 'year': 1900, 'month': 1, 'day': 1 }
537        elif 1 == len(args):
538            value = args[0]
539            if isinstance(value, six.string_types):
540                ctor_kw.update(cls._LexicalToKeywords(value))
541            elif isinstance(value, datetime.datetime):
542                cls._SetKeysFromPython(value, ctor_kw, cls.__CtorFields)
543            elif isinstance(value, six.integer_types):
544                raise TypeError('function takes at least 3 arguments (%d given)' % (len(args),))
545            else:
546                raise SimpleTypeValueError(cls, value)
547        elif 3 <= len(args):
548            for fi in range(len(cls.__CtorFields)):
549                fn = cls.__CtorFields[fi]
550                if fi < len(args):
551                    ctor_kw[fn] = args[fi]
552                elif fn in kw:
553                    ctor_kw[fn] = kw[fn]
554                kw.pop(fn, None)
555        else:
556            raise TypeError('function takes at least 3 arguments (%d given)' % (len(args),))
557
558        cls._AdjustForTimezone(ctor_kw)
559        kw.update(ctor_kw)
560        year = kw.pop('year')
561        month = kw.pop('month')
562        day = kw.pop('day')
563        rv = super(dateTime, cls).__new__(cls, year, month, day, **kw)
564        return rv
565
566    @classmethod
567    def today (cls):
568        """Return today.
569
570        Just like datetime.datetime.today(), except this one sets a
571        tzinfo field so it's clear the value is UTC."""
572        return cls(datetime.datetime.now(cls._UTCTimeZone))
573
574    def aslocal (self):
575        """Returns a C{datetime.datetime} instance denoting the same
576        time as this instance but adjusted to be in the local time
577        zone.
578
579        @rtype: C{datetime.datetime} (B{NOT} C{xsd.dateTime})
580        """
581        dt = self
582        if dt.tzinfo is None:
583            dt = dt.replace(tzinfo=self._UTCTimeZone)
584        return dt.astimezone(self._LocalTimeZone)
585
586_PrimitiveDatatypes.append(dateTime)
587
588class time (_PyXBDateTime_base, datetime.time):
589    """XMLSchema datatype U{time<http://www.w3.org/TR/xmlschema-2/#time>}.
590
591    This class uses the Python C{datetime.time} class as its
592    underlying representation.  Note that per the XMLSchema spec, all
593    dateTime objects are in UTC, and that timezone information in the
594    string representation in XML is an indication of the local time
595    zone's offset from UTC.  Presence of time zone information in the
596    lexical space is indicated by the tzinfo field.
597
598    @note: C{pyxb.PreserveInputTimeZone()} can be used to bypass the
599    normalization to UTC.
600    """
601
602    _XsdBaseType = anySimpleType
603    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('time')
604
605    _Lexical_fmt = '%H:%M:%S'
606    __CtorFields = ( 'hour', 'minute', 'second', 'microsecond', 'tzinfo' )
607
608    def __new__ (cls, *args, **kw):
609        args = cls._ConvertArguments(args, kw)
610        ctor_kw = { }
611        if kw.get('_nil'):
612            pass
613        elif 0 == len(args):
614            if kw.get('_from_xml'):
615                raise SimpleTypeValueError(cls, args)
616        else:
617            value = args[0]
618            if isinstance(value, six.string_types):
619                ctor_kw.update(cls._LexicalToKeywords(value))
620            elif isinstance(value, (datetime.time, datetime.datetime)):
621                cls._SetKeysFromPython(value, ctor_kw, cls.__CtorFields)
622            elif isinstance(value, six.integer_types):
623                for fi in range(len(cls.__CtorFields)):
624                    fn = cls.__CtorFields[fi]
625                    if fi < len(args):
626                        ctor_kw[fn] = args[fi]
627                    elif fn in kw:
628                        ctor_kw[fn] = kw[fn]
629                    kw.pop(fn, None)
630            else:
631                raise SimpleTypeValueError(cls, value)
632
633        cls._AdjustForTimezone(ctor_kw)
634        kw.update(ctor_kw)
635        return super(time, cls).__new__(cls, **kw)
636
637_PrimitiveDatatypes.append(time)
638
639class _PyXBDateOnly_base (_PyXBDateTime_base, datetime.datetime):
640    _XsdBaseType = anySimpleType
641
642    _ValidFields = ( 'year', 'month', 'day' )
643
644    def __new__ (cls, *args, **kw):
645        args = cls._ConvertArguments(args, kw)
646        ctor_kw = { }
647        ctor_kw['year'] = cls._DefaultYear
648        ctor_kw['month'] = cls._DefaultMonth
649        ctor_kw['day'] = cls._DefaultDay
650        ctor_kw['hour'] = 0
651        ctor_kw['minute'] = 0
652        ctor_kw['second'] = 0
653        if kw.get('_nil'):
654            pass
655        elif 1 <= len(args):
656            value = args[0]
657            if isinstance(value, six.string_types):
658                if 1 != len(args):
659                    raise TypeError('construction from string requires exactly 1 argument')
660                ctor_kw.update(cls._LexicalToKeywords(value))
661            elif isinstance(value, (datetime.date, datetime.datetime)):
662                if 1 != len(args):
663                    raise TypeError('construction from instance requires exactly 1 argument')
664                cls._SetKeysFromPython(value, ctor_kw, cls._ValidFields)
665                try:
666                    tzinfo = value.tzinfo
667                    if tzinfo is not None:
668                        ctor_kw['tzinfo'] = tzinfo
669                except AttributeError:
670                    pass
671            else:
672                fi = 0
673                while fi < len(cls._ValidFields):
674                    fn = cls._ValidFields[fi]
675                    if fi < len(args):
676                        ctor_kw[fn] = args[fi]
677                    elif fn in kw:
678                        ctor_kw[fn] = kw[fn]
679                    kw.pop(fn, None)
680                    fi += 1
681                if fi < len(args):
682                    ctor_kw['tzinfo'] = args[fi]
683                    fi += 1
684                if fi != len(args):
685                    raise TypeError('function takes %d arguments plus optional tzinfo (%d given)' % (len(cls._ValidFields), len(args)))
686        else:
687            raise TypeError('function takes %d arguments plus optional tzinfo' % (len(cls._ValidFields),))
688
689        # Do not adjust for the timezone here.  Only xsd:date provides
690        # a recoverable timezone, so just preserve the as-supplied
691        # timezone, and we'll canonicalize the date one if/when it's
692        # converted back to lexical form.
693        kw.update(ctor_kw)
694        argv = []
695        argv.append(kw.pop('year'))
696        argv.append(kw.pop('month'))
697        argv.append(kw.pop('day'))
698        return super(_PyXBDateOnly_base, cls).__new__(cls, *argv, **kw)
699
700    @classmethod
701    def XsdLiteral (cls, value):
702        # Work around strftime year restriction
703        fmt = cls._Lexical_fmt
704        if value.year < 1900:
705            fmt = fmt.replace('%Y', '%04d' % (value.year,))
706            value = value.replace(year=1900)
707        if value.tzinfo is not None:
708            fmt += value.tzinfo.tzname(value)
709        return value.strftime(fmt)
710
711class date (_PyXBDateOnly_base):
712    """XMLSchema datatype U{date<http://www.w3.org/TR/xmlschema-2/#date>}.
713
714    This class uses the Python C{datetime.datetime} class as its
715    underlying representation; fields not relevant to this type are
716    derived from 1900-01-01T00:00:00.
717
718    @note: Unlike L{dateTime}, timezoned date values are not converted
719    to UTC.  The provided timezone information is retained along with
720    the instance; however, the lexical representation generated for
721    output is canonicalized (timezones no more than 12 hours off UTC).
722    """
723
724    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('date')
725    _Lexical_fmt = '%Y-%m-%d'
726    _Fields = ( 'year', 'month', 'day' )
727
728    __SecondsPerMinute = 60
729    __MinutesPerHalfDay = 12 * 60
730    __MinutesPerDay = 24 * 60
731    def xsdRecoverableTzinfo (self):
732        """Return the recoverable tzinfo for the date.
733
734        Return a L{pyxb.utils.utility.UTCOffsetTimeZone} instance
735        reflecting the timezone associated with the date, or C{None}
736        if the date is not timezoned.
737
738        @note: This is not the recoverable timezone, because timezones are
739        represented as timedeltas which get normalized in ways that
740        don't match what we expect for a tzinfo.
741        """
742        if self.tzinfo is None:
743            return None
744        sdt = self.replace(hour=0, minute=0, second=0, tzinfo=self._UTCTimeZone)
745        utc_offset = (sdt - self).seconds // self.__SecondsPerMinute
746        if utc_offset > self.__MinutesPerHalfDay:
747            utc_offset -= self.__MinutesPerDay
748        return pyxb.utils.utility.UTCOffsetTimeZone(utc_offset)
749
750    @classmethod
751    def XsdLiteral (cls, value):
752        # Work around strftime year restriction
753        fmt = cls._Lexical_fmt
754        rtz = value.xsdRecoverableTzinfo()
755        if rtz is not None:
756            # If the date is timezoned, convert it to UTC
757            value -= value.tzinfo.utcoffset(value)
758            value = value.replace(tzinfo=cls._UTCTimeZone)
759        # Use the midpoint of the one-day interval to get the correct
760        # month/day.
761        value += datetime.timedelta(minutes=cls.__MinutesPerHalfDay)
762        if value.year < 1900:
763            fmt = fmt.replace('%Y', '%04d' % (value.year,))
764            value = value.replace(year=1900)
765        if rtz is not None:
766            fmt += rtz.tzname(value)
767        return value.strftime(fmt)
768
769_PrimitiveDatatypes.append(date)
770
771class gYearMonth (_PyXBDateOnly_base):
772    """XMLSchema datatype U{gYearMonth<http://www.w3.org/TR/xmlschema-2/#gYearMonth>}.
773
774    This class uses the Python C{datetime.datetime} class as its
775    underlying representation; fields not relevant to this type are
776    derived from 1900-01-01T00:00:00.
777    """
778    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gYearMonth')
779    _Lexical_fmt = '%Y-%m'
780    _ValidFields = ( 'year', 'month' )
781
782_PrimitiveDatatypes.append(gYearMonth)
783
784class gYear (_PyXBDateOnly_base):
785    """XMLSchema datatype U{gYear<http://www.w3.org/TR/xmlschema-2/#gYear>}.
786
787    This class uses the Python C{datetime.datetime} class as its
788    underlying representation; fields not relevant to this type are
789    derived from 1900-01-01T00:00:00.
790    """
791    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gYear')
792    _Lexical_fmt = '%Y'
793    _ValidFields = ( 'year', )
794_PrimitiveDatatypes.append(gYear)
795
796class gMonthDay (_PyXBDateOnly_base):
797    """XMLSchema datatype U{gMonthDay<http://www.w3.org/TR/xmlschema-2/#gMonthDay>}.
798
799    This class uses the Python C{datetime.datetime} class as its
800    underlying representation; fields not relevant to this type are
801    derived from 1900-01-01T00:00:00.
802    """
803    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gMonthDay')
804    _Lexical_fmt = '--%m-%d'
805    _ValidFields = ( 'month', 'day' )
806_PrimitiveDatatypes.append(gMonthDay)
807
808class gDay (_PyXBDateOnly_base):
809    """XMLSchema datatype U{gDay<http://www.w3.org/TR/xmlschema-2/#gDay>}.
810
811    This class uses the Python C{datetime.datetime} class as its
812    underlying representation; fields not relevant to this type are
813    derived from 1900-01-01T00:00:00.
814    """
815    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gDay')
816    _Lexical_fmt = '---%d'
817    _ValidFields = ( 'day', )
818_PrimitiveDatatypes.append(gDay)
819
820class gMonth (_PyXBDateOnly_base):
821    """XMLSchema datatype U{gMonth<http://www.w3.org/TR/xmlschema-2/#gMonth>}.
822
823    This class uses the Python C{datetime.datetime} class as its
824    underlying representation; fields not relevant to this type are
825    derived from 1900-01-01T00:00:00.
826    """
827    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gMonth')
828    _Lexical_fmt = '--%m'
829    _ValidFields = ( 'month', )
830_PrimitiveDatatypes.append(gMonth)
831
832class hexBinary (basis.simpleTypeDefinition, six.binary_type):
833    """XMLSchema datatype U{hexBinary<http://www.w3.org/TR/xmlschema-2/#hexBinary>}."""
834    _XsdBaseType = anySimpleType
835    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('hexBinary')
836
837    @classmethod
838    def _ConvertArguments_vx (cls, args, kw):
839        if (1 <= len(args)) and kw.get('_from_xml', False):
840            xmlt = args[0]
841            try:
842                xmld = xmlt.encode('utf-8')
843                arg0 = binascii.unhexlify(xmld)
844                args = (arg0,) + args[1:]
845            except (TypeError, binascii.Error):
846                raise SimpleTypeValueError(cls, args[0])
847        return args
848
849    @classmethod
850    def XsdLiteral (cls, value):
851        if isinstance(value, six.text_type):
852            value = value.encode('utf-8')
853        rvd = binascii.hexlify(value)
854        rvt = rvd.decode('utf-8')
855        return rvt.upper()
856
857    @classmethod
858    def XsdValueLength (cls, value):
859        return len(value)
860
861_PrimitiveDatatypes.append(hexBinary)
862
863class base64Binary (basis.simpleTypeDefinition, six.binary_type):
864    """XMLSchema datatype U{base64Binary<http://www.w3.org/TR/xmlschema-2/#base64Binary>}.
865
866    See also U{RFC2045<http://tools.ietf.org/html/rfc2045>} and U{RFC4648<http://tools.ietf.org/html/rfc4648>}.
867    """
868    _XsdBaseType = anySimpleType
869    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('base64Binary')
870
871    # base64 is too lenient: it accepts 'ZZZ=' as an encoding of
872    # 'e\x96', while the required XML Schema production requires
873    # 'ZZY='.  Define a regular expression per section 3.2.16.
874
875    _B04 = '[AQgw]'
876    _B04S = '(%s ?)' % (_B04,)
877    _B16 = '[AEIMQUYcgkosw048]'
878    _B16S = '(%s ?)' % (_B16,)
879    _B64 = '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/]'
880    _B64S = '(%s ?)' % (_B64,)
881
882    __Pattern = '^((' + _B64S + '{4})*((' + _B64S + '{3}' + _B64 + ')|(' + _B64S + '{2}' + _B16S + '=)|(' + _B64S + _B04S + '= ?=)))?$'
883    __Lexical_re = re.compile(__Pattern)
884
885    __ValidateLength = None
886
887    @classmethod
888    def XsdValidateLength (cls, length):
889        """Control the maximum encoded size that is checked for XML literal validity.
890
891        Python's base64 module allows some literals that are invalid
892        according to XML rules.  PyXB verifies the validity using a
893        regular expression, which is costly for something that is
894        unlikely to occur.  Use this function to inhibit checks for
895        validity based on the length of the XML literal.
896
897        @param length: C{None} (default) to check all literals,
898        otherwise the maximum length literal that will be checked.
899        Pass C{-1} to disable the validity check.
900
901        @return: the previous validation length
902
903        """
904        rv = cls.__ValidateLength
905        if (length is None) or isinstance(length, six.integer_types):
906            cls.__ValidateLength = length
907            return rv
908        raise TypeError('must provide None or integer length')
909
910    @classmethod
911    def _ConvertArguments_vx (cls, args, kw):
912        if (1 <= len(args)) and kw.get('_from_xml', False):
913            xmlt = args[0]
914            try:
915                xmld = xmlt.encode('utf-8')
916                arg0 = base64.standard_b64decode(xmld)
917                args = (arg0,) + args[1:]
918            except (TypeError, binascii.Error):
919                raise SimpleTypeValueError(cls, xmlt)
920            if (cls.__ValidateLength is None) or (cls.__ValidateLength >= len(xmlt)):
921                # This is what it costs to try to be a validating processor.
922                if cls.__Lexical_re.match(xmlt) is None:
923                    raise SimpleTypeValueError(cls, xmlt)
924        return args
925
926    @classmethod
927    def XsdLiteral (cls, value):
928        if isinstance(value, six.text_type):
929            value = value.encode('utf-8')
930        rvd = base64.standard_b64encode(value)
931        rvt = rvd.decode('utf-8')
932        return rvt
933
934    @classmethod
935    def XsdValueLength (cls, value):
936        return len(value)
937
938_PrimitiveDatatypes.append(base64Binary)
939
940class anyURI (basis.simpleTypeDefinition, six.text_type):
941    """XMLSchema datatype U{anyURI<http://www.w3.org/TR/xmlschema-2/#anyURI>}."""
942    _XsdBaseType = anySimpleType
943    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('anyURI')
944
945    @classmethod
946    def XsdValueLength (cls, value):
947        return len(value)
948
949    @classmethod
950    def XsdLiteral (cls, value):
951        return six.text_type(value)
952
953_PrimitiveDatatypes.append(anyURI)
954
955class QName (basis.simpleTypeDefinition, pyxb.namespace.ExpandedName):
956    """XMLSchema datatype U{QName<http://www.w3.org/TR/xmlschema-2/#QName>}."""
957    _XsdBaseType = anySimpleType
958    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('QName')
959
960    @classmethod
961    def XsdValueLength (cls, value):
962        """Section 4.3.1.3: Legacy length return None to indicate no check"""
963        return None
964
965    @classmethod
966    def _ConvertIf (cls, value, xmlns_context):
967        if isinstance(value, pyxb.namespace.ExpandedName):
968            assert 0 > value.localName().find(':')
969            return value
970        if not isinstance(value, six.string_types):
971            raise SimpleTypeValueError(cls, value)
972        if 0 <= value.find(':'):
973            (prefix, local) = value.split(':', 1)
974            if (NCName._ValidRE.match(prefix) is None) or (NCName._ValidRE.match(local) is None):
975                raise SimpleTypeValueError(cls, value)
976            if xmlns_context is None:
977                raise pyxb.QNameResolutionError('QName resolution requires namespace context', value, xmlns_context)
978            return xmlns_context.interpretQName(value, default_no_namespace=True)
979        if NCName._ValidRE.match(value) is None:
980            raise SimpleTypeValueError(cls, value)
981        if xmlns_context is not None:
982            return xmlns_context.interpretQName(value, default_no_namespace=True)
983        return pyxb.namespace.ExpandedName(value)
984
985    @classmethod
986    def _ConvertArguments_vx (cls, args, kw):
987        if 1 == len(args):
988            xmlns_context = kw.pop('_xmlns_context', pyxb.namespace.NamespaceContext.Current())
989            args = (cls._ConvertIf(args[0], xmlns_context),)
990        super_fn = getattr(super(QName, cls), '_ConvertArguments_vx', lambda *a,**kw: args)
991        return super_fn(args, kw)
992
993    @classmethod
994    def XsdLiteral (cls, value):
995        # A QName has no unicode/XSD representation in the absence of
996        # a registered namespace.  Whatever called this should have
997        # detected that the value is a QName and used
998        # BindingDOMSupport.qnameToText() to convert it to a lexical
999        # representation that incorporates a declared namespace.
1000        raise pyxb.UsageError('Cannot represent QName without namespace declaration')
1001
1002    @classmethod
1003    def _XsdConstraintsPreCheck_vb (cls, value):
1004        super_fn = getattr(super(QName, cls), '_XsdConstraintsPreCheck_vb', lambda *a,**kw: True)
1005        return super_fn(cls._ConvertIf(value, pyxb.namespace.NamespaceContext.Current()))
1006
1007
1008_PrimitiveDatatypes.append(QName)
1009
1010class NOTATION (basis.simpleTypeDefinition):
1011    """XMLSchema datatype U{NOTATION<http://www.w3.org/TR/xmlschema-2/#NOTATION>}."""
1012    _XsdBaseType = anySimpleType
1013    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('NOTATION')
1014
1015    @classmethod
1016    def XsdValueLength (cls, value):
1017        """Section 4.3.1.3: Legacy length return None to indicate no check"""
1018        return None
1019
1020_PrimitiveDatatypes.append(NOTATION)
1021
1022class normalizedString (string):
1023    """XMLSchema datatype U{normalizedString<http:///www.w3.org/TR/xmlschema-2/#normalizedString>}.
1024
1025    Normalized strings can't have carriage returns, linefeeds, or
1026    tabs in them."""
1027
1028    # All descendents of normalizedString constrain the lexical/value
1029    # space in some way.  Subclasses should set the _ValidRE class
1030    # variable to a compiled regular expression that matches valid
1031    # input, or the _InvalidRE class variable to a compiled regular
1032    # expression that detects invalid inputs.
1033    #
1034    # Alternatively, subclasses can override the _ValidateString_va
1035    # method.
1036
1037    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('normalizedString')
1038
1039    # @todo Implement pattern constraints and just rely on them
1040
1041    # No CR, LF, or TAB
1042    __BadChars = re.compile("[\r\n\t]")
1043
1044    _ValidRE = None
1045    _InvalidRE = None
1046
1047    @classmethod
1048    def __ValidateString (cls, value):
1049        # This regular expression doesn't work.  Don't know why.
1050        #if cls.__BadChars.match(value) is not None:
1051        #    raise SimpleTypeValueError('CR/NL/TAB characters illegal in %s' % (cls.__name__,))
1052        if (0 <= value.find("\n")) or (0 <= value.find("\r")) or (0 <= value.find("\t")):
1053            raise SimpleTypeValueError(cls, value)
1054        if cls._ValidRE is not None:
1055            match_object = cls._ValidRE.match(value)
1056            if match_object is None:
1057                raise SimpleTypeValueError(cls, value)
1058        if cls._InvalidRE is not None:
1059            match_object = cls._InvalidRE.match(value)
1060            if not (match_object is None):
1061                raise SimpleTypeValueError(cls, value)
1062        return True
1063
1064    @classmethod
1065    def _ValidateString_va (cls, value):
1066        """Post-extended method to validate that a string matches a given pattern.
1067
1068        If you can express the valid strings as a compiled regular
1069        expression in the class variable _ValidRE, or the invalid
1070        strings as a compiled regular expression in the class variable
1071        _InvalidRE, you can just use those.  If the acceptable matches
1072        are any trickier, you should invoke the superclass
1073        implementation, and if it returns True then perform additional
1074        tests."""
1075        super_fn = getattr(super(normalizedString, cls), '_ValidateString_va', lambda *a,**kw: True)
1076        if not super_fn(value):
1077            return False
1078        return cls.__ValidateString(value)
1079
1080    @classmethod
1081    def _XsdConstraintsPreCheck_vb (cls, value):
1082        if not isinstance(value, six.string_types):
1083            raise SimpleTypeValueError(cls, value)
1084        if not cls._ValidateString_va(value):
1085            raise SimpleTypeValueError(cls, value)
1086        super_fn = getattr(super(normalizedString, cls), '_XsdConstraintsPreCheck_vb', lambda *a,**kw: True)
1087        return super_fn(value)
1088
1089_DerivedDatatypes.append(normalizedString)
1090assert normalizedString.XsdSuperType() == string
1091
1092class token (normalizedString):
1093    """XMLSchema datatype U{token<http:///www.w3.org/TR/xmlschema-2/#token>}.
1094
1095    Tokens cannot leading or trailing space characters; any
1096    carriage return, line feed, or tab characters; nor any occurrence
1097    of two or more consecutive space characters."""
1098
1099    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('token')
1100
1101    @classmethod
1102    def _ValidateString_va (cls, value):
1103        super_fn = getattr(super(token, cls), '_ValidateString_va', lambda *a,**kw: True)
1104        if not super_fn(value):
1105            return False
1106        if value.startswith(" ") \
1107           or value.endswith(" ") \
1108           or (0 <= value.find('  ')):
1109            raise SimpleTypeValueError(cls, value)
1110        return True
1111_DerivedDatatypes.append(token)
1112
1113class language (token):
1114    """XMLSchema datatype U{language<http:///www.w3.org/TR/xmlschema-2/#language>}"""
1115    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('language')
1116    _ValidRE = re.compile('^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$')
1117_DerivedDatatypes.append(language)
1118
1119class NMTOKEN (token):
1120    """XMLSchema datatype U{NMTOKEN<http:///www.w3.org/TR/xmlschema-2/#NMTOKEN>}.
1121
1122    See U{http://www.w3.org/TR/2000/WD-xml-2e-20000814.html#NT-Nmtoken}.
1123
1124    NMTOKEN is an identifier that can start with any character that is
1125    legal in it."""
1126    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('NMTOKEN')
1127    _ValidRE = pyxb.utils.unicode.XML1p0e2.NmToken_re
1128_DerivedDatatypes.append(NMTOKEN)
1129
1130class NMTOKENS (basis.STD_list):
1131    _ItemType = NMTOKEN
1132_ListDatatypes.append(NMTOKENS)
1133
1134class Name (token):
1135    """XMLSchema datatype U{Name<http:///www.w3.org/TR/xmlschema-2/#Name>}.
1136
1137    See U{http://www.w3.org/TR/2000/WD-xml-2e-20000814.html#NT-Name}."""
1138    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('Name')
1139    _ValidRE = pyxb.utils.unicode.XML1p0e2.Name_re
1140_DerivedDatatypes.append(Name)
1141
1142class NCName (Name):
1143    """XMLSchema datatype U{NCName<http:///www.w3.org/TR/xmlschema-2/#NCName>}.
1144
1145    See U{http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName}."""
1146    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('NCName')
1147    _ValidRE = pyxb.utils.unicode.XML1p0e2.NCName_re
1148_DerivedDatatypes.append(NCName)
1149
1150class ID (NCName):
1151    """XMLSchema datatype U{ID<http:///www.w3.org/TR/xmlschema-2/#ID>}."""
1152    # Lexical and value space match that of parent NCName
1153    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('ID')
1154    pass
1155_DerivedDatatypes.append(ID)
1156
1157class IDREF (NCName):
1158    """XMLSchema datatype U{IDREF<http:///www.w3.org/TR/xmlschema-2/#IDREF>}."""
1159    # Lexical and value space match that of parent NCName
1160    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('IDREF')
1161    pass
1162_DerivedDatatypes.append(IDREF)
1163
1164class IDREFS (basis.STD_list):
1165    """XMLSchema datatype U{IDREFS<http:///www.w3.org/TR/xmlschema-2/#IDREFS>}."""
1166    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('IDREFS')
1167    _ItemType = IDREF
1168_ListDatatypes.append(IDREFS)
1169
1170class ENTITY (NCName):
1171    """XMLSchema datatype U{ENTITY<http:///www.w3.org/TR/xmlschema-2/#ENTITY>}."""
1172    # Lexical and value space match that of parent NCName; we're gonna
1173    # ignore the additional requirement that it be declared as an
1174    # unparsed entity
1175    #
1176    # @todo Don't ignore the requirement that this be declared as an
1177    # unparsed entity.
1178    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('ENTITY')
1179    pass
1180_DerivedDatatypes.append(ENTITY)
1181
1182class ENTITIES (basis.STD_list):
1183    """XMLSchema datatype U{ENTITIES<http:///www.w3.org/TR/xmlschema-2/#ENTITIES>}."""
1184    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('ENTITIES')
1185    _ItemType = ENTITY
1186_ListDatatypes.append(ENTITIES)
1187
1188class integer (basis.simpleTypeDefinition, six.long_type, basis._NoNullaryNonNillableNew_mixin):
1189    """XMLSchema datatype U{integer<http://www.w3.org/TR/xmlschema-2/#integer>}."""
1190    _XsdBaseType = decimal
1191    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('integer')
1192
1193    @classmethod
1194    def XsdLiteral (cls, value):
1195        return '%d' % (value,)
1196
1197_DerivedDatatypes.append(integer)
1198
1199class nonPositiveInteger (integer):
1200    """XMLSchema datatype U{nonPositiveInteger<http://www.w3.org/TR/xmlschema-2/#nonPositiveInteger>}."""
1201    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('nonPositiveInteger')
1202_DerivedDatatypes.append(nonPositiveInteger)
1203
1204class negativeInteger (nonPositiveInteger):
1205    """XMLSchema datatype U{negativeInteger<http://www.w3.org/TR/xmlschema-2/#negativeInteger>}."""
1206    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('negativeInteger')
1207_DerivedDatatypes.append(negativeInteger)
1208
1209class long (integer):
1210    """XMLSchema datatype U{long<http://www.w3.org/TR/xmlschema-2/#long>}."""
1211    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('long')
1212_DerivedDatatypes.append(long)
1213
1214class int (basis.simpleTypeDefinition, six.int_type, basis._NoNullaryNonNillableNew_mixin):
1215    """XMLSchema datatype U{int<http://www.w3.org/TR/xmlschema-2/#int>}."""
1216    _XsdBaseType = long
1217    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('int')
1218
1219    @classmethod
1220    def XsdLiteral (cls, value):
1221        return '%s' % (value,)
1222
1223    pass
1224_DerivedDatatypes.append(int)
1225
1226class short (int):
1227    """XMLSchema datatype U{short<http://www.w3.org/TR/xmlschema-2/#short>}."""
1228    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('short')
1229_DerivedDatatypes.append(short)
1230
1231class byte (short):
1232    """XMLSchema datatype U{byte<http://www.w3.org/TR/xmlschema-2/#byte>}."""
1233    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('byte')
1234_DerivedDatatypes.append(byte)
1235
1236class nonNegativeInteger (integer):
1237    """XMLSchema datatype U{nonNegativeInteger<http://www.w3.org/TR/xmlschema-2/#nonNegativeInteger>}."""
1238    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('nonNegativeInteger')
1239_DerivedDatatypes.append(nonNegativeInteger)
1240
1241class unsignedLong (nonNegativeInteger):
1242    """XMLSchema datatype U{unsignedLong<http://www.w3.org/TR/xmlschema-2/#unsignedLong>}."""
1243    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('unsignedLong')
1244_DerivedDatatypes.append(unsignedLong)
1245
1246class unsignedInt (unsignedLong):
1247    """XMLSchema datatype U{unsignedInt<http://www.w3.org/TR/xmlschema-2/#unsignedInt>}."""
1248    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('unsignedInt')
1249_DerivedDatatypes.append(unsignedInt)
1250
1251class unsignedShort (unsignedInt):
1252    """XMLSchema datatype U{unsignedShort<http://www.w3.org/TR/xmlschema-2/#unsignedShort>}."""
1253    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('unsignedShort')
1254_DerivedDatatypes.append(unsignedShort)
1255
1256class unsignedByte (unsignedShort):
1257    """XMLSchema datatype U{unsignedByte<http://www.w3.org/TR/xmlschema-2/#unsignedByte>}."""
1258    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('unsignedByte')
1259_DerivedDatatypes.append(unsignedByte)
1260
1261class positiveInteger (nonNegativeInteger):
1262    """XMLSchema datatype U{positiveInteger<http://www.w3.org/TR/xmlschema-2/#positiveInteger>}."""
1263    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('positiveInteger')
1264_DerivedDatatypes.append(positiveInteger)
1265
1266from . import content
1267
1268class anyType (basis.complexTypeDefinition):
1269    """XMLSchema datatype U{anyType<http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/#key-urType>}."""
1270    _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('anyType')
1271    _DefinitionLocation = pyxb.utils.utility.Location('http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/#key-urType', 1, 1)
1272    _ContentTypeTag = basis.complexTypeDefinition._CT_MIXED
1273    _Abstract = False
1274    _HasWildcardElement = True
1275    _AttributeWildcard = content.Wildcard(namespace_constraint=content.Wildcard.NC_any, process_contents=content.Wildcard.PC_lax)
1276
1277def _BuildAutomaton ():
1278    # Remove this helper function from the namespace after it's invoked
1279    global _BuildAutomaton
1280    del _BuildAutomaton
1281    import pyxb.utils.fac as fac
1282
1283    counters = set()
1284    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))
1285    counters.add(cc_0)
1286    states = set()
1287    final_update = set()
1288    final_update.add(fac.UpdateInstruction(cc_0, False))
1289    symbol = content.WildcardUse(content.Wildcard(process_contents=content.Wildcard.PC_lax, namespace_constraint=content.Wildcard.NC_any), None)
1290    st_0 = fac.State(symbol, is_initial=True, final_update=final_update, is_unordered_catenation=False)
1291    states.add(st_0)
1292    transitions = set()
1293    transitions.add(fac.Transition(st_0, [
1294        fac.UpdateInstruction(cc_0, True) ]))
1295    st_0._set_transitionSet(transitions)
1296    return fac.Automaton(states, counters, True, containing_state=None)
1297anyType._Automaton = _BuildAutomaton()
1298
1299
1300# anyType._IsUrType() is True; foo._IsUrType() for descendents of it
1301# should be false.
1302anyType._IsUrType = classmethod(lambda _c: _c == anyType)
1303