X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2Fos.cpp;h=ab9d4159a6cc8180864e760f330af3fc95bbb5d7;hb=9234516731fac37651f5dacfc0942dc40775b96e;hp=4d2c55ed378e3862c0d4ce7c520f07e13a1bdcd4;hpb=9d0ea8aeff32833a90b3fe64df0c5518a9e241be;p=lyx.git diff --git a/src/support/os.cpp b/src/support/os.cpp index 4d2c55ed37..ab9d4159a6 100644 --- a/src/support/os.cpp +++ b/src/support/os.cpp @@ -4,13 +4,22 @@ * Licence details can be found in the file COPYING. * * \author Ruurd A. Reitsma + * \author Enrico Forestieri * * Full author contact details are available in file CREDITS. */ #include -#if defined(__CYGWIN__) || defined(__CYGWIN32__) +#include "support/convert.h" +#include "support/debug.h" +#include "support/filetools.h" +#include "support/qstring_helpers.h" +#include "support/regex.h" + +#include + +#if defined(__CYGWIN__) #include "support/os_cygwin.cpp" #elif defined(_WIN32) #include "support/os_win32.cpp" @@ -18,18 +27,133 @@ #include "support/os_unix.cpp" #endif +// Static assert to break compilation on platforms where +// int/unsigned int is not 4 bytes. Added to make sure that +// e.g., the author hash is always 32-bit. +template struct static_assert_helper; +template <> struct static_assert_helper {}; +enum { + dummy = sizeof(static_assert_helper) +}; + namespace lyx { namespace support { namespace os { -std::string const python() +int timeout_min() { - // Use the -tt switch so that mixed tab/whitespace indentation is - // an error - static std::string const command("python -tt"); - return command; + return 3; } + +static string const python23_call(string const & binary, bool verbose = false) +{ + const string version_info = " -c 'from __future__ import print_function;import sys; print(sys.version_info[:2], end=\"\")'"; + // Default to "python" if no binary is given. + if (binary.empty()) + return "python -tt"; + + if (verbose) + lyxerr << "Examining " << binary << "\n"; + // Check whether this is a python 2 or 3 binary. + cmd_ret const out = runCommand(binary + version_info); + + smatch sm; + try { + static regex const python_reg("\\((\\d*), (\\d*)\\)"); + if (out.first < 0 || !regex_match(out.second, sm, python_reg)) + return string(); + } catch(regex_error const & /*e*/) { + LYXERR0("Regex error! This should not happen."); + return string(); + } + + int major = convert(sm.str(1)); + int minor = convert(sm.str(2)); + if((major == 2 && minor < 7) || (major == 3 && minor < 5)) + return string(); + + if (verbose) + lyxerr << "Found Python " << out.second << "\n"; + // Add the -tt switch so that mixed tab/whitespace + // indentation is an error + return binary + " -tt"; } + + +static string const find_python_binary() +{ + // This function takes inspiration from PEP 394 and PEP 397 + // PEP 394 -- The "python" Command on Unix-Like Systems + // https://www.python.org/dev/peps/pep-0394/ + // PEP 397 -- Python launcher for Windows + // https://www.python.org/dev/peps/pep-0397/ + + // Check whether python3 in PATH is the right one. + string command = python23_call("python3"); + if (!command.empty()) + return command; + + // python3 does not exists, let us try to find python3.x in PATH + // the search is probably broader than required + // but we are trying hard to find a valid python binary + vector const path = getEnvPath("PATH"); + lyxerr << "Looking for python 3.x ...\n"; + for (auto bin: path) { + QString const dir = toqstr(bin); + string const localdir = dir.toLocal8Bit().constData(); + QDir qdir(dir); + qdir.setFilter(QDir::Files | QDir::Executable); + QStringList list = qdir.entryList(QStringList("python3*")); + for (auto bin: list) { + string const binary = addName(localdir, + bin.toLocal8Bit().constData()); + command = python23_call(binary, true); + if (!command.empty()) + return command; + } + } + + // python 3 was not found let us look for python 2 + command = python23_call("python2"); + if (!command.empty()) + return command; + + // python2 does not exists, let us try to find python2.x in PATH + // the search is probably broader than required + // but we are trying hard to find a valid python binary + lyxerr << "Looking for python 2.x ...\n"; + for (auto bin: path) { + QString const dir = toqstr(bin); + string const localdir = dir.toLocal8Bit().constData(); + QDir qdir(dir); + qdir.setFilter(QDir::Files | QDir::Executable); + QStringList list = qdir.entryList(QStringList("python2*")); + for (auto bin: list) { + string const binary = addName(localdir, + bin.toLocal8Bit().constData()); + command = python23_call(binary, true); + if (!command.empty()) + return command; + } + } + + // If this happens all hope is lost that this is a sane system + lyxerr << "Warning: No python v2.x or 3.x binary found.\n"; + return python23_call(""); } + + +string const python(bool reset) +{ + static string command = find_python_binary(); + // FIXME THREAD + if (reset) { + command = find_python_binary(); + } + return command; } + +} // namespace os +} // namespace support +} // namespace lyx