changeset 19381:06eae3ac1c19

11522 illumos-gate has some runtime dependencies on Python 2.7 12192 python3 modules treat strings incorrectly Reviewed by: Andrew Stormont <andyjstormont@gmail.com> Reviewed by: Andy Fiddaman <omnios@citrus-it.co.uk> Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> Reviewed by: Toomas Soome <tsoome@me.com> Approved by: Dan McDonald <danmcd@joyent.com>
author Alexander Pyhalov <apyhalov@gmail.com>
date Tue, 14 Jan 2020 21:23:25 +0300
parents b7b867e9322a
children 1bfec601f870
files usr/src/Makefile.master usr/src/cmd/pyzfs/pyzfs.py usr/src/lib/pylibbe/common/libbe_py.c usr/src/lib/pyzfs/common/ioctl.c usr/src/test/test-runner/cmd/run
diffstat 5 files changed, 50 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/Makefile.master	Tue Nov 12 15:47:35 2019 +0000
+++ b/usr/src/Makefile.master	Tue Jan 14 21:23:25 2020 +0300
@@ -282,6 +282,8 @@
 # python scripts to the proto area. This is overridden by makefiles to
 # select to the correct version.
 PYSHEBANG=	$(PYTHON)
+$(BUILDPY3)PYSHEBANG=	$(PYTHON3)
+$(BUILDPY2)PYSHEBANG=	$(PYTHON)
 
 #
 # Python bakes the mtime of the .py file into the compiled .pyc and
--- a/usr/src/cmd/pyzfs/pyzfs.py	Tue Nov 12 15:47:35 2019 +0000
+++ b/usr/src/cmd/pyzfs/pyzfs.py	Tue Jan 14 21:23:25 2020 +0300
@@ -1,4 +1,4 @@
-#!@PYTHON@ -S
+#!@PYTHON@ -Es
 #
 # CDDL HEADER START
 #
