root/rdfalchemy/trunk/rdfalchemy/Literal.py

Revision 145, 4.2 KB (checked in by phil, 3 years ago)

fix for Decimal Literal Mapping in rdflib 2.4.1

Line 
1#!/usr/bin/env python
2# encoding: utf-8
3"""
4Literal.py
5
6Created by Philip Cooper on 2008-02-09.
7Copyright (c) 2008 Openvest. All rights reserved.
8"""
9from rdflib import Namespace, Literal
10from rdflib.Literal import bind as bindLiteral
11from rdflib.Literal import _PythonToXSD
12import re
13import logging
14
15XSD = Namespace(u'http://www.w3.org/2001/XMLSchema#')
16
17################################################################################
18# Let's fix the logging.  This seems like a lot of work...
19# all that it does is not log rebinding errors.
20# We know already about them ... and the warnings confuse the citizenry.
21_log = logging.getLogger("rdflib")
22if not _log.handlers:
23    class rebindingLogFilter(logging.Filter):
24        def filter(self, record):
25            if record.getMessage().find("Rebinding") > -1:
26                return False
27            return True
28   
29    h = logging.StreamHandler()
30    h.addFilter(rebindingLogFilter())
31    _log.addHandler(h)
32   
33################################################################################
34## Let's make toPython return a Decimal if an XSD.decimal in in the triplestore
35try:
36    from decimal import Decimal
37    bindLiteral(XSD.decimal,Decimal)
38    _PythonToXSD.update(dict([(Decimal,(str,XSD.decimal))]))
39except AttributeError:
40    ## rdflib2.4.1 changed  _PythonToXSD from a dict to a list
41    _PythonToXSD.extend([(Decimal,(str,XSD.decimal))]) 
42except:
43    pass
44   
45################################################################################
46## Default behavior returns untyped literals as literals
47## this brings untyped literals back as unicode strings
48bindLiteral(None,unicode)
49
50################################################################################
51## Default behavior returns string literals as literals
52## this brings  string literals back as unicode strings
53bindLiteral(XSD.string,unicode)
54       
55################################################################################
56## Let's make toPython return a datetime if the literal has fractional seconds
57## Note: dateparser adapted from http://www.mnot.net/python/isodate.py
58## modified to: handle fractional seconds beyond tenths
59##              and to allow pseudo iso i.e. "2001-12-15 22:43:46"
60##                                        vs "2001-12-15T22:43:46"
61import datetime
62
63date_parser = re.compile(r"""^
64    (?P<year>\d{4})
65    (?:-
66        (?P<month>\d{1,2})
67        (?:-
68            (?P<day>\d{1,2})
69            (?:[T ]
70                (?P<hour>\d{1,2})
71                :
72                (?P<minute>\d{1,2})
73                (?::
74                    (?P<second>\d{1,2})
75                    (?P<dec_second>\.\d+)?
76                )?                   
77                (?:Z|(?:
78                        (?P<tz_sign>[+-])
79                        (?P<tz_hour>\d{1,2})
80                        :?
81                        (?P<tz_min>\d{2,2})
82                     )
83                )?
84            )?
85        )?
86    )?
87$""", re.VERBOSE)
88
89def _strToDateTime(s):
90        """ parse a string and return a datetime object. """
91        assert isinstance(s, basestring)
92        r = date_parser.search(s)
93        try:
94            a = r.groupdict('0')
95        except:
96            raise ValueError, 'invalid date string format'
97           
98        dt = datetime.datetime(int(a['year']),
99                               int(a['month']) or 1,
100                               int(a['day']) or 1,
101                               # If not given these will default to 00:00:00.0
102                               int(a['hour']),
103                               int(a['minute']),
104                               int(a['second']),
105                               # Convert into microseconds
106                               int(float(a['dec_second'])*1000000),
107                               )
108        tz_hours_offset = int(a['tz_hour'])
109        tz_mins_offset = int(a['tz_min'])
110        if a.get('tz_sign', '+') == "-":
111            return dt + datetime.timedelta(hours = tz_hours_offset,
112                                           minutes = tz_mins_offset)
113        else:
114            return dt - datetime.timedelta(hours = tz_hours_offset,
115                                           minutes = tz_mins_offset)
116
117bindLiteral(XSD.dateTime,_strToDateTime)
Note: See TracBrowser for help on using the browser.