Implement _nt_quote_args using subprocess module's
list2cmdline since that handles all the tricky quoting
logic properly while the previous implementation was
not capable of handling anything more complicated than
the most basic commandline arguments and those with
spaces (so no tabs, or double quotes etc).
A specific example of trouble this caused was on MSYS2
when building the gobject-introspection part of GEGL 0.3.4
and a macro of -DG_LOG_DOMAIN="GEGL"-__FILE__ was passed
to the C compiler. From distutils perspective, the final
call ended up as:
gegl-introspection-module =
Extensions('gegl-introspection',
define_macros=
[('G_LOG_DOMAIN', '"GEGL-"__FILE__')])
This *will* cause trouble in software that special-cased
Windows. An example existed in Python's own setup.py when
building the sqlite module.
The MODULE_NAME define was set to '"sqlite3"' for everything
else and to '\\"sqlite3\\"' for Windows. This commit removes
this special-casing, obviously!
The bad-old-implementation has existed for so long now that
everyone's hacked around it, which means that it's probably
too late for this change, so this means in the long-term,
this commit will go one of three ways:
1. It'll stay in and we'll fix everything up that's broken.
pip and C extensions will screw up badly here.
2. I implement a two-pass scheme where I try both the old
way and the new way for things that fail on first attempt.
3. I remove this altogether, and hack up GEGL like everything
else has been hacked up, lesson learnt.
I'm leaning towards 2 at present.
Either way, I need to figure out why GEGL was hanging before
this change as that was less than useful. Some good came out
of it; we can build debuggable python2 and py-bt works now
too!
Also renamed python-gdb.py to python_gdb.py
222 lines
7.7 KiB
Diff
222 lines
7.7 KiB
Diff
diff -urN Python-2.7.10.orig/Lib/distutils/spawn.py Python-2.7.10/Lib/distutils/spawn.py
|
|
--- Python-2.7.10.orig/Lib/distutils/spawn.py 2016-01-02 00:59:12.580711100 +0000
|
|
+++ Python-2.7.10/Lib/distutils/spawn.py 2016-01-02 01:45:53.195782000 +0000
|
|
@@ -14,6 +14,7 @@
|
|
from distutils.errors import DistutilsPlatformError, DistutilsExecError
|
|
from distutils.debug import DEBUG
|
|
from distutils import log
|
|
+from list2cmdline import list2cmdline
|
|
|
|
def spawn(cmd, search_path=1, verbose=0, dry_run=0):
|
|
"""Run another program, specified as a command list 'cmd', in a new process.
|
|
@@ -47,17 +48,13 @@
|
|
def _nt_quote_args(args):
|
|
"""Quote command-line arguments for DOS/Windows conventions.
|
|
|
|
- Just wraps every argument which contains blanks in double quotes, and
|
|
- returns a new argument list.
|
|
+ Defer to list2cmdline as the logic is complex.
|
|
+ The previous implementation here failed to handle
|
|
+ -DG_LOG_DOMAIN="GEGL-"__FILE__ which was encountered in MSYS2
|
|
+ while building the gobject-introspection part of GEGL 0.3.4.
|
|
"""
|
|
- # XXX this doesn't seem very robust to me -- but if the Windows guys
|
|
- # say it'll work, I guess I'll have to accept it. (What if an arg
|
|
- # contains quotes? What other magic characters, other than spaces,
|
|
- # have to be escaped? Is there an escaping mechanism other than
|
|
- # quoting?)
|
|
for i, arg in enumerate(args):
|
|
- if ' ' in arg:
|
|
- args[i] = '"%s"' % arg
|
|
+ args[i] = list2cmdline([args[i]])
|
|
return args
|
|
|
|
def _spawn_nt(cmd, search_path=1, verbose=0, dry_run=0):
|
|
diff -urN Python-2.7.10.orig/Lib/list2cmdline.py Python-2.7.10/Lib/list2cmdline.py
|
|
--- Python-2.7.10.orig/Lib/list2cmdline.py 1970-01-01 01:00:00.000000000 +0100
|
|
+++ Python-2.7.10/Lib/list2cmdline.py 2016-01-02 01:15:25.244121800 +0000
|
|
@@ -0,0 +1,79 @@
|
|
+# list2cmdline - Utility to escape nt commandline arguments
|
|
+#
|
|
+# Copyright (c) 2003-2005 by Peter Astrand <astrand@lysator.liu.se>
|
|
+#
|
|
+# Licensed to PSF under a Contributor Agreement.
|
|
+# See http://www.python.org/2.4/license for licensing details.
|
|
+
|
|
+def list2cmdline(seq):
|
|
+ """
|
|
+ Translate a sequence of arguments into a command line
|
|
+ string, using the same rules as the MS C runtime:
|
|
+
|
|
+ 1) Arguments are delimited by white space, which is either a
|
|
+ space or a tab.
|
|
+
|
|
+ 2) A string surrounded by double quotation marks is
|
|
+ interpreted as a single argument, regardless of white space
|
|
+ contained within. A quoted string can be embedded in an
|
|
+ argument.
|
|
+
|
|
+ 3) A double quotation mark preceded by a backslash is
|
|
+ interpreted as a literal double quotation mark.
|
|
+
|
|
+ 4) Backslashes are interpreted literally, unless they
|
|
+ immediately precede a double quotation mark.
|
|
+
|
|
+ 5) If backslashes immediately precede a double quotation mark,
|
|
+ every pair of backslashes is interpreted as a literal
|
|
+ backslash. If the number of backslashes is odd, the last
|
|
+ backslash escapes the next double quotation mark as
|
|
+ described in rule 3.
|
|
+
|
|
+ Extracted from subprocess.py so that distutils spawn.py can
|
|
+ use it too.
|
|
+ """
|
|
+
|
|
+ # See
|
|
+ # http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
|
|
+ # or search http://msdn.microsoft.com for
|
|
+ # "Parsing C++ Command-Line Arguments"
|
|
+ result = []
|
|
+ needquote = False
|
|
+ for arg in seq:
|
|
+ bs_buf = []
|
|
+
|
|
+ # Add a space to separate this argument from the others
|
|
+ if result:
|
|
+ result.append(' ')
|
|
+
|
|
+ needquote = (" " in arg) or ("\t" in arg) or not arg
|
|
+ if needquote:
|
|
+ result.append('"')
|
|
+
|
|
+ for c in arg:
|
|
+ if c == '\\':
|
|
+ # Don't know if we need to double yet.
|
|
+ bs_buf.append(c)
|
|
+ elif c == '"':
|
|
+ # Double backslashes.
|
|
+ result.append('\\' * len(bs_buf)*2)
|
|
+ bs_buf = []
|
|
+ result.append('\\"')
|
|
+ else:
|
|
+ # Normal char
|
|
+ if bs_buf:
|
|
+ result.extend(bs_buf)
|
|
+ bs_buf = []
|
|
+ result.append(c)
|
|
+
|
|
+ # Add remaining backslashes, if any.
|
|
+ if bs_buf:
|
|
+ result.extend(bs_buf)
|
|
+
|
|
+ if needquote:
|
|
+ result.extend(bs_buf)
|
|
+ result.append('"')
|
|
+
|
|
+ return ''.join(result)
|
|
+
|
|
diff -urN Python-2.7.10.orig/Lib/subprocess.py Python-2.7.10/Lib/subprocess.py
|
|
--- Python-2.7.10.orig/Lib/subprocess.py 2016-01-02 00:59:10.775707300 +0000
|
|
+++ Python-2.7.10/Lib/subprocess.py 2016-01-02 01:33:13.687423600 +0000
|
|
@@ -395,6 +395,7 @@
|
|
import gc
|
|
import signal
|
|
import errno
|
|
+from list2cmdline import list2cmdline
|
|
|
|
# Exception classes used by this module.
|
|
class CalledProcessError(Exception):
|
|
@@ -574,76 +575,6 @@
|
|
return output
|
|
|
|
|
|
-def list2cmdline(seq):
|
|
- """
|
|
- Translate a sequence of arguments into a command line
|
|
- string, using the same rules as the MS C runtime:
|
|
-
|
|
- 1) Arguments are delimited by white space, which is either a
|
|
- space or a tab.
|
|
-
|
|
- 2) A string surrounded by double quotation marks is
|
|
- interpreted as a single argument, regardless of white space
|
|
- contained within. A quoted string can be embedded in an
|
|
- argument.
|
|
-
|
|
- 3) A double quotation mark preceded by a backslash is
|
|
- interpreted as a literal double quotation mark.
|
|
-
|
|
- 4) Backslashes are interpreted literally, unless they
|
|
- immediately precede a double quotation mark.
|
|
-
|
|
- 5) If backslashes immediately precede a double quotation mark,
|
|
- every pair of backslashes is interpreted as a literal
|
|
- backslash. If the number of backslashes is odd, the last
|
|
- backslash escapes the next double quotation mark as
|
|
- described in rule 3.
|
|
- """
|
|
-
|
|
- # See
|
|
- # http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
|
|
- # or search http://msdn.microsoft.com for
|
|
- # "Parsing C++ Command-Line Arguments"
|
|
- result = []
|
|
- needquote = False
|
|
- for arg in seq:
|
|
- bs_buf = []
|
|
-
|
|
- # Add a space to separate this argument from the others
|
|
- if result:
|
|
- result.append(' ')
|
|
-
|
|
- needquote = (" " in arg) or ("\t" in arg) or not arg
|
|
- if needquote:
|
|
- result.append('"')
|
|
-
|
|
- for c in arg:
|
|
- if c == '\\':
|
|
- # Don't know if we need to double yet.
|
|
- bs_buf.append(c)
|
|
- elif c == '"':
|
|
- # Double backslashes.
|
|
- result.append('\\' * len(bs_buf)*2)
|
|
- bs_buf = []
|
|
- result.append('\\"')
|
|
- else:
|
|
- # Normal char
|
|
- if bs_buf:
|
|
- result.extend(bs_buf)
|
|
- bs_buf = []
|
|
- result.append(c)
|
|
-
|
|
- # Add remaining backslashes, if any.
|
|
- if bs_buf:
|
|
- result.extend(bs_buf)
|
|
-
|
|
- if needquote:
|
|
- result.extend(bs_buf)
|
|
- result.append('"')
|
|
-
|
|
- return ''.join(result)
|
|
-
|
|
-
|
|
class Popen(object):
|
|
_child_created = False # Set here since __del__ checks it
|
|
|
|
diff -urN Python-2.7.10.orig/setup.py Python-2.7.10/setup.py
|
|
--- Python-2.7.10.orig/setup.py 2016-01-02 00:59:17.405520700 +0000
|
|
+++ Python-2.7.10/setup.py 2016-01-02 01:00:52.537873000 +0000
|
|
@@ -1167,11 +1167,7 @@
|
|
'_sqlite/statement.c',
|
|
'_sqlite/util.c', ]
|
|
|
|
- sqlite_defines = []
|
|
- if host_platform != "win32":
|
|
- sqlite_defines.append(('MODULE_NAME', '"sqlite3"'))
|
|
- else:
|
|
- sqlite_defines.append(('MODULE_NAME', '\\"sqlite3\\"'))
|
|
+ sqlite_defines = [('MODULE_NAME', '"sqlite3"')]
|
|
|
|
# Comment this out if you want the sqlite3 module to be able to load extensions.
|
|
sqlite_defines.append(("SQLITE_OMIT_LOAD_EXTENSION", "1"))
|