[Zope3-checkins] CVS: zopeproducts/pypgsqlda - adapter.py:1.6
Christian 'Tiran' Heimes
heimes@faho.rwth-aachen.de
Wed, 19 Mar 2003 17:18:51 -0500
Update of /cvs-repository/zopeproducts/pypgsqlda
In directory cvs.zope.org:/tmp/cvs-serv30925/zopeproducts/pypgsqlda
Modified Files:
adapter.py
Log Message:
modified converter_mapping after some testing
added converter for geometric types, inet and smallint
=== zopeproducts/pypgsqlda/adapter.py 1.5 => 1.6 ===
--- zopeproducts/pypgsqlda/adapter.py:1.5 Tue Mar 18 15:23:35 2003
+++ zopeproducts/pypgsqlda/adapter.py Wed Mar 19 17:18:50 2003
@@ -20,6 +20,8 @@
from zope.app.rdb import ZopeDatabaseAdapter, parseDSN, identity
+import string
+
class pypgsqlAdapter(ZopeDatabaseAdapter):
"""A pypgsql adapter for Zope3"""
@@ -49,8 +51,31 @@
else:
return identity
+# helpers
+
+def isPgArray(data):
+ """Check if data is a postgres array"""
+ return isinstance(data, PgArray)
+
# Converters
+def convertINet(data):
+ """Converts inet and cidr to an nested tuple
+
+ Return a nested tuple of the form (hostaddress, netmask) where
+ hostaddress itself is a tuple of ints and netmask is an int.
+
+ FYI: cidr and inet can handle only ipv4 (12 bytes)
+
+ XXX: make this a special type
+ """
+ addr = unicode(data).split('/')
+ if len(addr) == 2:
+ addr[1] = string.atoi(addr[1])
+ 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
@@ -58,65 +83,157 @@
def convertBool(data):
"""Returns a boolean as normal python boolean."""
return not not data
+
+def convertSmallInt(data):
+ """Converts a string containing a small int (int2) to int"""
+ return string.atoi(unicode(data))
+
+
+class GeometricError(Exception): pass
+
+import re
+# matching an open path e.g. [(0,0),(1,1)]
+isOpenPath = re.compile(r"^\[\(.*\)\]$")
+
+# matching a closed path e.g. ((0,0),(1,1))
+isClosedPath = re.compile(r"^\(\(.*\)\)$")
+
+# group a circle e.g. <(1,1),0.5> into (1.0,1.0) as the middle point
+# and 0.5 as the radius
+groupCircle = re.compile(r"^<(\([\d.]+,[\d.]+\)),([\d.]+)>$")
+
+# group a single point e.g. (0,1) into 0 as the x value and 1 as the y value
+groupPoint = re.compile(r"^\(([\d.]+),([\d.]+)\)$")
+
+# group a path or a box e.g.((0,0),(1,1)) or [(0,0),(1,1)] into a
+# list of points
+groupPointList = re.compile(r"(\([\d.]+,[\d.]+\))")
+
+def convertPoint(data):
+ """Returns tuple (x,y) coordinate of floats
-def convertMac(data):
- """Return a Mac as a normal string."""
- return unicode(data)
-
-def convertNet(data):
- """Return a network address as tuple (network, mask)."""
- return unicode(data).split('/')
+ XXX: make this a special type
+ """
+ point = groupPoint.match(unicode(data)).groups()
+ if len(point) != 2:
+ raise GeometricError, u"'%s' has wrong size" % data
+ return tuple([string.atof(p) for p in point])
+
+def convertBox(data):
+ """Returns nested list upper right and lower left point
+
+ XXX: make this a special type
+ """
+ box = groupPointList.findall(unicode(data))
+ if len(box) != 2:
+ raise GeometricError, u"'%s' has wrong size" % data
+ return tuple([convertPoint(p) for p in box])
+
+def convertCircle(data):
+ """Returns tuple ((x,y), radius) of floats
+
+ XXX: make this a special type
+ """
+ circle = groupCircle.match(unicode(data)).groups()
+ if len(circle) != 2:
+ raise GeometricError, u"'%s' has wrong size" % data
+ return (convertPoint(circle[0]), string.atof(circle[1]))
+
+def convertLine(data):
+ """Returns tuple of two points, which defines the infinite line
+
+ XXX: make this a special type
+ """
+ line = groupPointList.findall(unicode(data))
+ if len(line) != 2:
+ raise GeometricError, u"'%s' has wrong size" % data
+ return tuple([convertPoint(p) for p in line])
+
+def convertLSeg(data):
+ """Returns list of two points
+
+ XXX: make this a special type
+ """
+ lseg = groupPointList.findall(unicode(data))
+ if len(lseg) != 2:
+ raise GeometricError, u"'%s' has wrong size" % data
+ return [convertPoint(p) for p in lseg]
+
+def convertPath(data):
+ """Returns list or tuple of n points, tuple is used for a closed path
+
+ XXX: make this a special type
+ """
+ if isOpenPath.match(unicode(data)):
+ return [convertPoint(p)
+ for p in groupPointList.findall(unicode(data))]
+ elif isClosedPath.match(unicode(data)):
+ return tuple([convertPoint(p)
+ for p in groupPointList.findall(unicode(data))])
+ else:
+ raise GeometricError, u"'%s' has wrong format" % data
+
+def convertPolygon(data):
+ """Returns tuple of n points
+
+ XXX: make this a special type
+ """
+ return tuple([convertPoint(p) for p in groupPointList.findall(unicode(data))])
-def debug(data):
+def debug(data):
+ """XXX used for debugging"""
import pdb;
pdb.set_trace()
print data
-# types from pypgsql/libpqmodule.c
+# types from pypgsql/libpqmodule.c
converter_mapping = {
- 'abstime' : debug, # PG_ABSTIME time
- 'aclitem' : debug, # PG_ACLITEM unicode (sys)
- 'blob' : debug, # PG_BLOB string
- 'bool' : convertBool, # PG_BOOL boolean
- 'box' : debug, # PG_BOX geometric.box
- 'char' : debug, # PG_BPCHAR identity
- 'bytea' : debug, # PG_BYTEA string
- 'money' : debug, # PG_CASH float
- 'cid' : debug, # PG_CID unicode (sys)
- 'cidr' : debug, # PG_CIDR unicode
- 'circle' : debug, # PG_CIRCLE geometric.circle
- 'date' : debug, # PG_DATE datetime.date
- 'float4' : debug, # PG_FLOAT4 float
- 'float' : debug, # PG_FLOAT8 float
- 'inet' : debug, # PG_INET unicode
- 'int2' : debug, # PG_INT2 integer
- 'int2vector' : debug, # PG_INT2VECTOR unicode (sys)
- 'integer' : debug, # PG_INT4 integer
- 'bigint' : debug, # PG_INT8 longint
- 'interval' : convertInterval, # PG_INTERVAL datetime.delta
- 'line' : debug, # PG_LINE geometric.line
- 'lseg' : debug, # PG_LSEG geometric.linesegment
- 'macaddr' : debug, # PG_MACADDR unicode
- 'name' : debug, # PG_NAME unicode
- 'numeric' : debug, # PG_NUMERIC float
- 'oid' : debug, # PG_OID unicode (sys)
- 'oidvector' : debug, # PG_OIDVECTOR unicode (sys)
- 'path' : debug, # PG_PATH geometric.path
- 'point' : debug, # PG_POINT geometric.point
- 'polygon' : debug, # PG_POLYGON geometric.polygon
- 'refcursor' : debug, # PG_REFCURSOR unicode (sys)
- 'regproc' : debug, # PG_REGPROC unicode (sys)
- 'reltime' : debug, # PG_RELTIME datetime.delta
- 'rowid' : debug, # PG_ROWID longint
- 'text' : debug, # PG_TEXT unicode
- 'tid' : debug, # PG_TID unicode (sys)
- 'time' : debug, # PG_TIME datetime.time
- 'timestamp' : debug, # PG_TIMESTAMP datetime.datetime
- 'timestamptz' : debug, # PG_TIMESTAMPTZ datetime.datetime
- 'tinterval' : debug, # PG_TINTERVAL datetime.delta
- 'unknown' : debug, # PG_UNKNOWN unicode (sys)
- 'varbit' : debug, # PG_VARBIT XXX
- 'varchar' : debug, # PG_VARCHAR unicode
- 'xid' : debug, # PG_XID unicode (sys)
- 'zpbit' : debug # PG_ZPBIT identity XXX debug this
+ 'abstime' : debug, # PG_ABSTIME time
+ 'aclitem' : unicode, # PG_ACLITEM S unicode XXX PgArray
+ 'blob' : string, # PG_BLOB string
+ 'bool' : convertBool, # PG_BOOL boolean
+ 'box' : convertBox, # PG_BOX geometric.box
+ 'char' : identity, # PG_BPCHAR identity XXX ??
+ 'bytea' : string, # PG_BYTEA string
+ 'money' : float, # PG_CASH float XXX: special?
+ 'cid' : debug, # PG_CID S unicode XXX number?
+ # 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
+ 'float4' : identity, # PG_FLOAT4 float
+ 'float' : identity, # PG_FLOAT8 float
+ 'inet' : convertINet, # PG_INET network XXX
+ 'int2' : convertSmallInt, # PG_INT2 integer
+ 'int2vector' : unicode, # PG_INT2VECTOR S unicode XXX PgArray of int2
+ 'integer' : identity, # PG_INT4 integer
+ 'bigint' : long, # PG_INT8 longint
+ 'interval' : convertInterval, # PG_INTERVAL datetime.delta
+ 'line' : convertLine, # PG_LINE geometric.line (XXX not implemented in pgsql 7.2)
+ 'lseg' : convertLSeg, # PG_LSEG geometric.linesegment
+ 'macaddr' : unicode, # PG_MACADDR unicode
+ 'name' : identity, # PG_NAME S identity == unicode
+ 'numeric' : float, # PG_NUMERIC float XXX: special?
+ 'oid' : debug, # PG_OID S unicode XXX: what? is NOT oid in pgpPgAdmin, see rowid
+ 'oidvector' : unicode, # PG_OIDVECTOR S unicode XXX: PgArray
+ 'path' : convertPath, # PG_PATH geometric.path
+ 'point' : convertPoint, # PG_POINT geometric.point
+ '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
+ '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
+ 'unknown' : unicode, # PG_UNKNOWN S? unicode (unknown), XXX what?
+ 'varbit' : unicode, # PG_VARBIT XXX see zpbit!
+ 'varchar' : identity, # PG_VARCHAR unicode
+ 'xid' : long, # PG_XID S xid is a longint [was: unicode]
+ 'zpbit' : unicode # PG_ZPBIT unicode XXX: pgsql returns string
+ # make int?, this would kill all leading zeros!
}