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