[Zope3-checkins] CVS: zopeproducts/psycopgda - adapter.py:1.5
Stephan Richter
srichter at cosmos.phy.tufts.edu
Fri Mar 19 20:25:21 EST 2004
Update of /cvs-repository/zopeproducts/psycopgda
In directory cvs.zope.org:/tmp/cvs-serv31175/src/zopeproducts/psycopgda
Modified Files:
adapter.py
Log Message:
Applied patch from issue 197. The patch had a little bug, which I corrected.
=== zopeproducts/psycopgda/adapter.py 1.4 => 1.5 ===
--- zopeproducts/psycopgda/adapter.py:1.4 Mon Jun 2 04:22:49 2003
+++ zopeproducts/psycopgda/adapter.py Fri Mar 19 20:25:20 2004
@@ -15,11 +15,11 @@
$Id$
"""
-
from zope.app.rdb import ZopeDatabaseAdapter, parseDSN
from datetime import date, time, datetime, timedelta
import psycopg
+import re
# These OIDs are taken from pg_types.h from PostgreSQL headers.
# Unfortunatelly psycopg does not export them as constants, and
@@ -36,6 +36,9 @@
#TINTERVAL_OID = 704
# Date/time parsing functions
+
+_dateFmt = re.compile(r"^(\d\d\d\d)-?([01]\d)-?([0-3]\d)$")
+
def parse_date(s):
"""Parses ISO-8601 compliant dates and returns a tuple (year, month,
day).
@@ -44,12 +47,15 @@
YYYY-MM-DD (extended format)
YYYYMMDD (basic format)
"""
- if len(s) == 8:
- return (int(s[:4]), int(s[4:6]), int(s[6:])) # YYYYMMDD
- elif len(s) == 10 and s[4] == s[7] == '-':
- return (int(s[:4]), int(s[5:7]), int(s[8:])) # YYYY-MM-DD
- else:
+ m = _dateFmt.match(s)
+ if m is None:
raise ValueError, 'invalid date string: %s' % s
+ year, month, day = m.groups()
+ return int(year), int(month), int(day)
+
+
+_timeFmt = re.compile(
+ r"^([0-2]\d)(?::?([0-5]\d)(?::?([0-5]\d)(?:[.,](\d+))?)?)?$")
def parse_time(s):
"""Parses ISO-8601 compliant times and returns a tuple (hour, minute,
@@ -62,28 +68,18 @@
HH:MM or HHMM
HH
"""
- if len(s) == 2:
- return (int(s[:2]), 0, 0) # HH
- elif len(s) == 4:
- return (int(s[:2]), int(s[2:]), 0) # HHMM
- elif len(s) == 5 and s[2] == ':':
- return (int(s[:2]), int(s[3:]), 0) # HH:MM
- elif len(s) == 6:
- return (int(s[:2]), int(s[2:4]), int(s[4:])) # HHMMSS
- elif len(s) == 8 and s[2] == s[5] == ':':
- return (int(s[:2]), int(s[3:5]), int(s[6:])) # HH:MM:SS
- elif len(s) > 9 and s[2] == s[5] == ':' and s[8] == '.':
- return (int(s[:2]), int(s[3:5]), float(s[6:])) # HH:MM:SS.ssss
- elif len(s) > 9 and s[2] == s[5] == ':' and s[8] == ',':
- return (int(s[:2]), int(s[3:5]), float(s[6:8] + "." + s[9:]))
- # HH:MM:SS,ssss
- elif len(s) > 7 and s[6] == '.':
- return (int(s[:2]), int(s[2:4]), float(s[4:])) # HHMMSS.ssss
- elif len(s) > 7 and s[6] == ',':
- return (int(s[:2]), int(s[2:4]), float(s[4:6] + "." + s[7:]))
- # HHMMSS,ssss
- else:
+ m = _timeFmt.match(s)
+ if m is None:
raise ValueError, 'invalid time string: %s' % s
+ hr, mn, sc, msc = m.groups(0)
+ if msc != 0:
+ sc = float("%s.%s" % (sc, msc))
+ else:
+ sc = int(sc)
+ return int(hr), int(mn), sc
+
+
+_tzFmt = re.compile(r"^([+-])([0-2]\d)(?::?([0-5]\d))?$")
def parse_tz(s):
"""Parses ISO-8601 timezones and returns the offset east of UTC in
@@ -95,22 +91,18 @@
+/-HH
Z (equivalent to +0000)
"""
- if s == "Z":
+ if s == 'Z':
return 0
- if len(s) in (3, 5, 6) and s[0] in ('+', '-'):
- hoff = int(s[1:3])
- if len(s) > 3:
- moff = int(s[-2:])
- if len(s) == 6 and s[3] != ':':
- raise ValueError, 'invalid time zone: %s' % s
- else:
- moff = 0
- if s[0] == '-':
- return - hoff * 60 - moff
- else:
- return hoff * 60 + moff
- else:
+ m = _tzFmt.match(s)
+ if m is None:
raise ValueError, 'invalid time zone: %s' % s
+ d, hoff, moff = m.groups(0)
+ if d == "-":
+ return - int(hoff) * 60 - int(moff)
+ return int(hoff) * 60 + int(moff)
+
+
+_tzPos = re.compile(r"[Z+-]")
def parse_timetz(s):
"""Parses ISO-8601 compliant times that may include timezone information
@@ -123,13 +115,27 @@
parse_tz(). Time zone should immediatelly follow time without intervening
spaces.
"""
- idx = s.find('+')
- if idx < 0: idx = s.find('-')
- if idx < 0: idx = s.find('Z')
- if idx < 0:
+ m = _tzPos.search(s)
+ if m is None:
return parse_time(s) + (None,)
- else:
- return parse_time(s[:idx]) + (parse_tz(s[idx:]),)
+ pos = m.start()
+ return parse_time(s[:pos]) + (parse_tz(s[pos:]),)
+
+
+_datetimeFmt = re.compile(r"[T ]")
+
+def _split_datetime(s):
+ """Split date and time parts of ISO-8601 compliant timestamp and
+ return a tuple (date, time).
+
+ ' ' or 'T' used to separate date and time parts.
+ """
+ m = _datetimeFmt.search(s)
+ if m is None:
+ raise ValueError, 'time part of datetime missing: %s' % s
+ pos = m.start()
+ return s[:pos], s[pos + 1:]
+
def parse_datetime(s):
"""Parses ISO-8601 compliant timestamp and returns a tuple (year, month,
@@ -138,11 +144,9 @@
Formats accepted are those listed in the descriptions of parse_date() and
parse_time() with ' ' or 'T' used to separate date and time parts.
"""
- idx = s.find('T')
- if idx < 0: idx = s.find(' ')
- if idx < 0:
- raise ValueError, 'time part of datetime missing: %s' % s
- return parse_date(s[:idx]) + parse_time(s[idx + 1:])
+ dt, tm = _split_datetime(s)
+ return parse_date(dt) + parse_time(tm)
+
def parse_datetimetz(s):
"""Parses ISO-8601 compliant timestamp that may include timezone
@@ -155,11 +159,8 @@
Formats accepted are those listed in the descriptions of parse_date() and
parse_timetz() with ' ' or 'T' used to separate date and time parts.
"""
- idx = s.find('T')
- if idx < 0: idx = s.find(' ')
- if idx < 0:
- raise ValueError, 'time part of datetime missing: %s' % s
- return parse_date(s[:idx]) + parse_timetz(s[idx + 1:])
+ dt, tm = _split_datetime(s)
+ return parse_date(dt) + parse_timetz(tm)
def parse_interval(s):
@@ -216,7 +217,7 @@
hr, mn, sc = parse_time(s)
sc, micro = divmod(sc, 1.0)
micro = round(micro * 1000000)
- return time(hr, mn, sc, micro)
+ return time(hr, mn, int(sc), int(micro))
def _conv_timetz(s):
if s:
@@ -225,14 +226,14 @@
sc, micro = divmod(sc, 1.0)
micro = round(micro * 1000000)
if tz: tz = tzinfo(tz)
- return time(hr, mn, sc, micro, tz)
+ return time(hr, mn, int(sc), int(micro), tz)
def _conv_timestamp(s):
if s:
y, m, d, hr, mn, sc = parse_datetime(s)
sc, micro = divmod(sc, 1.0)
micro = round(micro * 1000000)
- return datetime(y, m, d, hr, mn, sc, micro)
+ return datetime(y, m, d, hr, mn, int(sc), int(micro))
def _conv_timestamptz(s):
if s:
@@ -241,7 +242,7 @@
sc, micro = divmod(sc, 1.0)
micro = round(micro * 1000000)
if tz: tz = tzinfo(tz)
- return datetime(y, m, d, hr, mn, sc, micro, tz)
+ return datetime(y, m, d, hr, mn, int(sc), int(micro), tz)
def _conv_interval(s):
if s:
@@ -286,15 +287,13 @@
it might be something like '1 month', which is a variable number of days.
"""
-
def _connection_factory(self):
"""Create a Psycopg DBI connection based on the DSN"""
conn_info = parseDSN(self.dsn)
conn_list = []
- for option in dsn2option_mapping:
- if conn_info[option]:
- conn_list.append('%s=%s' %(dsn2option_mapping[option],
- conn_info[option]))
+ for dsnname, optname in dsn2option_mapping.iteritems():
+ if conn_info[dsnname]:
+ conn_list.append('%s=%s' % (optname, conn_info[dsnname]))
conn_str = ' '.join(conn_list)
self._registerTypes()
return psycopg.connect(conn_str)
@@ -307,4 +306,3 @@
psycopg.register_type(TIMESTAMP)
psycopg.register_type(TIMESTAMPTZ)
psycopg.register_type(INTERVAL)
-
More information about the Zope3-Checkins
mailing list