[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gpsd-dev] [PATCH 2/4] Fixes leapseconds.py for Python 3.
From: |
Fred Wright |
Subject: |
[gpsd-dev] [PATCH 2/4] Fixes leapseconds.py for Python 3. |
Date: |
Sat, 9 Apr 2016 19:57:14 -0700 |
This fixes two Python 3 issues with leapsecond.py:
1) The urllib module is subdivided in Python 3. Only the 'request'
submodule is needed here. Either that or the Python 2 urllib is now
imported as 'urlrequest'.
2) The data returned by urlopen() is 'bytes' in Python 3, requiring
the polystr transformation to be usable as a string.
Also, the (duplicate) isotime() definition here has been updated to
match the version in gps/misc.py. It is still duplicated to avoid a
dependency on the latter, as is the needed portion of the polystr
code.
TESTED:
Ran "scons build-all check". Also ran "leapsecond.py -f" with all six
supported Python versions, and verified that the result matches the
existing leapseconds.cache. Did *not* test the updated retrieve()
function, but it's not used anywhere.
---
leapsecond.py | 88 +++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 61 insertions(+), 27 deletions(-)
diff --git a/leapsecond.py b/leapsecond.py
index 3bd13e2..e43f353 100755
--- a/leapsecond.py
+++ b/leapsecond.py
@@ -46,13 +46,69 @@ BSD terms apply: see the file COPYING in the distribution
root for details.
# This code runs under both Python 2 and Python 3. Preserve this property!
from __future__ import print_function, division
-import os, urllib, re, random, time, calendar, math, sys, signal
+import os, re, random, time, calendar, math, sys, signal
+
+try:
+ import urllib.request as urlrequest # Python 3
+except ImportError:
+ import urllib as urlrequest # Python 2
# Set a socket timeout for slow servers
import socket
socket.setdefaulttimeout(30)
del socket
+# *** Duplicate some code from gps.misc to avoid a dependency ***
+
+# Determine a single class for testing "stringness"
+try:
+ STR_CLASS = basestring # Base class for 'str' and 'unicode' in Python 2
+except NameError:
+ STR_CLASS = str # In Python 3, 'str' is the base class
+
+# Polymorphic str/bytes handling
+
+BINARY_ENCODING = 'latin-1'
+
+if bytes is str: # In Python 2 these functions can be null transformations
+
+ polystr = str
+
+else: # Otherwise we do something real
+
+ def polystr(o):
+ "Convert bytes or str to str with proper encoding."
+ if isinstance(o, str):
+ return o
+ if isinstance(o, bytes):
+ return str(o, encoding=BINARY_ENCODING)
+ raise ValueError
+
+
+def isotime(s):
+ "Convert timestamps in ISO8661 format to and from Unix time including
optional fractional seconds."
+ if isinstance(s, int):
+ return time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(s))
+ elif isinstance(s, float):
+ date = int(s)
+ msec = s - date
+ date = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(s))
+ return date + "." + repr(msec)[3:]
+ elif isinstance(s, STR_CLASS):
+ if s[-1] == "Z":
+ s = s[:-1]
+ if "." in s:
+ (date, msec) = s.split(".")
+ else:
+ date = s
+ msec = "0"
+ # Note: no leap-second correction!
+ return calendar.timegm(time.strptime(date, "%Y-%m-%dT%H:%M:%S")) +
float("0." + msec)
+ else:
+ raise TypeError
+
+# *** End of duplicated code ***
+
verbose = 0
__locations = [
@@ -87,29 +143,6 @@ def gps_rollovers(t):
return (t - GPS_EPOCH) // SECS_PER_WEEK // ROLLOVER
-def isotime(s):
- "Convert timestamps in ISO8661 format to and from Unix time including
optional fractional seconds."
- if type(s) == type(1):
- return time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(s))
- elif type(s) == type(1.0):
- date = int(s)
- msec = s - date
- date = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(s))
- return date + "." + repr(msec)[3:]
- elif type(s) == type("") or type(s) == type(""):
- if s[-1] == "Z":
- s = s[:-1]
- if "." in s:
- (date, msec) = s.split(".")
- else:
- date = s
- msec = "0"
- # Note: no leap-second correction!
- return calendar.timegm(time.strptime(date, "%Y-%m-%dT%H:%M:%S")) +
float("0." + msec)
- else:
- raise TypeError
-
-
def retrieve():
"Retrieve current leap-second from Web sources."
random.shuffle(__locations) # To spread the load
@@ -118,8 +151,8 @@ def retrieve():
if os.path.exists(url):
ifp = open(url)
else:
- ifp = urllib.urlopen(url)
- txt = ifp.read()
+ ifp = urlrequest.urlopen(url)
+ txt = polystr(ifp.read())
ifp.close()
if verbose:
sys.stderr.write("%s\n" % txt)
@@ -163,7 +196,7 @@ def save_leapseconds(outfile):
for (_, _, _, _, url) in __locations:
skip = True
try:
- fetchobj = urllib.urlopen(url)
+ fetchobj = urlrequest.urlopen(url)
except IOError:
sys.stderr.write("Fetch from %s failed.\n" % url)
continue
@@ -171,6 +204,7 @@ def save_leapseconds(outfile):
# always integrally one second and every increment is listed here
fp = open(outfile, "w")
for line in fetchobj:
+ line = polystr(line)
if verbose:
sys.stderr.write("%s\n" % line[:-1])
if line.startswith(" 1980"):
--
2.8.1
- [gpsd-dev] [PATCH 12/12] Removes redundant polystr/polybytes defs from client.py., (continued)
- Re: [gpsd-dev] Python 3 Updates, Gary E. Miller, 2016/04/08
- Re: [gpsd-dev] Python 3 Updates, Eric S. Raymond, 2016/04/09
- Re: [gpsd-dev] Python 3 Updates, Fred Wright, 2016/04/09
- Re: [gpsd-dev] Python 3 Updates, Fred Wright, 2016/04/10
- [gpsd-dev] [PATCH] Fixes devtools/*.py for Python 3., Fred Wright, 2016/04/10