Package RDFClosure :: Module DatatypeHandling
[hide private]
[frames] | no frames]

Source Code for Module RDFClosure.DatatypeHandling

  1  #!/d/Bin/Python/python.exe 
  2  # -*- coding: utf-8 -*- 
  3  # 
  4  """ 
  5  Most of the XSD datatypes are handled directly by RDFLib. However, in some cases, that is not good enough. There are two 
  6  major reasons for this: 
  7   
  8   1. Some datatypes are missing from RDFLib and required by OWL 2 RL and/or RDFS 
  9   2. In other cases, though the datatype is present, RDFLib is fairly lax in checking the lexical value of those datatypes. Typical case is boolean. 
 10   
 11  Some of these defficiencies are handled by this module. All the functions convert the lexical value into a 
 12  python datatype (or return the original string if this is not possible) which will be used, eg, 
 13  for comparisons (equalities). If the lexical value constraints are not met, exceptions are raised. 
 14   
 15  @requires: U{RDFLib<http://rdflib.net>}, 2.2.2. and higher 
 16  @license: This software is available for use under the U{W3C Software License<http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231>} 
 17  @organization: U{World Wide Web Consortium<http://www.w3.org>} 
 18  @author: U{Ivan Herman<a href="http://www.w3.org/People/Ivan/">} 
 19  """ 
 20   
 21  """ 
 22  $Id: DatatypeHandling.py,v 1.7 2009/11/05 10:43:55 ivan Exp $ $Date: 2009/11/05 10:43:55 $ 
 23  """ 
 24   
 25  __author__  = 'Ivan Herman' 
 26  __contact__ = 'Ivan Herman, ivan@w3.org' 
 27  __license__ = u'W3C® SOFTWARE NOTICE AND LICENSE, http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231' 
 28   
 29  from rdflib.RDF                 import RDFNS as ns_rdf 
 30  from rdflib.Literal             import XSDToPython, Literal, _toPythonMapping, _PythonToXSD 
 31  from rdflib.Literal             import _XSD_NS as ns_xsd 
 32  import rdflib 
 33   
 34  import datetime, time, re 
 35   
 36  #: The Decimal type is available on python version 2.4 or higher. The flag is set whether the module can be imported or not 
 37  Decimal_available = True 
 38  try : 
 39          from decimal import Decimal 
 40  except : 
 41          Decimal_available = False 
 42   
