Port swift.common.utils.Timestamp to Python 3

* Fix Timestamp.isoformat(): on Python 3, round manually to use the
  same rounding method than Python 2.
* Use @functoos.total_ordering on Timestamp instead of the __cmp__()
  special method. On Python 3, the __cmp__() method is no more used,
  and other special methods must be defined (__eq__, __lt__, etc.).
  Only define __eq__() and __lt__() methods but use
  @functools.total_ordering to generate other methods.
* Fix also a Python 3 issues in swift.common.swob._datetime_property:
  replace (float, int, long) with (float,) + six.integer_types. The
  long type was renamed to int in Python 3.

Change-Id: Id26777ac2c780316ff10ef7d954c48cc1fd480b5
This commit is contained in:
Victor Stinner 2015-10-19 16:31:12 +02:00
parent 0e91aa8368
commit 9c403d5e1b
2 changed files with 26 additions and 10 deletions

View File

@ -164,7 +164,7 @@ def _datetime_property(header):
return None return None
def setter(self, value): def setter(self, value):
if isinstance(value, (float, int, long)): if isinstance(value, (float,) + six.integer_types):
self.headers[header] = time.strftime( self.headers[header] = time.strftime(
"%a, %d %b %Y %H:%M:%S GMT", time.gmtime(value)) "%a, %d %b %Y %H:%M:%S GMT", time.gmtime(value))
elif isinstance(value, datetime): elif isinstance(value, datetime):

View File

@ -22,6 +22,7 @@ import fcntl
import grp import grp
import hmac import hmac
import json import json
import math
import operator import operator
import os import os
import pwd import pwd
@ -702,6 +703,7 @@ PRECISION = 1e-5
FORCE_INTERNAL = False # or True FORCE_INTERNAL = False # or True
@functools.total_ordering
class Timestamp(object): class Timestamp(object):
""" """
Internal Representation of Swift Time. Internal Representation of Swift Time.
@ -814,8 +816,27 @@ class Timestamp(object):
@property @property
def isoformat(self): def isoformat(self):
isoformat = datetime.datetime.utcfromtimestamp( t = float(self.normal)
float(self.normal)).isoformat() if six.PY3:
# On Python 3, round manually using ROUND_HALF_EVEN rounding
# method, to use the same rounding method than Python 2. Python 3
# used a different rounding method, but Python 3.4.4 and 3.5.1 use
# again ROUND_HALF_EVEN as Python 2.
# See https://bugs.python.org/issue23517
frac, t = math.modf(t)
us = round(frac * 1e6)
if us >= 1000000:
t += 1
us -= 1000000
elif us < 0:
t -= 1
us += 1000000
dt = datetime.datetime.utcfromtimestamp(t)
dt = dt.replace(microsecond=us)
else:
dt = datetime.datetime.utcfromtimestamp(t)
isoformat = dt.isoformat()
# python isoformat() doesn't include msecs when zero # python isoformat() doesn't include msecs when zero
if len(isoformat) < len("1970-01-01T00:00:00.000000"): if len(isoformat) < len("1970-01-01T00:00:00.000000"):
isoformat += ".000000" isoformat += ".000000"
@ -826,15 +847,10 @@ class Timestamp(object):
other = Timestamp(other) other = Timestamp(other)
return self.internal == other.internal return self.internal == other.internal
def __ne__(self, other): def __lt__(self, other):
if not isinstance(other, Timestamp): if not isinstance(other, Timestamp):
other = Timestamp(other) other = Timestamp(other)
return self.internal != other.internal return self.internal < other.internal
def __cmp__(self, other):
if not isinstance(other, Timestamp):
other = Timestamp(other)
return cmp(self.internal, other.internal)
def __hash__(self): def __hash__(self):
return hash(self.internal) return hash(self.internal)