diff -urN MySQL-python-1.2.1.orig/metadata.cfg MySQL-python-1.2.1.new/metadata.cfg --- MySQL-python-1.2.1.orig/metadata.cfg 2006-04-03 00:30:24.000000000 +0700 +++ MySQL-python-1.2.1.new/metadata.cfg 2006-09-22 11:28:17.000000000 +0700 @@ -51,6 +51,10 @@ MySQLdb.cursors MySQLdb.release MySQLdb.times + MySQLdb.pytimes + MySQLdb.mxdatetimes + MySQLdb.stringtimes + MySQLdb.sets MySQLdb.constants.CR MySQLdb.constants.FIELD_TYPE MySQLdb.constants.ER diff -urN MySQL-python-1.2.1.orig/MySQLdb/connections.py MySQL-python-1.2.1.new/MySQLdb/connections.py --- MySQL-python-1.2.1.orig/MySQLdb/connections.py 2006-04-03 00:16:49.000000000 +0700 +++ MySQL-python-1.2.1.new/MySQLdb/connections.py 2006-09-22 11:41:22.000000000 +0700 @@ -12,6 +12,13 @@ NotSupportedError, ProgrammingError import types, _mysql +def _dpop(d,k,default): + if d.has_key(k): + ret = d[k] + del d[k] + else: + ret = default + return ret def defaulterrorhandler(connection, cursor, errorclass, errorvalue): """ @@ -141,16 +148,16 @@ kwargs2['conv'] = dict([ (k, v) for k, v in conv.items() if type(k) is int ]) - self.cursorclass = kwargs2.pop('cursorclass', self.default_cursor) - charset = kwargs2.pop('charset', '') + self.cursorclass = _dpop(kwargs2, 'cursorclass', self.default_cursor) + charset = _dpop(kwargs2, 'charset', '') if charset: use_unicode = True else: use_unicode = False - use_unicode = kwargs2.pop('use_unicode', use_unicode) - sql_mode = kwargs2.pop('sql_mode', '') + use_unicode = _dpop(kwargs2, 'use_unicode', use_unicode) + sql_mode = _dpop(kwargs2, 'sql_mode', '') client_flag = kwargs.get('client_flag', 0) client_version = tuple([ int(n) for n in _mysql.get_client_info().split('.')[:2] ]) diff -urN MySQL-python-1.2.1.orig/MySQLdb/converters.py MySQL-python-1.2.1.new/MySQLdb/converters.py --- MySQL-python-1.2.1.orig/MySQLdb/converters.py 2006-04-03 00:16:49.000000000 +0700 +++ MySQL-python-1.2.1.new/MySQLdb/converters.py 2006-09-22 11:33:11.000000000 +0700 @@ -123,7 +123,7 @@ types.StringType: Thing2Literal, # default types.UnicodeType: Unicode2Str, types.ObjectType: Instance2Str, - types.BooleanType: Bool2Str, +# types.BooleanType: Bool2Str, DateTimeType: DateTime2literal, DateTimeDeltaType: DateTimeDelta2literal, Set: Set2Str, diff -urN MySQL-python-1.2.1.orig/MySQLdb/mxdatetimes.py MySQL-python-1.2.1.new/MySQLdb/mxdatetimes.py --- MySQL-python-1.2.1.orig/MySQLdb/mxdatetimes.py 1970-01-01 07:00:00.000000000 +0700 +++ MySQL-python-1.2.1.new/MySQLdb/mxdatetimes.py 2006-09-22 11:22:56.000000000 +0700 @@ -0,0 +1,50 @@ +"""Use mx.DateTime to handle date and time columns.""" + +from time import strftime, localtime + +try: + # new packaging + from mx.DateTime import Date, Time, Timestamp, ISO, \ + DateTimeType, DateTimeDeltaType +except ImportError: + # old packaging, deprecated + from DateTime import Date, Time, Timestamp, ISO, \ + DateTimeType, DateTimeDeltaType + +def DateFromTicks(ticks): + """Convert UNIX ticks into a mx.DateTime.Date.""" + return apply(Date, localtime(ticks)[:3]) + +def TimeFromTicks(ticks): + """Convert UNIX ticks into a mx.DateTime.Time.""" + return apply(Time, localtime(ticks)[3:6]) + +def TimestampFromTicks(ticks): + """Convert UNIX ticks into a mx.DateTime.Timestamp.""" + return apply(Timestamp, localtime(ticks)[:6]) + +def format_DATE(d): + """Format a DateTime object as an ISO date.""" + return d.strftime("%Y-%m-%d") + +def format_TIME(d): + """Format a DateTime object as a time value.""" + return d.strftime("%H:%M:%S") + +def format_TIMESTAMP(d): + """Format a DateTime object as an ISO timestamp.""" + return d.strftime("%Y-%m-%d %H:%M:%S") + +def DateTime_or_None(s): + try: return ISO.ParseDateTime(s) + except: return None + +def TimeDelta_or_None(s): + try: return ISO.ParseTimeDelta(s) + except: return None + +Time_or_None = TimeDelta_or_None + +def Date_or_None(s): + try: return ISO.ParseDate(s) + except: return None diff -urN MySQL-python-1.2.1.orig/MySQLdb/pytimes.py MySQL-python-1.2.1.new/MySQLdb/pytimes.py --- MySQL-python-1.2.1.orig/MySQLdb/pytimes.py 1970-01-01 07:00:00.000000000 +0700 +++ MySQL-python-1.2.1.new/MySQLdb/pytimes.py 2006-09-22 11:22:56.000000000 +0700 @@ -0,0 +1,72 @@ +"""Use Python datetime module to handle date and time columns.""" + +# datetime is only in Python 2.3 or newer, so it is safe to use +# string methods. However, have to use apply(func, args) instead +# of func(*args) because 1.5.2 will reject the syntax. + +from time import localtime +from datetime import date, datetime, time, timedelta + +Date = date +Time = time +Timestamp = datetime + +DateTimeDeltaType = type(timedelta) +DateTimeType = type(datetime) + +def DateFromTicks(ticks): + """Convert UNIX ticks into a date instance.""" + return apply(date, localtime(ticks)[:3]) + +def TimeFromTicks(ticks): + """Convert UNIX ticks into a time instance.""" + return apply(time, localtime(ticks)[3:6]) + +def TimestampFromTicks(ticks): + """Convert UNIX ticks into a datetime instance.""" + return apply(datetime, localtime(ticks)[:6]) + +format_TIME = format_DATE = str + +def format_TIMESTAMP(d): + return d.strftime("%Y-%m-%d %H:%M:%S") + +def DateTime_or_None(s): + if ' ' in s: + sep = ' ' + elif 'T' in s: + sep = 'T' + else: + return None + + try: + d, t = s.split(sep, 1) + return apply(datetime, tuple(map(int, d.split('-')+t.split(':')))) + except: + return None + +def TimeDelta_or_None(s): + from math import modf + try: + h, m, s = s.split(':') + td = timedelta(hours=int(h), minutes=int(m), seconds=int(s), + microseconds=int(modf(float(s)[0]))*1000000) + if h < 0: + return -td + else: + return td + except: + return None + +def Time_or_None(s): + from math import modf + try: + h, m, s = s.split(':') + return time(hour=int(h), minute=int(m), second=int(s), + microsecond=int(modf(float(s))[0])*1000000) + except: + return None + +def Date_or_None(s): + try: return apply(date, tuple(map(int, s.split('-',2)))) + except: return None diff -urN MySQL-python-1.2.1.orig/MySQLdb/sets.py MySQL-python-1.2.1.new/MySQLdb/sets.py --- MySQL-python-1.2.1.orig/MySQLdb/sets.py 1970-01-01 07:00:00.000000000 +0700 +++ MySQL-python-1.2.1.new/MySQLdb/sets.py 2006-09-22 11:28:07.000000000 +0700 @@ -0,0 +1,573 @@ +"""Classes to represent arbitrary sets (including sets of sets). + +This module implements sets using dictionaries whose values are +ignored. The usual operations (union, intersection, deletion, etc.) +are provided as both methods and operators. + +Important: sets are not sequences! While they support 'x in s', +'len(s)', and 'for x in s', none of those operations are unique for +sequences; for example, mappings support all three as well. The +characteristic operation for sequences is subscripting with small +integers: s[i], for i in range(len(s)). Sets don't support +subscripting at all. Also, sequences allow multiple occurrences and +their elements have a definite order; sets on the other hand don't +record multiple occurrences and don't remember the order of element +insertion (which is why they don't support s[i]). + +The following classes are provided: + +BaseSet -- All the operations common to both mutable and immutable + sets. This is an abstract class, not meant to be directly + instantiated. + +Set -- Mutable sets, subclass of BaseSet; not hashable. + +ImmutableSet -- Immutable sets, subclass of BaseSet; hashable. + An iterable argument is mandatory to create an ImmutableSet. + +_TemporarilyImmutableSet -- A wrapper around a Set, hashable, + giving the same hash value as the immutable set equivalent + would have. Do not use this class directly. + +Only hashable objects can be added to a Set. In particular, you cannot +really add a Set as an element to another Set; if you try, what is +actually added is an ImmutableSet built from it (it compares equal to +the one you tried adding). + +When you ask if `x in y' where x is a Set and y is a Set or +ImmutableSet, x is wrapped into a _TemporarilyImmutableSet z, and +what's tested is actually `z in y'. + +""" + +# Code history: +# +# - Greg V. Wilson wrote the first version, using a different approach +# to the mutable/immutable problem, and inheriting from dict. +# +# - Alex Martelli modified Greg's version to implement the current +# Set/ImmutableSet approach, and make the data an attribute. +# +# - Guido van Rossum rewrote much of the code, made some API changes, +# and cleaned up the docstrings. +# +# - Raymond Hettinger added a number of speedups and other +# improvements. + +from __future__ import generators +try: + from itertools import ifilter, ifilterfalse +except ImportError: + # Code to make the module run under Py2.2 + def ifilter(predicate, iterable): + if predicate is None: + def predicate(x): + return x + for x in iterable: + if predicate(x): + yield x + def ifilterfalse(predicate, iterable): + if predicate is None: + def predicate(x): + return x + for x in iterable: + if not predicate(x): + yield x + try: + True, False + except NameError: + True, False = (0==0, 0!=0) + +__all__ = ['BaseSet', 'Set', 'ImmutableSet'] + +class BaseSet(object): + """Common base class for mutable and immutable sets.""" + + __slots__ = ['_data'] + + # Constructor + + def __init__(self): + """This is an abstract class.""" + # Don't call this from a concrete subclass! + if self.__class__ is BaseSet: + raise TypeError, ("BaseSet is an abstract class. " + "Use Set or ImmutableSet.") + + # Standard protocols: __len__, __repr__, __str__, __iter__ + + def __len__(self): + """Return the number of elements of a set.""" + return len(self._data) + + def __repr__(self): + """Return string representation of a set. + + This looks like 'Set([])'. + """ + return self._repr() + + # __str__ is the same as __repr__ + __str__ = __repr__ + + def _repr(self, sorted=False): + elements = self._data.keys() + if sorted: + elements.sort() + return '%s(%r)' % (self.__class__.__name__, elements) + + def __iter__(self): + """Return an iterator over the elements or a set. + + This is the keys iterator for the underlying dict. + """ + return self._data.iterkeys() + + # Three-way comparison is not supported. However, because __eq__ is + # tried before __cmp__, if Set x == Set y, x.__eq__(y) returns True and + # then cmp(x, y) returns 0 (Python doesn't actually call __cmp__ in this + # case). + + def __cmp__(self, other): + raise TypeError, "can't compare sets using cmp()" + + # Equality comparisons using the underlying dicts. Mixed-type comparisons + # are allowed here, where Set == z for non-Set z always returns False, + # and Set != z always True. This allows expressions like "x in y" to + # give the expected result when y is a sequence of mixed types, not + # raising a pointless TypeError just because y contains a Set, or x is + # a Set and y contain's a non-set ("in" invokes only __eq__). + # Subtle: it would be nicer if __eq__ and __ne__ could return + # NotImplemented instead of True or False. Then the other comparand + # would get a chance to determine the result, and if the other comparand + # also returned NotImplemented then it would fall back to object address + # comparison (which would always return False for __eq__ and always + # True for __ne__). However, that doesn't work, because this type + # *also* implements __cmp__: if, e.g., __eq__ returns NotImplemented, + # Python tries __cmp__ next, and the __cmp__ here then raises TypeError. + + def __eq__(self, other): + if isinstance(other, BaseSet): + return self._data == other._data + else: + return False + + def __ne__(self, other): + if isinstance(other, BaseSet): + return self._data != other._data + else: + return True + + # Copying operations + + def copy(self): + """Return a shallow copy of a set.""" + result = self.__class__() + result._data.update(self._data) + return result + + __copy__ = copy # For the copy module + + def __deepcopy__(self, memo): + """Return a deep copy of a set; used by copy module.""" + # This pre-creates the result and inserts it in the memo + # early, in case the deep copy recurses into another reference + # to this same set. A set can't be an element of itself, but + # it can certainly contain an object that has a reference to + # itself. + from copy import deepcopy + result = self.__class__() + memo[id(self)] = result + data = result._data + value = True + for elt in self: + data[deepcopy(elt, memo)] = value + return result + + # Standard set operations: union, intersection, both differences. + # Each has an operator version (e.g. __or__, invoked with |) and a + # method version (e.g. union). + # Subtle: Each pair requires distinct code so that the outcome is + # correct when the type of other isn't suitable. For example, if + # we did "union = __or__" instead, then Set().union(3) would return + # NotImplemented instead of raising TypeError (albeit that *why* it + # raises TypeError as-is is also a bit subtle). + + def __or__(self, other): + """Return the union of two sets as a new set. + + (I.e. all elements that are in either set.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.union(other) + + def union(self, other): + """Return the union of two sets as a new set. + + (I.e. all elements that are in either set.) + """ + result = self.__class__(self) + result._update(other) + return result + + def __and__(self, other): + """Return the intersection of two sets as a new set. + + (I.e. all elements that are in both sets.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.intersection(other) + + def intersection(self, other): + """Return the intersection of two sets as a new set. + + (I.e. all elements that are in both sets.) + """ + if not isinstance(other, BaseSet): + other = Set(other) + if len(self) <= len(other): + little, big = self, other + else: + little, big = other, self + common = ifilter(big._data.has_key, little) + return self.__class__(common) + + def __xor__(self, other): + """Return the symmetric difference of two sets as a new set. + + (I.e. all elements that are in exactly one of the sets.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.symmetric_difference(other) + + def symmetric_difference(self, other): + """Return the symmetric difference of two sets as a new set. + + (I.e. all elements that are in exactly one of the sets.) + """ + result = self.__class__() + data = result._data + value = True + selfdata = self._data + try: + otherdata = other._data + except AttributeError: + otherdata = Set(other)._data + for elt in ifilterfalse(otherdata.has_key, selfdata): + data[elt] = value + for elt in ifilterfalse(selfdata.has_key, otherdata): + data[elt] = value + return result + + def __sub__(self, other): + """Return the difference of two sets as a new Set. + + (I.e. all elements that are in this set and not in the other.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.difference(other) + + def difference(self, other): + """Return the difference of two sets as a new Set. + + (I.e. all elements that are in this set and not in the other.) + """ + result = self.__class__() + data = result._data + try: + otherdata = other._data + except AttributeError: + otherdata = Set(other)._data + value = True + for elt in ifilterfalse(otherdata.has_key, self): + data[elt] = value + return result + + # Membership test + + def __contains__(self, element): + """Report whether an element is a member of a set. + + (Called in response to the expression `element in self'.) + """ + try: + return element in self._data + except TypeError: + transform = getattr(element, "__as_temporarily_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + return transform() in self._data + + # Subset and superset test + + def issubset(self, other): + """Report whether another set contains this set.""" + self._binary_sanity_check(other) + if len(self) > len(other): # Fast check for obvious cases + return False + for elt in ifilterfalse(other._data.has_key, self): + return False + return True + + def issuperset(self, other): + """Report whether this set contains another set.""" + self._binary_sanity_check(other) + if len(self) < len(other): # Fast check for obvious cases + return False + for elt in ifilterfalse(self._data.has_key, other): + return False + return True + + # Inequality comparisons using the is-subset relation. + __le__ = issubset + __ge__ = issuperset + + def __lt__(self, other): + self._binary_sanity_check(other) + return len(self) < len(other) and self.issubset(other) + + def __gt__(self, other): + self._binary_sanity_check(other) + return len(self) > len(other) and self.issuperset(other) + + # Assorted helpers + + def _binary_sanity_check(self, other): + # Check that the other argument to a binary operation is also + # a set, raising a TypeError otherwise. + if not isinstance(other, BaseSet): + raise TypeError, "Binary operation only permitted between sets" + + def _compute_hash(self): + # Calculate hash code for a set by xor'ing the hash codes of + # the elements. This ensures that the hash code does not depend + # on the order in which elements are added to the set. This is + # not called __hash__ because a BaseSet should not be hashable; + # only an ImmutableSet is hashable. + result = 0 + for elt in self: + result ^= hash(elt) + return result + + def _update(self, iterable): + # The main loop for update() and the subclass __init__() methods. + data = self._data + + # Use the fast update() method when a dictionary is available. + if isinstance(iterable, BaseSet): + data.update(iterable._data) + return + + value = True + + if type(iterable) in (list, tuple, xrange): + # Optimized: we know that __iter__() and next() can't + # raise TypeError, so we can move 'try:' out of the loop. + it = iter(iterable) + while True: + try: + for element in it: + data[element] = value + return + except TypeError: + transform = getattr(element, "__as_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + data[transform()] = value + else: + # Safe: only catch TypeError where intended + for element in iterable: + try: + data[element] = value + except TypeError: + transform = getattr(element, "__as_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + data[transform()] = value + + +class ImmutableSet(BaseSet): + """Immutable set class.""" + + __slots__ = ['_hashcode'] + + # BaseSet + hashing + + def __init__(self, iterable=None): + """Construct an immutable set from an optional iterable.""" + self._hashcode = None + self._data = {} + if iterable is not None: + self._update(iterable) + + def __hash__(self): + if self._hashcode is None: + self._hashcode = self._compute_hash() + return self._hashcode + + def __getstate__(self): + return self._data, self._hashcode + + def __setstate__(self, state): + self._data, self._hashcode = state + +class Set(BaseSet): + """ Mutable set class.""" + + __slots__ = [] + + # BaseSet + operations requiring mutability; no hashing + + def __init__(self, iterable=None): + """Construct a set from an optional iterable.""" + self._data = {} + if iterable is not None: + self._update(iterable) + + def __getstate__(self): + # getstate's results are ignored if it is not + return self._data, + + def __setstate__(self, data): + self._data, = data + + def __hash__(self): + """A Set cannot be hashed.""" + # We inherit object.__hash__, so we must deny this explicitly + raise TypeError, "Can't hash a Set, only an ImmutableSet." + + # In-place union, intersection, differences. + # Subtle: The xyz_update() functions deliberately return None, + # as do all mutating operations on built-in container types. + # The __xyz__ spellings have to return self, though. + + def __ior__(self, other): + """Update a set with the union of itself and another.""" + self._binary_sanity_check(other) + self._data.update(other._data) + return self + + def union_update(self, other): + """Update a set with the union of itself and another.""" + self._update(other) + + def __iand__(self, other): + """Update a set with the intersection of itself and another.""" + self._binary_sanity_check(other) + self._data = (self & other)._data + return self + + def intersection_update(self, other): + """Update a set with the intersection of itself and another.""" + if isinstance(other, BaseSet): + self &= other + else: + self._data = (self.intersection(other))._data + + def __ixor__(self, other): + """Update a set with the symmetric difference of itself and another."""+ self._binary_sanity_check(other) + self.symmetric_difference_update(other) + return self + + def symmetric_difference_update(self, other): + """Update a set with the symmetric difference of itself and another."""+ data = self._data + value = True + if not isinstance(other, BaseSet): + other = Set(other) + for elt in other: + if elt in data: + del data[elt] + else: + data[elt] = value + + def __isub__(self, other): + """Remove all elements of another set from this set.""" + self._binary_sanity_check(other) + self.difference_update(other) + return self + + def difference_update(self, other): + """Remove all elements of another set from this set.""" + data = self._data + if not isinstance(other, BaseSet): + other = Set(other) + for elt in ifilter(data.has_key, other): + del data[elt] + + # Python dict-like mass mutations: update, clear + + def update(self, iterable): + """Add all values from an iterable (such as a list or file).""" + self._update(iterable) + + def clear(self): + """Remove all elements from this set.""" + self._data.clear() + + # Single-element mutations: add, remove, discard + + def add(self, element): + """Add an element to a set. + + This has no effect if the element is already present. + """ + try: + self._data[element] = True + except TypeError: + transform = getattr(element, "__as_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + self._data[transform()] = True + + def remove(self, element): + """Remove an element from a set; it must be a member. + + If the element is not a member, raise a KeyError. + """ + try: + del self._data[element] + except TypeError: + transform = getattr(element, "__as_temporarily_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + del self._data[transform()] + + def discard(self, element): + """Remove an element from a set if it is a member. + + If the element is not a member, do nothing. + """ + try: + self.remove(element) + except KeyError: + pass + + def pop(self): + """Remove and return an arbitrary set element.""" + return self._data.popitem()[0] + + def __as_immutable__(self): + # Return a copy of self as an immutable set + return ImmutableSet(self) + + def __as_temporarily_immutable__(self): + # Return self wrapped in a temporarily immutable set + return _TemporarilyImmutableSet(self) + + +class _TemporarilyImmutableSet(BaseSet): + # Wrap a mutable set as if it was temporarily immutable. + # This only supplies hashing and equality comparisons. + + def __init__(self, set): + self._set = set + self._data = set._data # Needed by ImmutableSet.__eq__() + + def __hash__(self): + return self._set._compute_hash() diff -urN MySQL-python-1.2.1.orig/MySQLdb/stringtimes.py MySQL-python-1.2.1.new/MySQLdb/stringtimes.py --- MySQL-python-1.2.1.orig/MySQLdb/stringtimes.py 1970-01-01 07:00:00.000000000 +0700 +++ MySQL-python-1.2.1.new/MySQLdb/stringtimes.py 2006-09-22 11:22:56.000000000 +0700 @@ -0,0 +1,38 @@ +"""Use strings to handle date and time columns as a last resort.""" + +from time import strftime, localtime + +DateTimeDeltaType = "DateTimeDeltaType" +DateTimeType = "DateTimeType" + +def Date(year, month, day): + """Construct an ISO date string.""" + return "%04d-%02d-%02d" % (year, month, day) + +def Time(hour, min, sec): + """Construct a TIME string.""" + return "%02d:%02d:%02d" % (hour, min, sec) + +def Timestamp(year, month, day, hour, min, sec): + """Construct an ISO timestamp.""" + return "%04d-%02d-%02d %02d:%02d:%02d" % \ + (year, month, day, hour, min, sec) + +def DateFromTicks(ticks): + """Convert UNIX ticks to ISO date format.""" + return strftime("%Y-%m-%d", localtime(ticks)) + +def TimeFromTicks(ticks): + """Convert UNIX ticks to time format.""" + return strftime("%H:%M:%S", localtime(ticks)) + +def TimestampFromTicks(ticks): + """Convert UNIX ticks to ISO timestamp format.""" + return strftime("%Y-%m-%d %H:%M:%S", localtime(ticks)) + +def format_DATE(d): + """Format a date as a date (does nothing, you don't have mx.DateTime)""" + return d + +format_TIME = format_TIMESTAMP = format_DATE +Time_or_None = TimeDelta_or_None = Date_or_None = DateTime_or_None = format_DATE diff -urN MySQL-python-1.2.1.orig/MySQLdb/times.py MySQL-python-1.2.1.new/MySQLdb/times.py --- MySQL-python-1.2.1.orig/MySQLdb/times.py 2006-04-03 00:16:49.000000000 +0700 +++ MySQL-python-1.2.1.new/MySQLdb/times.py 2006-09-22 11:22:58.000000000 +0700 @@ -1,78 +1,20 @@ """times module This module provides some Date and Time classes for dealing with MySQL data. +""" -Use Python datetime module to handle date and time columns.""" - -from time import localtime -from datetime import date, datetime, time, timedelta from _mysql import string_literal -Date = date -Time = time -TimeDelta = timedelta -Timestamp = datetime - -DateTimeDeltaType = timedelta -DateTimeType = datetime - -def DateFromTicks(ticks): - """Convert UNIX ticks into a date instance.""" - return date(*localtime(ticks)[:3]) - -def TimeFromTicks(ticks): - """Convert UNIX ticks into a time instance.""" - return time(*localtime(ticks)[3:6]) - -def TimestampFromTicks(ticks): - """Convert UNIX ticks into a datetime instance.""" - return datetime(*localtime(ticks)[:6]) - -format_TIME = format_DATE = str - -def format_TIMESTAMP(d): - return d.strftime("%Y-%m-%d %H:%M:%S") - - -def DateTime_or_None(s): - if ' ' in s: - sep = ' ' - elif 'T' in s: - sep = 'T' - else: - return Date_or_None(s) - - try: - d, t = s.split(sep, 1) - return datetime(*[ int(x) for x in d.split('-')+t.split(':') ]) - except: - return Date_or_None(s) - -def TimeDelta_or_None(s): - from math import modf - try: - h, m, s = s.split(':') - td = timedelta(hours=int(h), minutes=int(m), seconds=int(float(s)), - microseconds=int(modf(float(s))[0]*1000000)) - if h < 0: - return -td - else: - return td - except: - return None +try: + from mxdatetimes import * -def Time_or_None(s): - from math import modf +except ImportError: try: - h, m, s = s.split(':') - return time(hour=int(h), minute=int(m), second=int(float(s)), - microsecond=int(modf(float(s))[0]*1000000)) - except: - return None + from pytimes import * -def Date_or_None(s): - try: return date(*[ int(x) for x in s.split('-',2)]) - except: return None + except ImportError: + # no DateTime? We'll muddle through somehow. + from stringtimes import * def DateTime2literal(d, c): """Format a DateTime object as an ISO timestamp.""" @@ -84,10 +26,8 @@ def mysql_timestamp_converter(s): """Convert a MySQL TIMESTAMP to a Timestamp object.""" - # MySQL>4.1 returns TIMESTAMP in the same format as DATETIME - if s[4] == '-': return DateTime_or_None(s) s = s + "0"*(14-len(s)) # padding parts = map(int, filter(None, (s[:4],s[4:6],s[6:8], s[8:10],s[10:12],s[12:14]))) - try: return Timestamp(*parts) + try: return apply(Timestamp, tuple(parts)) except: return None diff -urN MySQL-python-1.2.1.orig/setup.py MySQL-python-1.2.1.new/setup.py --- MySQL-python-1.2.1.orig/setup.py 2006-04-03 00:16:50.000000000 +0700 +++ MySQL-python-1.2.1.new/setup.py 2006-09-22 11:22:14.000000000 +0700 @@ -6,16 +6,22 @@ import sys from distutils.core import setup from distutils.extension import Extension -from ConfigParser import SafeConfigParser +from ConfigParser import ConfigParser -if sys.version_info < (2, 3): - raise Abort, "Python-2.3 or newer is required" +#if sys.version_info < (2, 3): +# raise Abort, "Python-2.3 or newer is required" -config = SafeConfigParser() +def config_items(config,section): + l = [] + for k in config.options(section): + l.append((k,config.get(section, k))) + return l + +config = ConfigParser() config.read(['metadata.cfg', 'site.cfg']) -metadata = dict(config.items('metadata')) -options = dict(config.items('options')) +metadata = dict(config_items(config, 'metadata')) +options = dict(config_items(config, 'options')) metadata['py_modules'] = filter(None, metadata['py_modules'].split('\n')) metadata['classifiers'] = filter(None, metadata['classifiers'].split('\n')) @@ -93,7 +99,10 @@ del metadata['version_info'] -ext_mysql_metadata = dict( +def kwdict(**kw): + return kw + +ext_mysql_metadata = kwdict( name="_mysql", include_dirs=include_dirs, library_dirs=library_dirs,