Package pyxb :: Package binding :: Module datatypes
[hide private]
[frames] | no frames]

Source Code for Module pyxb.binding.datatypes

   1  # Copyright 2009, Peter A. Bigot 
   2  # 
   3  # Licensed under the Apache License, Version 2.0 (the "License"); you may 
   4  # not use this file except in compliance with the License. You may obtain a 
   5  # copy of the License at: 
   6  # 
   7  #            http://www.apache.org/licenses/LICENSE-2.0 
   8  # 
   9  # Unless required by applicable law or agreed to in writing, software 
  10  # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
  11  # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
  12  # License for the specific language governing permissions and limitations 
  13  # under the License. 
  14   
  15  """Classes supporting U{XMLSchema Part 2: Datatypes<http://www.w3.org/TR/xmlschema-2/>}. 
  16   
  17  Each L{simple type definition<pyxb.xmlschema.structures.SimpleTypeDefinition>} component 
  18  instance is paired with at most one L{basis.simpleTypeDefinition} 
  19  class, which is a subclass of a Python type augmented with facets and 
  20  other constraining information.  This file contains the definitions of 
  21  these types. 
  22   
  23  We want the simple datatypes to be efficient Python values, but to 
  24  also hold specific constraints that don't apply to the Python types. 
  25  To do this, we subclass each PST.  Primitive PSTs inherit from the 
  26  Python type that represents them, and from a 
  27  pyxb.binding.basis.simpleTypeDefinition class which adds in the 
  28  constraint infrastructure.  Derived PSTs inherit from the parent PST. 
  29   
  30  There is an exception to this when the Python type best suited for a 
  31  derived SimpleTypeDefinition differs from the type associated with its 
  32  parent STD: for example, L{xsd:integer<integer>} has a value range 
  33  that requires it be represented by a Python C{long}, but 
  34  L{xsd:int<int>} allows representation by a Python C{int}.  In this 
  35  case, the derived PST class is structured like a primitive type, but 
  36  the PST associated with the STD superclass is recorded in a class 
  37  variable C{_XsdBaseType}. 
  38   
  39  Note the strict terminology: "datatype" refers to a class which is a 
  40  subclass of a Python type, while "type definition" refers to an 
  41  instance of either SimpleTypeDefinition or ComplexTypeDefinition. 
  42   
  43  """ 
  44   
  45  from pyxb.exceptions_ import * 
  46  import types 
  47  import pyxb.namespace 
  48  import pyxb.utils.domutils as domutils 
  49  import pyxb.utils.utility as utility 
  50  import basis 
  51  import re 
  52  import binascii 
  53  import base64 
  54   
  55  _PrimitiveDatatypes = [] 
  56  _DerivedDatatypes = [] 
  57  _ListDatatypes = [] 
