[Zope3-checkins] CVS: zopeproducts/pypgsqlda - adapter.py:1.7

Christian 'Tiran' Heimes heimes@faho.rwth-aachen.de
Fri, 21 Mar 2003 17:17:02 -0500


Update of /cvs-repository/zopeproducts/pypgsqlda
In directory cvs.zope.org:/tmp/cvs-serv29731/zopeproducts/pypgsqlda

Modified Files:
	adapter.py 
Log Message:
backport from branch with datetime converter added
now all types are basicly supported so you can use this adapter for testing
WARNING: timestamptz and interval have bugs due problems with mxDateTime and/or pyPgSQL. See code for more informations

=== zopeproducts/pypgsqlda/adapter.py 1.6 => 1.7 ===
--- zopeproducts/pypgsqlda/adapter.py:1.6	Wed Mar 19 17:18:50 2003
+++ zopeproducts/pypgsqlda/adapter.py	Fri Mar 21 17:17:01 2003
@@ -22,6 +22,10 @@
 
 import string
 
+import datetime
+from zope.app import datetimeutils
+
+
 class pypgsqlAdapter(ZopeDatabaseAdapter):
     """A pypgsql adapter for Zope3"""
 
@@ -53,10 +57,17 @@
 
 # helpers
 
-def isPgArray(data):
+def _isPgArray(data):
     """Check if data is a postgres array"""   
     return isinstance(data, PgArray)
 
+def _sec2my(sec):
+    """ Return second and mikro for a float second"""
+    # from psycopgda
+    sec, my = divmod(sec, 1.0)
+    my = round(my * 1000000) 
+    return (sec, my)
+
 # Converters
 
 def convertINet(data):
@@ -75,11 +86,7 @@
     else:
         addr.append(32)
     return (tuple([string.atoi(a) for a in addr[0].split('.')]), addr[1])
-
-def convertInterval(data):
-    """Returns the length of the interval in seconds."""
-    return data.seconds
-    
+ 
 def convertBool(data):
     """Returns a boolean as normal python boolean."""
     return not not data
@@ -180,15 +187,63 @@
     """
     return tuple([convertPoint(p) for p in groupPointList.findall(unicode(data))]) 
     
+def convertTime(data):
+    """Converts a mxDateTime.time object to a datetime.time object"""
+    # XXX: day?
+    if not data: return None
+    d, h, min, sec = data.tuple()
+    sec, my = _sec2my(sec)
+    return datetime.time(h, min, sec, my)
+
+def convertTimestamp(data):
+    """Converts a mxDateTime.datetime object to a datetime.datetime object"""
+    if not data: return None
+    y, m, d, h, min, sec, dayOfWeek, dayOfYear, dst = data.tuple()
+    sec, my = _sec2my(sec)
+    return datetime.datetime(y, m, d, h, min, sec, my)
+
+def convertTimestampTZ(data):
+    """Converts a mxDateTime.time object to a datetime.time object with timezone
+    
+    XXX BUG BUG BUG
+    Warning: mxDateTime.DateTime returns wrong timezone
+    I got only CET (my local tz) as tz
+    XXX BUG BUG BUG
+    """
+    if not data: return None
+    y, m, d, h, min, sec, dayOfWeek, dayOfYear, dst = data.tuple()
+    sec, my = _sec2my(sec)
+    # time zone offset in minutes
+    tzoffset = data.gmtoffset().minutes
+    if tzoffset: tz = datetimeutils.tzinfo(tzoffset) 
+    else: tz = datetimeutils.tzinfo(0)
+    return datetime.datetime(y, m, d, h, min, sec, my, tz)
+
+def convertInterval(data):
+    """Converts a mxDateTime.DateTimeDelta object to a datetime.timedelta object
+    
+    XXX BUG BUG BUG
+    Warning: mxDateTime.DateTimeDelta returns wrong data for large intervals
+    for example 20 years are 20 days!
+    XXX BUG BUG BUG
+    """
+    days, hours, min, sec = data.tuple()
+    sec, my = _sec2my(sec)
+    return datetime.timedelta(days=days, hours=hours, minutes=min,
+                              seconds=sec, microseconds=my)
+
 def debug(data):
     """XXX  used for debugging"""
     import pdb;
     pdb.set_trace()
     print data
+    return data
 
+# http://www.cs.nott.ac.uk/TSG/manuals/databases/postgres/user/x774.htm#AEN1354
+# http://www.postgresql.org/docs/view.php?version=7.2&idoc=0&file=datatype.html
 # types from pypgsql/libpqmodule.c
 converter_mapping = {
-    'abstime'   : debug,            # PG_ABSTIME        time 
+    'abstime'   : unicode,           # PG_ABSTIME        XXXtime (obsolet)
     'aclitem'   : unicode,          # PG_ACLITEM    S   unicode XXX PgArray
     'blob'      : string,           # PG_BLOB           string
     'bool'      : convertBool,      # PG_BOOL           boolean
@@ -200,7 +255,7 @@
                                     # need more information! could be connection id
     'cidr'      : convertINet,      # PG_CIDR           network XXX
     'circle'    : convertCircle,    # PG_CIRCLE         geometric.circle
-    'date'      : debug,            # PG_DATE           datetime.date
+    'date'      : convertTimestamp, # PG_DATE           datetime.date
     'float4'    : identity,         # PG_FLOAT4         float
     'float'     : identity,         # PG_FLOAT8         float
     'inet'      : convertINet,      # PG_INET           network XXX 
@@ -221,15 +276,15 @@
     'polygon'   : convertPolygon,   # PG_POLYGON        geometric.polygon
     'refcursor' : unicode,          # PG_REFCURSOR  S   unicode XXX: what? identitiy?
     'regproc'   : unicode,          # PG_REGPROC    S   unicode XXX: what? identitiy?
-    'reltime'   : debug,            # PG_RELTIME        datetime.delta
+    'reltime'   : unicode,           # PG_RELTIME        XXX datetime.delta (obsolet)
     'rowid'     : long,             # PG_ROWID      S   longint; rowid is oid in pgpPgAdmin
     'text'      : identity,         # PG_TEXT           unicode 
     'tid'       : debug,            # PG_TID        S   unicode XXX number? what?
                                     # need more information, could be transaction id
-    'time'      : debug,            # PG_TIME           datetime.time
-    'timestamp' : debug,            # PG_TIMESTAMP      datetime.datetime
-    'timestamptz' : debug,          # PG_TIMESTAMPTZ    datetime.datetime
-    'tinterval' : debug,            # PG_TINTERVAL      datetime.delta
+    'time'      : convertTime,      # PG_TIME           datetime.time
+    'timestamp' : convertTimestamp, # PG_TIMESTAMP      datetime.datetime
+    'timestamptz' : convertTimestampTZ, # PG_TIMESTAMPTZ    datetime.datetime
+    'tinterval' : unicode,           # PG_TINTERVAL      XXX datetime.delta (obsolet)
     'unknown'   : unicode,          # PG_UNKNOWN    S?  unicode (unknown), XXX what?
     'varbit'    : unicode,          # PG_VARBIT         XXX see zpbit!
     'varchar'   : identity,         # PG_VARCHAR        unicode