From: Billy G. A. <bal...@us...> - 2002-11-03 19:48:52
|
Update of /cvsroot/pypgsql/pypgsql/pyPgSQL In directory usw-pr-cvs1:/tmp/cvs-serv30692/pyPgSQL Modified Files: PgSQL.py Log Message: 02NOV2002 bga - Added the PgArray class. This is a wrapper around a Python list and is used for all PostgreSQL arrays. This change was made so that lists and tuples no longer have a special mean- ing in the Cursor.execute() method. - Changed the quoting methods defined in the various classes defining PostgreSQL support types to __quote__. Index: PgSQL.py =================================================================== RCS file: /cvsroot/pypgsql/pypgsql/pyPgSQL/PgSQL.py,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** PgSQL.py 1 Nov 2002 04:34:16 -0000 1.20 --- PgSQL.py 3 Nov 2002 19:48:48 -0000 1.21 *************** *** 30,33 **** --- 30,40 ---- # Date Ini Description | # --------- --- ------------------------------------------------------- | + # 02NOV2002 bga - Added the PgArray class. This is a wrapper around a | + # Python list and is used for all PostgreSQL arrays. | + # This change was made so that lists and tuples no | + # longer have a special meaning in the Cursor.execute() | + # method. | + # - Changed the quoting methods defined in the various | + # classes defining PostgreSQL support types to __quote__| # 27OCT2002 gh - Merged the Unicode patch. Closes #484468. | # - Convert ROWID to PgInt8 instead of PgInt4 (the origi- | *************** *** 374,377 **** --- 381,385 ---- from types import * from sys import getrefcount, getdefaultencoding + import sys import copy import string *************** *** 574,578 **** class LeaveLoopException(Exception): pass ! lst = [] s = s[1:-1] # drop '{' and '}' at start/end --- 582,621 ---- class LeaveLoopException(Exception): pass ! # Get rid of the escaping in the array string ! def convertEscapes(s): ! # If we're called with a list in a multi-dimensional ! # array, simply return the list. We only convert the ! # elements of the multi-dimensional array. ! if type(s) is ListType: ! return s ! ! schars = [] ! escape = 0 ! octdigits = [] ! ! for char in s: ! if char == '\\': ! escape += 1 ! if escape == 2: ! schars.append(char) ! escape = 0 ! else: ! if escape: ! if char in string.digits: ! octdigits.append(char) ! else: ! if octdigits != []: ! curchar = chr(int(octdigits[0]) * 64) + \ ! chr(int(octdigits[1]) * 8) + \ ! chr(int(octdigits[2])) ! schars.append(curchar) ! octdigits = [] ! schars.append(char) ! else: ! schars.append(char) ! escape = 0 ! return "".join(schars) ! ! lst = PgArray() s = s[1:-1] # drop '{' and '}' at start/end *************** *** 599,603 **** escape = 0 end_quote_pos += 1 ! lst.append(s[pos + 1:end_quote_pos]) # Skip quote char and next comma --- 642,646 ---- escape = 0 end_quote_pos += 1 ! lst.append(convertEscapes(s[pos + 1:end_quote_pos])) # Skip quote char and next comma *************** *** 618,622 **** if next_comma_pos >= len(s): # This is the last array element. ! lst.append(s[pos:]) raise LeaveLoopException --- 661,665 ---- if next_comma_pos >= len(s): # This is the last array element. ! lst.append(convertEscapes(s[pos:])) raise LeaveLoopException *************** *** 635,639 **** lst.append(self.parseArray(curelem[1:-1])) else: ! lst.append(curelem) pos = next_comma_pos + 1 if s[pos] == ',': --- 678,682 ---- lst.append(self.parseArray(curelem[1:-1])) else: ! lst.append(convertEscapes(curelem)) pos = next_comma_pos + 1 if s[pos] == ',': *************** *** 680,719 **** pass ! # Get rid of the escaping in the array string ! def convertEscapes(s): ! # If we're called with a list in a multi-dimensional ! # array, simply return the list. We only convert the ! # elements of the multi-dimensional array. ! if type(s) is ListType: ! return s ! ! schars = [] ! escape = 0 ! octdigits = [] ! ! for char in s: ! if char == '\\': ! escape += 1 ! if escape == 2: ! schars.append(char) ! escape = 0 ! else: ! if escape: ! if char in string.digits: ! octdigits.append(char) ! else: ! if octdigits != []: ! curchar = chr(int(octdigits[0]) * 64) + \ ! chr(int(octdigits[1]) * 8) + \ ! chr(int(octdigits[2])) ! schars.append(curchar) ! octdigits = [] ! schars.append(char) ! else: ! schars.append(char) ! escape = 0 ! return "".join(schars) ! ! lst = map(convertEscapes, lst) return lst --- 723,727 ---- pass ! #lst = map(convertEscapes, lst) return lst *************** *** 732,736 **** if _ia: ! # Convert string representation of the array into list. _list = self.parseArray(value) return self.handleArray(colinfo, _list) --- 740,744 ---- if _ia: ! # Convert string representation of the array into PgArray object. _list = self.parseArray(value) return self.handleArray(colinfo, _list) *************** *** 794,797 **** --- 802,806 ---- def handleArray(self, colinfo, lst): # If the list is empty, just return the empty list. + if len(lst) == 0: return lst *************** *** 802,806 **** for _i in range(len(lst)): ! if type(lst[_i]) is ListType: lst[_i] = self.handleArray(colinfo, lst[_i]) elif _ftv == PG_INT4 or _ftv == ROWID: --- 811,815 ---- for _i in range(len(lst)): ! if isinstance(lst[_i], PgArray): lst[_i] = self.handleArray(colinfo, lst[_i]) elif _ftv == PG_INT4 or _ftv == ROWID: *************** *** 909,913 **** # NOTE: A PgOther object will use the PgQuoteString() function in libpq. ! def _quote(self, forArray=0): if self.value: return PgQuoteString(self.value, forArray) --- 918,922 ---- # NOTE: A PgOther object will use the PgQuoteString() function in libpq. ! def __quote__(self, forArray=0): if self.value: return PgQuoteString(self.value, forArray) *************** *** 915,918 **** --- 924,1091 ---- #-----------------------------------------------------------------------+ + # Name: PgArray | + # | + # Description: A Python wrapper class for PostgreSQL arrays. | + # It is used so that the list type can be used as an arg- | + # ument to Connection.execute() without being treated as | + # a PostgreSQL array. | + #-----------------------------------------------------------------------+ + + class PgArray: + def __init__(self, value=None): + if value is None: + self.value = [] + return + + if type(value) is not ListType and not isinstance(value, PgArray): + raise TypeError, "argument must be a list or a PgArray." + + # We have to insure that nested mutable sequences (list and PgArray) + # get copied. + for i in range(len(value)): + if type(value[i]) is ListType or isinstance(value[i], PgArray): + value[i] = PgArray(value[i][:]) + + self.value = value + + # Define the methods used + def append(self, item): + if type(item) is ListType: + item = PgArray(item) + self.value.append(item) + + def count(self, item): + return self.value.count(item) + + def extend(self, item): + if type(item) is ListType: + item = PgArray(item) + self.value.extend(item) + + def index(self, item): + return self.value.index(item) + + def insert(self, key, item): + if type(item) is ListType: + item = PgArray(item) + self.value.insert(key, item) + + def pop(self, key=-1): + return self.value.pop(key) + + def remove(self, item): + self.value.remove(item) + + def reverse(self): + self.value.reverse() + + def sort(self, compfunc=None): + if compfunc is None: + self.value.sort() + else: + self.value.sort(compfunc) + + def __cmp__(self, other): + if not isinstance(other, PgArray): + return cmp(id(self), id(other)) + + # PgArray objects are considered equal if: + # 1. The lengh of the PgArray objects are equal and + # 2. Each item[k] in the PgArray objects are equal. + + res = cmp(len(self), len(other)) + if res != 0: + return res + + for i in range(len(self.value)): + res = cmp(self.value[i], other.value[i]) + if res != 0: + return res + + return 0 + + def __len__(self): + return len(self.value) + + def __getitem__(self, index): + if type(index) is SliceType: + if index.step is None: + return PgArray(self.value[index.start:index.stop]) + else: + return PgArray(self.value[index.start:index.stop:index.step]) + + return self.value[index]; + + def __setitem__(self, index, item): + if type(item) is ListType: + item = PgArray(item) + + if type(index) is SliceType: + if index.step is None: + self.value[index.start:index.stop] = item + else: + self.value[index.start:index.stop:index.step] = item + else: + self.value[index] = item + + def __delitem__(self, index): + if type(index) is SliceType: + if index.step is None: + del self.value[index.start:index.stop] + else: + del self.value[index.start:index.stop:index.step] + else: + del self.value[index]; + + def __contains__(self, item): + return (item in self.value) + + if sys.version_info < (2, 0): + # They won't be defined if version is at least 2.0 final + def __getslice__(self, i, j): + return PgArray(self.value[max(0, i):max(0, j)]) + + def __setslice__(self, i, j, seq): + if type(seq) is ListType: + seq = PgArray(seq) + self.value[max(0, i):max(0, j)] = seq.value + + def __delslice__(self, i, j): + del self.value[max(0, i):max(0, j)] + + def __add__(self, other): + return PgArray((self.value + other)) + + def __radd__(self, other): + return PgArray(other + self.value) + + def __iadd__(self, other): + value = value + other + return self + + def __mul__(self, other): + return PgArray((self.value * other)) + + def __rmul__(self, other): + return PgArray((self.value * other)) + + def __imul__(self, other): + value = value * other + return self + + def __repr__(self): + return repr(self.value) + + def __str__(self): + return str(self.value) + + # NOTE: A PgArray object will use the _handleArray() function to quote + # itself. + def __quote__(self, forArray=0): + if self.value: + return _handleArray(self.value) + return 'NULL' + + #-----------------------------------------------------------------------+ # Name: PgBytea | # | *************** *** 959,963 **** # NOTE: A PgBytea object will use the PgQuoteBytea() function in libpq ! def _quote(self, forArray=0): if self.value: return PgQuoteBytea(self.value, forArray) --- 1132,1136 ---- # NOTE: A PgBytea object will use the PgQuoteBytea() function in libpq ! def __quote__(self, forArray=0): if self.value: return PgQuoteBytea(self.value, forArray) *************** *** 1330,1334 **** return -self ! def _quote(self, forArray=0): if self.__v: if forArray: --- 1503,1507 ---- return -self ! def __quote__(self, forArray=0): if self.__v: if forArray: *************** *** 1468,1472 **** return '$%s' % _s ! def _quote(self, forArray=0): if self.value: if forArray: --- 1641,1645 ---- return '$%s' % _s ! def __quote__(self, forArray=0): if self.value: if forArray: *************** *** 1631,1635 **** return str(self.value) ! def _quote(self, forArray=0): if self.value is not None: s = str(self.value) --- 1804,1808 ---- return str(self.value) ! def __quote__(self, forArray=0): if self.value is not None: s = str(self.value) *************** *** 1797,1802 **** # | # connect() -- connect to a PostgreSQL database. | ! # _handleArray() -- Transform a Python list into a string repre- | ! # senting a PostgreSQL array. | # _quote() -- Transform a Python object representing a | # PostgreSQL type into a appropiately quoted | --- 1970,1975 ---- # | # connect() -- connect to a PostgreSQL database. | ! # _handleArray() -- Transform a PgArray class into a string rep- | ! # resenting a PostgreSQL array. | # _quote() -- Transform a Python object representing a | # PostgreSQL type into a appropiately quoted | *************** *** 1872,1878 **** if _i is None: _j += "," ! elif type(_i) in [ListType, TupleType]: ! _v = list(_i) ! _j = _j + _handleArray(_v)[1:-1] + ',' elif hasattr(_i, '_quote'): _j = '%s%s,' % (_j, _i._quote(1)) --- 2045,2050 ---- if _i is None: _j += "," ! elif isinstance(_i, PgArray): ! _j = _j + _handleArray(_i)[1:-1] + ',' elif hasattr(_i, '_quote'): _j = '%s%s,' % (_j, _i._quote(1)) *************** *** 1899,1907 **** return 'NULL' ! if type(value) in [ListType, TupleType]: ! return _handleArray(list(value)) ! ! if hasattr(value, '_quote'): ! return value._quote() if type(value) in [DateTimeType, DateTimeDeltaType]: --- 2071,2076 ---- return 'NULL' ! if hasattr(value, '__quote__'): ! return value.__quote__() if type(value) in [DateTimeType, DateTimeDeltaType]: |