From 7dfb29db81c7a07bfaefd148258c6a897e8bac1b Mon Sep 17 00:00:00 2001 From: clutton Date: Thu, 14 Apr 2016 22:33:21 +0300 Subject: include_server python(3) ready --- Makefile.in | 47 ++++---- configure.ac | 27 +---- include_server/__init__.py | 0 include_server/basics.py | 28 ++--- include_server/basics_test.py | 28 ++--- .../c_extensions/distcc_pump_c_extensions_module.c | 128 +++++++++++++-------- include_server/c_extensions_test.py | 32 +++--- include_server/cache_basics.py | 27 +++-- include_server/compiler_defaults.py | 12 +- include_server/compress_files.py | 16 +-- include_server/include_analyzer.py | 16 +-- include_server/include_analyzer_memoizing_node.py | 48 ++++---- .../include_analyzer_memoizing_node_test.py | 30 ++--- include_server/include_analyzer_test.py | 40 +++---- include_server/include_server.py | 123 ++++++++++---------- include_server/include_server_test.py | 28 ++--- include_server/macro_eval.py | 28 +++-- include_server/macro_eval_test.py | 14 +-- include_server/mirror_path.py | 2 +- include_server/mirror_path_test.py | 6 +- include_server/parse_command.py | 24 ++-- include_server/parse_command_test.py | 16 +-- include_server/parse_file.py | 22 ++-- include_server/parse_file_test.py | 20 ++-- include_server/run.py | 17 ++- include_server/setup.py | 8 +- include_server/statistics.py | 76 ++++++------ test/comfychair.py | 2 +- test/onetest.py | 2 +- test/testdistcc.py | 2 +- 30 files changed, 434 insertions(+), 435 deletions(-) delete mode 100755 include_server/__init__.py diff --git a/Makefile.in b/Makefile.in index b398bc8..693500d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,6 +29,8 @@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ ${DIR_DEFS} \ -Isrc -I"$(srcdir)/src" -I"$(srcdir)/lzo" $(POPT_INCLUDES) +PYTHON = @PYTHON@ + srcdir = @srcdir@ top_srcdir = @top_srcdir@ builddir = @builddir@ @@ -72,14 +74,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ -# We use python for two tasks in distcc: running the unittests, and -# running the include-server. The latter requires python 2.4 or -# higher, while the former only requires python 2.2. So it's possible -# a particular machine will be able to run one but not the other. -# Thus we have two variables. -TEST_PYTHON = @TEST_PYTHON@ -INCLUDESERVER_PYTHON = @INCLUDESERVER_PYTHON@ - # RESTRICTED_PATH is a colon separated list of directory names. It # contains the locations of 'make', 'sh', 'gcc', and 'python' for use # in installation tests. This path is used to avoid confusion caused @@ -578,7 +572,8 @@ distccmon-gnome@EXEEXT@: $(mon_obj) $(gnome_obj) # the distcc version, the source location, the CPP flags (for location of the # includes), and the build location. include-server: - if test -z "$(INCLUDESERVER_PYTHON)"; then \ + if test -z "$(PYTHON)"; then \ + echo "$(PYTHON)" \ echo "Not building $@: No suitable python found"; \ else \ mkdir -p "$(include_server_builddir)" && \ @@ -586,7 +581,7 @@ include-server: SRCDIR="$(srcdir)" \ CFLAGS="$(CFLAGS) $(PYTHON_CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ - $(INCLUDESERVER_PYTHON) "$(srcdir)/include_server/setup.py" \ + $(PYTHON) "$(srcdir)/include_server/setup.py" \ build \ --build-base="$(include_server_builddir)" \ --build-temp="$(include_server_builddir)"; \ @@ -711,17 +706,17 @@ TESTDISTCC_OPTS = # satisfied w/o actually building an include server (or rather the C extension); # this logic needs to be verified or amended. maintainer-check-no-set-path: - @if ! $(TEST_PYTHON) -c 'import sys; print sys.version'; then \ + @if ! $(PYTHON) -c 'import sys; print(sys.version)'; then \ echo "WARNING: python not found; tests skipped"; \ else \ - if ! gcc --version 2>/dev/null; then \ - echo "Could not find gcc on the restricted path used to avoid"; \ + if ! $(CC) --version 2>/dev/null; then \ + echo "Could not find CC on the restricted path used to avoid"; \ echo "confusion caused by distcc masquerades on the normal path."; \ echo "PATH is currently '$$PATH'."; \ echo "Please change RESTRICTED_PATH to change this PATH value."; \ exit 1; \ fi; \ - $(TEST_PYTHON) "$(srcdir)/test/testdistcc.py" $(TESTDISTCC_OPTS); \ + $(PYTHON) "$(srcdir)/test/testdistcc.py" $(TESTDISTCC_OPTS); \ fi distcc-maintainer-check: check_programs @@ -744,8 +739,8 @@ include-server-maintainer-check: include-server for p in $(check_include_server_PY); do \ p_base=`basename "$$p"`; \ echo "Running:" \ - "PYTHONPATH=$$CURDIR/$$include_server_loc:$$PYTHONPATH $(INCLUDESERVER_PYTHON) $$p_base"; \ - if PYTHONPATH="$$CURDIR/$$include_server_loc:$$PYTHONPATH" $(INCLUDESERVER_PYTHON) "$$p_base" \ + "PYTHONPATH=$$CURDIR/$$include_server_loc:$$PYTHONPATH $(PYTHON) $$p_base"; \ + if PYTHONPATH="$$CURDIR/$$include_server_loc:$$PYTHONPATH" $(PYTHON) "$$p_base" \ > "$$CURDIR/$(tempdir)/$$p_base.out" 2>&1; then \ echo "PASS"; \ rm "$$CURDIR/$(tempdir)/$$p_base.out"; \ @@ -773,9 +768,9 @@ maintainer-check: distcc-maintainer-check include-server-maintainer-check \ pump-maintainer-check check: - @if test -n "$(INCLUDESERVER_PYTHON)"; then \ + @if test -n "$(PYTHON)"; then \ $(MAKE) maintainer-check; \ - elif test -n "$(TEST_PYTHON)"; then \ + elif test -n "$(PYTHON)"; then \ echo "WARNING: pump-mode not being tested"; \ $(MAKE) distcc-maintainer-check; \ else \ @@ -798,7 +793,7 @@ valgrind-check: TESTNAME = NoDetachDaemon_Case # Override this with the desired test. single-test: check_programs PATH="`pwd`:$(RESTRICTED_PATH)" \ - $(TEST_PYTHON) "$(srcdir)/test/onetest.py" $(TESTDISTCC_OPTS) $(TESTNAME) + $(PYTHON) "$(srcdir)/test/onetest.py" $(TESTDISTCC_OPTS) $(TESTNAME) # Run a single test in pump-mode. pump-single-test: pump include-server check_programs @@ -861,9 +856,9 @@ maintainer-installcheck: verify-binaries-installcheck distcc-installcheck \ pump-installcheck installcheck: - @if test -n "$(INCLUDESERVER_PYTHON)"; then \ + @if test -n "$(PYTHON)"; then \ $(MAKE) maintainer-installcheck; \ - elif test -n "$(TEST_PYTHON)"; then \ + elif test -n "$(PYTHON)"; then \ echo "WARNING: pump-mode not being tested"; \ $(MAKE) distcc-maintainer-installcheck; \ else \ @@ -913,7 +908,7 @@ benchmark: @echo "Pass BENCH_ARGS to make to specify which benchmarks to run." @echo @sleep 5 - cd bench && $(TEST_PYTHON) benchmark.py $(BENCH_ARGS) + cd bench && $(PYTHON) benchmark.py $(BENCH_ARGS) ###################################################################### @@ -943,12 +938,12 @@ clean-lzo: clean-include-server: - if test -n "$(INCLUDESERVER_PYTHON)"; then \ + if test -n "$(PYTHON)"; then \ DISTCC_VERSION="$(VERSION)" \ SRCDIR="$(srcdir)" \ CFLAGS="$(CFLAGS) $(PYTHON_CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ - $(INCLUDESERVER_PYTHON) "$(srcdir)/include_server/setup.py" \ + $(PYTHON) "$(srcdir)/include_server/setup.py" \ clean \ --build-base="$(include_server_builddir)" \ --build-temp="$(include_server_builddir)"; \ @@ -1062,7 +1057,7 @@ install-programs: $(bin_PROGRAMS) # line endings), so we need to convert it from DOS text file format to # Unix text file format (LF line endings); we use sed for that too. install-include-server: include-server pump - if test -z "$(INCLUDESERVER_PYTHON)"; then \ + if test -z "$(PYTHON)"; then \ echo "Not building $@: No suitable python found"; \ else \ mkdir -p "$(include_server_builddir)" && \ @@ -1071,7 +1066,7 @@ install-include-server: include-server pump SRCDIR="$(srcdir)" \ CFLAGS="$(CFLAGS) $(PYTHON_CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ - $(INCLUDESERVER_PYTHON) "$(srcdir)/include_server/setup.py" \ + $(PYTHON) "$(srcdir)/include_server/setup.py" \ build \ --build-base="$(include_server_builddir)" \ --build-temp="$(include_server_builddir)" \ diff --git a/configure.ac b/configure.ac index 16a593f..3626544 100644 --- a/configure.ac +++ b/configure.ac @@ -239,35 +239,12 @@ CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" AC_PROG_MAKE_SET AC_PROG_INSTALL -# We prefer to use the latest Python, but try to find an explicit -# version to make sure we don't get a really old one. -# -# The include server requires python 2.4 or later, but the 'make test' -# routines only require python 2.2. Thus we have two separate -# variables. Each variable is the empty string if the python that we -# haven't isn't recent enough for that use, or the path to a python -# executable if it is recent enough. +# We prefer to use the latest Python # # NB: Cannot use AC_CONFIG_LIBOBJ_DIR here, because it's not present # in autoconf 2.53. -AC_PATH_PROGS(PYTHON, [python2.7 python-2.7 python2.6 python-2.6 python2.5 python-2.5 python2.4 python-2.4 python]) +AM_PATH_PYTHON([3.1],,[:]) AC_ARG_VAR(PYTHON, [Python interpreter]) -# Python 1 doesn't even support -V -if ! "$PYTHON" -V 2>&1 | grep "^Python" >/dev/null; then - TEST_PYTHON="" - INCLUDESERVER_PYTHON="" -elif "$PYTHON" -V 2>&1 | grep "^Python 2.1" >/dev/null; then - TEST_PYTHON="" - INCLUDESERVER_PYTHON="" -elif "$PYTHON" -V 2>&1 | grep "^Python 2.[[23]]" >/dev/null; then - TEST_PYTHON="$PYTHON" - INCLUDESERVER_PYTHON="" -else - TEST_PYTHON="$PYTHON" - INCLUDESERVER_PYTHON="$PYTHON" -fi -AC_SUBST(TEST_PYTHON) -AC_SUBST(INCLUDESERVER_PYTHON) AC_SUBST(PYTHON_RELATIVE_LIB) AC_C_INLINE AC_C_BIGENDIAN diff --git a/include_server/__init__.py b/include_server/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/include_server/basics.py b/include_server/basics.py index f2c5301..1a088b3 100755 --- a/include_server/basics.py +++ b/include_server/basics.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2.4 +#!/usr/bin/env python3 # # Copyright 2007 Google Inc. # @@ -56,7 +56,7 @@ class ClientRootKeeper(object): invariant. Some client roots are padded with '/padding' to satisfy the invariant. """ - + # This constant is embedded in names of client root directories. INCLUDE_SERVER_NAME = 'include_server' @@ -84,7 +84,7 @@ class ClientRootKeeper(object): return glob.glob('%s/*.%s-%s-*' % (self.client_tmp, self.INCLUDE_SERVER_NAME, pid_expr)) - + def ClientRootMakedir(self, generation): """Make a new client directory for a generation of compressed files. @@ -104,7 +104,7 @@ class ClientRootKeeper(object): + '/padding' * self.number_missing_levels) if not os.path.isdir(self.client_root): os.makedirs(self.client_root) - except (IOError, OSError), why: + except (IOError, OSError) as why: sys.exit('Could not create client root directory %s: %s' % (self.client_root, why)) @@ -204,7 +204,7 @@ ALGORITHMS = [SIMPLE, MEMOIZING] # tested on a very large application, where include server time CPU time drops # from 151s to 118s (best times out of 10 runs). There was no seeming changes to # memory usage. Trying with 100,000 did not speed up the application further. -GC_THRESHOLD = 10000 +GC_THRESHOLD = 10000 # FLAGS FOR COMMAND LINE OPTIONS @@ -287,15 +287,15 @@ def Debug(trigger_pattern, message, *params): i = 1 for unused_j in range(DEBUG_NUM_BITS): if i & DEBUG_WARNING & triggered: - print >> sys.stderr, 'WARNING include server:', message % params + print('WARNING include server:', message % params, file=sys.stderr) if i & DEBUG_TRACE & triggered: - print >> sys.stderr, 'TRACE:', message % params + print('TRACE:', message % params, file=sys.stderr) elif i & DEBUG_TRACE1 & triggered: - print >> sys.stderr, 'TRACE1:', message % params + print(sys.stderr, 'TRACE1:', message % params, file=sys.stderr) elif i & DEBUG_TRACE2 & triggered: - print >> sys.stderr, 'TRACE2:', message % params + print('TRACE2:', message % params, file=sys.stderr) elif i & DEBUG_DATA & triggered: - print >> sys.stderr, 'DATA:', message % params + print('DATA:', message % params, file=sys.stderr) i *= 2 sys.stderr.flush() @@ -342,7 +342,7 @@ class NotCoveredError(Error): % (source_file, line_number, message)) else: message = """File: '%s': %s""" % (source_file, message) - # Message, a string, becomes self.args[0] + # Message, a string, becomes self.args[0] Error.__init__(self, message) @@ -390,8 +390,8 @@ class IncludeAnalyzerTimer(object): sys.stdout.flush() signal.alarm(0) signal.signal(signal.SIGALRM, self.old) - - + + class SignalSIGTERM(Error): pass @@ -415,7 +415,7 @@ def SafeNormPath(path): Returns: a string - + Python's os.path.normpath is an unsafe operation; the result may not point to the same file as the argument. Instead, this function just removes initial './'s and a final '/'s if present. diff --git a/include_server/basics_test.py b/include_server/basics_test.py index 02d4f75..ab8dfdc 100755 --- a/include_server/basics_test.py +++ b/include_server/basics_test.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -46,7 +46,7 @@ class BasicsTest(unittest.TestCase): os_makedirs = os.makedirs def Mock_tempfile_mkdtemp(pat, dir): - self.assert_((pat, dir) + self.assertTrue((pat, dir) in [('.%s-%s-%d' % (basics.ClientRootKeeper.INCLUDE_SERVER_NAME, @@ -56,15 +56,15 @@ class BasicsTest(unittest.TestCase): [(1,'/to/be'), (2, '/to')]]) return (dir == '/to/be' and '/to/be/xxxxxx' or dir == '/to' and '/to/xxxxxxx') - + def Mock_os_makedirs(f, *unused_args): if not f.startswith('/to/'): - raise Exception, f - + raise Exception(f) + tempfile.mkdtemp = Mock_tempfile_mkdtemp os.makedirs = Mock_os_makedirs - + os.environ['DISTCC_CLIENT_TMP'] = '/to/be' client_root_keeper = basics.ClientRootKeeper() client_root_keeper.ClientRootMakedir(1) @@ -91,13 +91,13 @@ class BasicsTest(unittest.TestCase): os.environ['DISTCC_CLIENT_TMP'] = '/tmp' client_root_keeper = basics.ClientRootKeeper() client_root_keeper.ClientRootMakedir(117) - self.assert_(os.path.isdir(client_root_keeper._client_root_before_padding)) - self.assert_(os.path.isdir(client_root_keeper.client_root)) - self.assert_(client_root_keeper.client_root.endswith('/padding')) + self.assertTrue(os.path.isdir(client_root_keeper._client_root_before_padding)) + self.assertTrue(os.path.isdir(client_root_keeper.client_root)) + self.assertTrue(client_root_keeper.client_root.endswith('/padding')) client_root_keeper.ClientRootMakedir(118) client_root_keeper.CleanOutClientRoots() # Directories must be gone now! - self.assert_(not os.path.isdir( + self.assertTrue(not os.path.isdir( client_root_keeper._client_root_before_padding)) # Test with a two-level value of DISTCC_CLIENT_TMP. try: @@ -105,14 +105,14 @@ class BasicsTest(unittest.TestCase): dir='/tmp') client_root_keeper = basics.ClientRootKeeper() client_root_keeper.ClientRootMakedir(117) - self.assert_(os.path.isdir( + self.assertTrue(os.path.isdir( client_root_keeper._client_root_before_padding)) - self.assert_(os.path.isdir(client_root_keeper.client_root)) + self.assertTrue(os.path.isdir(client_root_keeper.client_root)) client_root_keeper.ClientRootMakedir(118) client_root_keeper.CleanOutClientRoots() - self.assert_(os.path.isdir, + self.assertTrue(os.path.isdir, client_root_keeper._client_root_before_padding) finally: os.rmdir(os.environ['DISTCC_CLIENT_TMP']) -unittest.main() +unittest.main() diff --git a/include_server/c_extensions/distcc_pump_c_extensions_module.c b/include_server/c_extensions/distcc_pump_c_extensions_module.c index 549f922..2946df2 100644 --- a/include_server/c_extensions/distcc_pump_c_extensions_module.c +++ b/include_server/c_extensions/distcc_pump_c_extensions_module.c @@ -1,15 +1,15 @@ /* Copyright 2007 Google Inc. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, @@ -65,11 +65,11 @@ CompressLzo1xAlloc(PyObject *dummy, PyObject *args) { if (in_len < 0) return NULL; if (dcc_compress_lzo1x_alloc(in_buf, in_len, &out_buf, &out_len)) { - PyErr_SetString(distcc_pump_c_extensionsError, + PyErr_SetString(distcc_pump_c_extensionsError, "Couldn't compress that."); return NULL; } - string_object = PyString_FromStringAndSize(out_buf, out_len); + string_object = PyBytes_FromStringAndSize(out_buf, out_len); free(out_buf); return string_object; } @@ -101,7 +101,7 @@ RCwd(PyObject *dummy, PyObject *args) { "Couldn't read token string."); return NULL; } - return PyString_FromString(value_str); + return PyUnicode_FromString(value_str); } @@ -124,11 +124,12 @@ RTokenString(PyObject *dummy, PyObject *args) { if (!PyArg_ParseTuple(args, "is", &ifd, &expect_token)) return NULL; if (dcc_r_token_string(ifd, expect_token, &value_str)) { - PyErr_SetString(distcc_pump_c_extensionsError, + PyErr_SetString(distcc_pump_c_extensionsError, "Couldn't read token string."); return NULL; } - return PyString_FromString(value_str); + + return PyUnicode_FromString(value_str); } @@ -158,7 +159,7 @@ RArgv(PyObject *dummy, PyObject *args) { } if ((list_object = PyList_New(0)) == NULL) goto error; for (; argv[i]; i++) { - string_object = PyString_FromString(argv[i]); + string_object = PyUnicode_FromString(argv[i]); free(argv[i]); if (!string_object) { goto error; @@ -172,7 +173,7 @@ RArgv(PyObject *dummy, PyObject *args) { error: Py_XDECREF(list_object); Py_XDECREF(string_object); - for (i = i + 1; argv[i]; i++) + for (i = i + 1; argv[i]; i++) free(argv[i]); free(argv); return NULL; @@ -209,8 +210,9 @@ XArgv(PyObject *dummy, PyObject *args) { for (i = 0; i < len; i++) { PyObject *string_object; string_object = PyList_GetItem(list_object, i); /* borrowed ref */ - argv[i] = PyString_AsString(string_object); /* does not increase - ref count */ +/* TODO do it properly, catch exceptions for fancy Unicode symbols */ + argv[i] = PyUnicode_AsUTF8(string_object); /* does not increase + ref count */ } ret = dcc_x_argv(ifd, "ARGC", "ARGV", argv); free(argv); @@ -233,7 +235,7 @@ static /* const */ char OsPathExists_doc__[] = " Arguments:\n" " filepath: a string\n" " Returns:\n" -" True or False\n" +" True or False\n" ; static PyObject * @@ -241,20 +243,20 @@ OsPathExists(PyObject *dummy, PyObject *args) { const char *in; int len; int res; - + struct stat buf; - + UNUSED(dummy); if (!PyArg_ParseTuple(args, "s#", &in, &len)) return NULL; if (len < 0) return NULL; - res = stat(in, &buf); + res = stat(in, &buf); if (res == -1) Py_RETURN_FALSE; if (res == 0) Py_RETURN_TRUE; assert(0); return NULL; -} +} /*********************************************************************** OsPathIsFile @@ -267,7 +269,7 @@ static /* const */ char OsPathIsFile_doc__[] = " Arguments:\n" " filename: a string\n" " Returns:\n" -" True or False\n" +" True or False\n" ; static PyObject * @@ -275,20 +277,20 @@ OsPathIsFile(PyObject *dummy, PyObject *args) { const char *in; int len; int res; - + struct stat buf; - + UNUSED(dummy); if (!PyArg_ParseTuple(args, "s#", &in, &len)) return NULL; if (len < 0) return NULL; - res = stat(in, &buf); + res = stat(in, &buf); if (res == -1) Py_RETURN_FALSE; if ((res == 0) && S_ISREG(buf.st_mode)) Py_RETURN_TRUE; if ((res == 0) && !S_ISREG(buf.st_mode)) Py_RETURN_FALSE; return NULL; -} +} @@ -345,61 +347,93 @@ Realpath(PyObject *dummy, PyObject *args) { /* On Solaris this result may be a relative path, if the argument was relative. Fail hard if this happens. */ assert(res[0] == '/'); - result_str = PyString_FromStringAndSize(res, strlen(res)); + result_str = PyUnicode_FromStringAndSize(res, strlen(res)); if (result_str == NULL) return PyErr_NoMemory(); return result_str; - } + } else { - return PyString_FromStringAndSize(in, strlen(in)); + return PyUnicode_FromStringAndSize(in, strlen(in)); } } /*********************************************************************** -Bindings +Bindings; ************************************************************************/ -static PyMethodDef methods[] = { - {"OsPathExists", (PyCFunction)OsPathExists, METH_VARARGS, +struct module_state { + PyObject *error; +}; + +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) + +static const char module_documentation[]= +"Various utilities for distcc-pump.\n" +; + +static int module_traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(GETSTATE(m)->error); + return 0; +} + +static int module_clear(PyObject *m) { + Py_CLEAR(GETSTATE(m)->error); + return 0; +} + +static PyMethodDef module_methods[] = { + {"OsPathExists", (PyCFunction)OsPathExists, METH_VARARGS, OsPathExists_doc__}, - {"OsPathIsFile", (PyCFunction)OsPathIsFile, METH_VARARGS, + {"OsPathIsFile", (PyCFunction)OsPathIsFile, METH_VARARGS, OsPathIsFile_doc__}, {"Realpath", (PyCFunction)Realpath, METH_VARARGS, Realpath_doc__}, - {"RTokenString",(PyCFunction)RTokenString, METH_VARARGS, + {"RTokenString",(PyCFunction)RTokenString, METH_VARARGS, RTokenString_doc__}, {"RCwd", (PyCFunction)RCwd, METH_VARARGS, RCwd_doc__}, {"RArgv", (PyCFunction)RArgv, METH_VARARGS, RArgv_doc__}, {"XArgv", (PyCFunction)XArgv, METH_VARARGS, XArgv_doc__}, - {"CompressLzo1xAlloc", (PyCFunction)CompressLzo1xAlloc, METH_VARARGS, + {"CompressLzo1xAlloc", (PyCFunction)CompressLzo1xAlloc, METH_VARARGS, CompressLzo1xAlloc_doc__}, {NULL, NULL, 0, NULL} }; +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "distcc_pump_c_extensions", /* m_name */ + module_documentation, /* m_doc */ + sizeof(struct module_state),/* m_size */ + module_methods, /* m_methods */ + NULL, /* m_reload */ + module_traverse, /* m_traverse */ + module_clear, /* m_clear */ + NULL, /* m_free */ +}; -static /* const */ char module_documentation[]= -"Various utilities for distcc-pump.\n" -; - -void initdistcc_pump_c_extensions(void) { - PyObject *module; +PyObject * +PyInit_distcc_pump_c_extensions(void) { + PyObject *module = PyModule_Create(&moduledef); PyObject *py_str; distcc_pump_c_extensionsError = PyErr_NewException( (char *)"distcc_pump_c_extensions.Error", NULL, NULL); - - module = Py_InitModule4("distcc_pump_c_extensions", - methods, - module_documentation, - NULL, - PYTHON_API_VERSION); - - py_str = PyString_FromString("Nils Klarlund"); + + if (module == NULL) + return NULL; + + struct module_state *st = GETSTATE(module); + st->error = distcc_pump_c_extensionsError; + if (st->error == NULL) { + Py_DECREF(module); + return NULL; + } + + py_str = PyUnicode_FromString("Nils Klarlund"); + py_str = PyUnicode_FromString(version); PyModule_AddObject(module, "__author__", py_str); - py_str = PyString_FromString(version); PyModule_AddObject(module, "__version__", py_str); /* Make the exception class accessible */ PyModule_AddObject(module, "Error", distcc_pump_c_extensionsError); - + return module; } diff --git a/include_server/c_extensions_test.py b/include_server/c_extensions_test.py index bdb3eb4..c5cbfdb 100755 --- a/include_server/c_extensions_test.py +++ b/include_server/c_extensions_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2.4 +#!/usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. -# +# """Tests for distcc_pump_c_extensions. @@ -55,11 +55,11 @@ def RunTest(random_filename): # Pack something and try sending it fd = _MakeTempFile('wb') - fd.write('ARGC 2') - fd.write('ARGV 6') - fd.write('tomato') - fd.write('ARGV 7') - fd.write('potatos') + fd.write(b'ARGC 2') + fd.write(b'ARGV 6') + fd.write(b'tomato') + fd.write(b'ARGV 7') + fd.write(b'potatos') fd.close() # Now try to read it back with wrong expectations. @@ -97,24 +97,24 @@ def RunTest(random_filename): fd.close() # Libc functions --- also print out how fast they are compared to - # Python built-ins. + # Python built-ins. t = time.time() f = '/' for unused_i in range(10000): distcc_pump_c_extensions.OsPathExists(f) - print 'Stat', time.time() - t + print('Stat', time.time() - t) t = time.time() for unused_i in range(10000): os.path.exists(f) - print 'os.path.exists', time.time() - t + print('os.path.exists', time.time() - t) for unused_i in range(10000): distcc_pump_c_extensions.Realpath(f) - print 'c_realpath', time.time() - t + print('c_realpath', time.time() - t) t = time.time() for unused_i in range(10000): os.path.realpath(f) - print 'os.path.realpath', time.time() - t - print 'c_extenstions_test passed' + print('os.path.realpath', time.time() - t) + print('c_extenstions_test passed') def main(): @@ -124,12 +124,12 @@ def main(): try: if os.path.exists(random_testdir): os.removedirs(random_testdir) - os.mkdir(random_testdir, 0700) - except (IOError, OSError), why: + os.mkdir(random_testdir) + except (IOError, OSError) as why: sys.exit('Unable to create test dir %s: %s.' % (random_testdir, why)) random_filename = os.path.join(random_testdir, 'test') assert not os.path.exists(random_filename), random_filename - + try: RunTest(random_filename) finally: diff --git a/include_server/cache_basics.py b/include_server/cache_basics.py index 1826ce7..8f4ca2e 100755 --- a/include_server/cache_basics.py +++ b/include_server/cache_basics.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. -# +# """Classes enabling definition and composition of caches. @@ -347,7 +347,7 @@ class DirnameCache(object): self.cache[(currdir_idx, searchdir_idx, includepath_idx)] = (dir_idx, rp_idx) return (dir_idx, rp_idx) - + class SystemdirPrefixCache(object): """A cache of information about whether a file exists in a systemdir. @@ -389,14 +389,14 @@ class SystemdirPrefixCache(object): Argument: realpath_map: a string-to-int map of canonicalized filepaths we know. - + After this function is called, the cache entry is True iff realpath.startswith(systemdir) is True for any of the systemdirs passed in to our constructor. """ if len(self.cache) >= realpath_map.Length(): return # we're already all full - for realpath_idx in xrange(len(self.cache), realpath_map.Length()): + for realpath_idx in range(len(self.cache), realpath_map.Length()): realpath = realpath_map.string[realpath_idx] for systemdir in self.systemdirs: if realpath.startswith(systemdir): @@ -560,7 +560,7 @@ class CanonicalMapToIndex(MapToIndex): """ return MapToIndex.Index(self, self.canonicalize(filepath)) - + def RetrieveDirectoriesExceptSys(directory_map, realpath_map, systemdir_prefix_cache, directory_idxs): """Calculate the set of non-system directories of an index list. @@ -572,7 +572,7 @@ def RetrieveDirectoriesExceptSys(directory_map, realpath_map, Returns: the corresponding tuple of directories except for those whose realpath has a prefix that is a sysdir - + The directories in the returned list have their trailing '/' stripped. """ @@ -725,14 +725,13 @@ class BuildStatCache(object): assert searchdir_idx is None or 1 <= searchdir_idx < dir_map.Length() for sl_idx in searchlist_idxs: assert sl_idx < dir_map.Length() - assert os.getcwd() + '/' == dir_map_string[currdir_idx], ( - "'%s/' != '%s'" % (os.getcwd(), dir_map_string[currdir_idx])) + assert os.getcwd() + '/' == dir_map_string[currdir_idx] Debug(DEBUG_TRACE2, "Resolve: includepath: '%s', currdir: '%s', " "searchdir: '%s', searchlist: %s" % - (includepath, - dir_map_string[currdir_idx], - searchdir_idx and dir_map_string[searchdir_idx], - " \n".join([dir_map_string[idx] for idx in searchlist_idxs]))) + (includepath, + dir_map_string[currdir_idx], + searchdir_idx and dir_map_string[searchdir_idx], + " \n".join([dir_map_string[idx] for idx in searchlist_idxs]))) try: # Locate the array (list) relative to currdir_idx and includepath_idx searchdir_stats = build_stat[currdir_idx][includepath_idx] @@ -819,7 +818,7 @@ class SetUpCaches(object): """ def __init__(self, client_root): - + # A memoizing (caching) class to canonicalize a path: mostly by # resolving any symlinks in the path-component. self.canonical_path = CanonicalPath() diff --git a/include_server/compiler_defaults.py b/include_server/compiler_defaults.py index d0c27d5..da4e05a 100755 --- a/include_server/compiler_defaults.py +++ b/include_server/compiler_defaults.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -17,7 +17,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. - + """Divination of built-in system directories used by compiler installation. It is undesirable for the distcc-pump to send header files that reside @@ -48,7 +48,7 @@ DEBUG_TRACE = basics.DEBUG_TRACE DEBUG_DATA = basics.DEBUG_DATA NotCoveredError = basics.NotCoveredError - + def _RealPrefixWithinClientRoot(client_root, path): """Determine longest directory prefix of PATH and whether PATH contains a symlink. @@ -215,9 +215,9 @@ def _SystemSearchdirsGCC(compiler, sysroot, language, canonical_lookup): stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - env=trimmed_env) + env=trimmed_env,universal_newlines=True) out = p.communicate()[0] - except (IOError, OSError), why: + except (IOError, OSError) as why: raise NotCoveredError ( ( "Couldn't determine default system include directories\n" + "for compiler '%s', language '%s':\n" @@ -232,7 +232,7 @@ def _SystemSearchdirsGCC(compiler, sysroot, language, canonical_lookup): (compiler, language, command, p.returncode, out)) match_obj = re.search( - r"%s\n(.*?)\n%s" # don't ask + "%s\n(.*?)\n%s" # don't ask % ("#include <...> search starts here:", "End of search list"), out, re.MULTILINE + re.DOTALL) diff --git a/include_server/compress_files.py b/include_server/compress_files.py index 20512fd..880551e 100755 --- a/include_server/compress_files.py +++ b/include_server/compress_files.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. - + """Compress files in an include closure.""" import os @@ -67,10 +67,10 @@ class CompressFiles(object): if len(include_closure[realpath_idx]) > 0: # Designate by suffix '.abs' that this file is to become known by an # absolute filepath through a #line directive. - new_filepath = "%s%s.lzo.abs" % (client_root_keeper.client_root, + new_filepath = "%s%s.lzo.abs" % (client_root_keeper.client_root, realpath) else: - new_filepath = "%s%s.lzo" % (client_root_keeper.client_root, + new_filepath = "%s%s.lzo" % (client_root_keeper.client_root, realpath) files.append(new_filepath) if not new_filepath in self.files_compressed: @@ -80,7 +80,7 @@ class CompressFiles(object): if not os.path.isdir(dirname): my_root = client_root_keeper.client_root self.mirror_path.DoPath(realpath, currdir_idx, my_root) - except (IOError, OSError), why: + except (IOError, OSError) as why: # Kill include server sys.exit("Could not make directory '%s': %s" % (dirname, why)) if new_filepath.endswith('.abs'): @@ -99,17 +99,17 @@ class CompressFiles(object): prefix = "" try: real_file_fd = open(realpath, "r") - except (IOError, OSError), why: + except (IOError, OSError) as why: sys.exit("Could not open '%s' for reading: %s" % (realpath, why)) try: new_filepath_fd = open(new_filepath, "wb") - except (IOError, OSError), why: + except (IOError, OSError) as why: sys.exit("Could not open '%s' for writing: %s" % (new_filepath, why)) try: new_filepath_fd.write( distcc_pump_c_extensions.CompressLzo1xAlloc( prefix + real_file_fd.read())) - except (IOError, OSError), why: + except (IOError, OSError) as why: sys.exit("Could not write to '%s': %s" % (new_filepath, why)) new_filepath_fd.close() real_file_fd.close() diff --git a/include_server/include_analyzer.py b/include_server/include_analyzer.py index 450b593..b284bbd 100755 --- a/include_server/include_analyzer.py +++ b/include_server/include_analyzer.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. - + """The skeleton for an include analyzer. This module defines the basic caches and helper functions for an @@ -139,7 +139,7 @@ class IncludeAnalyzer(object): os.path.join(currdir, fpath), self.currdir_idx, self.client_root_keeper.client_root) - + closure = self.RunAlgorithm(fpath_resolved_pair, fpath_real) return closure @@ -194,7 +194,7 @@ class IncludeAnalyzer(object): def DoStatResetTriggers(self): """Reset stat caches if a glob evaluates differently from earlier. - + More precisely, if a path of a glob comes in or out of existence or has a new stamp, then reset stat caches.""" @@ -233,8 +233,8 @@ class IncludeAnalyzer(object): def DoCompilationCommand(self, cmd, currdir, client_root_keeper): """Parse and and process the command; then gather files and links.""" - - self.translation_unit = "unknown translation unit" # don't know yet + + self.translation_unit = "unknown translation unit" # don't know yet # Any relative paths in the globs in the --stat_reset_trigger argument # must be evaluated relative to the include server's original working @@ -346,7 +346,7 @@ class IncludeAnalyzer(object): where searchdir_i is an absolute path. realpath_idx is a realpath index corresponding to a single #include (more exactly, it's the index of the path that the #include resolves to). - + This include closure calculation omits any system header files, that is, header files found in a systemdir (recall systemdirs are those searchdirs that are built into the preprocessor, such as @@ -396,7 +396,7 @@ class IncludeAnalyzer(object): This method to be overridden by derived class. """ - raise Exception, "RunAlgorithm not implemented." + raise Exception("RunAlgorithm not implemented.") def ClearStatCaches(self): """Clear caches used for, or dependent on, stats.""" diff --git a/include_server/include_analyzer_memoizing_node.py b/include_server/include_analyzer_memoizing_node.py index c7471f5..e870c1c 100755 --- a/include_server/include_analyzer_memoizing_node.py +++ b/include_server/include_analyzer_memoizing_node.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. - + """A graph-based algorithm for memoizing include closure calculations.""" __author__ = "Nils Klarlund" @@ -66,9 +66,9 @@ class UnionCache(object): id_map: the set of frozen sets we have seen mapped to {1, 2, ..} """ self.members = {} - self.cache = {} + self.cache = {} self.id_map = {} - + def SetId(self, members): """Memoize the frozenset of members and return set id.""" frozen = frozenset(members) @@ -82,7 +82,7 @@ class UnionCache(object): def Elements(self, set_id): """The frozenset corresponding to a set id.""" return self.members[set_id] - + def Union(self, set1_id, set2_id): """Return the set id of the union of sets represented by set ids.""" try: @@ -108,7 +108,7 @@ class SupportRecord(object): def __init__(self, support_master): """Constructor. Argument: - support_master: a record for holding the reverse mapping from symbols to + support_master: a record for holding the reverse mapping from symbols to support records that contain them. Instance Variables: support_master: see above @@ -122,7 +122,7 @@ class SupportRecord(object): self.valid = True self.union_cache = support_master.union_cache self.support_id = self.union_cache.SetId([]) - + def Update(self, set_id): """Augment the support record with the set represented by set_id. """ @@ -148,7 +148,7 @@ class SupportMaster(object): A map symbol_to_records is maintained. For each symbol s self.symbol_to_records[s] is the set of support records r whose support set contains s.""" - + def __init__(self): """Constructor. @@ -171,8 +171,8 @@ class SupportMaster(object): if symbol in self.symbol_to_records: for support_record in self.symbol_to_records[symbol]: support_record.valid = False - - + + class IncludeAnalyzerMemoizingNode(include_analyzer.IncludeAnalyzer): """A memoizing algorithm for include analysis based on a graph construction. @@ -230,18 +230,18 @@ class IncludeAnalyzerMemoizingNode(include_analyzer.IncludeAnalyzer): directory as understood above must also be taken into account. In particular, we also use as keys pairs of the form: - + (realpath index of resolved file, real path index of filedir). This realpath-oriented memoization is not a frivolous attempt at optimization. It is essential to avoiding infinite loops as in: - + D/mem.h D/../D/mem.h D/../D/../D/mem.h generated by an include of the form "#include ../D/mem.h" in file mem.h. - + One would think that obviosly these prefixes denote the same location. But they need not! For D of the first line could be a symbolic link to a real directory dir1_D. And, the second D could be another symbolic link in @@ -312,13 +312,13 @@ class IncludeAnalyzerMemoizingNode(include_analyzer.IncludeAnalyzer): lhs, rhs = d_opt[0], "1" elif len(d_opt) == 2: [lhs, rhs] = d_opt - parse_file.InsertMacroDefInTable(lhs, rhs, self.symbol_table, + parse_file.InsertMacroDefInTable(lhs, rhs, self.symbol_table, self.support_master.InvalidateRecords) else: # Assume this is a syntax error of some sort. pass - - # Construct or find the node for filepath_resolved. + + # Construct or find the node for filepath_resolved. node = self.FindNode(nodes_for_incl_config, filepath_resolved_pair, RESOLVED, @@ -391,8 +391,8 @@ class IncludeAnalyzerMemoizingNode(include_analyzer.IncludeAnalyzer): # file_dir_idx, because the filepath is resolved against file_dir. key = (fp, resolution_mode, file_dir_idx) if key in nodes_for_incl_config: - # Is the support record valid? - if nodes_for_incl_config[key][self.SUPPORT_RECORD].valid: + # Is the support record valid? + if nodes_for_incl_config[key][self.SUPPORT_RECORD].valid: statistics.master_hit_counter += 1 return nodes_for_incl_config[key] else: @@ -408,7 +408,7 @@ class IncludeAnalyzerMemoizingNode(include_analyzer.IncludeAnalyzer): # code below -- we don't want to reuse an earlier result. [fp_real_idx, fp_resolved_pair, _, support_record] = node Debug(DEBUG_TRACE, - "Invalid record for translation unit: %s, file: %s", + "Invalid record for translation unit: %s, file: %s", self.translation_unit, self._PrintableFilePath(fp)) else: @@ -485,7 +485,7 @@ class IncludeAnalyzerMemoizingNode(include_analyzer.IncludeAnalyzer): # Now, we've got the resolution: (search directory, include path). assert (fp and fp_real_idx and fp_resolved_pair) (searchdir_idx, includepath_idx) = fp_resolved_pair - + # We need the realpath index of the current file directory. That's because # we are going to ask whether we have really visited this file, despite the # failure above to recognize it using a possibly relative name. Here, @@ -501,9 +501,9 @@ class IncludeAnalyzerMemoizingNode(include_analyzer.IncludeAnalyzer): except KeyError: (fp_dirname_idx, fp_dirname_real_idx) = ( self.dirname_cache.Lookup(currdir_idx, - searchdir_idx, + searchdir_idx, includepath_idx)) - + if resolution_mode != RESOLVED: # See whether we know about filepath post-resolution. if ((fp_real_idx, fp_dirname_real_idx) in nodes_for_incl_config @@ -522,7 +522,7 @@ class IncludeAnalyzerMemoizingNode(include_analyzer.IncludeAnalyzer): statistics.master_miss_counter += 1 # If we're revisiting because the support record was invalid, then it is # time to set it. - support_record.valid = True + support_record.valid = True # Try to get the cached result of parsing file. try: @@ -573,7 +573,7 @@ class IncludeAnalyzerMemoizingNode(include_analyzer.IncludeAnalyzer): self.quote_dirs, self.angle_dirs, self.symbol_table)) for (fp_resolved_pair_, fp_real_idx_) in files: - node_ = self.FindNode(nodes_for_incl_config, + node_ = self.FindNode(nodes_for_incl_config, fp_resolved_pair_, RESOLVED, None, fp_real_idx_) if node_: diff --git a/include_server/include_analyzer_memoizing_node_test.py b/include_server/include_analyzer_memoizing_node_test.py index d3247db..aeeef8e 100755 --- a/include_server/include_analyzer_memoizing_node_test.py +++ b/include_server/include_analyzer_memoizing_node_test.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. - + __author__ = "Nils Klarlund" import os @@ -31,7 +31,7 @@ import unittest NotCoveredError = basics.NotCoveredError class IncludeAnalyzerMemoizingNodeUnitTest(unittest.TestCase): - + def _ToString(self, include_closure): """Translate the indices in an include closure to their denoted strings.""" return ( @@ -40,7 +40,7 @@ class IncludeAnalyzerMemoizingNodeUnitTest(unittest.TestCase): self.includepath_map.string[ip_idx]) for (dir_idx, ip_idx) in include_closure[rp_idx] ]) for rp_idx in include_closure)) - + def setUp(self): basics.opt_debug_pattern = 1 client_root_keeper = basics.ClientRootKeeper() @@ -98,8 +98,8 @@ class IncludeAnalyzerMemoizingNodeUnitTest(unittest.TestCase): dir_idx = directory_map.Index("/dir") A_children = [] - A = (realpath_map.Index("/curr/src/a.h"), - (src_idx, includepath_map.Index("a.h")), + A = (realpath_map.Index("/curr/src/a.h"), + (src_idx, includepath_map.Index("a.h")), A_children) B_children = [] @@ -121,7 +121,7 @@ class IncludeAnalyzerMemoizingNodeUnitTest(unittest.TestCase): D = (None, None, D_children) E_children = [] - E = (realpath_map.Index("/dir/e.h"), + E = (realpath_map.Index("/dir/e.h"), (root_idx, includepath_map.Index("dir/e.h")), E_children) @@ -135,13 +135,13 @@ class IncludeAnalyzerMemoizingNodeUnitTest(unittest.TestCase): include_closure = {} self.include_analyzer._CalculateIncludeClosureExceptSystem(A, include_closure) stringified_include_closure = self._ToString(include_closure) - + # /curr/src/a.h is not known under absolute pathnames. self.assertEqual(stringified_include_closure['/curr/src/a.h'], []) # Neither is /curr/src/b.h. self.assertEqual(stringified_include_closure['/curr/src/b.h'], []) # But, /dir/c.h is known under two different absolute names. - self.assertEqual(stringified_include_closure['/dir/c.h'], + self.assertEqual(stringified_include_closure['/dir/c.h'], [('/dirlink/', 'c.h'), ('/', 'dir/c.h')]) # And, dir/e.h is known under exactly one absolute name. self.assertEqual(stringified_include_closure['/dir/e.h'], [('/', 'dir/e.h')]) @@ -160,7 +160,7 @@ class IncludeAnalyzerMemoizingNodeUnitTest(unittest.TestCase): " -Isrc" + " -I./lzo" + " -include include_me.h " + - " -o src/%s.o" + + " -o src/%s.o" + " -c src/%s.c") % (src_stem, src_stem) def test__CalculateIncludeClosureExceptSystem_on_distcc(self): @@ -180,12 +180,12 @@ class IncludeAnalyzerMemoizingNodeUnitTest(unittest.TestCase): parsed_command = ( parse_command.ParseCommandArgs( parse_command.ParseCommandLine(cmd), - current_dir, - include_analyzer.includepath_map, + current_dir, + include_analyzer.includepath_map, include_analyzer.directory_map, include_analyzer.compiler_defaults)) - (include_analyzer.quote_dirs, + (include_analyzer.quote_dirs, include_analyzer.angle_dirs, include_analyzer.include_files, translation_unit, @@ -208,7 +208,7 @@ class IncludeAnalyzerMemoizingNodeUnitTest(unittest.TestCase): "src/hosts.h", "src/bulk.h", "src/emaillog.h"] - + include_closure = ( include_analyzer.ProcessCompilationCommand(current_dir, parsed_command)) @@ -228,7 +228,7 @@ class IncludeAnalyzerMemoizingNodeUnitTest(unittest.TestCase): # different search path files are reported as absolute. That is, # provoke pairs (directory_idx, includepath_idx) to exist in # include_closure[rp_idx]. - + def tearDown(self): pass diff --git a/include_server/include_analyzer_test.py b/include_server/include_analyzer_test.py index 4232934..728eca5 100755 --- a/include_server/include_analyzer_test.py +++ b/include_server/include_analyzer_test.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -95,7 +95,7 @@ class IncludeAnalyzerTest(unittest.TestCase): self.CanonicalPathsForTestData(['test_computed_includes/src.c', 'test_computed_includes/helper.c', 'test_computed_includes/incl.h'])) - + includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc test_data/test_computed_includes/srcA.c", @@ -117,7 +117,7 @@ class IncludeAnalyzerTest(unittest.TestCase): def FindNode(self, *_): self.count += 1 if self.count == 2: - raise Exception, "Did not expect 2 calls of FindNode." + raise Exception("Did not expect 2 calls of FindNode.") return old_FindNode(*_) self.include_analyzer.FindNode = mock_FindNode().FindNode @@ -145,12 +145,12 @@ class IncludeAnalyzerTest(unittest.TestCase): 'test_computed_includes/inclA.h', 'dfoo/foo2.h'])) - + # Test: functional macros can be passed on the command line. includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( """gcc -D"STR(X)=# X" """ - + """-D"FINCLUDE(P)=STR(../MY_TEST_DATA/dfoo/P)" """ + + """-D"FINCLUDE(P)=STR(../MY_TEST_DATA/dfoo/P)" """ + """-DMY_TEST_DATA=test_data """ + "test_data/func_macro.c", os.getcwd())) @@ -207,16 +207,16 @@ class IncludeAnalyzerTest(unittest.TestCase): finally: basics.opt_unsafe_absolute_includes = opt_unsafe_absolute_includes shutil.rmtree(tmp_dir) - + def test_StatResetTriggers(self): - + """Check that the include analysis of a file is done from scratch after a trigger path went from non-existing to existing. """ def CheckGeneration(lst, expected): for f_name in lst: - self.failUnless( + self.assertTrue( re.match(r"%s/.+[.]include_server[-][0-9]+[-]%s" % (self.include_analyzer.client_root_keeper.client_tmp, expected), @@ -232,7 +232,7 @@ class IncludeAnalyzerTest(unittest.TestCase): + '/' + f_name.split('/')[-1][:-4] for f_name in lst if f_name.endswith('.lzo') ] - + self.include_analyzer.stat_reset_triggers = {"seven*": {}, "ate": {"ate": (1,111,2)}, "nine": {} } @@ -250,7 +250,7 @@ class IncludeAnalyzerTest(unittest.TestCase): def Mock_OsStat(f): # Return the same as initial value in two cases below. if f in ["seven", "nine"]: raise OSError - if f == 'ate': + if f == 'ate': obj = lambda: None obj.st_mtime = 1 obj.st_ino = 111 @@ -267,7 +267,7 @@ class IncludeAnalyzerTest(unittest.TestCase): return f in [ "test_data/stat_triggers.c", "test_data/dfoo/stat_triggers.h"] cache_basics._OsPathIsFile = Mock_OsPathIsFile - + files_and_links = self.include_analyzer.DoCompilationCommand( "gcc -Itest_data/dfoo test_data/stat_triggers.c".split(), os.getcwd(), @@ -307,7 +307,7 @@ class IncludeAnalyzerTest(unittest.TestCase): self.assertEqual(self.include_analyzer.generation, 2) CheckGeneration(files_and_links, 2) - + # Now, check that we picked up the test_data version of the .h file, not # the dfoo one! self.assertEqual(GetFileNamesFromAbsLzoName(files_and_links), @@ -328,13 +328,13 @@ class IncludeAnalyzerTest(unittest.TestCase): obj = lambda: None obj.st_mtime = 1 obj.st_ino = 111 - obj.st_dev = 3 + obj.st_dev = 3 return obj if f == 'seventy': obj = lambda: None obj.st_mtime = 2 obj.st_ino = 222 - obj.st_dev = 3 + obj.st_dev = 3 return obj return real_os_stat(f) os.stat = New_New_Mock_OsStat @@ -351,10 +351,10 @@ class IncludeAnalyzerTest(unittest.TestCase): self.assertEqual(GetFileNamesFromAbsLzoName(files_and_links), ['test_data/stat_triggers.c', 'dfoo/stat_triggers.h']) - + self.assertEqual(self.include_analyzer.generation, 3) CheckGeneration(files_and_links, 3) - + finally: glob.glob = real_glob_glob os.stat = real_os_stat @@ -375,7 +375,7 @@ class IncludeAnalyzerTest(unittest.TestCase): # symlink_farm/sub_farm/link_to_dd_dd_dfoo_include_dotdot_foo # # which is a link to ../../dfoo/include_dotdot_foo, that is, to - # + # # dfoo/include_dotdot_foo # # which is a file that contains: @@ -408,7 +408,7 @@ class IncludeAnalyzerTest(unittest.TestCase): ['dfoo/include_dotdot_foo', 'symlink_farm/foo'], "test_data")) - + def helper_test_IncludeAnalyzer(self, test_data_dir): """Test basic functionality assuming test data is in test_data_dir.""" @@ -523,7 +523,7 @@ class IncludeAnalyzerTest(unittest.TestCase): 'test_include_next/foo/y.h', 'test_include_next/baz/y.h'], test_data_dir)) - + # Test that a directory that has a name matching an include is not picked. # Here the directory is test_data/i_am_perhaps_a_directory.h, which is in # the file directory of the translation unit. Instead, @@ -553,7 +553,7 @@ class IncludeAnalyzerTest(unittest.TestCase): for algorithm in [ basics.MEMOIZING ]: try: - print "TESTING ALGORITHM %s" % algorithm + print("TESTING ALGORITHM %s" % algorithm) unittest.main() except: raise diff --git a/include_server/include_server.py b/include_server/include_server.py index 039a9ef..3b50247 100755 --- a/include_server/include_server.py +++ b/include_server/include_server.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2.4 +#!/usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -32,7 +32,7 @@ import os import re import shutil import signal -import SocketServer +import socketserver import sys import tempfile import traceback @@ -44,7 +44,7 @@ import include_analyzer_memoizing_node import statistics # The default size passed to listen by a streaming socket server of -# SocketServer is only 5. Make it 128 (which appears to be the hard +# socketserver is only 5. Make it 128 (which appears to be the hard # built-in limit for Linux). This enables requests to the include # server to be buffered better. REQUEST_QUEUE_SIZE = 128 @@ -61,7 +61,7 @@ NotCoveredTimeOutError = basics.NotCoveredTimeOutError # USAGE def Usage(): - print """Usage: + print("""Usage: include_server --port INCLUDE_SERVER_PORT [OPTIONS] @@ -77,15 +77,15 @@ OPTIONS: 1 = warnings 2 = trace some functions other powers of two: see basics.py. - + -e, --email Send email to discc-pump developers when include server gets in trouble. --email_bound NUMBER Maximal number of emails to send (in addition to a final email). Default: 3. - + --no-email Do not send email. - + --path_observation_re=RE Issue warning message whenever a filename is resolved to a realpath that is matched by RE, which is a regular expression in Python syntax. @@ -95,9 +95,9 @@ OPTIONS: --pid_file FILEPATH The pid of the include server is written to file FILEPATH. - + -s, --statistics Print information to stdout about include analysis. - + --stat_reset_triggers=LIST Flush stat caches when the timestamp of any filepath in LIST changes or the filepath comes in or out of existence. LIST is a colon separated @@ -110,7 +110,7 @@ OPTIONS: -t, --time Print elapsed, user, and system time to stderr. - --unsafe_absolute_includes Do preprocessing on the compilation server even if + --unsafe_absolute_includes Do preprocessing on the compilation server even if includes of absolute filepaths are encountered. Such includes are then ignored for the purposes of gathering the include closure. See the @@ -122,17 +122,17 @@ OPTIONS: some cases, but will break builds which use include structures like "" without including other files in foo/. - + -v, --verify Verify that files in CPP closure are contained in closure calculated by include processor. - + -w, --write_include_closure Write a .d_approx file which lists all the included files calculated by the include server; with -x, additionally write the included files as calculated by CPP to a .d_exact file. -x, --exact_analysis Use CPP instead, do not omit system headers files. -""" +""") # TODO(klarlund) # --simple_algorithm not currently implemented @@ -142,10 +142,10 @@ OPTIONS: def _PrintStackTrace(fd): """Print stacktrace to file object.""" - print >> fd, '------- Include server stack trace -----------' + print('------- Include server stack trace -----------', file=fd) # Limit is 1000 entries. traceback.print_exc(1000, fd) - print >> fd, '----------------------------------------------' + print('----------------------------------------------', file=fd) class _EmailSender(object): @@ -176,7 +176,7 @@ class _EmailSender(object): basics.EMAIL_SUBJECT, basics.DCC_EMAILLOG_WHOM_TO_BLAME, user_addr, - "Automated email number %d in include server session.\n" % + "Automated email number %d in include server session.\n" % self.number_sent, fd.read()) s = smtplib.SMTP() @@ -195,7 +195,7 @@ class _EmailSender(object): Arguments: fd: a file object that will be closed. force: send the mail even if number of emails sent exceed - basics.opt_email_bound + basics.opt_email_bound """ fd.seek(0, 0) Debug(DEBUG_WARNING, "%s", fd.read()) @@ -257,7 +257,7 @@ def ExactDependencies(cmd, realpath_map, systemdir_prefix_cache, fd_d_.read()))) fd_d_.close() _delete_temp_files() - # The sets of dependencies is a set the of realpath indices of the + # The sets of dependencies is a set the of realpath indices of the # absolute filenames corresponding to files in the dotd file. deps = set([ rp_idx for filepath in dotd.split() @@ -282,7 +282,7 @@ def WriteDependencies(deps, result_file, realpath_map): fd.write("\n".join([realpath_map.string[d] for d in deps])) fd.write("\n") fd.close() - except (IOError, OSError), why: + except (IOError, OSError) as why: raise NotCoveredError("Could not write to '%s': %s" % (result_file, why)) @@ -319,12 +319,12 @@ def VerifyExactDependencies(include_closure, # A SOCKET SERVER -class QueuingSocketServer(SocketServer.UnixStreamServer): +class Queuingsocketserver(socketserver.UnixStreamServer): """A socket server whose request queue have size REQUEST_QUEUE_SIZE.""" request_queue_size = REQUEST_QUEUE_SIZE def handle_error(self, _, client_address): - """Re-raise current exception; overrides SocketServer.handle_error. + """Re-raise current exception; overrides socketserver.handle_error. """ raise @@ -337,7 +337,7 @@ def DistccIncludeHandlerGenerator(include_analyzer): # TODO(klarlund): Can we do this without dynamic type generation? - class IncludeHandler(SocketServer.StreamRequestHandler): + class IncludeHandler(socketserver.StreamRequestHandler): """Define a handle() method that invokes the include closure algorithm .""" def handle(self): @@ -389,15 +389,14 @@ def DistccIncludeHandlerGenerator(include_analyzer): # all circumstances. include_analyzer.timer.Cancel() - except NotCoveredError, inst: + except NotCoveredError as inst: # Warn user. The 'Preprocessing locally' message is meant to # assure the user that the build process is otherwise intact. - fd = os.tmpfile() - print >> fd, ( - "Preprocessing locally. Include server not covering: %s for " + fd = tempfile.TemporaryFile(mode='w+') + print(("Preprocessing locally. Include server not covering: %s for " + "translation unit '%s'") % ( (inst.args and inst.args[0] or "unknown reason", - include_analyzer.translation_unit)), + include_analyzer.translation_unit)), file=fd, end=' ') # We don't include a stack trace here. include_analyzer.email_sender.MaybeSendEmail(fd, never=not inst.send_email) @@ -409,7 +408,7 @@ def DistccIncludeHandlerGenerator(include_analyzer): Debug(DEBUG_TRACE, "Clearing caches because of include server timeout.") include_analyzer.ClearStatCaches() - + except SignalSIGTERM: # Normally, we will get this exception when the include server is no # longer needed. But we also handle it here, during the servicing of a @@ -419,32 +418,30 @@ def DistccIncludeHandlerGenerator(include_analyzer): except KeyboardInterrupt: # Propagate to the last-chance exception handler in Main. raise - except SystemExit, inst: + except SystemExit as inst: # When handler tries to exit (by invoking sys.exit, which in turn raises # SystemExit), something is really wrong. Terminate the include # server. But, print out an informative message first. - fd = os.tmpfile() - print >> fd, ( - ("Preprocessing locally. Include server fatal error: '%s' for " + fd = tempfile.TemporaryFile(mode='w+') + print(("Preprocessing locally. Include server fatal error: '%s' for " + "translation unit '%s'") % ( - (inst.args, include_analyzer.translation_unit))), + (inst.args, include_analyzer.translation_unit)), file=fd, end=' ') _PrintStackTrace(fd) include_analyzer.email_sender.MaybeSendEmail(fd, force=True) distcc_pump_c_extensions.XArgv(self.wfile.fileno(), []) sys.exit("Now terminating include server.") # All other exceptions are trapped here. - except Exception, inst: + except Exception as inst: # Internal error. Better be safe than sorry: terminate include # server. But show error to user on stderr. We hope this message will be # reported. - fd = os.tmpfile() - print >> fd, ( - ("Preprocessing locally. Include server internal error: '%s: %s' " - + "for translation unit '%s'") % ( - (inst.__class__, inst.args, include_analyzer.translation_unit))), + fd = tempfile.TemporaryFile(mode='w+') + print(("Preprocessing locally. Include server internal error: '%s: %s'" + + " for translation unit '%s'") % ( + (inst.__class__, inst.args, include_analyzer.translation_unit)), file=fd) _PrintStackTrace(fd) - # Force this email through (if basics.opt_send_email is True), because - # this is the last one and this is an important case to report. + # # Force this email through (if basics.opt_send_email is True), because + # # this is the last one and this is an important case to report. include_analyzer.email_sender.MaybeSendEmail(fd, force=True) distcc_pump_c_extensions.XArgv(self.wfile.fileno(), []) raise SignalSIGTERM # to be caught in Main with no further stack trace @@ -468,7 +465,7 @@ def _ParseCommandLineOptions(): Returns: (include_server_port, pid_file), where include_server_port - is a string and pid_file is a string or None + is a string and pid_file is a string or None Modifies: option variables in module basics """ @@ -500,8 +497,8 @@ def _ParseCommandLineOptions(): for opt, arg in opts: try: if opt in ("-d", "--debug_pattern"): - basics.opt_debug_pattern = int(arg) - if opt in ("--port",): + basics.opt_debug_pattern = int(arg) + if opt in ("--port", ): include_server_port = arg if opt in ("--pid_file",): pid_file = arg @@ -541,9 +538,8 @@ def _ParseCommandLineOptions(): sys.exit(1) # We must have a port! if not include_server_port: - print >> sys.stderr, "INCLUDE_SERVER_PORT not provided. Aborting." - print >> sys.stderr, "-------------------------------------------" - print >> sys.stderr + print("INCLUDE_SERVER_PORT not provided. Aborting.", file=sys.stderr) + print("-------------------------------------------", "\n", file=sys.stderr) Usage() sys.exit(1) return (include_server_port, pid_file) @@ -561,10 +557,9 @@ def _PrintTimes(times_at_start, times_at_fork, times_child): + times_child[1] + times_child[1]) total_cpu = total_u + total_s total_e = times_child[4] - times_at_start[4] - print >> sys.stderr, "Include server timing. ", - print >> sys.stderr, ( - "Elapsed: %3.1fs User: %3.1fs System: %3.1fs User + System: %3.1fs" % - (total_e, total_u, total_s, total_cpu)) + print("Include server timing. ", sys.stderr) + print("Elapsed: %3.1fs User: %3.1fs System: %3.1fs User + System: %3.1fs" % + (total_e, total_u, total_s, total_cpu), file=sys.stderr) class _IncludeServerPortReady(object): @@ -581,12 +576,12 @@ class _IncludeServerPortReady(object): def Acquire(self): """Acquire the semaphore after fork; blocks until a call of Release.""" - if os.read(self.read_fd, 1) != '\n': + if os.read(self.read_fd, 1) != b'\n': sys.exit("Include server: _IncludeServerPortReady.Acquire failed.") def Release(self): """Release the semaphore after fork.""" - if os.write(self.write_fd, '\n') != 1: + if os.write(self.write_fd, b'\n') != 1: sys.exit("Include server: _IncludeServerPortReady.Release failed.") @@ -594,7 +589,7 @@ def _SetUp(include_server_port): """Setup include_analyzer and socket server. Returns: (include_analyzer, server)""" - + try: os.unlink(include_server_port) except (IOError, OSError): @@ -615,9 +610,9 @@ def _SetUp(include_server_port): client_root_keeper, basics.opt_stat_reset_triggers)) include_analyzer.email_sender = _EmailSender() - + # Wrap it inside a handler that is a part of a UnixStreamServer. - server = QueuingSocketServer( + server = Queuingsocketserver( include_server_port, # Now, produce a StreamRequestHandler subclass whose new objects has # a handler which calls the include_analyzer just made. @@ -647,12 +642,12 @@ def Main(): # the process id of child to the pid file. times_at_fork = os.times() pid = os.fork() - if pid != 0: + if pid != 0: # In parent. # if pid_file: pid_file_fd = open(pid_file, "w") - print >> pid_file_fd, pid + print(pid, file=pid_file_fd) pid_file_fd.close() # Just run to completion now -- after making sure that child is ready. include_server_port_ready.Acquire() @@ -673,15 +668,15 @@ def Main(): # gc.set_debug(gc.DEBUG_STATS + gc.DEBUG_COLLECTABLE) server.serve_forever() except KeyboardInterrupt: - print >> sys.stderr, ( - "Include server: keyboard interrupt, quitting after cleaning up.") + print("Include server: keyboard interrupt, quitting after cleaning up.", + file=sys.stderr) _CleanOut(include_analyzer, include_server_port) except SignalSIGTERM: Debug(DEBUG_TRACE, "Include server shutting down.") _CleanOut(include_analyzer, include_server_port) except: - print >> sys.stderr, ( - "Include server: exception occurred, quitting after cleaning up.") + print("Include server: exception occurred, quitting after cleaning up.", + file=sys.stderr) _PrintStackTrace(sys.stderr) _CleanOut(include_analyzer, include_server_port) raise # reraise exception @@ -689,8 +684,8 @@ def Main(): if basics.opt_print_times: _PrintTimes(times_at_start, times_at_fork, os.times()) - + if __name__ == "__main__": - # Treat SIGTERM (the default of kill) as Ctrl-C. + # Treat SIGTERM (the default of kill) as Ctrl-C. signal.signal(signal.SIGTERM, basics.RaiseSignalSIGTERM) Main() diff --git a/include_server/include_server_test.py b/include_server/include_server_test.py index c1f4a8e..c0b88e3 100755 --- a/include_server/include_server_test.py +++ b/include_server/include_server_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2.4 +#!/usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. - + """Exercise include server handler with respect to exceptions and email. To do this, we mock out socket servers, c_extensions, email handling, and even @@ -69,7 +69,7 @@ class IncludeServerTest(unittest.TestCase): old_XArgv = distcc_pump_c_extensions.XArgv distcc_pump_c_extensions.XArgv = lambda _, __: None old_StreamRequestHandler = ( - include_server.SocketServer.StreamRequestHandler) + include_server.socketserver.StreamRequestHandler) class Mock_StreamRequestHandler(object): def __init__(self): @@ -78,7 +78,7 @@ class IncludeServerTest(unittest.TestCase): self.wfile = lambda: None self.wfile.fileno = lambda: 27 - include_server.SocketServer.StreamRequestHandler = ( + include_server.socketserver.StreamRequestHandler = ( Mock_StreamRequestHandler) include_analyzer = ( @@ -111,7 +111,7 @@ class IncludeServerTest(unittest.TestCase): distcc_pump_c_extensions.RCwd = lambda self: os.getcwd() def Expect1(txt, force, never): - self_test.assert_( + self_test.assertTrue( "Include server not covering: " + "Could not find translation unit 'parse.c'" in txt, txt) self_test.assertEqual(never, True) @@ -124,6 +124,7 @@ class IncludeServerTest(unittest.TestCase): else: raise AssertionError + # Exercise 2: provoke assertion error in cache_basics by providing an # entirely false value of current directory as provided in RCwd. @@ -136,18 +137,17 @@ class IncludeServerTest(unittest.TestCase): # mock out, in a sense, the provoked assertion exception that we # expect. The variable got_here allows us to filter the provoked exception # away from unexpected ones. - got_here = [] + got_here = [] def Expect2(txt, force, never): - self_test.assert_("Include server internal error" in txt, txt) - self_test.assert_("exceptions.AssertionError" in txt, txt) - self_test.assert_("for translation unit 'parse.c'" in txt, txt) + got_here.append(True) + self_test.assertTrue("Include server internal error" in txt, txt) + self_test.assertTrue("exceptions.AssertionError" in txt, txt) + self_test.assertTrue("for translation unit 'parse.c'" in txt, txt) # This email should be sent. self_test.assertEqual(never, False) - got_here.append(True) - mock_email_sender.expect = Expect2 try: include_handler.handle() @@ -155,7 +155,7 @@ class IncludeServerTest(unittest.TestCase): os.chdir(oldcwd) # Make sure that we're catching the induced AssertionError, not one # produced in Except2. - self.assert_(got_here) + self.assertTrue(got_here) else: raise AssertionError @@ -166,7 +166,7 @@ class IncludeServerTest(unittest.TestCase): distcc_pump_c_extensions.RCwd = lambda self: os.getcwd() def Expect3(txt, force, never): - self_test.assert_( + self_test.assertTrue( "Filepath must be relative but isn't: '/love/of/my/life'." in txt, txt) # Now check that this email is scheduled to not be sent. @@ -181,7 +181,7 @@ class IncludeServerTest(unittest.TestCase): distcc_pump_c_extensions.RWcd = old_RWcd distcc_pump_c_extensions.RArgv = old_RArgv distcc_pump_c_extensions.XArgv = old_XArgv - include_server.SocketServer.StreamRequestHandler = ( + include_server.socketserver.StreamRequestHandler = ( old_StreamRequestHandler) unittest.main() diff --git a/include_server/macro_eval.py b/include_server/macro_eval.py index 49dce53..134a54e 100755 --- a/include_server/macro_eval.py +++ b/include_server/macro_eval.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. - + """Evaluation of macros acccording to an overapproximation semantics. This module generally follows CPP semantics for the evalution of macros. But we @@ -114,7 +114,7 @@ of dcc_build_somewhere, will then perform a local compilation. Symbol Table ------------ -The symbol table is a dictionary, whose entries are of the form +The symbol table is a dictionary, whose entries are of the form symbol: definition_list @@ -188,7 +188,7 @@ def _ParseArgs(string, pos): return (None, pos) # Prepare a list of comma and extremal positions. The '(' at the left is the # first extremal position. - commas = [pos] + commas = [pos] pos_end = None inside_quotes = False for i in range(pos, len(string)): @@ -241,7 +241,7 @@ def _EvalExprHelper(expr, symbol_table, disabled): Returns: [ expr_1, expr_2, ...], which is a non-empy list of strings, namely the expansions of expr. - """ + """ def _ReEvalRecursivelyForExpansion(expansion, after): """Reevalute the expansion that is the result of finding a match for a @@ -255,7 +255,7 @@ def _EvalExprHelper(expr, symbol_table, disabled): after: the string after the expansion Modifies: value_set: the set of all possible expansions of expr - + The value set is updated according to recursive evaluations of the string that results from inserting expansion between expr[:match.start()] and expr[match.end():] (for symbol-like macro) or expr[args_end:] (for @@ -325,7 +325,7 @@ def _EvalExprHelper(expr, symbol_table, disabled): _ReEvalRecursivelyForExpansion(real_expansion, expr[args_end:]) else: assert False, "Definition '%s' is unexpected." % definition - + # Look for a symbol. match = SYMBOL_RE.search(expr) if not match: @@ -408,8 +408,8 @@ def ResolveExpr(includepath_map_index, Returns: a pair(files, symbols), where files is a list of (filepath pair, realpath index), namely those files that are successful resolutions of - possible double-quoted and angle-quoted values of expr, and symbols is - the set of all identifiers occurring in expression or its possible + possible double-quoted and angle-quoted values of expr, and symbols is + the set of all identifiers occurring in expression or its possible expansions Raises: NotCoveredError @@ -424,13 +424,11 @@ def ResolveExpr(includepath_map_index, match_result = parse_file.INCLUDE_STRING_RE.match(val) if match_result: if match_result.group('quote'): - resolved = resolve(includepath_map_index(match_result.group('quote')), - currdir_idx, searchdir_idx, quote_dirs) - resolved_files.append(resolved) + resolved = resolve(includepath_map_index(match_result.group('quote')),currdir_idx, searchdir_idx, quote_dirs) + resolved_files.append(resolved) elif match_result.group('angle'): - resolved = resolve(includepath_map_index(match_result.group('angle')), - currdir_idx, None, angle_dirs) - resolved_files.append(resolved) + resolved = resolve(includepath_map_index(match_result.group('angle')), currdir_idx, None, angle_dirs) + resolved_files.append(resolved) else: symbols.extend(SYMBOL_RE.findall(val)) if __debug__: diff --git a/include_server/macro_eval_test.py b/include_server/macro_eval_test.py index 292cf35..8bc11dc 100755 --- a/include_server/macro_eval_test.py +++ b/include_server/macro_eval_test.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. - + __author__ = "Nils Klarlund" # See also tests in include_server_test.py. @@ -140,8 +140,8 @@ class MacroEvalTest(unittest.TestCase): macro_eval.EvalExpression("myfile(hello)", { 'myfile': [(['x'], "myquote(myplace/x)")], 'myquote': [(['y'], """#y""")] }), - set(['myfile(hello)', - '"myplace/hello"', + set(['myfile(hello)', + '"myplace/hello"', 'myquote(myplace/hello)'])) @@ -166,7 +166,7 @@ class MacroEvalTest(unittest.TestCase): # #define PLUS + # #define EMPTY # #define f(x) =x= - # + # # +PLUS -EMPTY- PLUS+ f(=) # ==> + + - - + + = = = # @@ -177,7 +177,7 @@ class MacroEvalTest(unittest.TestCase): { 'PLUS':['+'], 'EMPTY':[""], 'f':[(['x'], '=x=')] }), - set(['++ -EMPTY- ++ ===', + set(['++ -EMPTY- ++ ===', '++ -EMPTY- PLUS+ ===', '+PLUS -- ++ f(=)', '+PLUS -EMPTY- ++ ===', @@ -233,5 +233,5 @@ class MacroEvalTest(unittest.TestCase): 'AS_STRING', 'AS_STRING_INTERNAL', 'tpl', 'varnames', 'h', 'foo'])) - + unittest.main() diff --git a/include_server/mirror_path.py b/include_server/mirror_path.py index dcf83eb..f51a62b 100755 --- a/include_server/mirror_path.py +++ b/include_server/mirror_path.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2.4 +#!/usr/bin/env python3 # Copyright 2007 Google Inc. # diff --git a/include_server/mirror_path_test.py b/include_server/mirror_path_test.py index 91ae819..9001de1 100755 --- a/include_server/mirror_path_test.py +++ b/include_server/mirror_path_test.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. - + __author__ = "Nils Klarlund" import os @@ -108,7 +108,7 @@ class MirrorPathTest(unittest.TestCase): # Mirror the link /a/link. self.mirror_path.DoPath('/a/link', 117, '/root') self.assertEqual(self.mirror_path.Links(), ['/root/a/link']) - self.assert_(self.simple_build_stat.Lookup('/root/a')) + self.assertTrue(self.simple_build_stat.Lookup('/root/a')) # Check that symlink function is not called again, by verifying # that mirror_path.Links() doesn't grow. diff --git a/include_server/parse_command.py b/include_server/parse_command.py index 718affd..cb9652e 100755 --- a/include_server/parse_command.py +++ b/include_server/parse_command.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. - + """Parsing of C and C++ commands and extraction of search paths.""" __author__ = "opensource@google.com (Craig Silverstein, Nils Klarlund)" @@ -222,7 +222,7 @@ def ParseCommandLineSlowly(line): if m_unesc_q: unesc_q = m_unesc_q.end() - 1 else: - unesc_q = sys.maxint + unesc_q = sys.maxsize m_nonspc = NONSPACE_RE.search(line, 0) if not m_nonspc: return args @@ -232,10 +232,10 @@ def ParseCommandLineSlowly(line): # Invariant: (1) start is at the beginning of the next argument # (perhaps at a quote, which will later be removed). (2) end is # such that line[start:end] is a prefix of the argument. - assert start <= unesc_q + assert start <= unesc_q assert start < end <= len(line), (start, end, len(line)) assert not SPACE_RE.match(line, start) - assert unesc_q == sys.maxint or line[unesc_q] == '"' + assert unesc_q == sys.maxsize or line[unesc_q] == '"' try: end = SPACE_RE.search(line, end).start() except AttributeError: @@ -262,7 +262,7 @@ def ParseCommandLineSlowly(line): m_unesc_q = NONESC_QUOTE_RE.search(line, unesc_q + 1) if not m_unesc_q: raise NotCoveredError("""Missing '"', could not parse command line.""") - assert m_unesc_q.end() - 1 > unesc_q + assert m_unesc_q.end() - 1 > unesc_q end = m_unesc_q.end() if end == len(line): args.append(ESC_QUOTE_RE.sub( @@ -277,7 +277,7 @@ def ParseCommandLineSlowly(line): if m_unesc_q: unesc_q = m_unesc_q.end() - 1 else: - unesc_q = sys.maxint + unesc_q = sys.maxsize def ParseCommandLine(line): @@ -344,7 +344,7 @@ def ParseCommandArgs(args, current_dir, includepath_map, dir_map, compiler = args[0] - i = 1 + i = 1 while i < len(args): # First, deal with everything that's not a flag-option if args[i][0] != '-' or args[i] == '-': # - is the stdin file @@ -417,7 +417,7 @@ def ParseCommandArgs(args, current_dir, includepath_map, dir_map, i += 1 continue # Done parsing arguments! - + # Sanity-checking on arguments # -I- is a special form of the -I command. if "-" in parse_state.i_dirs: @@ -429,7 +429,7 @@ def ParseCommandArgs(args, current_dir, includepath_map, dir_map, send_email=False) source_file = parse_state.file_names[0] - + if parse_state.output_file: # Use output_file to create prefix source_file_prefix = re.sub("[.]o$", "", parse_state.output_file) @@ -484,9 +484,9 @@ def ParseCommandArgs(args, current_dir, includepath_map, dir_map, ignore_absolute_path_warning=True) for f in parse_state.include_files]) - if __debug__: Debug(DEBUG_TRACE, ("ParseCommand result: %s %s %s %s %s %s" % + if __debug__: Debug(DEBUG_TRACE, ("ParseCommand result: %s %s %s %s %s %s" % (quote_dirs, angle_dirs, include_files, source_file, source_file_prefix, parse_state.Dopts))) - return (quote_dirs, angle_dirs, include_files, source_file, source_file_prefix, + return (quote_dirs, angle_dirs, include_files, source_file, source_file_prefix, parse_state.Dopts) diff --git a/include_server/parse_command_test.py b/include_server/parse_command_test.py index b7ef4e6..91a5b3a 100755 --- a/include_server/parse_command_test.py +++ b/include_server/parse_command_test.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -55,11 +55,11 @@ class ParseCommandUnitTest(unittest.TestCase): def Mock_SetSystemDirsDefaults(compiler, sysroot, language, timer=None): if compiler != mock_compiler: - raise Exception, "compiler: %s, mock_compiler: %s" % ( - compiler, mock_compiler) + raise Exception("compiler: %s, mock_compiler: %s" % ( + compiler, mock_compiler)) if sysroot != mock_sysroot: - raise Exception, "sysroot: %s, mock_sysroot: %s" % ( - sysroot, mock_sysroot) + raise Exception("sysroot: %s, mock_sysroot: %s" % ( + sysroot, mock_sysroot)) self.compiler_defaults = lambda x: x self.compiler_defaults.SetSystemDirsDefaults = Mock_SetSystemDirsDefaults @@ -141,7 +141,7 @@ class ParseCommandUnitTest(unittest.TestCase): self.assertEqual( (self._RetrieveDirectoriesExceptSys(quote_dirs), - self._RetrieveDirectoriesExceptSys(angle_dirs), + self._RetrieveDirectoriesExceptSys(angle_dirs), [self.includepath_map.String(i) for i in include_files], filepath), (('/and', 'mice', '/men', 'system'), @@ -178,8 +178,8 @@ class ParseCommandUnitTest(unittest.TestCase): self.directory_map, self.compiler_defaults)) self.assertEqual( - (self._RetrieveDirectoriesExceptSys(quote_dirs), - self._RetrieveDirectoriesExceptSys(angle_dirs), + (self._RetrieveDirectoriesExceptSys(quote_dirs), + self._RetrieveDirectoriesExceptSys(angle_dirs), filepath), (('', 'obj/gcc-4.1.0-glibc-2.2.2-piii-linux-g0-dbg/genfiles/third_party/libxml/third_party/libxml', diff --git a/include_server/parse_file.py b/include_server/parse_file.py index ac9720f..5df853f 100755 --- a/include_server/parse_file.py +++ b/include_server/parse_file.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -70,9 +70,9 @@ NOT_COMMA_OR_PARENS = "([^(),])" # symbol (something, ..., something), where something is not ',', '(', or ')' MACRO_EXPR = r""" (?P\w+) # the symbol, named 'symbol' - ( \s* + ( \s* [(] \s* # beginning parenthesis - (?P # a parenthesized expression (with no + (?P # a parenthesized expression (with no # containing expressions -- a limitation) # named 'args' %(NOT_COMMA_OR_PARENS)s* # the first argument (if it exists) @@ -184,19 +184,19 @@ class ParseFile(object): of symbol is parsed. The callback allows an include processor to adjust its notion of which expressions are still current. If we (the include processor) already met - + #define A B - + and later meet - + #define B - + whether this is the first definition of B or not, then the possible meanings of A have changed. We set up a callback to identify such situations.""" self.define_callback = callback_function - + def _ParseFine(self, poundsign_match, includepath_map_index, file_contents, symbol_table, quote_includes, angle_includes, expr_includes, next_includes): @@ -246,7 +246,7 @@ class ParseFile(object): lhs = m.group('lhs') rhs = groupdict['rhs'] and groupdict['rhs'] or None InsertMacroDefInTable(lhs, rhs, symbol_table, self.define_callback) - except NotCoveredError, inst: + except NotCoveredError as inst: # Decorate this exception with the filename, by recreating it # appropriately. if not inst.source_file: @@ -279,7 +279,7 @@ class ParseFile(object): try: fd = open(filepath, "r") - except IOError, msg: + except IOError as msg: # This normally does not happen because the file should be known to # exists. Still there might be, say, a permissions issue that prevents it # from being read. @@ -331,7 +331,7 @@ class ParseFile(object): poundsign_match = POUND_SIGN_RE.match(file_contents, line_start) if not poundsign_match: - continue + continue self._ParseFine(poundsign_match, includepath_map_index, file_contents, symbol_table, quote_includes, angle_includes, diff --git a/include_server/parse_file_test.py b/include_server/parse_file_test.py index 660df0e..bf2d691 100755 --- a/include_server/parse_file_test.py +++ b/include_server/parse_file_test.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -67,15 +67,15 @@ class parse_file_Test(unittest.TestCase): self.assertEqual(parse_file.MACRO_EXPR_RE.match("random()").group('symbol'), "random") - self.assert_(parse_file.DIRECTIVE_RE.match( + self.assertTrue(parse_file.DIRECTIVE_RE.match( """ # include """).group('angle') == 'a.c') - self.assert_(parse_file.DIRECTIVE_RE.match( + self.assertTrue(parse_file.DIRECTIVE_RE.match( """ # include mac(a.c, mic)""").group('expr') == 'mac(a.c, mic)') - self.assert_(parse_file.DIRECTIVE_RE.match( + self.assertTrue(parse_file.DIRECTIVE_RE.match( """ # include "a.c" """).group('quote') == 'a.c') - self.assert_(parse_file.DIRECTIVE_RE.match( + self.assertTrue(parse_file.DIRECTIVE_RE.match( """ #include "a.c" """).group('quote') == 'a.c') - self.assert_(parse_file.DIRECTIVE_RE.match( + self.assertTrue(parse_file.DIRECTIVE_RE.match( """ #include"a.c" """).group('quote') == 'a.c') self.assertEqual(parse_file.DIRECTIVE_RE.match( @@ -133,9 +133,11 @@ b self.assertEqual(parse_file_obj.Parse( "test_data/more_macros.c", symbol_table), ([], [], ['TEMPLATE_VARNAME(foo)'], [])) - self.assertEqual(symbol_table.keys(), - ['ILLFORMED', 'AS_STRING_INTERNAL', - 'TEMPLATE_VARNAME', 'AS_STRING']) + symbol_table_keys = list(symbol_table.keys()) + symbol_table_keys.sort() + self.assertEqual(symbol_table_keys, + ['AS_STRING', 'AS_STRING_INTERNAL', + 'ILLFORMED', 'TEMPLATE_VARNAME']) [([arg], val)] = symbol_table['TEMPLATE_VARNAME'] self.assertEqual(arg, '_filename_') self.assertEqual(val, 'AS_STRING(maps/_filename_.tpl.varnames.h)') diff --git a/include_server/run.py b/include_server/run.py index 5580d68..d2cacca 100755 --- a/include_server/run.py +++ b/include_server/run.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -48,20 +48,20 @@ Examples: From anywhere: # Start include server. /home/distcc/include_server/run.py include_server.py - + In the include_server directory: # Run include_server tests. ./run.py include_server_test.py # Pycheck include_server. - ./run.py `which pychecker` include_server.py + ./run.py `which pychecker` include_server.py In installed distcc-pump: # See 'pump' script. - $include_server_location/run.py --run_in_install include_server.py .. + $include_server_location/run.py --run_in_install include_server.py .. """ def usage(): - print USAGE + print(USAGE) sys.exit(1) DEFAULT_PATH = "c_extensions/build/lib.*/*" @@ -91,7 +91,7 @@ else: sys.exit("More than one extension module found. " + " Cannot determine which one to use.") lib_directory = os.path.dirname(potential_libs[0]) - print "__________Using Python extension in %s" % lib_directory + print("__________Using Python extension in %s" % lib_directory) # Now, the all important change to PYTHONPATH. Note that we obliterate any # environmental setting setting as well. This improves performance in @@ -101,7 +101,6 @@ os.environ['PYTHONPATH'] = lib_directory try: os.execv(os.path.join(directory, sys.argv[1]), sys.argv[1:]) except OSError: - print >> sys.stderr, ( - "Could not run: '%s' with arguments: %s" % + print("Could not run: '%s' with arguments: %s" % (os.path.join(directory, sys.argv[1]), - sys.argv[1:])) + sys.argv[1:]), file=sys.stderr) diff --git a/include_server/setup.py b/include_server/setup.py index 03085b0..1cbc9f6 100755 --- a/include_server/setup.py +++ b/include_server/setup.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2.4 +#!/usr/bin/env python3 # Copyright 2007 Google Inc. # @@ -58,7 +58,7 @@ def GetIncludes(flags): In the doctests below, note that a single quoted backslash takes four backslashes to represent if it is inside a single quoted string inside this present triple-quoted string. - + >>> GetIncludes('-I x -X -I"y" -Y') ['x', 'y'] >>> GetIncludes('-Ix -Dfoo -Iy') @@ -103,7 +103,7 @@ cpp_flags_env = os.getenv('CPPFLAGS', '') if not cpp_flags_env: # Don't quit; perhaps the user is asking for help using '--help'. # CPPFLAGS checking. - print >> sys.stderr, 'setup.py: CPPFLAGS must be defined.' + print('setup.py: CPPFLAGS must be defined.', sys.stderr) # CPPFLAGS is passed to us as it's used in the Makefile: a string that the shell # will interpret. GetInclude uses shlex to do the same kind of interpretation # in order to identify the include directory options. @@ -112,7 +112,7 @@ cpp_flags_includes = GetIncludes(cpp_flags_env) # SRCDIR checking. if not os.getenv('SRCDIR'): # Don't quit; perhaps the user is asking for help using '--help'. - print >> sys.stderr, 'setup.py: SRCDIR must be defined.' + print('setup.py: SRCDIR must be defined.', sys.stderr) srcdir = 'UNDEFINED' srcdir_include_server = 'UNDEFINED' else: diff --git a/include_server/statistics.py b/include_server/statistics.py index 6aae5d5..9677af3 100755 --- a/include_server/statistics.py +++ b/include_server/statistics.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2.4 +#! /usr/bin/env python3 # # Copyright 2007 Google Inc. # @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. -# +# """Statistics gathering for the distcc-pump include server.""" __author__ = "Nils Klarlund" @@ -38,14 +38,14 @@ min_time = float('Inf') max_time = 0.0 total_time = 0.0 -parse_file_total_time = 0.0 +parse_file_total_time = 0.0 parse_file_counter = 0 # number of files parsed parse_file_counter_last = 0 # the number of files parsed after previous # translation unit quote_path_total = 0 # total length of quote directory lists -angle_path_total = 0 # total length of angle directory lists +angle_path_total = 0 # total length of angle directory lists len_calculated_closure = 0 # number of all included files len_calculated_closure_nonsys = 0 # same, but excluding system files @@ -54,7 +54,7 @@ len_exact_closure = 0 # number of all files in CPP-calculated closure len_surplus_nonsys = 0 # the difference between # len_calculated_closure and number of files # in exact closure that are not known to compiler - + find_node_counter = 0 # number of times FindNode is called @@ -78,45 +78,45 @@ def PrintStatistics(include_analyzer): # Avoid division by zero in non-interesting case. if translation_unit_counter == 0: return - print "TRANSLATION_UNIT: %s" % include_analyzer.translation_unit + print("TRANSLATION_UNIT: %s" % include_analyzer.translation_unit) print (("TIME: last %-2.3fs, min %-2.3fs, " - "max %-2.3fs, average %-2.3fs, #: %5d, total: %5.1fs") % + "max %-2.3fs, average %-2.3fs, #: %5d, total: %5.1fs") % (translation_unit_time, min_time, max_time, total_time/translation_unit_counter, translation_unit_counter, total_time)) print ("PARSING: total %-5.3fs, total count: %4d, new files: %-5d" % - (parse_file_total_time, parse_file_counter, + (parse_file_total_time, parse_file_counter, parse_file_counter - parse_file_counter_last)) - print "COUNTER: resolve_expr_counter: %8d" % resolve_expr_counter - print "COUNTER: master_hit_counter: %8d" % master_hit_counter - print "COUNTER: master_miss_counter: %8d" % master_miss_counter - print "SIZE: master_cache %8d" % ( - len(include_analyzer.master_cache)) - print "COUNTER: sys_stat_counter: %10d" % sys_stat_counter - print "COUNTER: build_stat_counter: %10d" % build_stat_counter + print("COUNTER: resolve_expr_counter: %8d" % resolve_expr_counter) + print("COUNTER: master_hit_counter: %8d" % master_hit_counter) + print("COUNTER: master_miss_counter: %8d" % master_miss_counter) + print("SIZE: master_cache %8d" % ( + len(include_analyzer.master_cache))) + print("COUNTER: sys_stat_counter: %10d" % sys_stat_counter) + print("COUNTER: build_stat_counter: %10d" % build_stat_counter) if resolve_counter != 0: - print "COUNTER: search_counter (average): %4.1f" % ( - float(search_counter)/resolve_counter) - print "SIZE: include_dir_pairs: %8d" % ( - len(include_analyzer.include_dir_pairs)) + print("COUNTER: search_counter (average): %4.1f" % ( + float(search_counter)/resolve_counter)) + print("SIZE: include_dir_pairs: %8d" % ( + len(include_analyzer.include_dir_pairs))) if 'quote_dirs' in include_analyzer.__dict__: - print "SIZE: quote_path %8d" % ( - len(include_analyzer.quote_dirs)) + print("SIZE: quote_path %8d" % ( + len(include_analyzer.quote_dirs))) if 'angle_dirs' in include_analyzer.__dict__: - print "SIZE: angle_path %8d" % ( - len(include_analyzer.angle_dirs)) - print "SIZE: quote_path (average) %4.1f" % ( - float(quote_path_total)/translation_unit_counter) - print "SIZE: angle_path (average) %4.1f" % ( - float(angle_path_total)/translation_unit_counter) - print "SIZE: quote_dirs_set %8d" % ( - len(include_analyzer.quote_dirs_set)) - print "SIZE: angle_dirs_set: %8d" % ( - len(include_analyzer.angle_dirs_set)) - print - print "SIZE: calculated_closure: %8d" % len_calculated_closure - print "SIZE: calculated_closure_nonsys: %8d" % ( - len_calculated_closure_nonsys) - print "SIZE: exact_closure %8d" % len_exact_closure - print "SIZE: surplus_nonsys %8d" % len_surplus_nonsys - print + print("SIZE: angle_path %8d" % ( + len(include_analyzer.angle_dirs))) + print("SIZE: quote_path (average) %4.1f" % ( + float(quote_path_total)/translation_unit_counter)) + print("SIZE: angle_path (average) %4.1f" % ( + float(angle_path_total)/translation_unit_counter)) + print("SIZE: quote_dirs_set %8d" % ( + len(include_analyzer.quote_dirs_set))) + print("SIZE: angle_dirs_set: %8d" % ( + len(include_analyzer.angle_dirs_set))) + print() + print("SIZE: calculated_closure: %8d" % len_calculated_closure) + print("SIZE: calculated_closure_nonsys: %8d" % ( + len_calculated_closure_nonsys)) + print("SIZE: exact_closure %8d" % len_exact_closure) + print("SIZE: surplus_nonsys %8d" % len_surplus_nonsys) + print() diff --git a/test/comfychair.py b/test/comfychair.py index b5dda91..12c72ef 100755 --- a/test/comfychair.py +++ b/test/comfychair.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 # Copyright (C) 2002, 2003 by Martin Pool # Copyright (C) 2003 by Tim Potter diff --git a/test/onetest.py b/test/onetest.py index 4ee0c2f..ef630a0 100755 --- a/test/onetest.py +++ b/test/onetest.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2007 Google Inc. # diff --git a/test/testdistcc.py b/test/testdistcc.py index 47c89fd..38647cd 100755 --- a/test/testdistcc.py +++ b/test/testdistcc.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 # Copyright (C) 2002, 2003, 2004 by Martin Pool # Copyright 2007 Google Inc. -- cgit v1.2.1