58 59 # We use unicode as the Python type for anything that isn't a normal 60 # primitive type. Presumably, only enumeration and pattern facets 61 # will be applied. 62 -class anySimpleType (basis.simpleTypeDefinition, unicode):
63 """XMLSchema datatype U{anySimpleType<http://www.w3.org/TR/xmlschema-2/#dt-anySimpleType>}.""" 64 _XsdBaseType = None 65 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('anySimpleType') 66 67 @classmethod
68 - def XsdLiteral (cls, value):
69 return value
70 # anySimpleType is not treated as a primitive, because its variety
71 # must be absent (not atomic). 72 73 -class string (basis.simpleTypeDefinition, unicode):
74 """XMLSchema datatype U{string<http://www.w3.org/TR/xmlschema-2/#string>}.""" 75 _XsdBaseType = anySimpleType 76 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('string') 77 78 @classmethod
79 - def XsdLiteral (cls, value):
80 assert isinstance(value, cls) 81 return value
82 83 @classmethod
84 - def XsdValueLength (cls, value):
85 return len(value)
86 87 _PrimitiveDatatypes.append(string)
88 89 # It is illegal to subclass the bool type in Python, so we subclass 90 # int instead. 91 -class boolean (basis.simpleTypeDefinition, types.IntType):
92 """XMLSchema datatype U{boolean<http://www.w3.org/TR/xmlschema-2/#boolean>}.""" 93 _XsdBaseType = anySimpleType 94 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('boolean') 95 96 @classmethod
97 - def XsdLiteral (cls, value):
98 if value: 99 return 'true' 100 return 'false'
101
102 - def __str__ (self):
103 if self: 104 return 'true' 105 return 'false'
106
107 - def __new__ (cls, *args, **kw):
108 args = cls._ConvertArguments(args, kw) 109 if 0 < len(args): 110 value = args[0] 111 args = args[1:] 112 if value in (1, 0, '1', '0', 'true', 'false'): 113 if value in (1, '1', 'true'): 114 iv = True 115 else: 116 iv = False 117 return super(boolean, cls).__new__(cls, iv, *args, **kw) 118 raise BadTypeValueError('[xsd:boolean] Initializer "%s" not valid for type' % (value,)) 119 return super(boolean, cls).__new__(cls, *args, **kw)
120 121 _PrimitiveDatatypes.append(boolean)
122 123 -class decimal (basis.simpleTypeDefinition, types.FloatType):
124 """XMLSchema datatype U{decimal<http://www.w3.org/TR/xmlschema-2/#decimal>}. 125 126 @todo: The Python base type for this is wrong. Consider 127 U{http://code.google.com/p/mpmath/}. 128 129 """ 130 _XsdBaseType = anySimpleType 131 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('decimal') 132 133 @classmethod
134 - def XsdLiteral (cls, value):
135 return '%s' % (value,)
136 137 _PrimitiveDatatypes.append(decimal)
138 139 -class float (basis.simpleTypeDefinition, types.FloatType):
140 """XMLSchema datatype U{float<http://www.w3.org/TR/xmlschema-2/#float>}.""" 141 _XsdBaseType = anySimpleType 142 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('float') 143 144 @classmethod
145 - def XsdLiteral (cls, value):
146 return '%s' % (value,)
147 148 _PrimitiveDatatypes.append(float)
149 150 -class double (basis.simpleTypeDefinition, types.FloatType):
151 """XMLSchema datatype U{double<http://www.w3.org/TR/xmlschema-2/#double>}.""" 152 _XsdBaseType = anySimpleType 153 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('double') 154 155 @classmethod
156 - def XsdLiteral (cls, value):
157 return '%s' % (value,)
158 159 _PrimitiveDatatypes.append(double) 160 161 import time as python_time 162 import datetime
163 164 -class duration (basis.simpleTypeDefinition, datetime.timedelta):
165 """XMLSchema datatype U{duration<http://www.w3.org/TR/xmlschema-2/#duration>}. 166 167 This class uses the Python C{datetime.timedelta} class as its 168 underlying representation. This works fine as long as no months 169 or years are involved, and no negative durations are involved. 170 Because the XML Schema value space is so much larger, it is kept 171 distinct from the Python value space, which reduces to integral 172 days, seconds, and microseconds. 173 174 In other words, the implementation of this type is a little 175 shakey. 176 177 """ 178 179 _XsdBaseType = anySimpleType 180 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('duration') 181 182 __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)?)?$') 183 184 # We do not use weeks 185 __XSDFields = ( 'years', 'months', 'days', 'hours', 'minutes', 'seconds' ) 186 __PythonFields = ( 'days', 'seconds', 'microseconds', 'minutes', 'hours' ) 187
188 - def negativeDuration (self):
189 return self.__negativeDuration
190 __negativeDuration = None 191
192 - def durationData (self):
193 return self.__durationData
194 __durationData = None 195
196 - def __new__ (cls, *args, **kw):
197 args = cls._ConvertArguments(args, kw) 198 text = args[0] 199 have_kw_update = False 200 if isinstance(text, (str, unicode)): 201 match = cls.__Lexical_re.match(text) 202 if match is None: 203 raise BadTypeValueError('Value "%s" not in %s lexical space' % (text, cls._ExpandedName)) 204 match_map = match.groupdict() 205 if 'T' == match_map.get('Time', None): 206 # Can't have T without additional time information 207 raise BadTypeValueError('Value "%s" not in %s lexical space' % (text, cls._ExpandedName)) 208 209 negative_duration = ('-' == match_map.get('neg', None)) 210 211 fractional_seconds = 0.0 212 if match_map.get('fracsec', None) is not None: 213 fractional_seconds = types.FloatType('0%s' % (match_map['fracsec'],)) 214 usec = types.IntType(1000000 * fractional_seconds) 215 if negative_duration: 216 kw['microseconds'] = - usec 217 else: 218 kw['microseconds'] = usec 219 else: 220 # Discard any bogosity passed in by the caller 221 kw.pop('microsecond', None) 222 223 data = { } 224 for fn in cls.__XSDFields: 225 v = match_map.get(fn, 0) 226 if v is None: 227 v = 0 228 data[fn] = types.IntType(v) 229 if fn in cls.__PythonFields: 230 if negative_duration: 231 kw[fn] = - data[fn] 232 else: 233 kw[fn] = data[fn] 234 data['seconds'] += fractional_seconds 235 have_kw_update = True 236 elif isinstance(text, cls): 237 data = text.durationData() 238 negative_duration = text.negativeDuration() 239 elif isinstance(text, datetime.timedelta): 240 data = { 'days' : text.days, 241 'seconds' : text.seconds + (text.microseconds / 1000000.0) } 242 negative_duration = (0 > data['days']) 243 if negative_duration: 244 data['days'] = 1 - data['days'] 245 data['seconds'] = 24 * 60 * 60.0 - data['seconds'] 246 data['minutes'] = 0 247 data['hours'] = 0 248 if not have_kw_update: 249 rem_time = data['seconds'] 250 use_seconds = rem_time 251 if (0 != (rem_time % 1)): 252 data['microseconds'] = types.IntType(1000000 * (rem_time % 1)) 253 rem_time = rem_time // 1 254 if 60 <= rem_time: 255 data['seconds'] = rem_time % 60 256 rem_time = data['minutes'] + (rem_time // 60) 257 if 60 <= rem_time: 258 data['minutes'] = rem_time % 60 259 rem_time = data['hours'] + (rem_time // 60) 260 data['hours'] = rem_time % 24 261 data['days'] += (rem_time // 24) 262 for fn in cls.__PythonFields: 263 if fn in data: 264 if negative_duration: 265 kw[fn] = - data[fn] 266 else: 267 kw[fn] = data[fn] 268 else: 269 kw.pop(fn, None) 270 kw['microseconds'] = data.pop('microseconds', 0) 271 data['seconds'] += kw['microseconds'] / 1000000.0 272 273 rv = super(duration, cls).__new__(cls, **kw) 274 rv.__durationData = data 275 rv.__negativeDuration = negative_duration 276 return rv
277 278 @classmethod
279 - def XsdLiteral (cls, value):
280 elts = [] 281 if value.negativeDuration(): 282 elts.append('-') 283 elts.append('P') 284 for k in ( 'years', 'months', 'days' ): 285 v = value.__durationData.get(k, 0) 286 if 0 != v: 287 elts.append('%d%s' % (v, k[0].upper())) 288 time_elts = [] 289 for k in ( 'hours', 'minutes' ): 290 v = value.__durationData.get(k, 0) 291 if 0 != v: 292 time_elts.append('%d%s' % (v, k[0].upper())) 293 v = value.__durationData.get('seconds', 0) 294 if 0 != v: 295 time_elts.append('%gS' % (v,)) 296 if 0 < len(time_elts): 297 elts.append('T') 298 elts.extend(time_elts) 299 return ''.join(elts)
300 301 _PrimitiveDatatypes.append(duration)
302 303 -class _PyXBDateTime_base (basis.simpleTypeDefinition):
304 305 __PatternMap = { '%Y' : '(?P<negYear>-?)(?P<year>\d{4,})' 306 , '%m' : '(?P<month>\d{2})' 307 , '%d' : '(?P<day>\d{2})' 308 , '%H' : '(?P<hour>\d{2})' 309 , '%M' : '(?P<minute>\d{2})' 310 , '%S' : '(?P<second>\d{2})(?P<fracsec>\.\d+)?' 311 , '%Z' : '(?P<tzinfo>Z|[-+]\d\d:\d\d)' } 312 @classmethod
313 - def _DateTimePattern (cls, pattern):
314 for (k, v) in cls.__PatternMap.items(): 315 pattern = pattern.replace(k, v) 316 return pattern
317 318 __Fields = ( 'year', 'month', 'day', 'hour', 'minute', 'second' ) 319 320 _DefaultYear = 1983 321 _DefaultMonth = 6 322 _DefaultDay = 18 323 324 @classmethod
325 - def _LexicalToKeywords (cls, text, lexical_re):
326 match = lexical_re.match(text) 327 if match is None: 328 raise BadTypeValueError('Value "%s" not in %s lexical space' % (text, cls._ExpandedName)) 329 match_map = match.groupdict() 330 kw = { } 331 for (k, v) in match_map.iteritems(): 332 if (k in cls.__Fields) and (v is not None): 333 kw[k] = types.IntType(v) 334 if '-' == match_map.get('negYear', None): 335 kw['year'] = - kw['year'] 336 if match_map.get('fracsec', None) is not None: 337 kw['microsecond'] = types.IntType(1000000 * types.FloatType('0%s' % (match_map['fracsec'],))) 338 else: 339 # Discard any bogosity passed in by the caller 340 kw.pop('microsecond', None) 341 if match_map.get('tzinfo', None) is not None: 342 kw['tzinfo'] = pyxb.utils.utility.UTCOffsetTimeZone(match_map['tzinfo'], flip=True) 343 else: 344 kw.pop('tzinfo', None) 345 return kw
346 347 @classmethod
348 - def _SetKeysFromPython_csc (cls, python_value, kw, fields):
349 for f in fields: 350 kw[f] = getattr(python_value, f) 351 return getattr(super(_PyXBDateTime_base, cls), '_SetKeysFromPython_csc', lambda *a,**kw: None)(python_value, kw, fields)
352 353 @classmethod
354 - def _SetKeysFromPython (cls, python_value, kw, fields):
355 return cls._SetKeysFromPython_csc(python_value, kw, fields)
356
357 -class _PyXBDateTimeZone_base (_PyXBDateTime_base):
358 - def hasTimeZone (self):
359 """True iff the time represented included time zone information. 360 361 Whether True or not, the moment denoted by an instance is 362 assumed to be in UTC. That state is expressed in the lexical 363 space iff hasTimeZone is True. 364 """ 365 return self.__hasTimeZone
366 - def _setHasTimeZone (self, has_time_zone):
367 self.__hasTimeZone = has_time_zone
368 __hasTimeZone = False 369 370 @classmethod
371 - def _AdjustForTimezone (cls, kw):
372 tzoffs = kw.pop('tzinfo', None) 373 has_time_zone = kw.pop('_force_timezone', False) 374 if tzoffs is not None: 375 use_kw = kw.copy() 376 use_kw.setdefault('year', cls._DefaultYear) 377 use_kw.setdefault('month', cls._DefaultMonth) 378 use_kw.setdefault('day', cls._DefaultDay) 379 dt = datetime.datetime(tzinfo=tzoffs, **use_kw) 380 dt = tzoffs.fromutc(dt) 381 for k in kw.iterkeys(): 382 kw[k] = getattr(dt, k) 383 has_time_zone = True 384 return has_time_zone
385 386 @classmethod
387 - def _SetKeysFromPython_csc (cls, python_value, kw, fields):
388 if python_value.tzinfo is not None: 389 kw['tzinfo'] = pyxb.utils.utility.UTCOffsetTimeZone(python_value.tzinfo.utcoffset(python_value), flip=True) 390 else: 391 kw.pop('tzinfo', None) 392 return getattr(super(_PyXBDateTimeZone_base, cls), '_SetKeysFromPython_csc', lambda *a,**kw: None)(python_value, kw, fields)
393
394 -class dateTime (_PyXBDateTimeZone_base, datetime.datetime):
395 """XMLSchema datatype U{dateTime<http://www.w3.org/TR/xmlschema-2/#dateTime>}. 396 397 This class uses the Python C{datetime.datetime} class as its 398 underlying representation. Note that per the XMLSchema spec, all 399 dateTime objects are in UTC, and that timezone information in the 400 string representation in XML is an indication of the local time 401 zone's offset from UTC. Presence of time zone information in the 402 lexical space is preserved through the value of the L{hasTimeZone()} 403 field. 404 405 @warning: The value space of Python's C{datetime.datetime} class 406 is more restricted than that of C{xs:datetime}. As a specific 407 example, Python does not support negative years or years with more 408 than four digits. For now, the convenience of having an object 409 that is compatible with Python is more important than supporting 410 the full value space. In the future, the choice may be left up to 411 the developer. 412 """ 413 414 _XsdBaseType = anySimpleType 415 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('dateTime') 416 417 __Lexical_re = re.compile(_PyXBDateTime_base._DateTimePattern('^%Y-%m-%dT%H:%M:%S%Z?$')) 418 __Fields = ( 'year', 'month', 'day', 'hour', 'minute', 'second', 'microsecond', 'tzinfo' ) 419
420 - def __new__ (cls, *args, **kw):
421 args = cls._ConvertArguments(args, kw) 422 ctor_kw = { } 423 if 1 == len(args): 424 value = args[0] 425 if isinstance(value, types.StringTypes): 426 ctor_kw.update(cls._LexicalToKeywords(value, cls.__Lexical_re)) 427 elif isinstance(value, (datetime.datetime, datetime.date, datetime.time)): 428 cls._SetKeysFromPython(value, ctor_kw, cls.__Fields) 429 if isinstance(value, _PyXBDateTimeZone_base): 430 ctor_kw['_force_timezone'] = True 431 elif isinstance(value, (types.IntType, types.LongType)): 432 raise TypeError('function takes at least 3 arguments (%d given)' % (len(args),)) 433 else: 434 raise BadTypeValueError('Unexpected type %s in %s' % (type(value), cls._ExpandedName)) 435 elif 3 <= len(args): 436 for fi in range(len(cls.__Fields)): 437 fn = cls.__Fields[fi] 438 if fi < len(args): 439 ctor_kw[fn] = args[fi] 440 elif fn in kw: 441 ctor_kw[fn] = kw[fn] 442 kw.pop(fn, None) 443 fi += 1 444 else: 445 raise TypeError('function takes at least 3 arguments (%d given)' % (len(args),)) 446 447 has_time_zone = cls._AdjustForTimezone(ctor_kw) 448 kw.update(ctor_kw) 449 year = kw.pop('year') 450 month = kw.pop('month') 451 day = kw.pop('day') 452 rv = super(dateTime, cls).__new__(cls, year, month, day, **kw) 453 rv._setHasTimeZone(has_time_zone) 454 return rv
455 456 @classmethod
457 - def XsdLiteral (cls, value):
458 iso = value.isoformat() 459 if 0 <= iso.find('.'): 460 iso = iso.rstrip('0') 461 if value.hasTimeZone(): 462 iso += 'Z' 463 return iso
464 465 __UTCZone = pyxb.utils.utility.UTCOffsetTimeZone(0) 466 __LocalZone = pyxb.utils.utility.LocalTimeZone() 467 468 @classmethod
469 - def today (cls):
470 """Return today. 471 472 Just like datetime.datetime.today(), except this one sets a 473 tzinfo field so it's clear the value is UTC.""" 474 return cls(datetime.datetime.now(cls.__UTCZone))
475
476 - def aslocal (self):
477 """Returns a C{datetime.datetime} instance denoting the same 478 time as this instance but adjusted to be in the local time 479 zone. 480 481 @rtype: C{datetime.datetime} (B{NOT} C{xsd.dateTime}) 482 """ 483 return self.replace(tzinfo=self.__UTCZone).astimezone(self.__LocalZone)
484 485 _PrimitiveDatatypes.append(dateTime)
486 487 -class time (_PyXBDateTimeZone_base, datetime.time):
488 """XMLSchema datatype U{time<http://www.w3.org/TR/xmlschema-2/#time>}. 489 490 This class uses the Python C{datetime.time} class as its 491 underlying representation. Note that per the XMLSchema spec, all 492 dateTime objects are in UTC, and that timezone information in the 493 string representation in XML is an indication of the local time 494 zone's offset from UTC. Presence of time zone information in the 495 lexical space is preserved through the value of the 496 L{hasTimeZone()} field. 497 """ 498 499 _XsdBaseType = anySimpleType 500 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('time') 501 502 __Lexical_re = re.compile(_PyXBDateTime_base._DateTimePattern('^%H:%M:%S%Z?$')) 503 __Fields = ( 'hour', 'minute', 'second', 'microsecond' ) 504
505 - def __new__ (cls, *args, **kw):
506 args = cls._ConvertArguments(args, kw) 507 ctor_kw = { } 508 if 1 <= len(args): 509 value = args[0] 510 if isinstance(value, types.StringTypes): 511 ctor_kw.update(cls._LexicalToKeywords(value, cls.__Lexical_re)) 512 elif isinstance(value, datetime.time): 513 cls._SetKeysFromPython(value, ctor_kw, cls.__Fields) 514 elif isinstance(value, (types.IntType, types.LongType)): 515 for fn in range(min(len(args), len(cls.__Fields))): 516 ctor_kw[cls.__Fields[fn]] = args[fn] 517 else: 518 raise BadTypeValueError('Unexpected type %s' % (type(value),)) 519 520 has_time_zone = cls._AdjustForTimezone(ctor_kw) 521 kw.update(ctor_kw) 522 rv = super(time, cls).__new__(cls, **kw) 523 rv._setHasTimeZone(has_time_zone) 524 return rv
525 526 @classmethod
527 - def XsdLiteral (cls, value):
528 iso = value.isoformat() 529 if 0 <= iso.find('.'): 530 iso = iso.rstrip('0') 531 if value.hasTimeZone(): 532 iso += 'Z' 533 return iso
534 535 _PrimitiveDatatypes.append(time)
536 537 -class _PyXBDateOnly_base (_PyXBDateTime_base, datetime.date):
538 _XsdBaseType = anySimpleType 539 540 __DateFields = ( 'year', 'month', 'day' ) 541 _ISO_beginYear = 0 542 _ISO_endYear = 4 543 _ISO_beginMonth = 5 544 _ISO_endMonth = 7 545 _ISO_beginDay = 8 546 _ISO_endDay = 10 547 _ISOBegin = _ISO_beginYear 548 _ISOEnd = _ISO_endDay 549
550 - def __getattribute__ (self, attr):
551 ga = super(_PyXBDateOnly_base, self).__getattribute__ 552 cls = ga('__class__') 553 if (attr in cls.__DateFields) and not (attr in cls._Fields): 554 raise AttributeError(self, attr) 555 return ga(attr)
556
557 - def __new__ (cls, *args, **kw):
558 args = cls._ConvertArguments(args, kw) 559 ctor_kw = { } 560 ctor_kw['year'] = cls._DefaultYear 561 ctor_kw['month'] = cls._DefaultMonth 562 ctor_kw['day'] = cls._DefaultDay 563 if 1 == len(args): 564 value = args[0] 565 if isinstance(value, types.StringTypes): 566 ctor_kw.update(cls._LexicalToKeywords(value, cls._Lexical_re)) 567 elif isinstance(value, datetime.date): 568 cls._SetKeysFromPython(value, ctor_kw, cls._Fields) 569 elif isinstance(value, (types.IntType, types.LongType)): 570 if (1 != len(cls._Fields)): 571 raise TypeError('function takes exactly %d arguments (%d given)' % (len(cls._Fields), len(args))) 572 ctor_kw[cls._Fields[0]] = value 573 else: 574 raise BadTypeValueError('Unexpected type %s' % (type(value),)) 575 elif len(cls._Fields) == len(args): 576 for fi in range(len(cls._Fields)): 577 ctor_kw[cls._Fields[fi]] = args[fi] 578 else: 579 raise TypeError('function takes exactly %d arguments (%d given)' % (len(cls._Fields), len(args))) 580 581 kw.update(ctor_kw) 582 argv = [] 583 for f in cls.__DateFields: 584 argv.append(kw.pop(f)) 585 return super(_PyXBDateOnly_base, cls).__new__(cls, *argv, **kw)
586 587 @classmethod
588 - def XsdLiteral (cls, value):
589 return value.isoformat()[cls._ISOBegin:cls._ISOEnd]
590
591 -class date (_PyXBDateOnly_base):
592 """XMLSchema datatype U{date<http://www.w3.org/TR/xmlschema-2/#date>}. 593 594 This class uses the Python C{datetime.date} class as its 595 underlying representation. 596 """ 597 598 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('date') 599 _Lexical_re = re.compile(_PyXBDateTime_base._DateTimePattern('^%Y-%m-%d$')) 600 _Fields = ( 'year', 'month', 'day' )
601 602 _PrimitiveDatatypes.append(date)
603 604 -class gYearMonth (_PyXBDateOnly_base):
605 """XMLSchema datatype U{gYearMonth<http://www.w3.org/TR/xmlschema-2/#gYearMonth>}. 606 607 This class uses the Python C{datetime.date} class as its 608 underlying representation. 609 """ 610 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gYearMonth') 611 _Lexical_re = re.compile(_PyXBDateTime_base._DateTimePattern('^%Y-%m$')) 612 _Fields = ( 'year', 'month' ) 613 _ISOEnd = _PyXBDateOnly_base._ISO_endMonth
614 615 _PrimitiveDatatypes.append(gYearMonth)
616 617 -class gYear (_PyXBDateOnly_base):
618 """XMLSchema datatype U{gYear<http://www.w3.org/TR/xmlschema-2/#gYear>}. 619 620 This class uses the Python C{datetime.date} class as its 621 underlying representation. 622 """ 623 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gYear') 624 _Lexical_re = re.compile(_PyXBDateTime_base._DateTimePattern('^%Y$')) 625 _Fields = ( 'year', ) 626 _ISOEnd = _PyXBDateOnly_base._ISO_endYear
627 _PrimitiveDatatypes.append(gYear)
628 629 -class gMonthDay (_PyXBDateOnly_base):
630 """XMLSchema datatype U{gMonthDay<http://www.w3.org/TR/xmlschema-2/#gMonthDay>}. 631 632 This class uses the Python C{datetime.date} class as its 633 underlying representation. 634 """ 635 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gMonthDay') 636 _Lexical_re = re.compile(_PyXBDateTime_base._DateTimePattern('^%m-%d$')) 637 _Fields = ( 'month', 'day' ) 638 _ISOBegin = _PyXBDateOnly_base._ISO_beginMonth
639 _PrimitiveDatatypes.append(gMonthDay)
640 641 -class gDay (_PyXBDateOnly_base):
642 """XMLSchema datatype U{gDay<http://www.w3.org/TR/xmlschema-2/#gDay>}. 643 644 This class uses the Python C{datetime.date} class as its 645 underlying representation. 646 """ 647 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gDay') 648 _Lexical_re = re.compile(_PyXBDateTime_base._DateTimePattern('^%d$')) 649 _Fields = ( 'day', ) 650 _ISOBegin = _PyXBDateOnly_base._ISO_beginDay
651 _PrimitiveDatatypes.append(gDay)
652 653 -class gMonth (_PyXBDateOnly_base):
654 """XMLSchema datatype U{gMonth<http://www.w3.org/TR/xmlschema-2/#gMonth>}. 655 656 This class uses the Python C{datetime.date} class as its 657 underlying representation. 658 """ 659 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('gMonth') 660 _Lexical_re = re.compile(_PyXBDateTime_base._DateTimePattern('^%m$')) 661 _Fields = ( 'month', ) 662 _ISOBegin = _PyXBDateOnly_base._ISO_beginMonth 663 _ISOEnd = _PyXBDateOnly_base._ISO_endMonth
664 _PrimitiveDatatypes.append(gMonth)
665 666 -class hexBinary (basis.simpleTypeDefinition, types.StringType):
667 """XMLSchema datatype U{hexBinary<http://www.w3.org/TR/xmlschema-2/#hexBinary>}.""" 668 _XsdBaseType = anySimpleType 669 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('hexBinary') 670 671 @classmethod
672 - def _ConvertArguments_vx (cls, args, kw):
673 if kw.get('_from_xml', False): 674 try: 675 args = (binascii.unhexlify(args[0]),) + args[1:] 676 except TypeError, e: 677 raise BadTypeValueError('%s is not a valid hexBinary string' % (cls.__class__.__name__,)) 678 return args
679 680 @classmethod
681 - def XsdLiteral (cls, value):
682 return binascii.hexlify(value).upper()
683 684 @classmethod
685 - def XsdValueLength (cls, value):
686 return len(value)
687 688 _PrimitiveDatatypes.append(hexBinary)
689 690 -class base64Binary (basis.simpleTypeDefinition, types.StringType):
691 """XMLSchema datatype U{base64Binary<http://www.w3.org/TR/xmlschema-2/#base64Binary>}. 692 693 See also U{RFC2045<http://tools.ietf.org/html/rfc2045>} and U{RFC4648<http://tools.ietf.org/html/rfc4648>}. 694 """ 695 _XsdBaseType = anySimpleType 696 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('base64Binary') 697 698 # base64 is too lenient: it accepts 'ZZZ=' as an encoding of 'e', while 699 # the required XML Schema production requires 'ZQ=='. Define a regular 700 # expression per section 3.2.16. 701 _B04 = '[AQgw]' 702 _B04S = '(%s ?)' % (_B04,) 703 _B16 = '[AEIMQUYcgkosw048]' 704 _B16S = '(%s ?)' % (_B16,) 705 _B64 = '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/]' 706 _B64S = '(%s ?)' % (_B64,) 707 708 __Pattern = '^((' + _B64S + '{4})*((' + _B64S + '{3}' + _B64 + ')|(' + _B64S + '{2}' + _B16S + '=)|(' + _B64S + _B04S + '= ?=)))?$' 709 __Lexical_re = re.compile(__Pattern) 710 711 @classmethod
712 - def _ConvertArguments_vx (cls, args, kw):
713 if kw.get('_from_xml', False): 714 xmls = args[0] 715 try: 716 args = (base64.standard_b64decode(xmls),) + args[1:] 717 except TypeError, e: 718 raise BadTypeValueError('%s is not a valid base64Binary string: %s' % (cls.__class__.__name__, str(e))) 719 # This is what it costs to try to be a validating processor. 720 if cls.__Lexical_re.match(xmls) is None: 721 raise BadTypeValueError('%s is not a valid base64Binary string: XML strict failed' % (cls.__class__.__name__,)) 722 return args
723 724 @classmethod
725 - def XsdLiteral (cls, value):
726 return base64.standard_b64encode(value)
727 728 @classmethod
729 - def XsdValueLength (cls, value):
730 return len(value)
731 732 _PrimitiveDatatypes.append(base64Binary)
733 734 -class anyURI (basis.simpleTypeDefinition, unicode):
735 """XMLSchema datatype U{anyURI<http://www.w3.org/TR/xmlschema-2/#anyURI>}.""" 736 _XsdBaseType = anySimpleType 737 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('anyURI') 738 739 @classmethod
740 - def XsdValueLength (cls, value):
741 return len(value)
742 743 @classmethod
744 - def XsdLiteral (cls, value):
745 return unicode(value)
746 747 _PrimitiveDatatypes.append(anyURI)
748 749 -class QName (basis.simpleTypeDefinition, unicode):
750 """XMLSchema datatype U{QName<http://www.w3.org/TR/xmlschema-2/#QName>}.""" 751 _XsdBaseType = anySimpleType 752 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('QName') 753 754 @classmethod
755 - def XsdValueLength (cls, value):
756 """Section 4.3.1.3: Legacy length return None to indicate no check""" 757 return None
758 759 __localName = None 760 __prefix = None 761
762 - def prefix (self):
763 """Return the prefix portion of the QName, or None if the name is not qualified.""" 764 if self.__localName is None: 765 self.__resolveLocals() 766 return self.__prefix
767
768 - def localName (self):
769 """Return the local portion of the QName.""" 770 if self.__localName is None: 771 self.__resolveLocals() 772 return self.__localName
773
774 - def __resolveLocals (self):
775 if self.find(':'): 776 (self.__prefix, self.__localName) = self.split(':', 1) 777 else: 778 self.__localName = unicode(self)
779 780 @classmethod
781 - def XsdLiteral (cls, value):
782 return unicode(value)
783 784 @classmethod
785 - def _XsdConstraintsPreCheck_vb (cls, value):
786 if not isinstance(value, types.StringTypes): 787 raise BadTypeValueError('%s value must be a string' % (cls.__name__,)) 788 if 0 <= value.find(':'): 789 (prefix, local) = value.split(':', 1) 790 if (NCName._ValidRE.match(prefix) is None) or (NCName._ValidRE.match(local) is None): 791 raise BadTypeValueError('%s lexical/value space violation for "%s"' % (cls.__name__, value)) 792 else: 793 if NCName._ValidRE.match(value) is None: 794 raise BadTypeValueError('%s lexical/value space violation for "%s"' % (cls.__name__, value)) 795 super_fn = getattr(super(QName, cls), '_XsdConstraintsPreCheck_vb', lambda *a,**kw: True) 796 return super_fn(value)
797 798 799 _PrimitiveDatatypes.append(QName)
800 801 -class NOTATION (basis.simpleTypeDefinition):
802 """XMLSchema datatype U{NOTATION<http://www.w3.org/TR/xmlschema-2/#NOTATION>}.""" 803 _XsdBaseType = anySimpleType 804 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('NOTATION') 805 806 @classmethod
807 - def XsdValueLength (cls, value):
808 """Section 4.3.1.3: Legacy length return None to indicate no check""" 809 return None
810 811 _PrimitiveDatatypes.append(NOTATION)
812 813 -class normalizedString (string):
814 """XMLSchema datatype U{normalizedString<http:///www.w3.org/TR/xmlschema-2/#normalizedString>}. 815 816 Normalized strings can't have carriage returns, linefeeds, or 817 tabs in them.""" 818 819 # All descendents of normalizedString constrain the lexical/value 820 # space in some way. Subclasses should set the _ValidRE class 821 # variable to a compiled regular expression that matches valid 822 # input, or the _InvalidRE class variable to a compiled regular 823 # expression that detects invalid inputs. 824 # 825 # Alternatively, subclasses can override the _ValidateString_va 826 # method. 827 828 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('normalizedString') 829 830 # @todo Implement pattern constraints and just rely on them 831 832 # No CR, LF, or TAB 833 __BadChars = re.compile("[\r\n\t]") 834 835 _ValidRE = None 836 _InvalidRE = None 837 838 @classmethod
839 - def __ValidateString (cls, value):
840 # This regular expression doesn't work. Don't know why. 841 #if cls.__BadChars.match(value) is not None: 842 # raise BadTypeValueError('CR/NL/TAB characters illegal in %s' % (cls.__name__,)) 843 if (0 <= value.find("\n")) or (0 <= value.find("\r")) or (0 <= value.find("\t")): 844 raise BadTypeValueError('CR/NL/TAB characters illegal in %s' % (cls.__name__,)) 845 if cls._ValidRE is not None: 846 match_object = cls._ValidRE.match(value) 847 if match_object is None: 848 raise BadTypeValueError('%s pattern constraint violation for "%s"' % (cls.__name__, value)) 849 if cls._InvalidRE is not None: 850 match_object = cls._InvalidRE.match(value) 851 if not (match_object is None): 852 raise BadTypeValueError('%s pattern constraint violation for "%s"' % (cls.__name__, value)) 853 return True
854 855 @classmethod
856 - def _ValidateString_va (cls, value):
857 """Post-extended method to validate that a string matches a given pattern. 858 859 If you can express the valid strings as a compiled regular 860 expression in the class variable _ValidRE, or the invalid 861 strings as a compiled regular expression in the class variable 862 _InvalidRE, you can just use those. If the acceptable matches 863 are any trickier, you should invoke the superclass 864 implementation, and if it returns True then perform additional 865 tests.""" 866 super_fn = getattr(super(normalizedString, cls), '_ValidateString_va', lambda *a,**kw: True) 867 if not super_fn(value): 868 return False 869 return cls.__ValidateString(value)
870 871 @classmethod
872 - def _XsdConstraintsPreCheck_vb (cls, value):
873 if not isinstance(value, types.StringTypes): 874 raise BadTypeValueError('%s value must be a string' % (cls.__name__,)) 875 if not cls._ValidateString_va(value): 876 raise BadTypeValueError('%s lexical/value space violation for "%s"' % (cls.__name__, value)) 877 super_fn = getattr(super(normalizedString, cls), '_XsdConstraintsPreCheck_vb', lambda *a,**kw: True) 878 return super_fn(value)
879 880 _DerivedDatatypes.append(normalizedString) 881 assert normalizedString.XsdSuperType() == string
882 883 -class token (normalizedString):
884 """XMLSchema datatype U{token<http:///www.w3.org/TR/xmlschema-2/#token>}. 885 886 Tokens cannot leading or trailing space characters; any 887 carriage return, line feed, or tab characters; nor any occurrence 888 of two or more consecutive space characters.""" 889 890 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('token') 891 892 @classmethod
893 - def _ValidateString_va (cls, value):
894 super_fn = getattr(super(token, cls), '_ValidateString_va', lambda *a,**kw: True) 895 if not super_fn(value): 896 return False 897 if value.startswith(" "): 898 raise BadTypeValueError('Leading spaces in token') 899 if value.endswith(" "): 900 raise BadTypeValueError('Trailing spaces in token') 901 if 0 <= value.find(' '): 902 raise BadTypeValueError('Multiple internal spaces in token') 903 return True
904 _DerivedDatatypes.append(token)
905 906 -class language (token):
907 """XMLSchema datatype U{language<http:///www.w3.org/TR/xmlschema-2/#language>}""" 908 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('language') 909 _ValidRE = re.compile('^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$')
910 _DerivedDatatypes.append(language)
911 912 -class NMTOKEN (token):
913 """XMLSchema datatype U{NMTOKEN<http:///www.w3.org/TR/xmlschema-2/#NMTOKEN>}. 914 915 See U{http://www.w3.org/TR/2000/WD-xml-2e-20000814.html#NT-Nmtoken}. 916 917 NMTOKEN is an identifier that can start with any character that is 918 legal in it.""" 919 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('NMTOKEN') 920 _ValidRE = re.compile('^[-_.:A-Za-z0-9]*$')
921 _DerivedDatatypes.append(NMTOKEN)
922 923 -class NMTOKENS (basis.STD_list):
924 _ItemType = NMTOKEN
925 _ListDatatypes.append(NMTOKENS)
926 927 -class Name (token):
928 """XMLSchema datatype U{Name<http:///www.w3.org/TR/xmlschema-2/#Name>}. 929 930 See U{http://www.w3.org/TR/2000/WD-xml-2e-20000814.html#NT-Name}.""" 931 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('Name') 932 _ValidRE = re.compile('^[A-Za-z_:][-_.:A-Za-z0-9]*$')
933 _DerivedDatatypes.append(Name)
934 935 -class NCName (Name):
936 """XMLSchema datatype U{NCName<http:///www.w3.org/TR/xmlschema-2/#NCName>}. 937 938 See U{http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName}.""" 939 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('NCName') 940 _ValidRE = re.compile('^[A-Za-z_][-_.A-Za-z0-9]*$')
941 _DerivedDatatypes.append(NCName)
942 943 -class ID (NCName):
944 """XMLSchema datatype U{ID<http:///www.w3.org/TR/xmlschema-2/#ID>}.""" 945 # Lexical and value space match that of parent NCName 946 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('ID') 947 pass
948 _DerivedDatatypes.append(ID)
949 950 -class IDREF (NCName):
951 """XMLSchema datatype U{IDREF<http:///www.w3.org/TR/xmlschema-2/#IDREF>}.""" 952 # Lexical and value space match that of parent NCName 953 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('IDREF') 954 pass
955 _DerivedDatatypes.append(IDREF)
956 957 -class IDREFS (basis.STD_list):
958 """XMLSchema datatype U{IDREFS<http:///www.w3.org/TR/xmlschema-2/#IDREFS>}.""" 959 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('IDREFS') 960 _ItemType = IDREF
961 _ListDatatypes.append(IDREFS)
962 963 -class ENTITY (NCName):
964 """XMLSchema datatype U{ENTITY<http:///www.w3.org/TR/xmlschema-2/#ENTITY>}.""" 965 # Lexical and value space match that of parent NCName; we're gonna 966 # ignore the additional requirement that it be declared as an 967 # unparsed entity 968 # 969 # @todo Don't ignore the requirement that this be declared as an 970 # unparsed entity. 971 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('ENTITY') 972 pass
973 _DerivedDatatypes.append(ENTITY)
974 975 -class ENTITIES (basis.STD_list):
976 """XMLSchema datatype U{ENTITIES<http:///www.w3.org/TR/xmlschema-2/#ENTITIES>}.""" 977 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('ENTITIES') 978 _ItemType = ENTITY
979 _ListDatatypes.append(ENTITIES)
980 981 -class integer (basis.simpleTypeDefinition, types.LongType):
982 """XMLSchema datatype U{integer<http://www.w3.org/TR/xmlschema-2/#integer>}.""" 983 _XsdBaseType = decimal 984 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('integer') 985 986 @classmethod
987 - def XsdLiteral (cls, value):
988 return '%d' % (value,)
989 990 _DerivedDatatypes.append(integer)
991 992 -class nonPositiveInteger (integer):
993 """XMLSchema datatype U{nonPositiveInteger<http://www.w3.org/TR/xmlschema-2/#nonPositiveInteger>}.""" 994 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('nonPositiveInteger')
995 _DerivedDatatypes.append(nonPositiveInteger)
996 997 -class negativeInteger (nonPositiveInteger):
998 """XMLSchema datatype U{negativeInteger<http://www.w3.org/TR/xmlschema-2/#negativeInteger>}.""" 999 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('negativeInteger')
1000 _DerivedDatatypes.append(negativeInteger)
1001 1002 -class long (integer):
1003 """XMLSchema datatype U{long<http://www.w3.org/TR/xmlschema-2/#long>}.""" 1004 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('long')
1005 _DerivedDatatypes.append(long)
1006 1007 -class int (basis.simpleTypeDefinition, types.IntType):
1008 """XMLSchema datatype U{int<http://www.w3.org/TR/xmlschema-2/#int>}.""" 1009 _XsdBaseType = long 1010 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('int') 1011 1012 @classmethod
1013 - def XsdLiteral (cls, value):
1014 return '%s' % (value,)
1015 1016 pass
1017 _DerivedDatatypes.append(int)
1018 1019 -class short (int):
1020 """XMLSchema datatype U{short<http://www.w3.org/TR/xmlschema-2/#short>}.""" 1021 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('short')
1022 _DerivedDatatypes.append(short)
1023 1024 -class byte (short):
1025 """XMLSchema datatype U{byte<http://www.w3.org/TR/xmlschema-2/#byte>}.""" 1026 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('byte')
1027 _DerivedDatatypes.append(byte)
1028 1029 -class nonNegativeInteger (integer):
1030 """XMLSchema datatype U{nonNegativeInteger<http://www.w3.org/TR/xmlschema-2/#nonNegativeInteger>}.""" 1031 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('nonNegativeInteger')
1032 _DerivedDatatypes.append(nonNegativeInteger)
1033 1034 -class unsignedLong (nonNegativeInteger):
1035 """XMLSchema datatype U{unsignedLong<http://www.w3.org/TR/xmlschema-2/#unsignedLong>}.""" 1036 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('unsignedLong')
1037 _DerivedDatatypes.append(unsignedLong)
1038 1039 -class unsignedInt (unsignedLong):
1040 """XMLSchema datatype U{unsignedInt<http://www.w3.org/TR/xmlschema-2/#unsignedInt>}.""" 1041 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('unsignedInt')
1042 _DerivedDatatypes.append(unsignedInt)
1043 1044 -class unsignedShort (unsignedInt):
1045 """XMLSchema datatype U{unsignedShort<http://www.w3.org/TR/xmlschema-2/#unsignedShort>}.""" 1046 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('unsignedShort')
1047 _DerivedDatatypes.append(unsignedShort)
1048 1049 -class unsignedByte (unsignedShort):
1050 """XMLSchema datatype U{unsignedByte<http://www.w3.org/TR/xmlschema-2/#unsignedByte>}.""" 1051 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('unsignedByte')
1052 _DerivedDatatypes.append(unsignedByte)
1053 1054 -class positiveInteger (nonNegativeInteger):
1055 """XMLSchema datatype U{positiveInteger<http://www.w3.org/TR/xmlschema-2/#positiveInteger>}.""" 1056 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('positiveInteger')
1057 _DerivedDatatypes.append(positiveInteger) 1058 1059 import datatypes_facets 1060 import content
1061 1062 -class anyType (basis.complexTypeDefinition):
1063 """XMLSchema datatype U{anyType<http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/#key-urType>}.""" 1064 _ExpandedName = pyxb.namespace.XMLSchema.createExpandedName('anyType') 1065 _ContentTypeTag = basis.complexTypeDefinition._CT_MIXED 1066 _Abstract = False 1067 _HasWildcardElement = True 1068 _AttributeWildcard = content.Wildcard(namespace_constraint=content.Wildcard.NC_any, process_contents=content.Wildcard.PC_lax) 1069 1070 # Generate from tests/schemas/anyType.xsd 1071 __Wildcard = content.Wildcard(process_contents=content.Wildcard.PC_lax, namespace_constraint=content.Wildcard.NC_any) 1072 __Inner = content.GroupSequence(content.ParticleModel(__Wildcard, min_occurs=0, max_occurs=None)) 1073 _ContentModel = content.ParticleModel(__Inner, min_occurs=1, max_occurs=1)
1074 1075 # anyType._IsUrType() is True; foo._IsUrType() for descendents of it 1076 # should be false. 1077 anyType._IsUrType = classmethod(lambda _c: _c == anyType) 1078