--- a/usr/src/lib/pylibbe/common/libbe_py.c	Tue Nov 12 15:47:35 2019 +0000
+++ b/usr/src/lib/pylibbe/common/libbe_py.c	Tue Jan 14 21:23:25 2020 +0300
@@ -202,9 +202,15 @@
 			    NULL, NULL));
 		}
 		while (PyDict_Next(beNameProperties, &pos, &pkey, &pvalue)) {
+#if PY_MAJOR_VERSION >= 3
 			if (!convertPyArgsToNvlist(&beProps, 2,
-			    PyBytes_AS_STRING(pkey),
-			    PyBytes_AS_STRING(pvalue))) {
+			    PyUnicode_AsUTF8(pkey),
+			    PyUnicode_AsUTF8(pvalue))) {
+#else
+			if (!convertPyArgsToNvlist(&beProps, 2,
+			    PyString_AsString(pkey),
+			    PyString_AsString(pvalue))) {
+#endif
 				nvlist_free(beProps);
 				nvlist_free(beAttrs);
 				return (Py_BuildValue("[iss]", BE_PY_ERR_NVLIST,
--- a/usr/src/lib/pyzfs/common/ioctl.c	Tue Nov 12 15:47:35 2019 +0000
+++ b/usr/src/lib/pyzfs/common/ioctl.c	Tue Jan 14 21:23:25 2020 +0300
@@ -144,7 +144,7 @@
 
 	while (PyDict_Next(d, &pos, &key, &value)) {
 #if PY_MAJOR_VERSION >= 3
-		char *keystr = PyBytes_AsString(key);
+		char *keystr = PyUnicode_AsUTF8(key);
 #else
 		char *keystr = PyString_AsString(key);
 #endif
@@ -161,12 +161,12 @@
 		} else if (value == Py_None) {
 			err = nvlist_add_boolean(nvl, keystr);
 #if PY_MAJOR_VERSION >= 3
-		} else if (PyBytes_Check(value)) {
+		} else if (PyUnicode_Check(value)) {
 #else
 		} else if (PyString_Check(value)) {
 #endif
 #if PY_MAJOR_VERSION >= 3
-			char *valstr = PyBytes_AsString(value);
+			char *valstr = PyUnicode_AsUTF8(value);
 #else
 			char *valstr = PyString_AsString(value);
 #endif
--- a/usr/src/test/test-runner/cmd/run	Tue Nov 12 15:47:35 2019 +0000
+++ b/usr/src/test/test-runner/cmd/run	Tue Jan 14 21:23:25 2020 +0300
@@ -17,7 +17,15 @@
 # Copyright 2019 Joyent, Inc.
 #
 
-import ConfigParser
+from __future__ import print_function
+import sys
+PY3 = sys.version_info[0] == 3
+
+if PY3:
+    import configparser
+else:
+    import ConfigParser as configparser
+
 import os
 import logging
 import platform
@@ -30,7 +38,8 @@
 from subprocess import PIPE
 from subprocess import Popen
 from sys import argv
-from sys import maxint
+from sys import exit
+from sys import maxsize
 from threading import Timer
 from time import time
 
@@ -137,7 +146,7 @@
         for easy sorting/merging later.
         """
         fd = self.fileno()
-        buf = os.read(fd, 4096)
+        buf = os.read(fd, 4096).decode()
         if not buf:
             return None
         if '\n' not in buf:
@@ -229,26 +238,27 @@
         if needed. Run the command, and update the result object.
         """
         if options.dryrun is True:
-            print self
+            print(self)
             return
 
         privcmd = self.update_cmd_privs(self.pathname, self.user)
         try:
             old = os.umask(0)
             if not os.path.isdir(self.outputdir):
-                os.makedirs(self.outputdir, mode=0777)
+                os.makedirs(self.outputdir, mode=0o777)
             os.umask(old)
-        except OSError, e:
+        except OSError as e:
             fail('%s' % e)
 
         try:
             self.result.starttime = time()
-            proc = Popen(privcmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
+            proc = Popen(privcmd, stdout=PIPE, stderr=PIPE, stdin=PIPE,
+                         universal_newlines=True)
             proc.stdin.close()
 
             # Allow a special timeout value of 0 to mean infinity
             if int(self.timeout) == 0:
-                self.timeout = maxint
+                self.timeout = maxsize
             t = Timer(int(self.timeout), self.kill_cmd, [proc])
             t.start()
             self.result.stdout, self.result.stderr = self.collect_output(proc)
@@ -300,7 +310,7 @@
             logger.debug('%s%s%s' % (msga, pad, msgb))
 
         lines = sorted(self.result.stdout + self.result.stderr,
-                       cmp=lambda x, y: cmp(x[0], y[0]))
+                       key=lambda x: x[0])
 
         for dt, line in lines:
             logger.debug('%s %s' % (dt.strftime("%H:%M:%S.%f ")[:11], line))
@@ -308,15 +318,15 @@
         if len(self.result.stdout):
             with open(os.path.join(self.outputdir, 'stdout'), 'w') as out:
                 for _, line in self.result.stdout:
-                    os.write(out.fileno(), '%s\n' % line)
+                    out.write('%s\n' % line)
         if len(self.result.stderr):
             with open(os.path.join(self.outputdir, 'stderr'), 'w') as err:
                 for _, line in self.result.stderr:
-                    os.write(err.fileno(), '%s\n' % line)
+                    err.write('%s\n' % line)
         if len(self.result.stdout) and len(self.result.stderr):
             with open(os.path.join(self.outputdir, 'merged'), 'w') as merged:
                 for _, line in lines:
-                    os.write(merged.fileno(), '%s\n' % line)
+                    merged.write('%s\n' % line)
 
 
 class Test(Cmd):
@@ -567,7 +577,7 @@
         in the 'DEFAULT' section. If the Test or TestGroup passes
         verification, add it to the TestRun.
         """
-        config = ConfigParser.RawConfigParser()
+        config = configparser.RawConfigParser()
         if not len(config.read(options.runfile)):
             fail("Coulnd't read config file %s" % options.runfile)
 
@@ -631,7 +641,7 @@
 
         defaults = dict([(prop, getattr(options, prop)) for prop, _ in
                          self.defaults])
-        config = ConfigParser.RawConfigParser(defaults)
+        config = configparser.RawConfigParser(defaults)
 
         for test in sorted(self.tests.keys()):
             config.add_section(test)
@@ -660,14 +670,14 @@
         """
         done = False
         components = 0
-        tmp_dict = dict(self.tests.items() + self.testgroups.items())
+        tmp_dict = dict(list(self.tests.items()) + list(self.testgroups.items()))
         total = len(tmp_dict)
         base = self.outputdir
 
         while not done:
             l = []
             components -= 1
-            for testfile in tmp_dict.keys():
+            for testfile in list(tmp_dict.keys()):
                 uniq = '/'.join(testfile.split('/')[components:]).lstrip('/')
                 if uniq not in l:
                     l.append(uniq)
@@ -695,9 +705,9 @@
         if options.cmd is not 'wrconfig':
             try:
                 old = os.umask(0)
-                os.makedirs(self.outputdir, mode=0777)
+                os.makedirs(self.outputdir, mode=0o777)
                 os.umask(old)
-            except OSError, e:
+            except OSError as e:
                 fail('%s' % e)
             filename = os.path.join(self.outputdir, 'log')
 
@@ -733,17 +743,17 @@
         if Result.total is 0:
             return
 
-        print '\nResults Summary'
-        for key in Result.runresults.keys():
+        print('\nResults Summary')
+        for key in list(Result.runresults.keys()):
             if Result.runresults[key] is not 0:
-                print '%s\t% 4d' % (key, Result.runresults[key])
+                print('%s\t% 4d' % (key, Result.runresults[key]))
 
         m, s = divmod(time() - self.starttime, 60)
         h, m = divmod(m, 60)
-        print '\nRunning Time:\t%02d:%02d:%02d' % (h, m, s)
-        print 'Percent passed:\t%.1f%%' % ((float(Result.runresults['PASS']) /
-                                            float(Result.total)) * 100)
-        print 'Log directory:\t%s' % self.outputdir
+        print('\nRunning Time:\t%02d:%02d:%02d' % (h, m, s))
+        print('Percent passed:\t%.1f%%' % ((float(Result.runresults['PASS']) /
+                                            float(Result.total)) * 100))
+        print('Log directory:\t%s' % self.outputdir)
 
 
 def verify_file(pathname):
@@ -806,7 +816,7 @@
 
 
 def fail(retstr, ret=1):
-    print '%s: %s' % (argv[0], retstr)
+    print('%s: %s' % (argv[0], retstr))
     exit(ret)