43 -class _namelessTZ(datetime.tzinfo):
44 """(Nameless) timezone object. The python datetime object requires timezones as 45 a specific object added to the conversion, rather than the explicit hour and minute 46 difference used by XSD. This class is used to wrap around the hour/minute values. 47 """
48 - def __init__(self, hours, minutes):
49 """ 50 @param hours: hour offset 51 @param minutes: minute offset 52 """ 53 self.__offset = datetime.timedelta(hours = hours, minutes = minutes) 54 self.__name = "nameless"
55
56 - def utcoffset(self, dt):
57 return self.__offset
58
59 - def tzname(self, dt):
60 return self.__name
61
62 - def dst(self, dt):
63 return datetime.timedelta(0)
64
65 -def _returnTimeZone(incoming_v) :
66 """Almost all time/date related methods require the extraction of an optional time zone information. 67 @param incoming_v: the time/date string 68 @return (v,timezone) tuple; 'v' is the input string with the timezone info cut off, 'timezone' is a L{_namelessTZ} instance or None 69 """ 70 tzone = None 71 if incoming_v[-1] == 'Z' : 72 v = incoming_v[:-1] 73 tzone = _namelessTZ(0,0) 74 else : 75 pattern = ".*(\+|-)([0-9][0-9]):([0-9][0-9])" 76 match = re.match(pattern,incoming_v) 77 if match == None : 78 v = incoming_v 79 tzone = None 80 else : 81 hours = int(match.groups()[1]) 82 if match.groups()[0] == '-' : hours = -hours - 1 83 minutes = int(match.groups()[2]) 84 v = incoming_v[:-6] 85 tzone = _namelessTZ(hours,minutes) 86 return (v, tzone)
87 88 89 #################################### Booleans ##################################################
90 -def _strToBool(v) :
91 """The built-in conversion to boolean is way too lax. The xsd specification requires that only true, false, 1 or 0 should be used... 92 @param v: the literal string defined as boolean 93 @return corresponding boolean value 94 @raise ValueError: invalid boolean values 95 """ 96 if v.lower() == "true" or v.lower() == "1" : 97 return bool(1) 98 elif v.lower() == "false" or v.lower() == "0" : 99 return bool(None) 100 else : 101 raise ValueError("Invalid boolean literal value %s" % v)
102 103 104 #################################### Decimals ##################################################
105 -def _strToDecimal(v) :
106 """The built in datatype handling for RDFLib maps a decimal number to float, but the python version 2.4 and upwards also 107 has a Decimal number. Better make use of that to use very high numbers. 108 However, there is also a big difference between Python's decimal and XSD's decimal, because the latter does not allow 109 for an exponential normal form (why???). This must be filtered out. 110 @param v: the literal string defined as decimal 111 @return Decimal if the local python version is >= 2.4, float otherwise 112 @raise ValueError: invalid decimal value 113 """ 114 # check whether the lexical form of 'v' is o.k. 115 if v.find('E') != -1 or v.find('e') != -1 : 116 # this is an invalid lexical form, though would be accepted by Python 117 raise ValueError("Invalid decimal literal value %s" %v) 118 else : 119 if Decimal_available : 120 # this may raise further exceptions, which is fine 121 return Decimal(v) 122 else : 123 # running an older version of python 124 # this may raise further exceptions, which is fine 125 return float(v)
126 127 #################################### ANY URIS ################################################## 128 #: set of characters allowed in a hexadecimal number 129 _hexc = ['A','B','C','D','E','F','a','b','c','d','e','f'] 130 #: set of numerals 131 _numb = ['1','2','3','4','5','6','7','8','9','0']
132 -def _strToAnyURI(v) :
133 """Rudimentary test for the AnyURI value. If it is a relative URI, then some tests are done to filter out 134 mistakes. I am not sure this is the full implementation of the RFC, though, may have to be checked at some point 135 later. 136 @param v: the literal string defined as a URI 137 @return the incoming value 138 @raise ValueError: invalid URI value 139 """ 140 import urlparse 141 if len(v) == 0 : return v 142 if urlparse.urlsplit(v)[0] != "" : 143 # this means that there is a proper scheme, the URI should be kosher 144 return v 145 else : 146 # this is meant to be a relative URI. 147 # If I am correct, that cannot begin with one or more "?" or ":" characters 148 # all others are o.k. 149 # if it begins with a % then it should be followed by two hexa charaters, 150 # otherwise it is also a bug 151 if v[0] == '%' : 152 if len(v) >= 3 and (v[1] in _hexc or v[1] in _numb) and (v[2] in _hexc or v[2] in _numb) : 153 return v 154 else : 155 raise ValueError("Invalid IRI %s" % v) 156 elif v[0] == '?' or v[0] == ':' : 157 raise ValueError("Invalid IRI %s" % v) 158 else : 159 return v
160 161 #################################### Base64Binary ##################################################
162 -def _strToBase64Binary(v) :
163 """Rudimentary test for the base64Binary value. The problem is that the built-in b64 module functions ignore the 164 fact that only a certain family of characters are allowed to appear in the lexical value, so this is checked first. 165 @param v: the literal string defined as a base64encoded string 166 @return the decoded (binary) content 167 @raise ValueError: invalid base 64 binary value 168 """ 169 import base64 170 if v.replace('=','x').replace('+','y').replace('/','z').isalnum() : 171 try : 172 return base64.standard_b64decode(v) 173 except : 174 raise ValueError("Invalid Base64Binary %s" % v) 175 else : 176 raise ValueError("Invalid Base64Binary %s" % v)
177 178 #################################### Numerical types ################################################## 179 #: limits for unsigned bytes 180 _limits_unsignedByte = [-1, 256] 181 182 #: limits for bytes 183 _limits_byte = [-129, 128] 184 185 #: limits for unsigned int 186 _limits_unsignedInt = [-1, 4294967296] 187 188 #: limits for int 189 _limits_int = [-2147483649, 2147483648] 190 191 #: limits for unsigned short 192 _limits_unsignedShort = [-1, 65536] 193 194 #: limits for short 195 _limits_short = [-32769, 32768] 196 197 #: limits for unsigned long 198 _limits_unsignedLong = [-1, 18446744073709551616] 199 200 #: limits for long 201 _limits_long = [-9223372036854775809, 9223372036854775808] 202 203 #: limits for positive integer 204 _limits_positiveInteger = [0, None] 205 206 #: limits for non positive integer 207 _limits_nonPositiveInteger = [None, 1] 208 209 #: limits for non negative ingteger 210 _limits_nonNegativeInteger = [-1, None] 211 212 #: limits for negative ingteger 213 _limits_negativeInteger = [None, 0] 214
215 -def _strToBoundNumeral(v, interval, conversion) :
216 """Test (and convert) a generic numerical type, with a check against a lower and upper limit. 217 @param v: the literal string to be converted 218 @param interval: lower and upper bounds (non inclusive). If the value is None, no comparison should be done 219 @param conversion: conversion function, ie, int, long, etc 220 @raise ValueError: invalid value 221 """ 222 try : 223 i = conversion(v) 224 if (interval[0] == None or interval[0] < i) and (interval[1] == None or i < interval[1]) : 225 return i 226 except : 227 pass 228 raise ValueError("Invalid numerical value %s" % v)
229 230 #################################### Double and float ##################################################
231 -def _strToDouble(v) :
232 """Test and convert a double value into a Decimal or float. Raises an exception if the number is outside the permitted 233 range, ie, 1.0E+310 and 1.0E-330. To be on the safe side (python does not have double!) Decimals are used 234 if possible. Upper and lower values, as required by xsd, are checked. 235 236 @param v: the literal string defined as a double 237 @return Decimal if the local python version is >= 2.4, float otherwise 238 @raise ValueError: invalid value 239 """ 240 if Decimal_available : 241 try : 242 value = Decimal(v) 243 avalue = abs(value) 244 upper = Decimal("1.0E+310") 245 lower = Decimal("1.0E-330") 246 if lower < avalue and avalue < upper : 247 # bingo 248 return value 249 else : 250 raise ValueError("Invalid double %s" % v) 251 except : 252 # there was a problem in creating a decimal... 253 raise ValueError("Invalid double %s" % v) 254 else : 255 # not much we can do, just convert to float. This will not be o.k., but will work on older python 256 # installations... 257 return float(v)
258
259 -def _strToFloat(v) :
260 """Test and convert a float value into Decimal or (python) float. Raises an exception if the number is outside the 261 permitted range, ie, 1.0E+40 and 1.0E-50. 262 263 @param v: the literal string defined as a float 264 @return Decimal if the local python version is >= 2.4, float otherwise 265 @raise ValueError: invalid value 266 """ 267 if Decimal_available : 268 try : 269 value = Decimal(v) 270 avalue = abs(value) 271 upper = Decimal("1.0E+40") 272 lower = Decimal("1.0E-50") 273 if lower < avalue and avalue < upper : 274 # bingo 275 return value 276 else : 277 raise ValueError("Invalid float %s" % v) 278 except : 279 # there was a problem in creating a decimal... 280 raise ValueError("Invalid float %s" % v) 281 else : 282 # it seems that the float range handled by python is larger than what is described in the spec 283 # the stuff below may go wrong at the edges but nevertheless gives some check 284 value = float(v) 285 avalue = abs(value) 286 if 1.0E-50 < avalue and avalue < 1.0E+40 : 287 return value 288 else: 289 raise ValueError("Invalid float %s" % v)
290 291 #################################### hexa ##################################################
292 -def _strToHexBinary(v) :
293 """Test (and convert) hexa integer values. The number of characters should be even. 294 @param v: the literal string defined as a hexa number 295 @return long value 296 @raise ValueError: invalid value 297 """ 298 # first of all, the number of characters must be even according to the xsd spec: 299 length = len(v) 300 if (length/2)*2 != length : 301 raise ValueError("Invalid hex binary number %s" % v) 302 return long(v,16)
303 304 #################################### Datetime, datetimestamp, etc ################################ 305
306 -def _strToDateTimeAndStamp(incoming_v, timezone_required = False) :
307 """Test (and convert) datetime and datetimestamp values. 308 @param incoming_v: the literal string defined as the date and time 309 @param timezone_required: whether the timezone is required (ie, for datetimestamp) or not 310 @return datetime 311 @rtype: datetime.datetime 312 @raise ValueError: invalid datetime or datetimestamp 313 """ 314 315 # First, handle the timezone portion, if there is any 316 (v, tzone) = _returnTimeZone(incoming_v) 317 318 # Check on the timezone. For timedatestamp object it is required 319 if timezone_required and tzone == None : 320 raise ValueError("Invalid datetime %s" % incoming_v) 321 322 # The microseconds should be handled here... 323 final_v = v 324 miliseconds = 0 325 milpattern = "(.*)(\.)([0-9]*)" 326 match = re.match(milpattern, v) 327 if match != None : 328 # we have a milisecond portion... 329 try : 330 final_v = match.groups()[0] 331 miliseconds = int(match.groups()[2]) 332 except : 333 raise ValueError("Invalid datetime %s" % incoming_v) 334 # 335 # By now, the pattern should be clear 336 # This may raise an exception... 337 try : 338 tstr = time.strptime(final_v,"%Y-%m-%dT%H:%M:%S") 339 if tzone != None : 340 return datetime.datetime(tstr.tm_year, tstr.tm_mon, tstr.tm_mday, tstr.tm_hour, tstr.tm_min, tstr.tm_sec, miliseconds, tzone) 341 else : 342 return datetime.datetime(tstr.tm_year, tstr.tm_mon, tstr.tm_mday, tstr.tm_hour, tstr.tm_min, tstr.tm_sec, miliseconds) 343 except : 344 raise ValueError("Invalid datetime %s" % incoming_v)
345
346 -def _strToTime(incoming_v) :
347 """Test (and convert) time values. 348 @param incoming_v: the literal string defined as time value 349 @return time 350 @rtype datetime.time 351 @raise ValueError: invalid datetime or datetimestamp 352 """ 353 354 # First, handle the timezone portion, if there is any 355 (v, tzone) = _returnTimeZone(incoming_v) 356 357 # The microseconds should be handled here... 358 final_v = v 359 miliseconds = 0 360 milpattern = "(.*)(\.)([0-9]*)" 361 match = re.match(milpattern, v) 362 if match != None : 363 # we have a milisecond portion... 364 try : 365 final_v = match.groups()[0] 366 miliseconds = int(match.groups()[2]) 367 except : 368 raise ValueError("Invalid datetime %s" % incoming_v) 369 # 370 # By now, the pattern should be clear 371 # This may raise an exception... 372 try : 373 tstr = time.strptime(final_v,"%H:%M:%S") 374 if tzone != None : 375 return datetime.time(tstr.tm_hour, tstr.tm_min, tstr.tm_sec, miliseconds, tzone) 376 else : 377 return datetime.time(tstr.tm_hour, tstr.tm_min, tstr.tm_sec, miliseconds) 378 except : 379 raise ValueError("Invalid time %s" % incoming_v)
380
381 -def _strToDate(incoming_v) :
382 """Test (and convert) date values. 383 @param incoming_v: the literal string defined as date (in iso format) 384 @return date 385 @return datetime.date 386 @raise ValueError: invalid datetime or datetimestamp 387 """ 388 389 # First, handle the timezone portion, if there is any 390 (final_v, tzone) = _returnTimeZone(incoming_v) 391 392 # This may raise an exception... 393 try : 394 tstr = time.strptime(final_v,"%Y-%m-%d") 395 return datetime.date(tstr.tm_year, tstr.tm_mon, tstr.tm_mday) 396 except : 397 raise ValueError("Invalid date %s" % incoming_v)
398 399 #################################### The 'g' series for dates ############################ 400 # The 'g' datatatypes (eg, gYear) cannot be directly represented as a python datatype 401 # the series of methods below simply check whether the incoming string is o.k., but the 402 # returned value is the same as the original
403 -def _strTogYearMonth(v) :
404 """Test gYearMonth value 405 @param v: the literal string 406 @return v 407 @raise ValueError: invalid value 408 """ 409 try : 410 time.strptime(v+"-01","%Y-%m-%d") 411 return v 412 except : 413 raise ValueError("Invalid gYearMonth %s" % v)
414
415 -def _strTogYear(v) :
416 """Test gYearMonth value 417 @param v: the literal string 418 @return v 419 @raise ValueError: invalid value 420 """ 421 try : 422 time.strptime(v+"-01-01","%Y-%m-%d") 423 return v 424 except : 425 raise ValueError("Invalid gYear %s" % v)
426
427 -def _strTogMonthDay(v) :
428 """Test gYearMonth value 429 @param v: the literal string 430 @return v 431 @raise ValueError: invalid value 432 """ 433 try : 434 time.strptime("2001-" + v,"%Y-%m-%d") 435 return v 436 except : 437 raise ValueError("Invalid gMonthDay %s" % v)
438
439 -def _strTogDay(v) :
440 """Test gYearMonth value 441 @param v: the literal string 442 @return v 443 @raise ValueError: invalid value 444 """ 445 try : 446 time.strptime("2001-01-" + v,"%Y-%m-%d") 447 return v 448 except : 449 raise ValueError("Invalid gDay %s" % v)
450
451 -def _strTogMonth(v) :
452 """Test gYearMonth value 453 @param v: the literal string 454 @return v 455 @raise ValueError: invalid value 456 """ 457 try : 458 time.strptime("2001-" + v + "-01","%Y-%m-%d") 459 return v 460 except : 461 raise ValueError("Invalid gMonth %s" % v)
462 463 #################################### XML Literal #########################################
464 -def _strToXMLLiteral(v) :
465 """Test (and convert) XML Literal values. 466 @param v: the literal string defined as an xml literal 467 @return the canonical version of the same xml text 468 @raise ValueError: incorrect xml string 469 """ 470 import xml.dom.minidom 471 try : 472 dom = xml.dom.minidom.parseString(v) 473 return dom.toxml() 474 except : 475 raise ValueError("Invalid XML Literal %s" % v)
476 477 #################################### language, NMTOKEN, NAME, etc ######################### 478 #: regular expression for a 'language' datatype 479 _re_language = "[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*" 480 481 #: regexp for NMTOKEN. It must be used with a re.U flag (the '(?U' regexp form did not work. It may depend on the locale...) 482 _re_NMTOKEN = "[\w:_.\-]+" 483 484 #: characters not permitted at a starting position for Name (otherwise Name is like NMTOKEN 485 _re_Name_ex = ['.','-'] + _numb 486 487 #: regexp for NCName. It must be used with a re.U flag (the '(?U' regexp form did not work. It may depend on the locale...) 488 _re_NCName = "[\w_.\-]+" 489 490 #: characters not permitted at a starting position for NCName 491 _re_NCName_ex = ['.','-'] + _numb 492
493 -def _strToVal_Regexp(v, regexp, flag = 0, excludeStart = []) :
494 """Test (and convert) a generic string type, with a check against a regular expression. 495 @param v: the literal string to be converted 496 @param regexp: the regular expression to check against 497 @param flag: flags to be used in the regular expression 498 @param excludeStart: array of characters disallowed in the first position 499 @return original string 500 @raise ValueError: invalid value 501 """ 502 match = re.match(regexp, v, flag) 503 if match == None or match.end() != len(v) : 504 raise ValueError("Invalid literal %s" % v) 505 else : 506 if len(excludeStart) > 0 and v[0] in excludeStart : 507 raise ValueError("Invalid literal %s" % v) 508 return v
509 510 #: Disallowed characters in a token or a normalized string, as a regexp 511 _re_token = "[^\n\t\r]+" 512
513 -def _strToToken(v) :
514 """Test (and convert) a string to a token. 515 @param v: the literal string to be converted 516 @return original string 517 @raise ValueError: invalid value 518 """ 519 if len(v) == 0 : return v 520 # filter out the case when there are new lines and similar (if there is a problem, an exception is raised) 521 _strToVal_Regexp(v, _re_token) 522 v1 = ' '.join(v.strip().split()) 523 # normalize the string, and see if the result is the same: 524 if len(v1) == len(v) : 525 # no characters lost, ie, no unnecessary spaces 526 return v 527 else : 528 raise ValueError("Invalid literal %s" % v)
529 530 #################################### plain literal ########################################
531 -def _strToPlainLiteral(v) :
532 """Test (and convert) a plain literal 533 @param v: the literal to be converted 534 @return a new RDFLib Literal with language tag 535 @raise ValueError: invalid value 536 """ 537 reg = "(.*)@([^@]*)" 538 # a plain literal must match this regexp! 539 match = re.match(reg,v) 540 if match == None : 541 raise ValueError("Invalid plain literal %s" % v) 542 else : 543 lit = match.groups()[0] 544 if len(match.groups()) == 1 or match.groups()[1] == "" : 545 # no language tag 546 lang = None 547 return Literal(lit) 548 else : 549 lang = match.groups()[1] 550 # check if this is a correct language tag. Note that can raise an exception! 551 try : 552 lang = _strToVal_Regexp(lang, _re_language) 553 return Literal(lit,lang=lang.lower()) 554 except : 555 raise ValueError("Invalid plain literal %s" % v)
556 557 ##################################################################################### 558 #: Replacement of RDFLib's conversion function. Each entry assigns a function to an XSD datatype, attempting to convert a string to a Python datatype (or raise an exception if some problem is found) 559 AltXSDToPYTHON = { 560 ns_xsd["language"] : lambda v: _strToVal_Regexp(v, _re_language), 561 ns_xsd["NMTOKEN"] : lambda v: _strToVal_Regexp(v, _re_NMTOKEN, re.U), 562 ns_xsd["Name"] : lambda v: _strToVal_Regexp(v, _re_NMTOKEN, re.U, _re_Name_ex), 563 ns_xsd["NCName"] : lambda v: _strToVal_Regexp(v, _re_NCName, re.U, _re_NCName_ex), 564 ns_xsd["token"] : _strToToken, 565 ns_rdf["PlainLiteral"] : _strToPlainLiteral, 566 ns_xsd["boolean"] : _strToBool, 567 ns_xsd["decimal"] : _strToDecimal, 568 ns_xsd["anyURI"] : _strToAnyURI, 569 ns_xsd["base64Binary"] : _strToBase64Binary, 570 ns_xsd["double"] : _strToDouble, 571 ns_xsd["float"] : _strToFloat, 572 ns_xsd["byte"] : lambda v: _strToBoundNumeral(v, _limits_byte, int), 573 ns_xsd["int"] : lambda v: _strToBoundNumeral(v, _limits_int, long), 574 ns_xsd["long"] : lambda v: _strToBoundNumeral(v, _limits_long, long), 575 ns_xsd["positiveInteger"] : lambda v: _strToBoundNumeral(v, _limits_positiveInteger, long), 576 ns_xsd["nonPositiveInteger"] : lambda v: _strToBoundNumeral(v, _limits_nonPositiveInteger, long), 577 ns_xsd["negativeInteger"] : lambda v: _strToBoundNumeral(v, _limits_negativeInteger, long), 578 ns_xsd["nonNegativeInteger"] : lambda v: _strToBoundNumeral(v, _limits_nonNegativeInteger, long), 579 ns_xsd["short"] : lambda v: _strToBoundNumeral(v, _limits_short, int), 580 ns_xsd["unsignedByte"] : lambda v: _strToBoundNumeral(v, _limits_unsignedByte, int), 581 ns_xsd["unsignedShort"] : lambda v: _strToBoundNumeral(v, _limits_unsignedShort, int), 582 ns_xsd["unsignedInt"] : lambda v: _strToBoundNumeral(v, _limits_unsignedInt, long), 583 ns_xsd["unsignedLong"] : lambda v: _strToBoundNumeral(v, _limits_unsignedLong, long), 584 ns_xsd["hexBinary"] : _strToHexBinary, 585 ns_xsd["dateTime"] : lambda v: _strToDateTimeAndStamp(v, False), 586 ns_xsd["dateTimeStamp"] : lambda v: _strToDateTimeAndStamp(v, True), 587 ns_rdf["XMLLiteral"] : _strToXMLLiteral, 588 ns_xsd["integer"] : long, 589 ns_xsd["string"] : lambda v: v, 590 ns_xsd["normalizedString"] : lambda v: _strToVal_Regexp(v, _re_token), 591 592 # These are RDFS specific... 593 ns_xsd["time"] : _strToTime, 594 ns_xsd["date"] : _strToDate, 595 ns_xsd["gYearMonth"] : _strTogYearMonth, 596 ns_xsd["gYear"] : _strTogYear, 597 ns_xsd["gMonthDay"] : _strTogMonthDay, 598 ns_xsd["gDay"] : _strTogDay, 599 ns_xsd["gMonth"] : _strTogMonth, 600 } 601
602 -def use_Alt_lexical_conversions() :
603 """Registering the datatypes item for RDFLib, ie, bind the dictionary values. The 'bind' method of RDFLib adds 604 extra datatypes to the registered ones in RDFLib, though the table used here (ie, L{AltXSDToPYTHON}) actually overrides 605 all of the default conversion routines. The method also add a Decimal entry to the PythonToXSD array of RDFLib. 606 """ 607 _toPythonMapping.update(AltXSDToPYTHON) 608 if Decimal_available : 609 # at some point in type, this structure has changed in rdflib... 610 import types 611 if isinstance(_PythonToXSD,types.DictType) : 612 _PythonToXSD[Decimal] = (None,ns_xsd[u'decimal']) 613 else : 614 _PythonToXSD.append((Decimal,(None,ns_xsd[u'decimal'])))
615
616 -def use_RDFLib_lexical_conversions() :
617 """Restore the original (ie, RDFLib) set of lexical conversion routines. 618 """ 619 _toPythonMapping.update(XSDToPython)
620 621 ####################################################################################### 622 # This module can pretty much tested individually... 623 if __name__ == '__main__' : 624 import sys 625 string = sys.argv[1] 626 datatype = ns_xsd["gMonth"] 627 result = AltXSDToPYTHON[datatype](string) 628 print type(result) 629 print result 630