Compare commits
24 Commits
Author | SHA1 | Date |
---|---|---|
Charalampos Stratakis | 3ef90dfc66 | |
Miro Hrončok | 3a8efff052 | |
Miro Hrončok | 8dd12915a9 | |
Miro Hrončok | f124ad4c93 | |
Miro Hrončok | 23b7cdc7ee | |
Miro Hrončok | 1c084246f6 | |
Miro Hrončok | e73306ff64 | |
Miro Hrončok | b0edf85387 | |
Miro Hrončok | 3324e84bc3 | |
Charalampos Stratakis | bc228b8ca2 | |
Charalampos Stratakis | 6e02335726 | |
Michal Cyprian | 956845fa5b | |
Charalampos Stratakis | 73123677e8 | |
Charalampos Stratakis | d20afa1807 | |
Charalampos Stratakis | d3a063dd35 | |
Charalampos Stratakis | 08e5703d68 | |
Igor Gnatenko | ec05ee2814 | |
Miro Hrončok | 2787c85b78 | |
Charalampos Stratakis | e7bbd26b13 | |
Charalampos Stratakis | 9109dafcdb | |
Charalampos Stratakis | bfc0c338e5 | |
Charalampos Stratakis | 8b736574c2 | |
Charalampos Stratakis | b5bbd7e7a9 | |
Charalampos Stratakis | 6eb19770a6 |
|
@ -1,762 +0,0 @@
|
||||||
diff -up Python-3.3.0rc2/configure.ac.systemtap Python-3.3.0rc2/configure.ac
|
|
||||||
--- Python-3.3.0rc2/configure.ac.systemtap 2012-09-09 05:11:14.000000000 -0400
|
|
||||||
+++ Python-3.3.0rc2/configure.ac 2012-09-10 09:17:21.114511781 -0400
|
|
||||||
@@ -2678,6 +2678,23 @@ if test "$with_valgrind" != no; then
|
|
||||||
OPT="-DDYNAMIC_ANNOTATIONS_ENABLED=1 $OPT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
+# Check for systemtap support
|
|
||||||
+# On Linux, /usr/bin/dtrace is in fact a shim to SystemTap
|
|
||||||
+AC_MSG_CHECKING([for --with-systemtap])
|
|
||||||
+AC_ARG_WITH([systemtap],
|
|
||||||
+ AC_HELP_STRING([--with(out)-systemtap], [disable/enable SystemTap support]),,
|
|
||||||
+ with_systemtap=no)
|
|
||||||
+AC_MSG_RESULT([$with_systemtap])
|
|
||||||
+if test "$with_systemtap" != no; then
|
|
||||||
+ AC_DEFINE(WITH_SYSTEMTAP, 1,
|
|
||||||
+ [Define if you want to compile in SystemTap support])
|
|
||||||
+ SYSTEMTAPOBJS="Python/pysystemtap.o"
|
|
||||||
+ SYSTEMTAPDEPS="\$(srcdir)/Python/pysystemtap.h"
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
+AC_SUBST(SYSTEMTAPOBJS)
|
|
||||||
+AC_SUBST(SYSTEMTAPDEPS)
|
|
||||||
+
|
|
||||||
# -I${DLINCLDIR} is added to the compile rule for importdl.o
|
|
||||||
AC_SUBST(DLINCLDIR)
|
|
||||||
DLINCLDIR=.
|
|
||||||
diff -up Python-3.3.0rc2/Doc/howto/index.rst.systemtap Python-3.3.0rc2/Doc/howto/index.rst
|
|
||||||
--- Python-3.3.0rc2/Doc/howto/index.rst.systemtap 2012-09-09 05:10:51.000000000 -0400
|
|
||||||
+++ Python-3.3.0rc2/Doc/howto/index.rst 2012-09-10 09:17:21.117511779 -0400
|
|
||||||
@@ -29,4 +29,5 @@ Currently, the HOWTOs are:
|
|
||||||
argparse.rst
|
|
||||||
ipaddress.rst
|
|
||||||
clinic.rst
|
|
||||||
+ instrumentation.rst
|
|
||||||
|
|
||||||
diff -up Python-3.3.0rc2/Doc/howto/instrumentation.rst.systemtap Python-3.3.0rc2/Doc/howto/instrumentation.rst
|
|
||||||
--- Python-3.3.0rc2/Doc/howto/instrumentation.rst.systemtap 2012-09-10 09:17:21.117511779 -0400
|
|
||||||
+++ Python-3.3.0rc2/Doc/howto/instrumentation.rst 2012-09-10 09:17:21.117511779 -0400
|
|
||||||
@@ -0,0 +1,295 @@
|
|
||||||
+.. _instrumentation:
|
|
||||||
+
|
|
||||||
+====================================
|
|
||||||
+Instrumenting CPython with SystemTap
|
|
||||||
+====================================
|
|
||||||
+
|
|
||||||
+:author: David Malcolm <dmalcolm@redhat.com>
|
|
||||||
+
|
|
||||||
+DTrace and SystemTap are monitoring tools, each providing a way to inspect
|
|
||||||
+what the processes on a computer system are doing. They both use
|
|
||||||
+domain-specific languages allowing a user to write scripts which:
|
|
||||||
+
|
|
||||||
+ - filter which processes are to be observed
|
|
||||||
+ - gather data from the processes of interest
|
|
||||||
+ - generate reports on the data
|
|
||||||
+
|
|
||||||
+As of Python 3.3, CPython can be built with embedded "markers" that can be
|
|
||||||
+observed by a SystemTap script, making it easier to monitor what the CPython
|
|
||||||
+processes on a system are doing.
|
|
||||||
+
|
|
||||||
+.. Potentially this document could be expanded to also cover DTrace markers.
|
|
||||||
+ However, I'm not a DTrace expert.
|
|
||||||
+
|
|
||||||
+.. I'm using ".. code-block:: c" for SystemTap scripts, as "c" is syntactically
|
|
||||||
+ the closest match that Sphinx supports
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Enabling the static markers
|
|
||||||
+---------------------------
|
|
||||||
+
|
|
||||||
+In order to build CPython with the embedded markers for SystemTap, the
|
|
||||||
+SystemTap development tools must be installed.
|
|
||||||
+
|
|
||||||
+On a Fedora or Red Hat Enterprise Linux machine, this can be done via::
|
|
||||||
+
|
|
||||||
+ yum install systemtap-sdt-devel
|
|
||||||
+
|
|
||||||
+CPython must then be configured `--with-systemtap`::
|
|
||||||
+
|
|
||||||
+ checking for --with-systemtap... yes
|
|
||||||
+
|
|
||||||
+You can verify if the SystemTap static markers are present in the built
|
|
||||||
+binary by seeing if it contains a ".note.stapsdt" section.
|
|
||||||
+
|
|
||||||
+.. code-block:: bash
|
|
||||||
+
|
|
||||||
+ $ eu-readelf -S ./python | grep .note.stapsdt
|
|
||||||
+ [29] .note.stapsdt NOTE 0000000000000000 00308d78 000000b8 0 0 0 4
|
|
||||||
+
|
|
||||||
+If you've built python as a shared library (with --enable-shared), you need
|
|
||||||
+to look instead within the shared library. For example:
|
|
||||||
+
|
|
||||||
+.. code-block:: bash
|
|
||||||
+
|
|
||||||
+ $ eu-readelf -S libpython3.3dm.so.1.0 | grep .note.stapsdt
|
|
||||||
+ [28] .note.stapsdt NOTE 0000000000000000 00365b68 000000b8 0 0 0 4
|
|
||||||
+
|
|
||||||
+Earlier versions of SystemTap stored the markers in a ".probes" section.
|
|
||||||
+
|
|
||||||
+For the curious, you can see the metadata for the static markers using this
|
|
||||||
+invocation.
|
|
||||||
+
|
|
||||||
+.. code-block:: bash
|
|
||||||
+
|
|
||||||
+ $ eu-readelf -x .note.stapsdt ./python
|
|
||||||
+
|
|
||||||
+ Hex dump of section [29] '.note.stapsdt', 184 bytes at offset 0x308d78:
|
|
||||||
+ 0x00000000 08000000 45000000 03000000 73746170 ....E.......stap
|
|
||||||
+ 0x00000010 73647400 d4664b00 00000000 4fc36600 sdt..fK.....O.f.
|
|
||||||
+ 0x00000020 00000000 488d9000 00000000 70797468 ....H.......pyth
|
|
||||||
+ 0x00000030 6f6e0066 756e6374 696f6e5f 5f656e74 on.function__ent
|
|
||||||
+ 0x00000040 72790038 40257261 78203840 25726478 ry.8@%rax 8@%rdx
|
|
||||||
+ 0x00000050 202d3440 25656378 00000000 08000000 -4@%ecx........
|
|
||||||
+ 0x00000060 46000000 03000000 73746170 73647400 F.......stapsdt.
|
|
||||||
+ 0x00000070 0d674b00 00000000 4fc36600 00000000 .gK.....O.f.....
|
|
||||||
+ 0x00000080 4a8d9000 00000000 70797468 6f6e0066 J.......python.f
|
|
||||||
+ 0x00000090 756e6374 696f6e5f 5f726574 75726e00 unction__return.
|
|
||||||
+ 0x000000a0 38402572 61782038 40257264 78202d34 8@%rax 8@%rdx -4
|
|
||||||
+ 0x000000b0 40256563 78000000 @%ecx...
|
|
||||||
+
|
|
||||||
+and a sufficiently modern eu-readelf can print the metadata:
|
|
||||||
+
|
|
||||||
+.. code-block:: bash
|
|
||||||
+
|
|
||||||
+ $ eu-readelf -n ./python
|
|
||||||
+
|
|
||||||
+ Note section [ 1] '.note.gnu.build-id' of 36 bytes at offset 0x190:
|
|
||||||
+ Owner Data size Type
|
|
||||||
+ GNU 20 GNU_BUILD_ID
|
|
||||||
+ Build ID: a28f8db1b224530b0d38ad7b82a249cf7c3f18d6
|
|
||||||
+
|
|
||||||
+ Note section [27] '.note.stapsdt' of 184 bytes at offset 0x1ae884:
|
|
||||||
+ Owner Data size Type
|
|
||||||
+ stapsdt 70 Version: 3
|
|
||||||
+ PC: 0xe0d3a, Base: 0x14b150, Semaphore: 0x3ae882
|
|
||||||
+ Provider: python, Name: function__return, Args: '8@%rbx 8@%r13 -4@%eax'
|
|
||||||
+ stapsdt 69 Version: 3
|
|
||||||
+ PC: 0xe0f37, Base: 0x14b150, Semaphore: 0x3ae880
|
|
||||||
+ Provider: python, Name: function__entry, Args: '8@%rbx 8@%r13 -4@%eax'
|
|
||||||
+
|
|
||||||
+The above metadata contains information for SystemTap describing how it can
|
|
||||||
+patch strategically-placed machine code instructions to enable the tracing
|
|
||||||
+hooks used by a SystemTap script.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Static markers
|
|
||||||
+--------------
|
|
||||||
+
|
|
||||||
+The low-level way to use the SystemTap integration is to use the static
|
|
||||||
+markers directly. This requires you to explicitly state the binary file
|
|
||||||
+containing them.
|
|
||||||
+
|
|
||||||
+For example, this script can be used to show the call/return hierarchy of a
|
|
||||||
+Python script:
|
|
||||||
+
|
|
||||||
+.. code-block:: c
|
|
||||||
+
|
|
||||||
+ probe process('python').mark("function__entry") {
|
|
||||||
+ filename = user_string($arg1);
|
|
||||||
+ funcname = user_string($arg2);
|
|
||||||
+ lineno = $arg3;
|
|
||||||
+
|
|
||||||
+ printf("%s => %s in %s:%d\\n",
|
|
||||||
+ thread_indent(1), funcname, filename, lineno);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ probe process('python').mark("function__return") {
|
|
||||||
+ filename = user_string($arg1);
|
|
||||||
+ funcname = user_string($arg2);
|
|
||||||
+ lineno = $arg3;
|
|
||||||
+
|
|
||||||
+ printf("%s <= %s in %s:%d\\n",
|
|
||||||
+ thread_indent(-1), funcname, filename, lineno);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+It can be invoked like this:
|
|
||||||
+
|
|
||||||
+.. code-block:: bash
|
|
||||||
+
|
|
||||||
+ $ stap \
|
|
||||||
+ show-call-hierarchy.stp \
|
|
||||||
+ -c ./python test.py
|
|
||||||
+
|
|
||||||
+The output looks like this::
|
|
||||||
+
|
|
||||||
+ 11408 python(8274): => __contains__ in Lib/_abcoll.py:362
|
|
||||||
+ 11414 python(8274): => __getitem__ in Lib/os.py:425
|
|
||||||
+ 11418 python(8274): => encode in Lib/os.py:490
|
|
||||||
+ 11424 python(8274): <= encode in Lib/os.py:493
|
|
||||||
+ 11428 python(8274): <= __getitem__ in Lib/os.py:426
|
|
||||||
+ 11433 python(8274): <= __contains__ in Lib/_abcoll.py:366
|
|
||||||
+
|
|
||||||
+where the columns are:
|
|
||||||
+
|
|
||||||
+ - time in microseconds since start of script
|
|
||||||
+
|
|
||||||
+ - name of executable
|
|
||||||
+
|
|
||||||
+ - PID of process
|
|
||||||
+
|
|
||||||
+and the remainder indicates the call/return hierarchy as the script executes.
|
|
||||||
+
|
|
||||||
+For a `--enable-shared` build of CPython, the markers are contained within the
|
|
||||||
+libpython shared library, and the probe's dotted path needs to reflect this. For
|
|
||||||
+example, this line from the above example::
|
|
||||||
+
|
|
||||||
+ probe process('python').mark("function__entry") {
|
|
||||||
+
|
|
||||||
+should instead read::
|
|
||||||
+
|
|
||||||
+ probe process('python').library("libpython3.3dm.so.1.0").mark("function__entry") {
|
|
||||||
+
|
|
||||||
+(assuming a debug build of CPython 3.3)
|
|
||||||
+
|
|
||||||
+.. I'm reusing the "c:function" type for markers
|
|
||||||
+
|
|
||||||
+.. c:function:: function__entry(str filename, str funcname, int lineno)
|
|
||||||
+
|
|
||||||
+ This marker indicates that execution of a Python function has begun. It is
|
|
||||||
+ only triggered for pure-python (bytecode) functions.
|
|
||||||
+
|
|
||||||
+ The filename, function name, and line number are provided back to the
|
|
||||||
+ tracing script as positional arguments, which must be accessed using
|
|
||||||
+ `$arg1`, `$arg2`:
|
|
||||||
+
|
|
||||||
+ * `$arg1` : `(const char *)` filename, accessible using `user_string($arg1)`
|
|
||||||
+
|
|
||||||
+ * `$arg2` : `(const char *)` function name, accessible using
|
|
||||||
+ `user_string($arg2)`
|
|
||||||
+
|
|
||||||
+ * `$arg3` : `int` line number
|
|
||||||
+
|
|
||||||
+ * `$arg4` : `(PyFrameObject *)`, the frame being executed
|
|
||||||
+
|
|
||||||
+.. c:function:: function__return(str filename, str funcname, int lineno)
|
|
||||||
+
|
|
||||||
+ This marker is the converse of `function__entry`, and indicates that
|
|
||||||
+ execution of a Python function has ended (either via ``return``, or via an
|
|
||||||
+ exception). It is only triggered for pure-python (bytecode) functions.
|
|
||||||
+
|
|
||||||
+ The arguments are the same as for `function__entry`
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Tapsets
|
|
||||||
+-------
|
|
||||||
+
|
|
||||||
+The higher-level way to use the SystemTap integration is to use a "tapset":
|
|
||||||
+SystemTap's equivalent of a library, which hides some of the lower-level
|
|
||||||
+details of the static markers.
|
|
||||||
+
|
|
||||||
+Here is a tapset file, based on a non-shared build of CPython:
|
|
||||||
+
|
|
||||||
+.. code-block:: c
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ Provide a higher-level wrapping around the function__entry and
|
|
||||||
+ function__return markers:
|
|
||||||
+ */
|
|
||||||
+ probe python.function.entry = process("python").mark("function__entry")
|
|
||||||
+ {
|
|
||||||
+ filename = user_string($arg1);
|
|
||||||
+ funcname = user_string($arg2);
|
|
||||||
+ lineno = $arg3;
|
|
||||||
+ frameptr = $arg4
|
|
||||||
+ }
|
|
||||||
+ probe python.function.return = process("python").mark("function__return")
|
|
||||||
+ {
|
|
||||||
+ filename = user_string($arg1);
|
|
||||||
+ funcname = user_string($arg2);
|
|
||||||
+ lineno = $arg3;
|
|
||||||
+ frameptr = $arg4
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+If this file is installed in SystemTap's tapset directory (e.g.
|
|
||||||
+`/usr/share/systemtap/tapset`), then these additional probepoints become
|
|
||||||
+available:
|
|
||||||
+
|
|
||||||
+.. c:function:: python.function.entry(str filename, str funcname, int lineno, frameptr)
|
|
||||||
+
|
|
||||||
+ This probe point indicates that execution of a Python function has begun.
|
|
||||||
+ It is only triggered for pure-python (bytecode) functions.
|
|
||||||
+
|
|
||||||
+.. c:function:: python.function.return(str filename, str funcname, int lineno, frameptr)
|
|
||||||
+
|
|
||||||
+ This probe point is the converse of `python.function.return`, and indicates
|
|
||||||
+ that execution of a Python function has ended (either via ``return``, or
|
|
||||||
+ via an exception). It is only triggered for pure-python (bytecode) functions.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Examples
|
|
||||||
+--------
|
|
||||||
+This SystemTap script uses the tapset above to more cleanly implement the
|
|
||||||
+example given above of tracing the Python function-call hierarchy, without
|
|
||||||
+needing to directly name the static markers:
|
|
||||||
+
|
|
||||||
+.. code-block:: c
|
|
||||||
+
|
|
||||||
+ probe python.function.entry
|
|
||||||
+ {
|
|
||||||
+ printf("%s => %s in %s:%d\n",
|
|
||||||
+ thread_indent(1), funcname, filename, lineno);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ probe python.function.return
|
|
||||||
+ {
|
|
||||||
+ printf("%s <= %s in %s:%d\n",
|
|
||||||
+ thread_indent(-1), funcname, filename, lineno);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+The following script uses the tapset above to provide a top-like view of all
|
|
||||||
+running CPython code, showing the top 20 most frequently-entered bytecode
|
|
||||||
+frames, each second, across the whole system:
|
|
||||||
+
|
|
||||||
+.. code-block:: c
|
|
||||||
+
|
|
||||||
+ global fn_calls;
|
|
||||||
+
|
|
||||||
+ probe python.function.entry
|
|
||||||
+ {
|
|
||||||
+ fn_calls[pid(), filename, funcname, lineno] += 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ probe timer.ms(1000) {
|
|
||||||
+ printf("\033[2J\033[1;1H") /* clear screen */
|
|
||||||
+ printf("%6s %80s %6s %30s %6s\n",
|
|
||||||
+ "PID", "FILENAME", "LINE", "FUNCTION", "CALLS")
|
|
||||||
+ foreach ([pid, filename, funcname, lineno] in fn_calls- limit 20) {
|
|
||||||
+ printf("%6d %80s %6d %30s %6d\n",
|
|
||||||
+ pid, filename, lineno, funcname,
|
|
||||||
+ fn_calls[pid, filename, funcname, lineno]);
|
|
||||||
+ }
|
|
||||||
+ delete fn_calls;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
diff -up Python-3.3.0rc2/Lib/test/test_systemtap.py.systemtap Python-3.3.0rc2/Lib/test/test_systemtap.py
|
|
||||||
--- Python-3.3.0rc2/Lib/test/test_systemtap.py.systemtap 2012-09-10 09:17:21.117511779 -0400
|
|
||||||
+++ Python-3.3.0rc2/Lib/test/test_systemtap.py 2012-09-10 09:17:21.117511779 -0400
|
|
||||||
@@ -0,0 +1,234 @@
|
|
||||||
+# Verify that systemtap static probes work
|
|
||||||
+#
|
|
||||||
+import subprocess
|
|
||||||
+import sys
|
|
||||||
+import sysconfig
|
|
||||||
+import os
|
|
||||||
+import unittest
|
|
||||||
+
|
|
||||||
+from test.support import run_unittest, TESTFN, unlink
|
|
||||||
+
|
|
||||||
+if '--with-systemtap' not in sysconfig.get_config_var('CONFIG_ARGS'):
|
|
||||||
+ raise unittest.SkipTest("Python was not configured --with-systemtap")
|
|
||||||
+
|
|
||||||
+try:
|
|
||||||
+ _, stap_version = subprocess.Popen(["stap", "-V"],
|
|
||||||
+ stdout=subprocess.PIPE,
|
|
||||||
+ stderr=subprocess.PIPE,
|
|
||||||
+ ).communicate()
|
|
||||||
+except OSError:
|
|
||||||
+ # This is what "no stap" looks like. There may, however, be other
|
|
||||||
+ # errors that manifest this way too.
|
|
||||||
+ raise unittest.SkipTest("Couldn't find stap on the path")
|
|
||||||
+
|
|
||||||
+def invoke_systemtap_script(script, cmd):
|
|
||||||
+ # Start a child process, probing with the given systemtap script
|
|
||||||
+ # (passed as stdin to the "stap" tool)
|
|
||||||
+ # The script should be a bytes instance
|
|
||||||
+ # Return (stdout, stderr) pair
|
|
||||||
+
|
|
||||||
+ p = subprocess.Popen(["stap", "-", '-vv', '-c', cmd],
|
|
||||||
+ stdin=subprocess.PIPE,
|
|
||||||
+ stdout=subprocess.PIPE,
|
|
||||||
+ stderr=subprocess.PIPE)
|
|
||||||
+ out, err = p.communicate(input=script)
|
|
||||||
+ return out, err
|
|
||||||
+
|
|
||||||
+# Verify that stap can run a simple "hello world"-style script
|
|
||||||
+# This can fail for various reasons:
|
|
||||||
+# - missing kernel headers
|
|
||||||
+# - permissions (a non-root user needs to be in the "stapdev" group)
|
|
||||||
+TRIVIAL_STAP_SCRIPT = b'probe begin { println("hello world") exit () }'
|
|
||||||
+
|
|
||||||
+out, err = invoke_systemtap_script(TRIVIAL_STAP_SCRIPT, 'true')
|
|
||||||
+if out != b'hello world\n':
|
|
||||||
+ raise unittest.SkipTest("Test systemtap script did not run; stderr was: %s" % err)
|
|
||||||
+
|
|
||||||
+# We don't expect stderr to be empty, since we're invoking stap with "-vv": stap
|
|
||||||
+# will (we hope) generate debugging output on stderr.
|
|
||||||
+
|
|
||||||
+def invoke_python_under_systemtap(script, pythoncode=None, pythonfile=None):
|
|
||||||
+ # Start a child python process, probing with the given systemtap script
|
|
||||||
+ # (passed as stdin to the "stap" tool)
|
|
||||||
+ # The script should be a bytes instance
|
|
||||||
+ # Return (stdout, stderr) pair
|
|
||||||
+
|
|
||||||
+ if pythonfile:
|
|
||||||
+ pythoncmd = '%s %s' % (sys.executable, pythonfile)
|
|
||||||
+ else:
|
|
||||||
+ pythoncmd = '%s -c %r' % (sys.executable, pythoncode)
|
|
||||||
+
|
|
||||||
+ # The process tree of a stap invocation of a command goes through
|
|
||||||
+ # something like this:
|
|
||||||
+ # stap ->fork/exec(staprun; exec stapio ->f/e(-c cmd); exec staprun -r)
|
|
||||||
+ # and this trip through setuid leads to LD_LIBRARY_PATH being dropped,
|
|
||||||
+ # which would lead to an --enable-shared build of python failing to be
|
|
||||||
+ # find its libpython, with an error like:
|
|
||||||
+ # error while loading shared libraries: libpython3.3dm.so.1.0: cannot
|
|
||||||
+ # open shared object file: No such file or directory
|
|
||||||
+ # Hence we need to jump through some hoops to expose LD_LIBRARY_PATH to
|
|
||||||
+ # the invoked python process:
|
|
||||||
+ LD_LIBRARY_PATH = os.environ.get('LD_LIBRARY_PATH', '')
|
|
||||||
+ if LD_LIBRARY_PATH:
|
|
||||||
+ pythoncmd = 'env LD_LIBRARY_PATH=%s ' % LD_LIBRARY_PATH + pythoncmd
|
|
||||||
+
|
|
||||||
+ return invoke_systemtap_script(script, pythoncmd)
|
|
||||||
+
|
|
||||||
+# When using the static markers, we need to supply the prefix of a systemtap
|
|
||||||
+# dotted probe point that containing the marker.
|
|
||||||
+# See http://sourceware.org/systemtap/langref/Probe_points.html
|
|
||||||
+#
|
|
||||||
+# We need to determine if this is a shared-library build
|
|
||||||
+#
|
|
||||||
+# Note that sysconfig can get this wrong; see:
|
|
||||||
+# http://bugs.python.org/issue14774
|
|
||||||
+#
|
|
||||||
+if '--enable-shared' in sysconfig.get_config_var('CONFIG_ARGS'):
|
|
||||||
+ # For a shared-library build, the markers are in library(INSTSONAME):
|
|
||||||
+ INSTSONAME = sysconfig.get_config_var('INSTSONAME')
|
|
||||||
+ probe_prefix = 'process("%s").library("%s")' % (sys.executable, INSTSONAME)
|
|
||||||
+else:
|
|
||||||
+ # For a non-shared-library build, we can simply use sys.executable:
|
|
||||||
+ probe_prefix = 'process("%s")' % sys.executable
|
|
||||||
+
|
|
||||||
+# The following script ought to generate lots of lines showing recursive
|
|
||||||
+# function entry and return, of the form:
|
|
||||||
+# 11408 python(8274): => __contains__ in Lib/_abcoll.py:362
|
|
||||||
+# 11414 python(8274): => __getitem__ in Lib/os.py:425
|
|
||||||
+# 11418 python(8274): => encode in Lib/os.py:490
|
|
||||||
+# 11424 python(8274): <= encode in Lib/os.py:493
|
|
||||||
+# 11428 python(8274): <= __getitem__ in Lib/os.py:426
|
|
||||||
+# 11433 python(8274): <= __contains__ in Lib/_abcoll.py:366
|
|
||||||
+# where the column are:
|
|
||||||
+# - time in microseconds since start of script
|
|
||||||
+# - name of executable
|
|
||||||
+# - PID of process
|
|
||||||
+# and the remainder indicates the call/return hierarchy
|
|
||||||
+
|
|
||||||
+hierarchy_script = ('''
|
|
||||||
+probe %s.mark("function__entry") {
|
|
||||||
+ filename = user_string($arg1);
|
|
||||||
+ funcname = user_string($arg2);
|
|
||||||
+ lineno = $arg3;
|
|
||||||
+
|
|
||||||
+ printf("%%s => %%s in %%s:%%d\\n", thread_indent(1), funcname, filename, lineno);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+probe %s.mark("function__return") {
|
|
||||||
+ filename = user_string($arg1);
|
|
||||||
+ funcname = user_string($arg2);
|
|
||||||
+ lineno = $arg3;
|
|
||||||
+
|
|
||||||
+ printf("%%s <= %%s in %%s:%%d\\n", thread_indent(-1), funcname, filename, lineno);
|
|
||||||
+}
|
|
||||||
+''' % (probe_prefix, probe_prefix)).encode('utf-8')
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+class ErrorDumper:
|
|
||||||
+ # A context manager that dumps extra information if an exception is raised,
|
|
||||||
+ # to help track down why the problem occurred
|
|
||||||
+ def __init__(self, out, err):
|
|
||||||
+ self.out = out
|
|
||||||
+ self.err = err
|
|
||||||
+
|
|
||||||
+ def __enter__(self):
|
|
||||||
+ pass
|
|
||||||
+
|
|
||||||
+ def __exit__(self, type_, value, traceback):
|
|
||||||
+ if type_:
|
|
||||||
+ # an exception is being raised:
|
|
||||||
+ print('stdout: %s' % out.decode())
|
|
||||||
+ print('stderr: %s' % err.decode())
|
|
||||||
+
|
|
||||||
+class SystemtapTests(unittest.TestCase):
|
|
||||||
+
|
|
||||||
+ def test_invoking_python(self):
|
|
||||||
+ # Ensure that we can invoke python under stap, with a trivial stap
|
|
||||||
+ # script:
|
|
||||||
+ out, err = invoke_python_under_systemtap(
|
|
||||||
+ b'probe begin { println("hello from stap") exit () }',
|
|
||||||
+ pythoncode="print('hello from python')")
|
|
||||||
+ with ErrorDumper(out, err):
|
|
||||||
+ self.assertIn(b'hello from stap', out)
|
|
||||||
+ self.assertIn(b'hello from python', out)
|
|
||||||
+
|
|
||||||
+ def test_function_entry(self):
|
|
||||||
+ # Ensure that the function_entry static marker works
|
|
||||||
+ out, err = invoke_python_under_systemtap(hierarchy_script)
|
|
||||||
+ # stdout ought to contain various lines showing recursive function
|
|
||||||
+ # entry and return (see above)
|
|
||||||
+
|
|
||||||
+ # Uncomment this for debugging purposes:
|
|
||||||
+ # print(out.decode('utf-8'))
|
|
||||||
+
|
|
||||||
+ # Executing the cmdline-supplied "pass":
|
|
||||||
+ # 0 python(8274): => <module> in <string>:1
|
|
||||||
+ # 5 python(8274): <= <module> in <string>:1
|
|
||||||
+ with ErrorDumper(out, err):
|
|
||||||
+ self.assertIn(b'=> <module> in <string>:1', out,
|
|
||||||
+ msg="stdout: %s\nstderr: %s\n" % (out, err))
|
|
||||||
+
|
|
||||||
+ def test_function_encoding(self):
|
|
||||||
+ # Ensure that function names containing non-Latin 1 code
|
|
||||||
+ # points are handled:
|
|
||||||
+ pythonfile = TESTFN
|
|
||||||
+ try:
|
|
||||||
+ unlink(pythonfile)
|
|
||||||
+ f = open(pythonfile, "wb")
|
|
||||||
+ f.write("""
|
|
||||||
+# Sample script with non-ASCII filename, for use by test_systemtap.py
|
|
||||||
+# Implicitly UTF-8
|
|
||||||
+
|
|
||||||
+def 文字化け():
|
|
||||||
+ '''Function with non-ASCII identifier; I believe this reads "mojibake"'''
|
|
||||||
+ print("hello world!")
|
|
||||||
+
|
|
||||||
+文字化け()
|
|
||||||
+""".encode('utf-8'))
|
|
||||||
+ f.close()
|
|
||||||
+
|
|
||||||
+ out, err = invoke_python_under_systemtap(hierarchy_script,
|
|
||||||
+ pythonfile=pythonfile)
|
|
||||||
+ out_utf8 = out.decode('utf-8')
|
|
||||||
+ with ErrorDumper(out, err):
|
|
||||||
+ self.assertIn('=> <module> in %s:5' % pythonfile, out_utf8)
|
|
||||||
+ self.assertIn(' => 文字化け in %s:5' % pythonfile, out_utf8)
|
|
||||||
+ self.assertIn(' <= 文字化け in %s:7' % pythonfile, out_utf8)
|
|
||||||
+ self.assertIn('<= <module> in %s:9' % pythonfile, out_utf8)
|
|
||||||
+ finally:
|
|
||||||
+ unlink(pythonfile)
|
|
||||||
+
|
|
||||||
+ @unittest.skipIf(sys.getfilesystemencoding() == 'ascii',
|
|
||||||
+ 'the test filename is not encodable with ASCII')
|
|
||||||
+ def test_filename_encoding(self):
|
|
||||||
+ # Ensure that scripts names containing non-Latin 1 code
|
|
||||||
+ # points are handled:
|
|
||||||
+ pythonfile = TESTFN + '_☠.py'
|
|
||||||
+ try:
|
|
||||||
+ unlink(pythonfile)
|
|
||||||
+ f = open(pythonfile, "wb")
|
|
||||||
+ f.write("""
|
|
||||||
+def foo():
|
|
||||||
+ '''Function with non-ASCII identifier; I believe this reads "mojibake"'''
|
|
||||||
+ print("hello world!")
|
|
||||||
+
|
|
||||||
+foo()
|
|
||||||
+""".encode('utf-8'))
|
|
||||||
+ f.close()
|
|
||||||
+
|
|
||||||
+ out, err = invoke_python_under_systemtap(hierarchy_script,
|
|
||||||
+ pythonfile=pythonfile)
|
|
||||||
+ out_utf8 = out.decode('utf-8')
|
|
||||||
+ with ErrorDumper(out, err):
|
|
||||||
+ self.assertIn('=> <module> in %s:2' % pythonfile, out_utf8)
|
|
||||||
+ self.assertIn(' => foo in %s:2' % pythonfile, out_utf8)
|
|
||||||
+ self.assertIn(' <= foo in %s:4' % pythonfile, out_utf8)
|
|
||||||
+ self.assertIn('<= <module> in %s:6' % pythonfile, out_utf8)
|
|
||||||
+ finally:
|
|
||||||
+ unlink(pythonfile)
|
|
||||||
+
|
|
||||||
+def test_main():
|
|
||||||
+ run_unittest(SystemtapTests)
|
|
||||||
+
|
|
||||||
+if __name__ == "__main__":
|
|
||||||
+ test_main()
|
|
||||||
diff -up Python-3.3.0rc2/Makefile.pre.in.systemtap Python-3.3.0rc2/Makefile.pre.in
|
|
||||||
--- Python-3.3.0rc2/Makefile.pre.in.systemtap 2012-09-09 05:11:05.000000000 -0400
|
|
||||||
+++ Python-3.3.0rc2/Makefile.pre.in 2012-09-10 09:19:51.195501518 -0400
|
|
||||||
@@ -363,6 +363,7 @@ PYTHON_OBJS= \
|
|
||||||
Python/formatter_unicode.o \
|
|
||||||
Python/fileutils.o \
|
|
||||||
Python/$(DYNLOADFILE) \
|
|
||||||
+ @SYSTEMTAPOBJS@ \
|
|
||||||
$(LIBOBJS) \
|
|
||||||
$(MACHDEP_OBJS) \
|
|
||||||
$(THREADOBJ)
|
|
||||||
@@ -713,7 +714,8 @@ Objects/setobject.o: $(srcdir)/Objects/s
|
|
||||||
$(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES)
|
|
||||||
$(OPCODETARGETGEN) $(OPCODETARGETS_H)
|
|
||||||
|
|
||||||
-Python/ceval.o: $(OPCODETARGETS_H) $(srcdir)/Python/ceval_gil.h
|
|
||||||
+Python/ceval.o: $(OPCODETARGETS_H) $(srcdir)/Python/ceval_gil.h \
|
|
||||||
+ $(srcdir)/Python/ceval_systemtap.h @SYSTEMTAPDEPS@
|
|
||||||
|
|
||||||
Python/frozen.o: Python/importlib.h Python/importlib_external.h
|
|
||||||
|
|
||||||
@@ -724,6 +726,13 @@ Objects/typeobject.o: $(srcdir)/Objects/
|
|
||||||
Objects/typeslots.inc: $(srcdir)/Include/typeslots.h $(srcdir)/Objects/typeslots.py
|
|
||||||
$(PYTHON) $(srcdir)/Objects/typeslots.py < $(srcdir)/Include/typeslots.h > Objects/typeslots.inc
|
|
||||||
|
|
||||||
+# Only needed with --with-systemtap; not a public header:
|
|
||||||
+$(srcdir)/Python/pysystemtap.h: $(srcdir)/Python/pysystemtap.d
|
|
||||||
+ dtrace -o $@ $(DFLAGS) -C -h -s $(srcdir)/Python/pysystemtap.d
|
|
||||||
+
|
|
||||||
+Python/pysystemtap.o: $(srcdir)/Python/pysystemtap.d Python/ceval.o
|
|
||||||
+ dtrace -o $@ $(DFLAGS) -C -G -s $(srcdir)/Python/pysystemtap.d Python/ceval.o
|
|
||||||
+
|
|
||||||
############################################################################
|
|
||||||
# Header files
|
|
||||||
|
|
||||||
@@ -1345,6 +1354,7 @@ clean: pycremoval
|
|
||||||
-rm -f Lib/lib2to3/*Grammar*.pickle
|
|
||||||
-rm -f Programs/_testembed Programs/_freeze_importlib
|
|
||||||
-rm -rf build
|
|
||||||
+ -rm -f $(srcdir)/Python/pysystemtap.h
|
|
||||||
|
|
||||||
profile-removal:
|
|
||||||
find . -name '*.gc??' -exec rm -f {} ';'
|
|
||||||
diff -up Python-3.3.0rc2/pyconfig.h.in.systemtap Python-3.3.0rc2/pyconfig.h.in
|
|
||||||
--- Python-3.3.0rc2/pyconfig.h.in.systemtap 2012-09-09 05:11:14.000000000 -0400
|
|
||||||
+++ Python-3.3.0rc2/pyconfig.h.in 2012-09-10 09:17:21.120511781 -0400
|
|
||||||
@@ -1306,6 +1306,9 @@
|
|
||||||
/* Define if you want to compile in Python-specific mallocs */
|
|
||||||
#undef WITH_PYMALLOC
|
|
||||||
|
|
||||||
+/* Define if you want to compile in SystemTap support */
|
|
||||||
+#undef WITH_SYSTEMTAP
|
|
||||||
+
|
|
||||||
/* Define if you want to compile in rudimentary thread support */
|
|
||||||
#undef WITH_THREAD
|
|
||||||
|
|
||||||
diff -up Python-3.3.0rc2/Python/ceval.c.systemtap Python-3.3.0rc2/Python/ceval.c
|
|
||||||
--- Python-3.3.0rc2/Python/ceval.c.systemtap 2012-09-09 05:11:12.000000000 -0400
|
|
||||||
+++ Python-3.3.0rc2/Python/ceval.c 2012-09-10 09:17:21.122511781 -0400
|
|
||||||
@@ -18,6 +18,8 @@
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
+#include "ceval_systemtap.h"
|
|
||||||
+
|
|
||||||
#ifndef WITH_TSC
|
|
||||||
|
|
||||||
#define READ_TIMESTAMP(var)
|
|
||||||
@@ -1160,6 +1162,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (PYTHON_FUNCTION_ENTRY_ENABLED()) {
|
|
||||||
+ systemtap_function_entry(f);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
co = f->f_code;
|
|
||||||
names = co->co_names;
|
|
||||||
consts = co->co_consts;
|
|
||||||
@@ -3077,6 +3083,11 @@ fast_yield:
|
|
||||||
|
|
||||||
/* pop frame */
|
|
||||||
exit_eval_frame:
|
|
||||||
+
|
|
||||||
+ if (PYTHON_FUNCTION_RETURN_ENABLED()) {
|
|
||||||
+ systemtap_function_return(f);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
Py_LeaveRecursiveCall();
|
|
||||||
f->f_executing = 0;
|
|
||||||
tstate->frame = f->f_back;
|
|
||||||
diff -up Python-3.3.0rc2/Python/ceval_systemtap.h.systemtap Python-3.3.0rc2/Python/ceval_systemtap.h
|
|
||||||
--- Python-3.3.0rc2/Python/ceval_systemtap.h.systemtap 2012-09-10 09:17:21.122511781 -0400
|
|
||||||
+++ Python-3.3.0rc2/Python/ceval_systemtap.h 2012-09-10 09:17:21.122511781 -0400
|
|
||||||
@@ -0,0 +1,86 @@
|
|
||||||
+/*
|
|
||||||
+ Support for SystemTap static markers
|
|
||||||
+*/
|
|
||||||
+
|
|
||||||
+#ifdef WITH_SYSTEMTAP
|
|
||||||
+
|
|
||||||
+#include "pysystemtap.h"
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ A struct to hold all of the information gathered when one of the traceable
|
|
||||||
+ markers is triggered
|
|
||||||
+*/
|
|
||||||
+struct frame_marker_info
|
|
||||||
+{
|
|
||||||
+ PyObject *filename_obj;
|
|
||||||
+ PyObject *funcname_obj;
|
|
||||||
+ const char *filename;
|
|
||||||
+ const char *funcname;
|
|
||||||
+ int lineno;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+get_frame_marker_info(PyFrameObject *f, struct frame_marker_info *fmi)
|
|
||||||
+{
|
|
||||||
+ PyObject *ptype;
|
|
||||||
+ PyObject *pvalue;
|
|
||||||
+ PyObject *ptraceback;
|
|
||||||
+
|
|
||||||
+ PyErr_Fetch(&ptype, &pvalue, &ptraceback);
|
|
||||||
+
|
|
||||||
+ fmi->filename_obj = PyUnicode_EncodeFSDefault(f->f_code->co_filename);
|
|
||||||
+ if (fmi->filename_obj) {
|
|
||||||
+ fmi->filename = PyBytes_AsString(fmi->filename_obj);
|
|
||||||
+ } else {
|
|
||||||
+ fmi->filename = NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fmi->funcname_obj = PyUnicode_AsUTF8String(f->f_code->co_name);
|
|
||||||
+ if (fmi->funcname_obj) {
|
|
||||||
+ fmi->funcname = PyBytes_AsString(fmi->funcname_obj);
|
|
||||||
+ } else {
|
|
||||||
+ fmi->funcname = NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fmi->lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
|
|
||||||
+
|
|
||||||
+ PyErr_Restore(ptype, pvalue, ptraceback);
|
|
||||||
+
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+release_frame_marker_info(struct frame_marker_info *fmi)
|
|
||||||
+{
|
|
||||||
+ Py_XDECREF(fmi->filename_obj);
|
|
||||||
+ Py_XDECREF(fmi->funcname_obj);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+systemtap_function_entry(PyFrameObject *f)
|
|
||||||
+{
|
|
||||||
+ struct frame_marker_info fmi;
|
|
||||||
+ get_frame_marker_info(f, &fmi);
|
|
||||||
+ PYTHON_FUNCTION_ENTRY(fmi.filename, fmi.funcname, fmi.lineno, f);
|
|
||||||
+ release_frame_marker_info(&fmi);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+systemtap_function_return(PyFrameObject *f)
|
|
||||||
+{
|
|
||||||
+ struct frame_marker_info fmi;
|
|
||||||
+ get_frame_marker_info(f, &fmi);
|
|
||||||
+ PYTHON_FUNCTION_RETURN(fmi.filename, fmi.funcname, fmi.lineno, f);
|
|
||||||
+ release_frame_marker_info(&fmi);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#else /* #ifdef WITH_SYSTEMTAP */
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ When configured --without-systemtap, everything compiles away to nothing:
|
|
||||||
+*/
|
|
||||||
+#define PYTHON_FUNCTION_ENTRY_ENABLED() 0
|
|
||||||
+#define PYTHON_FUNCTION_RETURN_ENABLED() 0
|
|
||||||
+#define systemtap_function_entry(f)
|
|
||||||
+#define systemtap_function_return(f)
|
|
||||||
+
|
|
||||||
+#endif
|
|
||||||
diff -up Python-3.3.0rc2/Python/pysystemtap.d.systemtap Python-3.3.0rc2/Python/pysystemtap.d
|
|
||||||
--- Python-3.3.0rc2/Python/pysystemtap.d.systemtap 2012-09-10 09:17:21.122511781 -0400
|
|
||||||
+++ Python-3.3.0rc2/Python/pysystemtap.d 2012-09-10 09:17:21.122511781 -0400
|
|
||||||
@@ -0,0 +1,4 @@
|
|
||||||
+provider python {
|
|
||||||
+ probe function__entry(const char *, const char *, int, PyFrameObject *);
|
|
||||||
+ probe function__return(const char *, const char *, int, PyFrameObject *);
|
|
||||||
+};
|
|
|
@ -110,7 +110,7 @@ index f698927..bc977b5 100644
|
||||||
@@ -248,8 +248,8 @@ class HelperFunctionsTests(unittest.TestCase):
|
@@ -248,8 +248,8 @@ class HelperFunctionsTests(unittest.TestCase):
|
||||||
self.assertEqual(dirs[1], wanted)
|
self.assertEqual(dirs[1], wanted)
|
||||||
elif os.sep == '/':
|
elif os.sep == '/':
|
||||||
# OS X non-framwework builds, Linux, FreeBSD, etc
|
# OS X non-framework builds, Linux, FreeBSD, etc
|
||||||
- self.assertEqual(len(dirs), 1)
|
- self.assertEqual(len(dirs), 1)
|
||||||
- wanted = os.path.join('xoxo', 'lib',
|
- wanted = os.path.join('xoxo', 'lib',
|
||||||
+ self.assertEqual(len(dirs), 2)
|
+ self.assertEqual(len(dirs), 2)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
diff --git a/Makefile.pre.in b/Makefile.pre.in
|
diff --git a/Makefile.pre.in b/Makefile.pre.in
|
||||||
index 70e5927..04c8e3d 100644
|
index 4b093e3..1088435 100644
|
||||||
--- a/Makefile.pre.in
|
--- a/Makefile.pre.in
|
||||||
+++ b/Makefile.pre.in
|
+++ b/Makefile.pre.in
|
||||||
@@ -556,7 +556,7 @@ clinic: $(BUILDPYTHON) $(srcdir)/Modules/_blake2/blake2s_impl.c
|
@@ -543,7 +543,7 @@ clinic: check-clean-src $(srcdir)/Modules/_blake2/blake2s_impl.c
|
||||||
$(RUNSHARED) $(PYTHON_FOR_BUILD) ./Tools/clinic/clinic.py --make
|
$(PYTHON_FOR_REGEN) ./Tools/clinic/clinic.py --make
|
||||||
|
|
||||||
# Build the interpreter
|
# Build the interpreter
|
||||||
-$(BUILDPYTHON): Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
|
-$(BUILDPYTHON): Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
|
||||||
|
@ -11,7 +11,7 @@ index 70e5927..04c8e3d 100644
|
||||||
$(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
|
$(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
|
||||||
|
|
||||||
platform: $(BUILDPYTHON) pybuilddir.txt
|
platform: $(BUILDPYTHON) pybuilddir.txt
|
||||||
@@ -601,18 +601,6 @@ sharedmods: $(BUILDPYTHON) pybuilddir.txt Modules/_math.o
|
@@ -588,18 +588,6 @@ sharedmods: $(BUILDPYTHON) pybuilddir.txt Modules/_math.o
|
||||||
$(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build
|
$(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ index 70e5927..04c8e3d 100644
|
||||||
libpython$(LDVERSION).so: $(LIBRARY_OBJS)
|
libpython$(LDVERSION).so: $(LIBRARY_OBJS)
|
||||||
if test $(INSTSONAME) != $(LDLIBRARY); then \
|
if test $(INSTSONAME) != $(LDLIBRARY); then \
|
||||||
$(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \
|
$(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \
|
||||||
@@ -702,7 +690,7 @@ Modules/Setup: $(srcdir)/Modules/Setup.dist
|
@@ -689,7 +677,7 @@ Modules/Setup: $(srcdir)/Modules/Setup.dist
|
||||||
echo "-----------------------------------------------"; \
|
echo "-----------------------------------------------"; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ index 70e5927..04c8e3d 100644
|
||||||
$(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
|
$(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
@@ -1382,18 +1370,6 @@ libainstall: all python-config
|
@@ -1425,18 +1413,6 @@ libainstall: @DEF_MAKE_RULE@ python-config
|
||||||
else true; \
|
else true; \
|
||||||
fi; \
|
fi; \
|
||||||
done
|
done
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
diff -Nur Python-3.4.1/Lib/ensurepip/__init__.py Python-3.4.1-rewheel/Lib/ensurepip/__init__.py
|
diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py
|
||||||
--- Python-3.4.1/Lib/ensurepip/__init__.py 2014-08-21 10:49:30.792695824 +0200
|
index d69e09f..5cb12df 100644
|
||||||
+++ Python-3.4.1-rewheel/Lib/ensurepip/__init__.py 2014-08-21 10:10:41.958341726 +0200
|
--- a/Lib/ensurepip/__init__.py
|
||||||
|
+++ b/Lib/ensurepip/__init__.py
|
||||||
@@ -1,8 +1,10 @@
|
@@ -1,8 +1,10 @@
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
|
@ -12,16 +13,16 @@ diff -Nur Python-3.4.1/Lib/ensurepip/__init__.py Python-3.4.1-rewheel/Lib/ensure
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["version", "bootstrap"]
|
__all__ = ["version", "bootstrap"]
|
||||||
@@ -38,6 +40,8 @@
|
@@ -25,6 +27,8 @@ def _run_pip(args, additional_paths=None):
|
||||||
|
|
||||||
# Install the bundled software
|
# Install the bundled software
|
||||||
import pip
|
import pip
|
||||||
+ if args[0] in ["install", "list", "wheel"]:
|
+ if args[0] in ["install", "list", "wheel"]:
|
||||||
+ args.append('--pre')
|
+ args.append('--pre')
|
||||||
pip.main(args)
|
return pip.main(args)
|
||||||
|
|
||||||
|
|
||||||
@@ -87,20 +91,39 @@
|
@@ -88,20 +92,39 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
|
||||||
# omit pip and easy_install
|
# omit pip and easy_install
|
||||||
os.environ["ENSUREPIP_OPTIONS"] = "install"
|
os.environ["ENSUREPIP_OPTIONS"] = "install"
|
||||||
|
|
||||||
|
@ -72,8 +73,8 @@ diff -Nur Python-3.4.1/Lib/ensurepip/__init__.py Python-3.4.1-rewheel/Lib/ensure
|
||||||
# Construct the arguments to be passed to the pip command
|
# Construct the arguments to be passed to the pip command
|
||||||
args = ["install", "--no-index", "--find-links", tmpdir]
|
args = ["install", "--no-index", "--find-links", tmpdir]
|
||||||
diff -Nur Python-3.4.1/Lib/ensurepip/rewheel/__init__.py Python-3.4.1-rewheel/Lib/ensurepip/rewheel/__init__.py
|
diff -Nur Python-3.4.1/Lib/ensurepip/rewheel/__init__.py Python-3.4.1-rewheel/Lib/ensurepip/rewheel/__init__.py
|
||||||
--- Python-3.4.1/Lib/ensurepip/rewheel/__init__.py 1970-01-01 01:00:00.000000000 +0100
|
--- Python-3.4.1/Lib/ensurepip/rewheel/__init__.py 1970-01-01 01:00:00.000000000 +0100
|
||||||
+++ Python-3.4.1-rewheel/Lib/ensurepip/rewheel/__init__.py 2014-08-21 10:11:22.560320121 +0200
|
+++ Python-3.4.1-rewheel/Lib/ensurepip/rewheel/__init__.py 2014-08-21 10:11:22.560320121 +0200
|
||||||
@@ -0,0 +1,143 @@
|
@@ -0,0 +1,143 @@
|
||||||
+import argparse
|
+import argparse
|
||||||
+import codecs
|
+import codecs
|
||||||
|
@ -219,8 +220,8 @@ diff -Nur Python-3.4.1/Lib/ensurepip/rewheel/__init__.py Python-3.4.1-rewheel/Li
|
||||||
+ pass # bad RECORD or empty line
|
+ pass # bad RECORD or empty line
|
||||||
+ return to_write, to_omit
|
+ return to_write, to_omit
|
||||||
diff -Nur Python-3.4.1/Makefile.pre.in Python-3.4.1-rewheel/Makefile.pre.in
|
diff -Nur Python-3.4.1/Makefile.pre.in Python-3.4.1-rewheel/Makefile.pre.in
|
||||||
--- Python-3.4.1/Makefile.pre.in 2014-08-21 10:49:31.512695040 +0200
|
--- Python-3.4.1/Makefile.pre.in 2014-08-21 10:49:31.512695040 +0200
|
||||||
+++ Python-3.4.1-rewheel/Makefile.pre.in 2014-08-21 10:10:41.961341722 +0200
|
+++ Python-3.4.1-rewheel/Makefile.pre.in 2014-08-21 10:10:41.961341722 +0200
|
||||||
@@ -1145,7 +1145,7 @@
|
@@ -1145,7 +1145,7 @@
|
||||||
test/test_asyncio \
|
test/test_asyncio \
|
||||||
collections concurrent concurrent/futures encodings \
|
collections concurrent concurrent/futures encodings \
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py
|
diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py
|
||||||
index 9d31d13..ed44a93 100644
|
index 0258d3d..4ebf50a 100644
|
||||||
--- a/Lib/distutils/command/install.py
|
--- a/Lib/distutils/command/install.py
|
||||||
+++ b/Lib/distutils/command/install.py
|
+++ b/Lib/distutils/command/install.py
|
||||||
@@ -424,8 +424,18 @@ class install(Command):
|
@@ -418,8 +418,19 @@ class install(Command):
|
||||||
raise DistutilsOptionError(
|
raise DistutilsOptionError(
|
||||||
"must not supply exec-prefix without prefix")
|
"must not supply exec-prefix without prefix")
|
||||||
|
|
||||||
- self.prefix = os.path.normpath(sys.prefix)
|
- self.prefix = os.path.normpath(sys.prefix)
|
||||||
- self.exec_prefix = os.path.normpath(sys.exec_prefix)
|
- self.exec_prefix = os.path.normpath(sys.exec_prefix)
|
||||||
+ # self.prefix is set to sys.prefix + /local/
|
+ # self.prefix is set to sys.prefix + /local/
|
||||||
+ # if the executable is /usr/bin/python* and RPM build
|
+ # if neither RPM build nor virtual environment is
|
||||||
+ # is not detected to make pip and distutils install into
|
+ # detected to make pip and distutils install packages
|
||||||
+ # the separate location.
|
+ # into the separate location.
|
||||||
+ if (sys.executable.startswith("/usr/bin/python")
|
+ if (not (hasattr(sys, 'real_prefix') or
|
||||||
+ and 'RPM_BUILD_ROOT' not in os.environ):
|
+ sys.prefix != sys.base_prefix) and
|
||||||
|
+ 'RPM_BUILD_ROOT' not in os.environ):
|
||||||
+ addition = "/local"
|
+ addition = "/local"
|
||||||
+ else:
|
+ else:
|
||||||
+ addition = ""
|
+ addition = ""
|
||||||
|
@ -24,22 +25,21 @@ index 9d31d13..ed44a93 100644
|
||||||
else:
|
else:
|
||||||
if self.exec_prefix is None:
|
if self.exec_prefix is None:
|
||||||
diff --git a/Lib/site.py b/Lib/site.py
|
diff --git a/Lib/site.py b/Lib/site.py
|
||||||
index 4744eb0..b5fe571 100644
|
index 0fc9200..c95202e 100644
|
||||||
--- a/Lib/site.py
|
--- a/Lib/site.py
|
||||||
+++ b/Lib/site.py
|
+++ b/Lib/site.py
|
||||||
@@ -326,7 +326,15 @@ def getsitepackages(prefixes=None):
|
@@ -322,7 +322,14 @@ def getsitepackages(prefixes=None):
|
||||||
return sitepackages
|
return sitepackages
|
||||||
|
|
||||||
def addsitepackages(known_paths, prefixes=None):
|
def addsitepackages(known_paths, prefixes=None):
|
||||||
- """Add site-packages to sys.path"""
|
- """Add site-packages to sys.path"""
|
||||||
+ """Add site-packages to sys.path.
|
+ """Add site-packages to sys.path
|
||||||
+
|
+
|
||||||
+ '/usr/local' is included in PREFIXES if the executable is /usr/bin/python*
|
+ '/usr/local' is included in PREFIXES if RPM build is not detected
|
||||||
+ and RPM build is not detected to make sudo pip installed packages visible.
|
+ to make packages installed into this location visible.
|
||||||
+
|
+
|
||||||
+ """
|
+ """
|
||||||
+ if (ENABLE_USER_SITE and sys.executable.startswith("/usr/bin/python")
|
+ if ENABLE_USER_SITE and 'RPM_BUILD_ROOT' not in os.environ:
|
||||||
+ and 'RPM_BUILD_ROOT' not in os.environ):
|
|
||||||
+ PREFIXES.insert(0, "/usr/local")
|
+ PREFIXES.insert(0, "/usr/local")
|
||||||
for sitedir in getsitepackages(prefixes):
|
for sitedir in getsitepackages(prefixes):
|
||||||
if os.path.isdir(sitedir):
|
if os.path.isdir(sitedir):
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst
|
diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst
|
||||||
index 195f63f..8ecd70f 100644
|
index 9ffb714..3f7201a 100644
|
||||||
--- a/Doc/using/cmdline.rst
|
--- a/Doc/using/cmdline.rst
|
||||||
+++ b/Doc/using/cmdline.rst
|
+++ b/Doc/using/cmdline.rst
|
||||||
@@ -713,6 +713,45 @@ conflict.
|
@@ -711,6 +711,45 @@ conflict.
|
||||||
|
|
||||||
.. versionadded:: 3.6
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
|
@ -500,37 +500,13 @@ index 0000000..635c98f
|
||||||
+if __name__ == "__main__":
|
+if __name__ == "__main__":
|
||||||
+ test_main()
|
+ test_main()
|
||||||
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
|
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
|
||||||
index 6c3625d..009f542 100644
|
index 6e4286e..594dfa9 100644
|
||||||
--- a/Lib/test/test_capi.py
|
--- a/Lib/test/test_capi.py
|
||||||
+++ b/Lib/test/test_capi.py
|
+++ b/Lib/test/test_capi.py
|
||||||
@@ -369,14 +369,21 @@ class EmbeddingTests(unittest.TestCase):
|
@@ -425,32 +425,21 @@ class EmbeddingTests(unittest.TestCase):
|
||||||
def tearDown(self):
|
def test_repeated_init_and_subinterpreters(self):
|
||||||
os.chdir(self.oldcwd)
|
|
||||||
|
|
||||||
- def run_embedded_interpreter(self, *args):
|
|
||||||
+ def run_embedded_interpreter(self, *args, env=None):
|
|
||||||
"""Runs a test in the embedded interpreter"""
|
|
||||||
cmd = [self.test_exe]
|
|
||||||
cmd.extend(args)
|
|
||||||
+ if env is not None and sys.platform == 'win32':
|
|
||||||
+ # Windows requires at least the SYSTEMROOT environment variable to
|
|
||||||
+ # start Python.
|
|
||||||
+ env = env.copy()
|
|
||||||
+ env['SYSTEMROOT'] = os.environ['SYSTEMROOT']
|
|
||||||
+
|
|
||||||
p = subprocess.Popen(cmd,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
- universal_newlines=True)
|
|
||||||
+ universal_newlines=True,
|
|
||||||
+ env=env)
|
|
||||||
(out, err) = p.communicate()
|
|
||||||
self.assertEqual(p.returncode, 0,
|
|
||||||
"bad returncode %d, stderr is %r" %
|
|
||||||
@@ -386,31 +393,21 @@ class EmbeddingTests(unittest.TestCase):
|
|
||||||
def test_subinterps(self):
|
|
||||||
# This is just a "don't crash" test
|
# This is just a "don't crash" test
|
||||||
out, err = self.run_embedded_interpreter()
|
out, err = self.run_embedded_interpreter('repeated_init_and_subinterpreters')
|
||||||
- if support.verbose:
|
- if support.verbose:
|
||||||
+ if support.verbose > 1:
|
+ if support.verbose > 1:
|
||||||
print()
|
print()
|
||||||
|
@ -549,49 +525,23 @@ index 6c3625d..009f542 100644
|
||||||
-
|
-
|
||||||
def test_forced_io_encoding(self):
|
def test_forced_io_encoding(self):
|
||||||
# Checks forced configuration of embedded interpreter IO streams
|
# Checks forced configuration of embedded interpreter IO streams
|
||||||
- out, err = self.run_embedded_interpreter("forced_io_encoding")
|
env = dict(os.environ, PYTHONIOENCODING="utf-8:surrogateescape")
|
||||||
|
out, err = self.run_embedded_interpreter("forced_io_encoding", env=env)
|
||||||
- if support.verbose:
|
- if support.verbose:
|
||||||
+ env = dict(os.environ, PYTHONIOENCODING="utf-8:surrogateescape")
|
|
||||||
+ out, err = self.run_embedded_interpreter("forced_io_encoding", env=env)
|
|
||||||
+ if support.verbose > 1:
|
+ if support.verbose > 1:
|
||||||
print()
|
print()
|
||||||
print(out)
|
print(out)
|
||||||
print(err)
|
print(err)
|
||||||
- expected_errors = sys.__stdout__.errors
|
expected_stream_encoding = "utf-8"
|
||||||
- expected_stdin_encoding = sys.__stdin__.encoding
|
expected_errors = "surrogateescape"
|
||||||
- expected_pipe_encoding = self._get_default_pipe_encoding()
|
- expected_pipe_encoding = self._get_default_pipe_encoding()
|
||||||
+ expected_stream_encoding = "utf-8"
|
|
||||||
+ expected_errors = "surrogateescape"
|
|
||||||
expected_output = '\n'.join([
|
expected_output = '\n'.join([
|
||||||
"--- Use defaults ---",
|
"--- Use defaults ---",
|
||||||
"Expected encoding: default",
|
"Expected encoding: default",
|
||||||
@@ -437,8 +434,8 @@ class EmbeddingTests(unittest.TestCase):
|
|
||||||
"stdout: latin-1:replace",
|
|
||||||
"stderr: latin-1:backslashreplace"])
|
|
||||||
expected_output = expected_output.format(
|
|
||||||
- in_encoding=expected_stdin_encoding,
|
|
||||||
- out_encoding=expected_pipe_encoding,
|
|
||||||
+ in_encoding=expected_stream_encoding,
|
|
||||||
+ out_encoding=expected_stream_encoding,
|
|
||||||
errors=expected_errors)
|
|
||||||
# This is useful if we ever trip over odd platform behaviour
|
|
||||||
self.maxDiff = None
|
|
||||||
diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py
|
diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py
|
||||||
index ae2bcd4..0a302ff 100644
|
index ae2bcd4..0a302ff 100644
|
||||||
--- a/Lib/test/test_cmd_line.py
|
--- a/Lib/test/test_cmd_line.py
|
||||||
+++ b/Lib/test/test_cmd_line.py
|
+++ b/Lib/test/test_cmd_line.py
|
||||||
@@ -9,8 +9,9 @@ import sys
|
|
||||||
import subprocess
|
|
||||||
import tempfile
|
|
||||||
from test.support import script_helper, is_android
|
|
||||||
-from test.support.script_helper import (spawn_python, kill_python, assert_python_ok,
|
|
||||||
- assert_python_failure)
|
|
||||||
+from test.support.script_helper import (
|
|
||||||
+ spawn_python, kill_python, assert_python_ok, assert_python_failure
|
|
||||||
+)
|
|
||||||
|
|
||||||
|
|
||||||
# XXX (ncoghlan): Move to script_helper and make consistent with run_python
|
|
||||||
@@ -151,6 +152,7 @@ class CmdLineTest(unittest.TestCase):
|
@@ -151,6 +152,7 @@ class CmdLineTest(unittest.TestCase):
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
# Use C locale to get ascii for the locale encoding
|
# Use C locale to get ascii for the locale encoding
|
||||||
|
@ -601,7 +551,7 @@ index ae2bcd4..0a302ff 100644
|
||||||
b'import locale; '
|
b'import locale; '
|
||||||
b'print(ascii("' + undecodable + b'"), '
|
b'print(ascii("' + undecodable + b'"), '
|
||||||
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
|
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
|
||||||
index df9ebd4..63145e4 100644
|
index 7866a5c..b41239a 100644
|
||||||
--- a/Lib/test/test_sys.py
|
--- a/Lib/test/test_sys.py
|
||||||
+++ b/Lib/test/test_sys.py
|
+++ b/Lib/test/test_sys.py
|
||||||
@@ -680,6 +680,7 @@ class SysModuleTest(unittest.TestCase):
|
@@ -680,6 +680,7 @@ class SysModuleTest(unittest.TestCase):
|
||||||
|
@ -613,7 +563,7 @@ index df9ebd4..63145e4 100644
|
||||||
'import sys',
|
'import sys',
|
||||||
'def dump(name):',
|
'def dump(name):',
|
||||||
diff --git a/Modules/main.c b/Modules/main.c
|
diff --git a/Modules/main.c b/Modules/main.c
|
||||||
index dd50211..f20cf24 100644
|
index b0fb78f..0d8590a 100644
|
||||||
--- a/Modules/main.c
|
--- a/Modules/main.c
|
||||||
+++ b/Modules/main.c
|
+++ b/Modules/main.c
|
||||||
@@ -105,7 +105,11 @@ static const char usage_6[] =
|
@@ -105,7 +105,11 @@ static const char usage_6[] =
|
||||||
|
@ -630,16 +580,15 @@ index dd50211..f20cf24 100644
|
||||||
static int
|
static int
|
||||||
usage(int exitcode, const wchar_t* program)
|
usage(int exitcode, const wchar_t* program)
|
||||||
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
|
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
|
||||||
index 3968399..1bd2bbf 100644
|
index b0f9087..da892bf 100644
|
||||||
--- a/Programs/_testembed.c
|
--- a/Programs/_testembed.c
|
||||||
+++ b/Programs/_testembed.c
|
+++ b/Programs/_testembed.c
|
||||||
@@ -1,4 +1,5 @@
|
@@ -1,4 +1,5 @@
|
||||||
-#include <Python.h>
|
#include <Python.h>
|
||||||
+#include "Python.h"
|
|
||||||
+#include "pyconfig.h"
|
+#include "pyconfig.h"
|
||||||
|
#include "pythread.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/*********************************************************
|
|
||||||
diff --git a/Programs/python.c b/Programs/python.c
|
diff --git a/Programs/python.c b/Programs/python.c
|
||||||
index a7afbc7..03f8295 100644
|
index a7afbc7..03f8295 100644
|
||||||
--- a/Programs/python.c
|
--- a/Programs/python.c
|
||||||
|
@ -713,7 +662,7 @@ index a7afbc7..03f8295 100644
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
PyMem_RawFree(argv_copy2[i]);
|
PyMem_RawFree(argv_copy2[i]);
|
||||||
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
|
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
|
||||||
index a4f7f82..3843297 100644
|
index 640271f..2a22b24 100644
|
||||||
--- a/Python/pylifecycle.c
|
--- a/Python/pylifecycle.c
|
||||||
+++ b/Python/pylifecycle.c
|
+++ b/Python/pylifecycle.c
|
||||||
@@ -167,6 +167,7 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
|
@@ -167,6 +167,7 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
|
||||||
|
@ -929,7 +878,7 @@ index a4f7f82..3843297 100644
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0')
|
if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0')
|
||||||
@@ -1242,12 +1428,8 @@ initstdio(void)
|
@@ -1251,12 +1437,8 @@ initstdio(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!errors && !(pythonioencoding && *pythonioencoding)) {
|
if (!errors && !(pythonioencoding && *pythonioencoding)) {
|
||||||
|
@ -944,90 +893,11 @@ index a4f7f82..3843297 100644
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/configure b/configure
|
|
||||||
index 2915246..39e5a27 100755
|
|
||||||
--- a/configure
|
|
||||||
+++ b/configure
|
|
||||||
@@ -834,6 +834,8 @@ with_thread
|
|
||||||
enable_ipv6
|
|
||||||
with_doc_strings
|
|
||||||
with_pymalloc
|
|
||||||
+with_c_locale_coercion
|
|
||||||
+with_c_locale_warning
|
|
||||||
with_valgrind
|
|
||||||
with_dtrace
|
|
||||||
with_fpectl
|
|
||||||
@@ -1527,6 +1529,12 @@ Optional Packages:
|
|
||||||
deprecated; use --with(out)-threads
|
|
||||||
--with(out)-doc-strings disable/enable documentation strings
|
|
||||||
--with(out)-pymalloc disable/enable specialized mallocs
|
|
||||||
+ --with(out)-c-locale-coercion
|
|
||||||
+ disable/enable C locale coercion to a UTF-8 based
|
|
||||||
+ locale
|
|
||||||
+ --with(out)-c-locale-warning
|
|
||||||
+ disable/enable locale compatibility warning in the C
|
|
||||||
+ locale
|
|
||||||
--with-valgrind Enable Valgrind support
|
|
||||||
--with(out)-dtrace disable/enable DTrace support
|
|
||||||
--with-fpectl enable SIGFPE catching
|
|
||||||
@@ -11010,6 +11018,52 @@ fi
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_pymalloc" >&5
|
|
||||||
$as_echo "$with_pymalloc" >&6; }
|
|
||||||
|
|
||||||
+# Check for --with-c-locale-coercion
|
|
||||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-c-locale-coercion" >&5
|
|
||||||
+$as_echo_n "checking for --with-c-locale-coercion... " >&6; }
|
|
||||||
+
|
|
||||||
+# Check whether --with-c-locale-coercion was given.
|
|
||||||
+if test "${with_c_locale_coercion+set}" = set; then :
|
|
||||||
+ withval=$with_c_locale_coercion;
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+if test -z "$with_c_locale_coercion"
|
|
||||||
+then
|
|
||||||
+ with_c_locale_coercion="yes"
|
|
||||||
+fi
|
|
||||||
+if test "$with_c_locale_coercion" != "no"
|
|
||||||
+then
|
|
||||||
+
|
|
||||||
+$as_echo "#define PY_COERCE_C_LOCALE 1" >>confdefs.h
|
|
||||||
+
|
|
||||||
+fi
|
|
||||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_c_locale_coercion" >&5
|
|
||||||
+$as_echo "$with_c_locale_coercion" >&6; }
|
|
||||||
+
|
|
||||||
+# Check for --with-c-locale-warning
|
|
||||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-c-locale-warning" >&5
|
|
||||||
+$as_echo_n "checking for --with-c-locale-warning... " >&6; }
|
|
||||||
+
|
|
||||||
+# Check whether --with-c-locale-warning was given.
|
|
||||||
+if test "${with_c_locale_warning+set}" = set; then :
|
|
||||||
+ withval=$with_c_locale_warning;
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+if test -z "$with_c_locale_warning"
|
|
||||||
+then
|
|
||||||
+ with_c_locale_warning="yes"
|
|
||||||
+fi
|
|
||||||
+if test "$with_c_locale_warning" != "no"
|
|
||||||
+then
|
|
||||||
+
|
|
||||||
+$as_echo "#define PY_WARN_ON_C_LOCALE 1" >>confdefs.h
|
|
||||||
+
|
|
||||||
+fi
|
|
||||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_c_locale_warning" >&5
|
|
||||||
+$as_echo "$with_c_locale_warning" >&6; }
|
|
||||||
+
|
|
||||||
# Check for Valgrind support
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-valgrind" >&5
|
|
||||||
$as_echo_n "checking for --with-valgrind... " >&6; }
|
|
||||||
diff --git a/configure.ac b/configure.ac
|
diff --git a/configure.ac b/configure.ac
|
||||||
index 67dfba3..b9c9f04 100644
|
index 601cc84..5cdc021 100644
|
||||||
--- a/configure.ac
|
--- a/configure.ac
|
||||||
+++ b/configure.ac
|
+++ b/configure.ac
|
||||||
@@ -3279,6 +3279,40 @@ then
|
@@ -3310,6 +3310,40 @@ then
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT($with_pymalloc)
|
AC_MSG_RESULT($with_pymalloc)
|
||||||
|
|
||||||
|
@ -1068,23 +938,3 @@ index 67dfba3..b9c9f04 100644
|
||||||
# Check for Valgrind support
|
# Check for Valgrind support
|
||||||
AC_MSG_CHECKING([for --with-valgrind])
|
AC_MSG_CHECKING([for --with-valgrind])
|
||||||
AC_ARG_WITH([valgrind],
|
AC_ARG_WITH([valgrind],
|
||||||
diff --git a/pyconfig.h.in b/pyconfig.h.in
|
|
||||||
index b10c57f..0a6f3e2 100644
|
|
||||||
--- a/pyconfig.h.in
|
|
||||||
+++ b/pyconfig.h.in
|
|
||||||
@@ -1244,9 +1244,15 @@
|
|
||||||
/* Define as the preferred size in bits of long digits */
|
|
||||||
#undef PYLONG_BITS_IN_DIGIT
|
|
||||||
|
|
||||||
+/* Define if you want to coerce the C locale to a UTF-8 based locale */
|
|
||||||
+#undef PY_COERCE_C_LOCALE
|
|
||||||
+
|
|
||||||
/* Define to printf format modifier for Py_ssize_t */
|
|
||||||
#undef PY_FORMAT_SIZE_T
|
|
||||||
|
|
||||||
+/* Define to emit a locale compatibility warning in the C locale */
|
|
||||||
+#undef PY_WARN_ON_C_LOCALE
|
|
||||||
+
|
|
||||||
/* Define if you want to build an interpreter with many run-time checks. */
|
|
||||||
#undef Py_DEBUG
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py
|
|
||||||
index 3eded77..ad7859a 100644
|
|
||||||
--- a/Lib/ctypes/test/test_structures.py
|
|
||||||
+++ b/Lib/ctypes/test/test_structures.py
|
|
||||||
@@ -392,6 +392,7 @@ class StructureTestCase(unittest.TestCase):
|
|
||||||
(1, 0, 0, 0, 0, 0))
|
|
||||||
self.assertRaises(TypeError, lambda: Z(1, 2, 3, 4, 5, 6, 7))
|
|
||||||
|
|
||||||
+ @unittest.skip('Fails on aarch64: http://bugs.python.org/issue29804')
|
|
||||||
def test_pass_by_value(self):
|
|
||||||
# This should mirror the structure in Modules/_ctypes/_ctypes_test.c
|
|
||||||
class X(Structure):
|
|
|
@ -1,16 +0,0 @@
|
||||||
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
|
|
||||||
index d203cdd..c128dae 100644
|
|
||||||
--- a/Lib/test/test_ssl.py
|
|
||||||
+++ b/Lib/test/test_ssl.py
|
|
||||||
@@ -3256,8 +3256,9 @@ if _have_threads:
|
|
||||||
except ssl.SSLError as e:
|
|
||||||
stats = e
|
|
||||||
|
|
||||||
- if expected is None and IS_OPENSSL_1_1:
|
|
||||||
- # OpenSSL 1.1.0 raises handshake error
|
|
||||||
+ if (expected is None and IS_OPENSSL_1_1
|
|
||||||
+ and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)):
|
|
||||||
+ # OpenSSL 1.1.0 to 1.1.0e raises handshake error
|
|
||||||
self.assertIsInstance(stats, ssl.SSLError)
|
|
||||||
else:
|
|
||||||
msg = "failed trying %s (s) and %s (c).\n" \
|
|
|
@ -1,99 +0,0 @@
|
||||||
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
|
|
||||||
index 492a84a2313..9746678607c 100644
|
|
||||||
--- a/Lib/test/test_asyncio/test_events.py
|
|
||||||
+++ b/Lib/test/test_asyncio/test_events.py
|
|
||||||
@@ -1980,19 +1980,26 @@ def test_subprocess_terminate(self):
|
|
||||||
|
|
||||||
@unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP")
|
|
||||||
def test_subprocess_send_signal(self):
|
|
||||||
- prog = os.path.join(os.path.dirname(__file__), 'echo.py')
|
|
||||||
-
|
|
||||||
- connect = self.loop.subprocess_exec(
|
|
||||||
- functools.partial(MySubprocessProtocol, self.loop),
|
|
||||||
- sys.executable, prog)
|
|
||||||
- transp, proto = self.loop.run_until_complete(connect)
|
|
||||||
- self.assertIsInstance(proto, MySubprocessProtocol)
|
|
||||||
- self.loop.run_until_complete(proto.connected)
|
|
||||||
-
|
|
||||||
- transp.send_signal(signal.SIGHUP)
|
|
||||||
- self.loop.run_until_complete(proto.completed)
|
|
||||||
- self.assertEqual(-signal.SIGHUP, proto.returncode)
|
|
||||||
- transp.close()
|
|
||||||
+ # bpo-31034: Make sure that we get the default signal handler (killing
|
|
||||||
+ # the process). The parent process may have decided to ignore SIGHUP,
|
|
||||||
+ # and signal handlers are inherited.
|
|
||||||
+ old_handler = signal.signal(signal.SIGHUP, signal.SIG_DFL)
|
|
||||||
+ try:
|
|
||||||
+ prog = os.path.join(os.path.dirname(__file__), 'echo.py')
|
|
||||||
+
|
|
||||||
+ connect = self.loop.subprocess_exec(
|
|
||||||
+ functools.partial(MySubprocessProtocol, self.loop),
|
|
||||||
+ sys.executable, prog)
|
|
||||||
+ transp, proto = self.loop.run_until_complete(connect)
|
|
||||||
+ self.assertIsInstance(proto, MySubprocessProtocol)
|
|
||||||
+ self.loop.run_until_complete(proto.connected)
|
|
||||||
+
|
|
||||||
+ transp.send_signal(signal.SIGHUP)
|
|
||||||
+ self.loop.run_until_complete(proto.completed)
|
|
||||||
+ self.assertEqual(-signal.SIGHUP, proto.returncode)
|
|
||||||
+ transp.close()
|
|
||||||
+ finally:
|
|
||||||
+ signal.signal(signal.SIGHUP, old_handler)
|
|
||||||
|
|
||||||
def test_subprocess_stderr(self):
|
|
||||||
prog = os.path.join(os.path.dirname(__file__), 'echo2.py')
|
|
||||||
diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py
|
|
||||||
index 2e14a8a9735..e8822c36698 100644
|
|
||||||
--- a/Lib/test/test_asyncio/test_subprocess.py
|
|
||||||
+++ b/Lib/test/test_asyncio/test_subprocess.py
|
|
||||||
@@ -166,25 +166,32 @@ def test_terminate(self):
|
|
||||||
|
|
||||||
@unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP")
|
|
||||||
def test_send_signal(self):
|
|
||||||
- code = 'import time; print("sleeping", flush=True); time.sleep(3600)'
|
|
||||||
- args = [sys.executable, '-c', code]
|
|
||||||
- create = asyncio.create_subprocess_exec(*args,
|
|
||||||
- stdout=subprocess.PIPE,
|
|
||||||
- loop=self.loop)
|
|
||||||
- proc = self.loop.run_until_complete(create)
|
|
||||||
-
|
|
||||||
- @asyncio.coroutine
|
|
||||||
- def send_signal(proc):
|
|
||||||
- # basic synchronization to wait until the program is sleeping
|
|
||||||
- line = yield from proc.stdout.readline()
|
|
||||||
- self.assertEqual(line, b'sleeping\n')
|
|
||||||
+ # bpo-31034: Make sure that we get the default signal handler (killing
|
|
||||||
+ # the process). The parent process may have decided to ignore SIGHUP,
|
|
||||||
+ # and signal handlers are inherited.
|
|
||||||
+ old_handler = signal.signal(signal.SIGHUP, signal.SIG_DFL)
|
|
||||||
+ try:
|
|
||||||
+ code = 'import time; print("sleeping", flush=True); time.sleep(3600)'
|
|
||||||
+ args = [sys.executable, '-c', code]
|
|
||||||
+ create = asyncio.create_subprocess_exec(*args,
|
|
||||||
+ stdout=subprocess.PIPE,
|
|
||||||
+ loop=self.loop)
|
|
||||||
+ proc = self.loop.run_until_complete(create)
|
|
||||||
|
|
||||||
- proc.send_signal(signal.SIGHUP)
|
|
||||||
- returncode = (yield from proc.wait())
|
|
||||||
- return returncode
|
|
||||||
-
|
|
||||||
- returncode = self.loop.run_until_complete(send_signal(proc))
|
|
||||||
- self.assertEqual(-signal.SIGHUP, returncode)
|
|
||||||
+ @asyncio.coroutine
|
|
||||||
+ def send_signal(proc):
|
|
||||||
+ # basic synchronization to wait until the program is sleeping
|
|
||||||
+ line = yield from proc.stdout.readline()
|
|
||||||
+ self.assertEqual(line, b'sleeping\n')
|
|
||||||
+
|
|
||||||
+ proc.send_signal(signal.SIGHUP)
|
|
||||||
+ returncode = (yield from proc.wait())
|
|
||||||
+ return returncode
|
|
||||||
+
|
|
||||||
+ returncode = self.loop.run_until_complete(send_signal(proc))
|
|
||||||
+ self.assertEqual(-signal.SIGHUP, returncode)
|
|
||||||
+ finally:
|
|
||||||
+ signal.signal(signal.SIGHUP, old_handler)
|
|
||||||
|
|
||||||
def prepare_broken_pipe_test(self):
|
|
||||||
# buffer large enough to feed the whole pipe buffer
|
|
|
@ -1,58 +0,0 @@
|
||||||
From 8c2d4cf092c5f0335e7982392a33927579c4d512 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Dong-hee Na <donghee.na92@gmail.com>
|
|
||||||
Date: Wed, 26 Jul 2017 21:11:25 +0900
|
|
||||||
Subject: [PATCH] [3.6] bpo-30119: fix ftplib.FTP.putline() to throw an error
|
|
||||||
for a illegal command (#1214) (#2886)
|
|
||||||
|
|
||||||
---
|
|
||||||
Lib/ftplib.py | 2 ++
|
|
||||||
Lib/test/test_ftplib.py | 6 +++++-
|
|
||||||
Misc/NEWS.d/next/Library/2017-07-26-15-15-00.bpo-30119.DZ6C_S.rst | 2 ++
|
|
||||||
3 files changed, 9 insertions(+), 1 deletion(-)
|
|
||||||
create mode 100644 Misc/NEWS.d/next/Library/2017-07-26-15-15-00.bpo-30119.DZ6C_S.rst
|
|
||||||
|
|
||||||
diff --git a/Lib/ftplib.py b/Lib/ftplib.py
|
|
||||||
index 8f36f537e8a..a02e595cb02 100644
|
|
||||||
--- a/Lib/ftplib.py
|
|
||||||
+++ b/Lib/ftplib.py
|
|
||||||
@@ -186,6 +186,8 @@ def sanitize(self, s):
|
|
||||||
|
|
||||||
# Internal: send one line to the server, appending CRLF
|
|
||||||
def putline(self, line):
|
|
||||||
+ if '\r' in line or '\n' in line:
|
|
||||||
+ raise ValueError('an illegal newline character should not be contained')
|
|
||||||
line = line + CRLF
|
|
||||||
if self.debugging > 1:
|
|
||||||
print('*put*', self.sanitize(line))
|
|
||||||
diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py
|
|
||||||
index 12fabc5e8be..a561e9efa03 100644
|
|
||||||
--- a/Lib/test/test_ftplib.py
|
|
||||||
+++ b/Lib/test/test_ftplib.py
|
|
||||||
@@ -484,6 +484,9 @@ def test_sanitize(self):
|
|
||||||
self.assertEqual(self.client.sanitize('PASS 12345'), repr('PASS *****'))
|
|
||||||
|
|
||||||
def test_exceptions(self):
|
|
||||||
+ self.assertRaises(ValueError, self.client.sendcmd, 'echo 40\r\n0')
|
|
||||||
+ self.assertRaises(ValueError, self.client.sendcmd, 'echo 40\n0')
|
|
||||||
+ self.assertRaises(ValueError, self.client.sendcmd, 'echo 40\r0')
|
|
||||||
self.assertRaises(ftplib.error_temp, self.client.sendcmd, 'echo 400')
|
|
||||||
self.assertRaises(ftplib.error_temp, self.client.sendcmd, 'echo 499')
|
|
||||||
self.assertRaises(ftplib.error_perm, self.client.sendcmd, 'echo 500')
|
|
||||||
@@ -492,7 +495,8 @@ def test_exceptions(self):
|
|
||||||
|
|
||||||
def test_all_errors(self):
|
|
||||||
exceptions = (ftplib.error_reply, ftplib.error_temp, ftplib.error_perm,
|
|
||||||
- ftplib.error_proto, ftplib.Error, OSError, EOFError)
|
|
||||||
+ ftplib.error_proto, ftplib.Error, OSError,
|
|
||||||
+ EOFError)
|
|
||||||
for x in exceptions:
|
|
||||||
try:
|
|
||||||
raise x('exception not included in all_errors set')
|
|
||||||
diff --git a/Misc/NEWS.d/next/Library/2017-07-26-15-15-00.bpo-30119.DZ6C_S.rst b/Misc/NEWS.d/next/Library/2017-07-26-15-15-00.bpo-30119.DZ6C_S.rst
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000000..a37d3703842
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/Misc/NEWS.d/next/Library/2017-07-26-15-15-00.bpo-30119.DZ6C_S.rst
|
|
||||||
@@ -0,0 +1,2 @@
|
|
||||||
+ftplib.FTP.putline() now throws ValueError on commands that contains CR or
|
|
||||||
+LF. Patch by Dong-hee Na.
|
|
|
@ -1,12 +0,0 @@
|
||||||
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py
|
|
||||||
index 66726d6496d..3318fa5df59 100644
|
|
||||||
--- a/Lib/test/test_float.py
|
|
||||||
+++ b/Lib/test/test_float.py
|
|
||||||
@@ -141,6 +141,7 @@ class GeneralFloatCases(unittest.TestCase):
|
|
||||||
# non-UTF-8 byte string
|
|
||||||
check(b'123\xa0')
|
|
||||||
|
|
||||||
+ @unittest.skip('Fails in Koji: https://bugzilla.redhat.com/show_bug.cgi?id=1484497')
|
|
||||||
@support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
|
|
||||||
def test_float_with_comma(self):
|
|
||||||
# set locale to something that doesn't use '.' for the decimal point
|
|
|
@ -1,43 +0,0 @@
|
||||||
From 54849962eacc38f4e6c6f8a72ae258b3e7c2ecd5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Victor Stinner <victor.stinner@gmail.com>
|
|
||||||
Date: Thu, 5 Oct 2017 15:05:30 +0200
|
|
||||||
Subject: [PATCH] bpo-31178: Mock os.waitpid() in test_subprocess
|
|
||||||
|
|
||||||
Fix test_exception_errpipe_bad_data() and
|
|
||||||
test_exception_errpipe_normal() of test_subprocess: mock os.waitpid()
|
|
||||||
to avoid calling the real os.waitpid(0, 0) which is an unexpected
|
|
||||||
side effect of the test.
|
|
||||||
---
|
|
||||||
Lib/test/test_subprocess.py | 12 ++++++++----
|
|
||||||
1 file changed, 8 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
|
|
||||||
index 00dc37bc2c7..3ba5c028517 100644
|
|
||||||
--- a/Lib/test/test_subprocess.py
|
|
||||||
+++ b/Lib/test/test_subprocess.py
|
|
||||||
@@ -1559,8 +1559,10 @@ def proper_error(*args):
|
|
||||||
|
|
||||||
fork_exec.side_effect = proper_error
|
|
||||||
|
|
||||||
- with self.assertRaises(IsADirectoryError):
|
|
||||||
- self.PopenNoDestructor(["non_existent_command"])
|
|
||||||
+ with mock.patch("subprocess.os.waitpid",
|
|
||||||
+ side_effect=ChildProcessError):
|
|
||||||
+ with self.assertRaises(IsADirectoryError):
|
|
||||||
+ self.PopenNoDestructor(["non_existent_command"])
|
|
||||||
|
|
||||||
@mock.patch("subprocess._posixsubprocess.fork_exec")
|
|
||||||
def test_exception_errpipe_bad_data(self, fork_exec):
|
|
||||||
@@ -1577,8 +1579,10 @@ def bad_error(*args):
|
|
||||||
|
|
||||||
fork_exec.side_effect = bad_error
|
|
||||||
|
|
||||||
- with self.assertRaises(subprocess.SubprocessError) as e:
|
|
||||||
- self.PopenNoDestructor(["non_existent_command"])
|
|
||||||
+ with mock.patch("subprocess.os.waitpid",
|
|
||||||
+ side_effect=ChildProcessError):
|
|
||||||
+ with self.assertRaises(subprocess.SubprocessError) as e:
|
|
||||||
+ self.PopenNoDestructor(["non_existent_command"])
|
|
||||||
|
|
||||||
self.assertIn(repr(error_data), str(e.exception))
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
diff --git a/Modules/getpath.c b/Modules/getpath.c
|
|
||||||
index c4055be..1258fcd 100644
|
|
||||||
--- a/Modules/getpath.c
|
|
||||||
+++ b/Modules/getpath.c
|
|
||||||
@@ -735,7 +735,7 @@ calculate_path(void)
|
|
||||||
bufsz += wcslen(zip_path) + 1;
|
|
||||||
bufsz += wcslen(exec_prefix) + 1;
|
|
||||||
|
|
||||||
- buf = PyMem_New(wchar_t, bufsz);
|
|
||||||
+ buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
|
|
||||||
if (buf == NULL) {
|
|
||||||
Py_FatalError(
|
|
||||||
"Not enough memory for dynamic PYTHONPATH");
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
|
||||||
|
index 847b50140a6..570dc3ed6fe 100644
|
||||||
|
--- a/Doc/whatsnew/3.6.rst
|
||||||
|
+++ b/Doc/whatsnew/3.6.rst
|
||||||
|
@@ -1852,10 +1852,10 @@ Build and C API Changes
|
||||||
|
* The :c:func:`PyUnicode_FSConverter` and :c:func:`PyUnicode_FSDecoder`
|
||||||
|
functions will now accept :term:`path-like objects <path-like object>`.
|
||||||
|
|
||||||
|
-* The ``PyExc_RecursionErrorInst`` singleton that was part of the public API
|
||||||
|
- has been removed as its members being never cleared may cause a segfault
|
||||||
|
- during finalization of the interpreter. Contributed by Xavier de Gaye in
|
||||||
|
- :issue:`22898` and :issue:`30697`.
|
||||||
|
+* The ``PyExc_RecursionErrorInst`` singleton is not used anymore as its members
|
||||||
|
+ being never cleared may cause a segfault during finalization of the
|
||||||
|
+ interpreter. Contributed by Xavier de Gaye in :issue:`22898` and
|
||||||
|
+ :issue:`30697`.
|
||||||
|
|
||||||
|
|
||||||
|
Other Improvements
|
||||||
|
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
|
||||||
|
index c28c1373f82..8c1dbc5047b 100644
|
||||||
|
--- a/Include/pyerrors.h
|
||||||
|
+++ b/Include/pyerrors.h
|
||||||
|
@@ -219,6 +219,8 @@ PyAPI_DATA(PyObject *) PyExc_IOError;
|
||||||
|
PyAPI_DATA(PyObject *) PyExc_WindowsError;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+PyAPI_DATA(PyObject *) PyExc_RecursionErrorInst;
|
||||||
|
+
|
||||||
|
/* Predefined warning categories */
|
||||||
|
PyAPI_DATA(PyObject *) PyExc_Warning;
|
||||||
|
PyAPI_DATA(PyObject *) PyExc_UserWarning;
|
||||||
|
diff --git a/Misc/NEWS.d/next/C API/2017-12-20-15-23-06.bpo-30697.v9FmgG.rst b/Misc/NEWS.d/next/C API/2017-12-20-15-23-06.bpo-30697.v9FmgG.rst
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000000..28f74ad4f30
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/C API/2017-12-20-15-23-06.bpo-30697.v9FmgG.rst
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Restore PyExc_RecursionErrorInst in 3.6
|
||||||
|
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
|
||||||
|
index df4899372a5..271e293e325 100644
|
||||||
|
--- a/Objects/exceptions.c
|
||||||
|
+++ b/Objects/exceptions.c
|
||||||
|
@@ -2430,6 +2430,12 @@ SimpleExtendsException(PyExc_Warning, ResourceWarning,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
+/* Pre-computed RecursionError instance for when recursion depth is reached.
|
||||||
|
+ Meant to be used when normalizing the exception for exceeding the recursion
|
||||||
|
+ depth will cause its own infinite recursion.
|
||||||
|
+*/
|
||||||
|
+PyObject *PyExc_RecursionErrorInst = NULL;
|
||||||
|
+
|
||||||
|
#define PRE_INIT(TYPE) \
|
||||||
|
if (!(_PyExc_ ## TYPE.tp_flags & Py_TPFLAGS_READY)) { \
|
||||||
|
if (PyType_Ready(&_PyExc_ ## TYPE) < 0) \
|
||||||
|
@@ -2691,11 +2697,37 @@ _PyExc_Init(PyObject *bltinmod)
|
||||||
|
ADD_ERRNO(TimeoutError, ETIMEDOUT);
|
||||||
|
|
||||||
|
preallocate_memerrors();
|
||||||
|
+
|
||||||
|
+ if (!PyExc_RecursionErrorInst) {
|
||||||
|
+ PyExc_RecursionErrorInst = BaseException_new(&_PyExc_RecursionError, NULL, NULL);
|
||||||
|
+ if (!PyExc_RecursionErrorInst)
|
||||||
|
+ Py_FatalError("Cannot pre-allocate RecursionError instance for "
|
||||||
|
+ "recursion errors");
|
||||||
|
+ else {
|
||||||
|
+ PyBaseExceptionObject *err_inst =
|
||||||
|
+ (PyBaseExceptionObject *)PyExc_RecursionErrorInst;
|
||||||
|
+ PyObject *args_tuple;
|
||||||
|
+ PyObject *exc_message;
|
||||||
|
+ exc_message = PyUnicode_FromString("maximum recursion depth exceeded");
|
||||||
|
+ if (!exc_message)
|
||||||
|
+ Py_FatalError("cannot allocate argument for RecursionError "
|
||||||
|
+ "pre-allocation");
|
||||||
|
+ args_tuple = PyTuple_Pack(1, exc_message);
|
||||||
|
+ if (!args_tuple)
|
||||||
|
+ Py_FatalError("cannot allocate tuple for RecursionError "
|
||||||
|
+ "pre-allocation");
|
||||||
|
+ Py_DECREF(exc_message);
|
||||||
|
+ if (BaseException_init(err_inst, args_tuple, NULL))
|
||||||
|
+ Py_FatalError("init of pre-allocated RecursionError failed");
|
||||||
|
+ Py_DECREF(args_tuple);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_PyExc_Fini(void)
|
||||||
|
{
|
||||||
|
+ Py_CLEAR(PyExc_RecursionErrorInst);
|
||||||
|
free_preallocated_memerrors();
|
||||||
|
Py_CLEAR(errnomap);
|
||||||
|
}
|
||||||
|
diff --git a/PC/python3.def b/PC/python3.def
|
||||||
|
index 4fc4a6814ee..ff70718fc37 100644
|
||||||
|
--- a/PC/python3.def
|
||||||
|
+++ b/PC/python3.def
|
||||||
|
@@ -224,6 +224,7 @@ EXPORTS
|
||||||
|
PyExc_PermissionError=python36.PyExc_PermissionError DATA
|
||||||
|
PyExc_ProcessLookupError=python36.PyExc_ProcessLookupError DATA
|
||||||
|
PyExc_RecursionError=python36.PyExc_RecursionError DATA
|
||||||
|
+ PyExc_RecursionErrorInst=python36.PyExc_RecursionErrorInst DATA
|
||||||
|
PyExc_ReferenceError=python36.PyExc_ReferenceError DATA
|
||||||
|
PyExc_ResourceWarning=python36.PyExc_ResourceWarning DATA
|
||||||
|
PyExc_RuntimeError=python36.PyExc_RuntimeError DATA
|
|
@ -0,0 +1,228 @@
|
||||||
|
diff --git a/Lib/ssl.py b/Lib/ssl.py
|
||||||
|
index 1f3a31a..b54a684 100644
|
||||||
|
--- a/Lib/ssl.py
|
||||||
|
+++ b/Lib/ssl.py
|
||||||
|
@@ -116,6 +116,7 @@ except ImportError:
|
||||||
|
|
||||||
|
|
||||||
|
from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_TLSv1_3
|
||||||
|
+from _ssl import _DEFAULT_CIPHERS
|
||||||
|
from _ssl import _OPENSSL_API_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
@@ -174,48 +175,7 @@ else:
|
||||||
|
CHANNEL_BINDING_TYPES = []
|
||||||
|
|
||||||
|
|
||||||
|
-# Disable weak or insecure ciphers by default
|
||||||
|
-# (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL')
|
||||||
|
-# Enable a better set of ciphers by default
|
||||||
|
-# This list has been explicitly chosen to:
|
||||||
|
-# * TLS 1.3 ChaCha20 and AES-GCM cipher suites
|
||||||
|
-# * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE)
|
||||||
|
-# * Prefer ECDHE over DHE for better performance
|
||||||
|
-# * Prefer AEAD over CBC for better performance and security
|
||||||
|
-# * Prefer AES-GCM over ChaCha20 because most platforms have AES-NI
|
||||||
|
-# (ChaCha20 needs OpenSSL 1.1.0 or patched 1.0.2)
|
||||||
|
-# * Prefer any AES-GCM and ChaCha20 over any AES-CBC for better
|
||||||
|
-# performance and security
|
||||||
|
-# * Then Use HIGH cipher suites as a fallback
|
||||||
|
-# * Disable NULL authentication, NULL encryption, 3DES and MD5 MACs
|
||||||
|
-# for security reasons
|
||||||
|
-_DEFAULT_CIPHERS = (
|
||||||
|
- 'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:'
|
||||||
|
- 'TLS13-AES-128-GCM-SHA256:'
|
||||||
|
- 'ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:'
|
||||||
|
- 'ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:'
|
||||||
|
- '!aNULL:!eNULL:!MD5:!3DES'
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-# Restricted and more secure ciphers for the server side
|
||||||
|
-# This list has been explicitly chosen to:
|
||||||
|
-# * TLS 1.3 ChaCha20 and AES-GCM cipher suites
|
||||||
|
-# * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE)
|
||||||
|
-# * Prefer ECDHE over DHE for better performance
|
||||||
|
-# * Prefer AEAD over CBC for better performance and security
|
||||||
|
-# * Prefer AES-GCM over ChaCha20 because most platforms have AES-NI
|
||||||
|
-# * Prefer any AES-GCM and ChaCha20 over any AES-CBC for better
|
||||||
|
-# performance and security
|
||||||
|
-# * Then Use HIGH cipher suites as a fallback
|
||||||
|
-# * Disable NULL authentication, NULL encryption, MD5 MACs, DSS, RC4, and
|
||||||
|
-# 3DES for security reasons
|
||||||
|
-_RESTRICTED_SERVER_CIPHERS = (
|
||||||
|
- 'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:'
|
||||||
|
- 'TLS13-AES-128-GCM-SHA256:'
|
||||||
|
- 'ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:'
|
||||||
|
- 'ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:'
|
||||||
|
- '!aNULL:!eNULL:!MD5:!DSS:!RC4:!3DES'
|
||||||
|
-)
|
||||||
|
+_RESTRICTED_SERVER_CIPHERS = _DEFAULT_CIPHERS
|
||||||
|
|
||||||
|
|
||||||
|
class CertificateError(ValueError):
|
||||||
|
@@ -389,8 +349,6 @@ class SSLContext(_SSLContext):
|
||||||
|
|
||||||
|
def __new__(cls, protocol=PROTOCOL_TLS, *args, **kwargs):
|
||||||
|
self = _SSLContext.__new__(cls, protocol)
|
||||||
|
- if protocol != _SSLv2_IF_EXISTS:
|
||||||
|
- self.set_ciphers(_DEFAULT_CIPHERS)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __init__(self, protocol=PROTOCOL_TLS):
|
||||||
|
@@ -505,8 +463,6 @@ def create_default_context(purpose=Purpose.SERVER_AUTH, *, cafile=None,
|
||||||
|
# verify certs and host name in client mode
|
||||||
|
context.verify_mode = CERT_REQUIRED
|
||||||
|
context.check_hostname = True
|
||||||
|
- elif purpose == Purpose.CLIENT_AUTH:
|
||||||
|
- context.set_ciphers(_RESTRICTED_SERVER_CIPHERS)
|
||||||
|
|
||||||
|
if cafile or capath or cadata:
|
||||||
|
context.load_verify_locations(cafile, capath, cadata)
|
||||||
|
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
|
||||||
|
index 54644e1..799100c 100644
|
||||||
|
--- a/Lib/test/test_ssl.py
|
||||||
|
+++ b/Lib/test/test_ssl.py
|
||||||
|
@@ -18,6 +18,7 @@ import asyncore
|
||||||
|
import weakref
|
||||||
|
import platform
|
||||||
|
import functools
|
||||||
|
+import sysconfig
|
||||||
|
try:
|
||||||
|
import ctypes
|
||||||
|
except ImportError:
|
||||||
|
@@ -36,7 +37,7 @@ PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
|
||||||
|
HOST = support.HOST
|
||||||
|
IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
|
||||||
|
IS_OPENSSL_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0)
|
||||||
|
-
|
||||||
|
+PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
|
||||||
|
|
||||||
|
def data_file(*name):
|
||||||
|
return os.path.join(os.path.dirname(__file__), *name)
|
||||||
|
@@ -889,6 +890,19 @@ class ContextTests(unittest.TestCase):
|
||||||
|
with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
|
||||||
|
ctx.set_ciphers("^$:,;?*'dorothyx")
|
||||||
|
|
||||||
|
+ @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
|
||||||
|
+ "Test applies only to Python default ciphers")
|
||||||
|
+ def test_python_ciphers(self):
|
||||||
|
+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||||
|
+ ciphers = ctx.get_ciphers()
|
||||||
|
+ for suite in ciphers:
|
||||||
|
+ name = suite['name']
|
||||||
|
+ self.assertNotIn("PSK", name)
|
||||||
|
+ self.assertNotIn("SRP", name)
|
||||||
|
+ self.assertNotIn("MD5", name)
|
||||||
|
+ self.assertNotIn("RC4", name)
|
||||||
|
+ self.assertNotIn("3DES", name)
|
||||||
|
+
|
||||||
|
@unittest.skipIf(ssl.OPENSSL_VERSION_INFO < (1, 0, 2, 0, 0), 'OpenSSL too old')
|
||||||
|
def test_get_ciphers(self):
|
||||||
|
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||||
|
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
|
||||||
|
index df8c6a7..e23a569 100644
|
||||||
|
--- a/Modules/_ssl.c
|
||||||
|
+++ b/Modules/_ssl.c
|
||||||
|
@@ -206,6 +206,31 @@ SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s)
|
||||||
|
|
||||||
|
#endif /* OpenSSL < 1.1.0 or LibreSSL */
|
||||||
|
|
||||||
|
+/* Default cipher suites */
|
||||||
|
+#ifndef PY_SSL_DEFAULT_CIPHERS
|
||||||
|
+#define PY_SSL_DEFAULT_CIPHERS 1
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#if PY_SSL_DEFAULT_CIPHERS == 0
|
||||||
|
+ #ifndef PY_SSL_DEFAULT_CIPHER_STRING
|
||||||
|
+ #error "Py_SSL_DEFAULT_CIPHERS 0 needs Py_SSL_DEFAULT_CIPHER_STRING"
|
||||||
|
+ #endif
|
||||||
|
+#elif PY_SSL_DEFAULT_CIPHERS == 1
|
||||||
|
+/* Python custom selection of sensible ciper suites
|
||||||
|
+ * DEFAULT: OpenSSL's default cipher list. Since 1.0.2 the list is in sensible order.
|
||||||
|
+ * !aNULL:!eNULL: really no NULL ciphers
|
||||||
|
+ * !MD5:!3DES:!DES:!RC4:!IDEA:!SEED: no weak or broken algorithms on old OpenSSL versions.
|
||||||
|
+ * !aDSS: no authentication with discrete logarithm DSA algorithm
|
||||||
|
+ * !SRP:!PSK: no secure remote password or pre-shared key authentication
|
||||||
|
+ */
|
||||||
|
+ #define PY_SSL_DEFAULT_CIPHER_STRING "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK"
|
||||||
|
+#elif PY_SSL_DEFAULT_CIPHERS == 2
|
||||||
|
+/* Ignored in SSLContext constructor, only used to as _ssl.DEFAULT_CIPHER_STRING */
|
||||||
|
+ #define PY_SSL_DEFAULT_CIPHER_STRING SSL_DEFAULT_CIPHER_LIST
|
||||||
|
+#else
|
||||||
|
+ #error "Unsupported PY_SSL_DEFAULT_CIPHERS"
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
|
||||||
|
enum py_ssl_error {
|
||||||
|
/* these mirror ssl.h */
|
||||||
|
@@ -2739,7 +2764,12 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
|
||||||
|
/* A bare minimum cipher list without completely broken cipher suites.
|
||||||
|
* It's far from perfect but gives users a better head start. */
|
||||||
|
if (proto_version != PY_SSL_VERSION_SSL2) {
|
||||||
|
- result = SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!eNULL:!MD5");
|
||||||
|
+#if PY_SSL_DEFAULT_CIPHERS == 2
|
||||||
|
+ /* stick to OpenSSL's default settings */
|
||||||
|
+ result = 1;
|
||||||
|
+#else
|
||||||
|
+ result = SSL_CTX_set_cipher_list(ctx, PY_SSL_DEFAULT_CIPHER_STRING);
|
||||||
|
+#endif
|
||||||
|
} else {
|
||||||
|
/* SSLv2 needs MD5 */
|
||||||
|
result = SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!eNULL");
|
||||||
|
@@ -5279,6 +5309,9 @@ PyInit__ssl(void)
|
||||||
|
(PyObject *)&PySSLSession_Type) != 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
+ PyModule_AddStringConstant(m, "_DEFAULT_CIPHERS",
|
||||||
|
+ PY_SSL_DEFAULT_CIPHER_STRING);
|
||||||
|
+
|
||||||
|
PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN",
|
||||||
|
PY_SSL_ERROR_ZERO_RETURN);
|
||||||
|
PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ",
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index 7ea62f8..4b42393 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -5555,6 +5555,42 @@ if test "$have_getrandom" = yes; then
|
||||||
|
[Define to 1 if the getrandom() function is available])
|
||||||
|
fi
|
||||||
|
|
||||||
|
+# ssl module default cipher suite string
|
||||||
|
+AH_TEMPLATE(PY_SSL_DEFAULT_CIPHERS,
|
||||||
|
+ [Default cipher suites list for ssl module.
|
||||||
|
+ 1: Python's preferred selection, 2: leave OpenSSL defaults untouched, 0: custom string])
|
||||||
|
+AH_TEMPLATE(PY_SSL_DEFAULT_CIPHER_STRING,
|
||||||
|
+ [Cipher suite string for PY_SSL_DEFAULT_CIPHERS=0]
|
||||||
|
+)
|
||||||
|
+AC_MSG_CHECKING(for --with-ssl-default-suites)
|
||||||
|
+AC_ARG_WITH(ssl-default-suites,
|
||||||
|
+ AS_HELP_STRING([--with-ssl-default-suites=@<:@python|openssl|STRING@:>@],
|
||||||
|
+ [Override default cipher suites string,
|
||||||
|
+ python: use Python's preferred selection (default),
|
||||||
|
+ openssl: leave OpenSSL's defaults untouched,
|
||||||
|
+ STRING: use a custom string,
|
||||||
|
+ PROTOCOL_SSLv2 ignores the setting]),
|
||||||
|
+[
|
||||||
|
+AC_MSG_RESULT($withval)
|
||||||
|
+case "$withval" in
|
||||||
|
+ python)
|
||||||
|
+ AC_DEFINE(PY_SSL_DEFAULT_CIPHERS, 1)
|
||||||
|
+ ;;
|
||||||
|
+ openssl)
|
||||||
|
+ AC_DEFINE(PY_SSL_DEFAULT_CIPHERS, 2)
|
||||||
|
+ ;;
|
||||||
|
+ *)
|
||||||
|
+ AC_DEFINE(PY_SSL_DEFAULT_CIPHERS, 0)
|
||||||
|
+ AC_DEFINE_UNQUOTED(PY_SSL_DEFAULT_CIPHER_STRING, "$withval")
|
||||||
|
+ ;;
|
||||||
|
+esac
|
||||||
|
+],
|
||||||
|
+[
|
||||||
|
+AC_MSG_RESULT(python)
|
||||||
|
+AC_DEFINE(PY_SSL_DEFAULT_CIPHERS, 1)
|
||||||
|
+])
|
||||||
|
+
|
||||||
|
+
|
||||||
|
# generate output files
|
||||||
|
AC_CONFIG_FILES(Makefile.pre Modules/Setup.config Misc/python.pc Misc/python-config.sh)
|
||||||
|
AC_CONFIG_FILES([Modules/ld_so_aix], [chmod +x Modules/ld_so_aix])
|
|
@ -0,0 +1,104 @@
|
||||||
|
From 5affd5c29eb1493cb31ef3cfdde15538ac134689 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
|
||||||
|
Date: Tue, 13 Mar 2018 10:56:43 +0100
|
||||||
|
Subject: [PATCH] bpo-32885: Tools/scripts/pathfix.py: Add -n option for no
|
||||||
|
backup~ (#5772)
|
||||||
|
|
||||||
|
Creating backup files with ~ suffix can be undesirable in some environment,
|
||||||
|
such as when building RPM packages. Instead of requiring the user to remove
|
||||||
|
those files manually, option -n was added, that simply disables this feature.
|
||||||
|
|
||||||
|
-n was selected because 2to3 has the same option with this behavior.
|
||||||
|
---
|
||||||
|
Misc/ACKS | 1 +
|
||||||
|
.../2018-02-20-12-16-47.bpo-32885.dL5x7C.rst | 2 ++
|
||||||
|
Tools/scripts/pathfix.py | 28 +++++++++++++++-------
|
||||||
|
3 files changed, 23 insertions(+), 8 deletions(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Tools-Demos/2018-02-20-12-16-47.bpo-32885.dL5x7C.rst
|
||||||
|
|
||||||
|
diff --git a/Misc/ACKS b/Misc/ACKS
|
||||||
|
index d8179c8b03ab..d752d8a35434 100644
|
||||||
|
--- a/Misc/ACKS
|
||||||
|
+++ b/Misc/ACKS
|
||||||
|
@@ -687,6 +687,7 @@ Ken Howard
|
||||||
|
Brad Howes
|
||||||
|
Mike Hoy
|
||||||
|
Ben Hoyt
|
||||||
|
+Miro Hrončok
|
||||||
|
Chiu-Hsiang Hsu
|
||||||
|
Chih-Hao Huang
|
||||||
|
Christian Hudon
|
||||||
|
diff --git a/Misc/NEWS.d/next/Tools-Demos/2018-02-20-12-16-47.bpo-32885.dL5x7C.rst b/Misc/NEWS.d/next/Tools-Demos/2018-02-20-12-16-47.bpo-32885.dL5x7C.rst
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000000..e003e1d84fd0
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Tools-Demos/2018-02-20-12-16-47.bpo-32885.dL5x7C.rst
|
||||||
|
@@ -0,0 +1,2 @@
|
||||||
|
+Add an ``-n`` flag for ``Tools/scripts/pathfix.py`` to disbale automatic
|
||||||
|
+backup creation (files with ``~`` suffix).
|
||||||
|
diff --git a/Tools/scripts/pathfix.py b/Tools/scripts/pathfix.py
|
||||||
|
index 562bbc737812..c5bf984306a3 100755
|
||||||
|
--- a/Tools/scripts/pathfix.py
|
||||||
|
+++ b/Tools/scripts/pathfix.py
|
||||||
|
@@ -7,8 +7,9 @@
|
||||||
|
# Directories are searched recursively for files whose name looks
|
||||||
|
# like a python module.
|
||||||
|
# Symbolic links are always ignored (except as explicit directory
|
||||||
|
-# arguments). Of course, the original file is kept as a back-up
|
||||||
|
-# (with a "~" attached to its name).
|
||||||
|
+# arguments).
|
||||||
|
+# The original file is kept as a back-up (with a "~" attached to its name),
|
||||||
|
+# -n flag can be used to disable this.
|
||||||
|
#
|
||||||
|
# Undoubtedly you can do this using find and sed or perl, but this is
|
||||||
|
# a nice example of Python code that recurses down a directory tree
|
||||||
|
@@ -31,14 +32,17 @@
|
||||||
|
|
||||||
|
new_interpreter = None
|
||||||
|
preserve_timestamps = False
|
||||||
|
+create_backup = True
|
||||||
|
+
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global new_interpreter
|
||||||
|
global preserve_timestamps
|
||||||
|
- usage = ('usage: %s -i /interpreter -p file-or-directory ...\n' %
|
||||||
|
+ global create_backup
|
||||||
|
+ usage = ('usage: %s -i /interpreter -p -n file-or-directory ...\n' %
|
||||||
|
sys.argv[0])
|
||||||
|
try:
|
||||||
|
- opts, args = getopt.getopt(sys.argv[1:], 'i:p')
|
||||||
|
+ opts, args = getopt.getopt(sys.argv[1:], 'i:pn')
|
||||||
|
except getopt.error as msg:
|
||||||
|
err(str(msg) + '\n')
|
||||||
|
err(usage)
|
||||||
|
@@ -48,6 +52,8 @@ def main():
|
||||||
|
new_interpreter = a.encode()
|
||||||
|
if o == '-p':
|
||||||
|
preserve_timestamps = True
|
||||||
|
+ if o == '-n':
|
||||||
|
+ create_backup = False
|
||||||
|
if not new_interpreter or not new_interpreter.startswith(b'/') or \
|
||||||
|
not args:
|
||||||
|
err('-i option or file-or-directory missing\n')
|
||||||
|
@@ -134,10 +140,16 @@ def fix(filename):
|
||||||
|
except OSError as msg:
|
||||||
|
err('%s: warning: chmod failed (%r)\n' % (tempname, msg))
|
||||||
|
# Then make a backup of the original file as filename~
|
||||||
|
- try:
|
||||||
|
- os.rename(filename, filename + '~')
|
||||||
|
- except OSError as msg:
|
||||||
|
- err('%s: warning: backup failed (%r)\n' % (filename, msg))
|
||||||
|
+ if create_backup:
|
||||||
|
+ try:
|
||||||
|
+ os.rename(filename, filename + '~')
|
||||||
|
+ except OSError as msg:
|
||||||
|
+ err('%s: warning: backup failed (%r)\n' % (filename, msg))
|
||||||
|
+ else:
|
||||||
|
+ try:
|
||||||
|
+ os.remove(filename)
|
||||||
|
+ except OSError as msg:
|
||||||
|
+ err('%s: warning: removing failed (%r)\n' % (filename, msg))
|
||||||
|
# Now move the temp file to the original file
|
||||||
|
try:
|
||||||
|
os.rename(tempname, filename)
|
|
@ -1,17 +0,0 @@
|
||||||
/* Systemtap tapset to make it easier to trace Python */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Define python.function.entry/return:
|
|
||||||
*/
|
|
||||||
probe python.function.entry = process("python3").library("LIBRARY_PATH").mark("function__entry")
|
|
||||||
{
|
|
||||||
filename = user_string($arg1);
|
|
||||||
funcname = user_string($arg2);
|
|
||||||
lineno = $arg3;
|
|
||||||
}
|
|
||||||
probe python.function.return = process("python3").library("LIBRARY_PATH").mark("function__return")
|
|
||||||
{
|
|
||||||
filename = user_string($arg1);
|
|
||||||
funcname = user_string($arg2);
|
|
||||||
lineno = $arg3;
|
|
||||||
}
|
|
|
@ -3,8 +3,23 @@
|
||||||
# Python's compile_all module only works on directories, and requires a max
|
# Python's compile_all module only works on directories, and requires a max
|
||||||
# recursion depth
|
# recursion depth
|
||||||
|
|
||||||
|
# Note that the py_byte_compile macro should work for python2 as well
|
||||||
|
# Which unfortunately makes the definition more complicated than it should be
|
||||||
|
# The condition should be reversed once /usr/bin/python is python3!
|
||||||
|
|
||||||
%py_byte_compile()\
|
%py_byte_compile()\
|
||||||
python_binary="%1"\
|
py2_byte_compile () {\
|
||||||
bytecode_compilation_path="%2"\
|
python_binary="%1"\
|
||||||
find $bytecode_compilation_path -type f -a -name "*.py" -print0 | xargs -0 $python_binary -O -c 'import py_compile, sys; [py_compile.compile(f, dfile=f.partition("$RPM_BUILD_ROOT")[2], optimize=opt) for opt in range(2) for f in sys.argv[1:]]' || :\
|
bytecode_compilation_path="%2"\
|
||||||
|
find $bytecode_compilation_path -type f -a -name "*.py" -print0 | xargs -0 $python_binary -c 'import py_compile, sys; [py_compile.compile(f, dfile=f.partition("$RPM_BUILD_ROOT")[2]) for f in sys.argv[1:]]' || :\
|
||||||
|
find $bytecode_compilation_path -type f -a -name "*.py" -print0 | xargs -0 $python_binary -O -c 'import py_compile, sys; [py_compile.compile(f, dfile=f.partition("$RPM_BUILD_ROOT")[2]) for f in sys.argv[1:]]' || :\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
py3_byte_compile () {\
|
||||||
|
python_binary="%1"\
|
||||||
|
bytecode_compilation_path="%2"\
|
||||||
|
find $bytecode_compilation_path -type f -a -name "*.py" -print0 | xargs -0 $python_binary -O -c 'import py_compile, sys; [py_compile.compile(f, dfile=f.partition("$RPM_BUILD_ROOT")[2], optimize=opt) for opt in range(2) for f in sys.argv[1:]]' || :\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
[[ "%1" == *python3* ]] || py2_byte_compile "%1" "%2" && py3_byte_compile "%1" "%2" \
|
||||||
%{nil}
|
%{nil}
|
||||||
|
|
21
pyfuntop.stp
21
pyfuntop.stp
|
@ -1,21 +0,0 @@
|
||||||
#!/usr/bin/stap
|
|
||||||
|
|
||||||
global fn_calls;
|
|
||||||
|
|
||||||
probe python.function.entry
|
|
||||||
{
|
|
||||||
fn_calls[pid(), filename, funcname, lineno] += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
probe timer.ms(1000) {
|
|
||||||
printf("\033[2J\033[1;1H") /* clear screen */
|
|
||||||
printf("%6s %80s %6s %30s %6s\n",
|
|
||||||
"PID", "FILENAME", "LINE", "FUNCTION", "CALLS")
|
|
||||||
foreach ([pid, filename, funcname, lineno] in fn_calls- limit 20) {
|
|
||||||
printf("%6d %80s %6d %30s %6d\n",
|
|
||||||
pid, filename, lineno, funcname,
|
|
||||||
fn_calls[pid, filename, funcname, lineno]);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete fn_calls;
|
|
||||||
}
|
|
1380
python-gdb.py
1380
python-gdb.py
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,64 @@
|
||||||
|
# KNOWN BUGS:
|
||||||
|
# https://bugzilla.redhat.com/show_bug.cgi?id=1489816
|
||||||
|
addFilter(r'crypto-policy-non-compliance-openssl')
|
||||||
|
|
||||||
|
|
||||||
|
# TESTS:
|
||||||
|
addFilter(r'(zero-length|pem-certificate|uncompressed-zip) /usr/lib(64)?/python3.\d/test')
|
||||||
|
|
||||||
|
|
||||||
|
# OTHER DELIBERATES:
|
||||||
|
# chroot function
|
||||||
|
addFilter(r'missing-call-to-chdir-with-chroot')
|
||||||
|
|
||||||
|
# intentionally unversioned and selfobsoleted
|
||||||
|
addFilter(r'unversioned-explicit-obsoletes python')
|
||||||
|
addFilter(r'self-obsoletion python3\d obsoletes python3\d')
|
||||||
|
|
||||||
|
# intentionally hardcoded
|
||||||
|
addFilter(r'hardcoded-library-path in %{_prefix}/lib/(debug/%{_libdir}|python%{pybasever})')
|
||||||
|
|
||||||
|
# we have non binary stuff, python files
|
||||||
|
addFilter(r'only-non-binary-in-usr-lib')
|
||||||
|
|
||||||
|
# some devel files that are deliberately needed
|
||||||
|
addFilter(r'devel-file-in-non-devel-package /usr/include/python3\.\dm/pyconfig-(32|64)\.h')
|
||||||
|
addFilter(r'devel-file-in-non-devel-package /usr/lib64/python3\.\d/distutils/tests/xxmodule\.c')
|
||||||
|
|
||||||
|
|
||||||
|
# SORRY, NOT SORRY:
|
||||||
|
# manual pages
|
||||||
|
addFilter(r'no-manual-page-for-binary (idle|pydoc|pyvenv|2to3|python3-debug|pathfix\.py)')
|
||||||
|
addFilter(r'no-manual-page-for-binary python3.*-config$')
|
||||||
|
addFilter(r'no-manual-page-for-binary python3.\dd?m$')
|
||||||
|
|
||||||
|
# missing documentation from subpackages
|
||||||
|
addFilter(r'^python3\d?-(debug|tkinter|test|idle)\.[^:]+: (E|W): no-documentation')
|
||||||
|
|
||||||
|
# platform python is obsoleted, but not provided
|
||||||
|
addFilter(r'obsolete-not-provided platform-python')
|
||||||
|
|
||||||
|
|
||||||
|
# RPMLINT IMPERFECTIONS:
|
||||||
|
# ifarch applied patches are OK
|
||||||
|
# https://fedoraproject.org/wiki/Packaging:Guidelines#Architecture_Support
|
||||||
|
addFilter(r'%ifarch-applied-patch')
|
||||||
|
|
||||||
|
# debugsource
|
||||||
|
addFilter(r'^python3\d?-debugsource\.[^:]+: (E|W): no-documentation')
|
||||||
|
|
||||||
|
# debuginfo
|
||||||
|
addFilter(r'^python3\d?-debuginfo\.[^:]+: (E|W): useless-provides debuginfo\(build-id\)')
|
||||||
|
|
||||||
|
# debug package contains devel and non-devel files
|
||||||
|
addFilter(r'python3\d?-debug.[^:]+: (E|W): (non-)?devel-file-in-(non-)?devel-package')
|
||||||
|
|
||||||
|
# this goes to other subpackage, hence not actually dangling, the read error is bogus
|
||||||
|
addFilter(r'dangling-relative-symlink /usr/lib(64)?/pkgconfig/python-3\.\ddm\.pc python-3\.\d\.pc')
|
||||||
|
addFilter(r'read-error /usr/lib(64)?/pkgconfig/python-3\.\ddm\.pc \[Errno 2\]')
|
||||||
|
|
||||||
|
# we need this macro to evaluate, even if the line starts with #
|
||||||
|
addFilter(r'macro-in-comment %\{_pyconfig(32|64)_h\}')
|
||||||
|
|
||||||
|
# SPELLING ERRORS
|
||||||
|
addFilter(r'spelling-error .* en_US (bytecode|pyc|filename|tkinter|namespaces|pytest) ')
|
194
python3.spec
194
python3.spec
|
@ -13,8 +13,8 @@ URL: https://www.python.org/
|
||||||
|
|
||||||
# WARNING When rebasing to a new Python version,
|
# WARNING When rebasing to a new Python version,
|
||||||
# remember to update the python3-docs package as well
|
# remember to update the python3-docs package as well
|
||||||
Version: %{pybasever}.3
|
Version: %{pybasever}.5
|
||||||
Release: 2%{?dist}
|
Release: 1%{?dist}
|
||||||
License: Python
|
License: Python
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,9 +47,6 @@ License: Python
|
||||||
# Support for the GDB debugger
|
# Support for the GDB debugger
|
||||||
%bcond_without gdb_hooks
|
%bcond_without gdb_hooks
|
||||||
|
|
||||||
# Support for systemtap instrumentation
|
|
||||||
%bcond_with systemtap
|
|
||||||
|
|
||||||
# The dbm.gnu module (key-value database)
|
# The dbm.gnu module (key-value database)
|
||||||
%bcond_without gdbm
|
%bcond_without gdbm
|
||||||
|
|
||||||
|
@ -176,7 +173,7 @@ BuildRequires: expat-devel
|
||||||
BuildRequires: findutils
|
BuildRequires: findutils
|
||||||
BuildRequires: gcc-c++
|
BuildRequires: gcc-c++
|
||||||
%if %{with gdbm}
|
%if %{with gdbm}
|
||||||
BuildRequires: gdbm-devel
|
BuildRequires: gdbm-devel >= 1:1.13
|
||||||
%endif
|
%endif
|
||||||
BuildRequires: glibc-devel
|
BuildRequires: glibc-devel
|
||||||
BuildRequires: gmp-devel
|
BuildRequires: gmp-devel
|
||||||
|
@ -192,12 +189,6 @@ BuildRequires: readline-devel
|
||||||
BuildRequires: sqlite-devel
|
BuildRequires: sqlite-devel
|
||||||
BuildRequires: gdb
|
BuildRequires: gdb
|
||||||
|
|
||||||
%if %{with systemtap}
|
|
||||||
BuildRequires: systemtap-devel
|
|
||||||
BuildRequires: systemtap-sdt-devel
|
|
||||||
%global tapsetdir /usr/share/systemtap/tapset
|
|
||||||
%endif
|
|
||||||
|
|
||||||
BuildRequires: tar
|
BuildRequires: tar
|
||||||
BuildRequires: tcl-devel
|
BuildRequires: tcl-devel
|
||||||
BuildRequires: tix-devel
|
BuildRequires: tix-devel
|
||||||
|
@ -232,19 +223,6 @@ Source: https://www.python.org/ftp/python/%{version}/Python-%{version}.tar.xz
|
||||||
# with different Python runtimes as necessary:
|
# with different Python runtimes as necessary:
|
||||||
Source3: macros.pybytecompile%{pybasever}
|
Source3: macros.pybytecompile%{pybasever}
|
||||||
|
|
||||||
# Systemtap tapset to make it easier to use the systemtap static probes
|
|
||||||
# (actually a template; LIBRARY_PATH will get fixed up during install)
|
|
||||||
# Written by dmalcolm; not yet sent upstream
|
|
||||||
Source5: libpython.stp
|
|
||||||
|
|
||||||
# Example systemtap script using the tapset
|
|
||||||
# Written by wcohen, mjw, dmalcolm; not yet sent upstream
|
|
||||||
Source6: systemtap-example.stp
|
|
||||||
|
|
||||||
# Another example systemtap script that uses the tapset
|
|
||||||
# Written by dmalcolm; not yet sent upstream
|
|
||||||
Source7: pyfuntop.stp
|
|
||||||
|
|
||||||
# A simple script to check timestamps of bytecode files
|
# A simple script to check timestamps of bytecode files
|
||||||
# Run in check section with Python that is currently being built
|
# Run in check section with Python that is currently being built
|
||||||
# Written by bkabrda
|
# Written by bkabrda
|
||||||
|
@ -265,16 +243,9 @@ Source11: idle3.appdata.xml
|
||||||
# Was Patch0 in ivazquez' python3000 specfile:
|
# Was Patch0 in ivazquez' python3000 specfile:
|
||||||
Patch1: 00001-rpath.patch
|
Patch1: 00001-rpath.patch
|
||||||
|
|
||||||
# 00055 #
|
|
||||||
# Systemtap support: add statically-defined probe points
|
|
||||||
# Patch sent upstream as http://bugs.python.org/issue14776
|
|
||||||
# with some subsequent reworking to cope with LANG=C in an rpmbuild
|
|
||||||
# (where sys.getfilesystemencoding() == 'ascii')
|
|
||||||
Patch55: 00055-systemtap.patch
|
|
||||||
|
|
||||||
# 00102 #
|
# 00102 #
|
||||||
# Change the various install paths to use /usr/lib64/ instead or /usr/lib
|
# Change the various install paths to use /usr/lib64/ instead or /usr/lib
|
||||||
# Only used when "%{_lib}" == "lib64"
|
# Only used when "%%{_lib}" == "lib64"
|
||||||
# Not yet sent upstream.
|
# Not yet sent upstream.
|
||||||
Patch102: 00102-lib64.patch
|
Patch102: 00102-lib64.patch
|
||||||
|
|
||||||
|
@ -361,34 +332,29 @@ Patch251: 00251-change-user-install-location.patch
|
||||||
# Original proposal: https://bugzilla.redhat.com/show_bug.cgi?id=1404918
|
# Original proposal: https://bugzilla.redhat.com/show_bug.cgi?id=1404918
|
||||||
Patch262: 00262-pep538_coerce_legacy_c_locale.patch
|
Patch262: 00262-pep538_coerce_legacy_c_locale.patch
|
||||||
|
|
||||||
# 00264 #
|
|
||||||
# test_pass_by_value was added in Python 3.6.1 and on aarch64
|
|
||||||
# it is catching an error that was there, but wasn't tested before.
|
|
||||||
# Therefore skipping the test on aarch64 until fixed upstream.
|
|
||||||
# Reported upstream: http://bugs.python.org/issue29804
|
|
||||||
Patch264: 00264-skip-test-failing-on-aarch64.patch
|
|
||||||
|
|
||||||
# 00273 #
|
|
||||||
# Skip test_float_with_comma, which fails in Koji with UnicodeDecodeError
|
|
||||||
# See https://bugzilla.redhat.com/show_bug.cgi?id=1484497
|
|
||||||
Patch273: 00273-skip-float-test.patch
|
|
||||||
|
|
||||||
# 00274 #
|
# 00274 #
|
||||||
# Upstream uses Debian-style architecture naming. Change to match Fedora.
|
# Upstream uses Debian-style architecture naming. Change to match Fedora.
|
||||||
Patch274: 00274-fix-arch-names.patch
|
Patch274: 00274-fix-arch-names.patch
|
||||||
|
|
||||||
# 00277 #
|
# 00292 #
|
||||||
# Fix test_exception_errpipe_bad_data() and
|
# Restore the public PyExc_RecursionErrorInst symbol that was removed
|
||||||
# test_exception_errpipe_normal() of test_subprocess: mock os.waitpid()
|
# from the 3.6.4 release upstream.
|
||||||
# to avoid calling the real os.waitpid(0, 0) which is an unexpected
|
# Reported upstream: https://bugs.python.org/issue30697
|
||||||
# side effect of the test, which makes the koji builds hang.
|
Patch292: 00292-restore-PyExc_RecursionErrorInst-symbol.patch
|
||||||
# Fixed upstream: https://github.com/python/cpython/commit/11045c9d8a21dd9bd182a3939189db02815f9783
|
|
||||||
Patch277: 00277-fix-test-subprocess-hanging-tests.patch
|
|
||||||
|
|
||||||
# 00279 #
|
# 00294 #
|
||||||
# Fix memory corruption due to allocator mix
|
# Define TLS cipher suite on build time depending
|
||||||
# Fixed upstream: https://bugs.python.org/issue31532
|
# on the OpenSSL default cipher suite selection.
|
||||||
Patch279: 00279-fix-memory-corruption-due-to-allocator-mix.patch
|
# Fixed upstream on CPython's 3.7 branch:
|
||||||
|
# https://bugs.python.org/issue31429
|
||||||
|
# See also: https://bugzilla.redhat.com/show_bug.cgi?id=1489816
|
||||||
|
Patch294: 00294-define-TLS-cipher-suite-on-build-time.patch
|
||||||
|
|
||||||
|
# 00301 #
|
||||||
|
# Tools/scripts/pathfix.py: Add -n option for no backup~
|
||||||
|
# See: https://bugzilla.redhat.com/show_bug.cgi?id=1546990
|
||||||
|
# Fixed upstream: https://bugs.python.org/issue32885
|
||||||
|
Patch301: 00301-pathfix-add-n-option-for-no-backup.patch
|
||||||
|
|
||||||
# (New patches go here ^^^)
|
# (New patches go here ^^^)
|
||||||
#
|
#
|
||||||
|
@ -440,7 +406,7 @@ language, designed with an emphasis on code readibility.
|
||||||
It includes an extensive standard library, and has a vast ecosystem of
|
It includes an extensive standard library, and has a vast ecosystem of
|
||||||
third-party libraries.
|
third-party libraries.
|
||||||
|
|
||||||
The ${name} package provides the "python3" executable: the reference
|
The %{name} package provides the "python3" executable: the reference
|
||||||
interpreter for the Python language, version 3.
|
interpreter for the Python language, version 3.
|
||||||
The majority of its standard library is provided in the %{name}-libs package,
|
The majority of its standard library is provided in the %{name}-libs package,
|
||||||
which should be installed automatically along with %{name}.
|
which should be installed automatically along with %{name}.
|
||||||
|
@ -466,6 +432,11 @@ Obsoletes: python3-enum34 < 1.0.4-5%{?dist}
|
||||||
# See https://bugzilla.redhat.com/show_bug.cgi?id=1410644
|
# See https://bugzilla.redhat.com/show_bug.cgi?id=1410644
|
||||||
Requires: glibc%{?_isa} >= 2.24.90-26
|
Requires: glibc%{?_isa} >= 2.24.90-26
|
||||||
|
|
||||||
|
%if %{with gdbm}
|
||||||
|
# When built with this (as guarded by the BuildRequires above), require it
|
||||||
|
Requires: gdbm%{?_isa} >= 1:1.13
|
||||||
|
%endif
|
||||||
|
|
||||||
# For backward compatibility only, remove in F29:
|
# For backward compatibility only, remove in F29:
|
||||||
Provides: system-python-libs = %{version}-%{release}
|
Provides: system-python-libs = %{version}-%{release}
|
||||||
Provides: system-python-libs%{?_isa} = %{version}-%{release}
|
Provides: system-python-libs%{?_isa} = %{version}-%{release}
|
||||||
|
@ -589,18 +560,12 @@ so extensions for both verisons can co-exist in the same directory.
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n Python-%{version}%{?prerel}
|
%setup -q -n Python-%{version}%{?prerel}
|
||||||
|
|
||||||
%if %{with systemtap}
|
|
||||||
# Provide an example of usage of the tapset:
|
|
||||||
cp -a %{SOURCE6} .
|
|
||||||
cp -a %{SOURCE7} .
|
|
||||||
%endif # with systemtap
|
|
||||||
|
|
||||||
# Remove bundled libraries to ensure that we're using the system copy.
|
# Remove bundled libraries to ensure that we're using the system copy.
|
||||||
rm -r Modules/expat
|
rm -r Modules/expat
|
||||||
rm -r Modules/zlib
|
rm -r Modules/zlib
|
||||||
|
|
||||||
%if %{with rewheel}
|
%if %{with rewheel}
|
||||||
%global pip_version 9.0.1
|
%global pip_version 9.0.3
|
||||||
sed -r -i s/'_PIP_VERSION = "[0-9.]+"'/'_PIP_VERSION = "%{pip_version}"'/ Lib/ensurepip/__init__.py
|
sed -r -i s/'_PIP_VERSION = "[0-9.]+"'/'_PIP_VERSION = "%{pip_version}"'/ Lib/ensurepip/__init__.py
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
@ -609,10 +574,6 @@ sed -r -i s/'_PIP_VERSION = "[0-9.]+"'/'_PIP_VERSION = "%{pip_version}"'/ Lib/en
|
||||||
#
|
#
|
||||||
%patch1 -p1
|
%patch1 -p1
|
||||||
|
|
||||||
%if %{with systemtap}
|
|
||||||
%patch55 -p1 -b .systemtap
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%if "%{_lib}" == "lib64"
|
%if "%{_lib}" == "lib64"
|
||||||
%patch102 -p1
|
%patch102 -p1
|
||||||
%endif
|
%endif
|
||||||
|
@ -631,15 +592,10 @@ sed -r -i s/'_PIP_VERSION = "[0-9.]+"'/'_PIP_VERSION = "%{pip_version}"'/ Lib/en
|
||||||
%patch205 -p1
|
%patch205 -p1
|
||||||
%patch251 -p1
|
%patch251 -p1
|
||||||
%patch262 -p1
|
%patch262 -p1
|
||||||
|
|
||||||
%ifarch aarch64
|
|
||||||
%patch264 -p1
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%patch273 -p1
|
|
||||||
%patch274 -p1
|
%patch274 -p1
|
||||||
%patch277 -p1
|
%patch292 -p1
|
||||||
%patch279 -p1
|
%patch294 -p1
|
||||||
|
%patch301 -p1
|
||||||
|
|
||||||
|
|
||||||
# Remove files that should be generated by the build
|
# Remove files that should be generated by the build
|
||||||
|
@ -711,9 +667,7 @@ BuildPython() {
|
||||||
--enable-loadable-sqlite-extensions \
|
--enable-loadable-sqlite-extensions \
|
||||||
--with-dtrace \
|
--with-dtrace \
|
||||||
--with-lto \
|
--with-lto \
|
||||||
%if %{with systemtap}
|
--with-ssl-default-suites=openssl \
|
||||||
--with-systemtap \
|
|
||||||
%endif
|
|
||||||
%if %{with valgrind}
|
%if %{with valgrind}
|
||||||
--with-valgrind \
|
--with-valgrind \
|
||||||
%endif
|
%endif
|
||||||
|
@ -835,16 +789,6 @@ InstallPython() {
|
||||||
#endif
|
#endif
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Systemtap hooks
|
|
||||||
%if %{with systemtap}
|
|
||||||
mkdir -p %{buildroot}%{tapsetdir}
|
|
||||||
sed \
|
|
||||||
-e "s|LIBRARY_PATH|%{_libdir}/${PyInstSoName}|" \
|
|
||||||
-e 's|"python3"|"python3${Postfix}"|' \
|
|
||||||
%{_sourcedir}/libpython.stp \
|
|
||||||
> %{buildroot}%{tapsetdir}/libpython%{pybasever}${Postfix}-%{wordsize}.stp
|
|
||||||
%endif # with systemtap
|
|
||||||
|
|
||||||
echo FINISHED: INSTALL OF PYTHON FOR CONFIGURATION: $ConfName
|
echo FINISHED: INSTALL OF PYTHON FOR CONFIGURATION: $ConfName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -919,9 +863,10 @@ sed -i -e "s/'pyconfig.h'/'%{_pyconfig_h}'/" \
|
||||||
# so handle files named using other naming scheme separately.
|
# so handle files named using other naming scheme separately.
|
||||||
LD_LIBRARY_PATH=./build/optimized ./build/optimized/python \
|
LD_LIBRARY_PATH=./build/optimized ./build/optimized/python \
|
||||||
Tools/scripts/pathfix.py \
|
Tools/scripts/pathfix.py \
|
||||||
-i "%{_bindir}/python%{pybasever}" \
|
-i "%{_bindir}/python%{pybasever}" -pn \
|
||||||
%{buildroot} %{buildroot}%{pylibdir}/Tools/scripts/*-*.py \
|
%{buildroot} %{buildroot}%{pylibdir}/Tools/scripts/*-*.py \
|
||||||
%{buildroot}%{pylibdir}/Tools/pynche/{pynche,pynche.pyw}
|
%{buildroot}%{pylibdir}/Tools/pynche/{pynche,pynche.pyw} \
|
||||||
|
%{?with_gdb_hooks:%{buildroot}$DirHoldingGdbPy/*.py}
|
||||||
# not covered, also redundant and useless:
|
# not covered, also redundant and useless:
|
||||||
rm %{buildroot}%{pylibdir}/Tools/scripts/{2to3,idle3,pydoc3,pyvenv}
|
rm %{buildroot}%{pylibdir}/Tools/scripts/{2to3,idle3,pydoc3,pyvenv}
|
||||||
|
|
||||||
|
@ -1026,14 +971,6 @@ done
|
||||||
# Running the upstream test suite
|
# Running the upstream test suite
|
||||||
# ======================================================
|
# ======================================================
|
||||||
|
|
||||||
# For ppc64 we need a larger stack than default
|
|
||||||
# See https://bugzilla.redhat.com/show_bug.cgi?id=1292462
|
|
||||||
%ifarch %{power64}
|
|
||||||
ulimit -a
|
|
||||||
ulimit -s 16384
|
|
||||||
%endif
|
|
||||||
|
|
||||||
|
|
||||||
topdir=$(pwd)
|
topdir=$(pwd)
|
||||||
CheckPython() {
|
CheckPython() {
|
||||||
ConfName=$1
|
ConfName=$1
|
||||||
|
@ -1241,7 +1178,6 @@ fi
|
||||||
%{dynload_dir}/spwd.%{SOABI_optimized}.so
|
%{dynload_dir}/spwd.%{SOABI_optimized}.so
|
||||||
%{dynload_dir}/syslog.%{SOABI_optimized}.so
|
%{dynload_dir}/syslog.%{SOABI_optimized}.so
|
||||||
%{dynload_dir}/termios.%{SOABI_optimized}.so
|
%{dynload_dir}/termios.%{SOABI_optimized}.so
|
||||||
#%{dynload_dir}/time.%{SOABI_optimized}.so
|
|
||||||
%{dynload_dir}/_testmultiphase.%{SOABI_optimized}.so
|
%{dynload_dir}/_testmultiphase.%{SOABI_optimized}.so
|
||||||
%{dynload_dir}/unicodedata.%{SOABI_optimized}.so
|
%{dynload_dir}/unicodedata.%{SOABI_optimized}.so
|
||||||
%{dynload_dir}/xxlimited.%{SOABI_optimized}.so
|
%{dynload_dir}/xxlimited.%{SOABI_optimized}.so
|
||||||
|
@ -1332,12 +1268,6 @@ fi
|
||||||
|
|
||||||
%{_libdir}/%{py_INSTSONAME_optimized}
|
%{_libdir}/%{py_INSTSONAME_optimized}
|
||||||
%{_libdir}/libpython3.so
|
%{_libdir}/libpython3.so
|
||||||
%if %{with systemtap}
|
|
||||||
%dir %(dirname %{tapsetdir})
|
|
||||||
%dir %{tapsetdir}
|
|
||||||
%{tapsetdir}/%{libpython_stp_optimized}
|
|
||||||
%doc systemtap-example.stp pyfuntop.stp
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%files devel
|
%files devel
|
||||||
%defattr(-,root,root)
|
%defattr(-,root,root)
|
||||||
|
@ -1477,7 +1407,6 @@ fi
|
||||||
%{dynload_dir}/spwd.%{SOABI_debug}.so
|
%{dynload_dir}/spwd.%{SOABI_debug}.so
|
||||||
%{dynload_dir}/syslog.%{SOABI_debug}.so
|
%{dynload_dir}/syslog.%{SOABI_debug}.so
|
||||||
%{dynload_dir}/termios.%{SOABI_debug}.so
|
%{dynload_dir}/termios.%{SOABI_debug}.so
|
||||||
#%{dynload_dir}/time.%{SOABI_debug}.so
|
|
||||||
%{dynload_dir}/_testmultiphase.%{SOABI_debug}.so
|
%{dynload_dir}/_testmultiphase.%{SOABI_debug}.so
|
||||||
%{dynload_dir}/unicodedata.%{SOABI_debug}.so
|
%{dynload_dir}/unicodedata.%{SOABI_debug}.so
|
||||||
%{dynload_dir}/zlib.%{SOABI_debug}.so
|
%{dynload_dir}/zlib.%{SOABI_debug}.so
|
||||||
|
@ -1487,11 +1416,6 @@ fi
|
||||||
# now; they're listed below, under "-devel":
|
# now; they're listed below, under "-devel":
|
||||||
|
|
||||||
%{_libdir}/%{py_INSTSONAME_debug}
|
%{_libdir}/%{py_INSTSONAME_debug}
|
||||||
%if %{with systemtap}
|
|
||||||
%dir %(dirname %{tapsetdir})
|
|
||||||
%dir %{tapsetdir}
|
|
||||||
%{tapsetdir}/%{libpython_stp_debug}
|
|
||||||
%endif
|
|
||||||
|
|
||||||
# Analog of the -devel subpackage's files:
|
# Analog of the -devel subpackage's files:
|
||||||
%{pylibdir}/config-%{LDVERSION_debug}-%{_arch}-linux%{_gnu}
|
%{pylibdir}/config-%{LDVERSION_debug}-%{_arch}-linux%{_gnu}
|
||||||
|
@ -1520,7 +1444,7 @@ fi
|
||||||
# We put the debug-gdb.py file inside /usr/lib/debug to avoid noise from ldconfig
|
# We put the debug-gdb.py file inside /usr/lib/debug to avoid noise from ldconfig
|
||||||
# See https://bugzilla.redhat.com/show_bug.cgi?id=562980
|
# See https://bugzilla.redhat.com/show_bug.cgi?id=562980
|
||||||
#
|
#
|
||||||
# The /usr/lib/rpm/redhat/macros defines %__debug_package to use
|
# The /usr/lib/rpm/redhat/macros defines %%__debug_package to use
|
||||||
# debugfiles.list, and it appears that everything below /usr/lib/debug and
|
# debugfiles.list, and it appears that everything below /usr/lib/debug and
|
||||||
# (/usr/src/debug) gets added to this file (via LISTFILES) in
|
# (/usr/src/debug) gets added to this file (via LISTFILES) in
|
||||||
# /usr/lib/rpm/find-debuginfo.sh
|
# /usr/lib/rpm/find-debuginfo.sh
|
||||||
|
@ -1538,6 +1462,50 @@ fi
|
||||||
# ======================================================
|
# ======================================================
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Mar 29 2018 Charalampos Stratakis <cstratak@redhat.com> - 3.6.5-1
|
||||||
|
- Update to 3.6.5
|
||||||
|
|
||||||
|
* Sat Mar 24 2018 Miro Hrončok <mhroncok@redhat.com> - 3.6.4-12
|
||||||
|
- Fix broken macro invocation and broken building of C Python extensions
|
||||||
|
Resolves: rhbz#1560103
|
||||||
|
|
||||||
|
* Fri Mar 16 2018 Miro Hrončok <mhroncok@redhat.com> - 3.6.4-11
|
||||||
|
- Add -n option for pathfix.py
|
||||||
|
Resolves: rhbz#1546990
|
||||||
|
|
||||||
|
* Thu Mar 15 2018 Miro Hrončok <mhroncok@redhat.com> - 3.6.4-10
|
||||||
|
- Fix the py_byte_compile macro to work on Python 2
|
||||||
|
- Remove the pybytecompile macro file from the flat package
|
||||||
|
Resolves: rhbz#1484993
|
||||||
|
|
||||||
|
* Tue Mar 13 2018 Charalampos Stratakis <cstratak@redhat.com> - 3.6.4-9
|
||||||
|
- Do not send IP addresses in SNI TLS extension
|
||||||
|
|
||||||
|
* Fri Feb 02 2018 Michal Cyprian <mcyprian@redhat.com> - 3.6.4-8
|
||||||
|
- Remove sys.executable check from change-user-install-location patch
|
||||||
|
Resolves: rhbz#1532287
|
||||||
|
|
||||||
|
* Thu Feb 01 2018 Charalampos Stratakis <cstratak@redhat.com> - 3.6.4-7
|
||||||
|
- Define TLS cipher suite on build time.
|
||||||
|
|
||||||
|
* Tue Jan 23 2018 Charalampos Stratakis <cstratak@redhat.com> - 3.6.4-6
|
||||||
|
- Restore the PyExc_RecursionErrorInst public symbol
|
||||||
|
|
||||||
|
* Fri Jan 19 2018 Charalampos Stratakis <cstratak@redhat.com> - 3.6.4-5
|
||||||
|
- Fix localeconv() encoding for LC_NUMERIC
|
||||||
|
|
||||||
|
* Thu Jan 18 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 3.6.4-4
|
||||||
|
- R: gdbm-devel → R: gdbm for python3-libs
|
||||||
|
|
||||||
|
* Wed Jan 17 2018 Miro Hrončok <mhroncok@redhat.com> - 3.6.4-3
|
||||||
|
- Require large enough gdbm (fixup for previous bump)
|
||||||
|
|
||||||
|
* Tue Jan 16 2018 Charalampos Stratakis <cstratak@redhat.com> - 3.6.4-2
|
||||||
|
- Rebuild for reverted gdbm 1.13 on Fedora 27
|
||||||
|
|
||||||
|
* Mon Jan 15 2018 Charalampos Stratakis <cstratak@redhat.com> - 3.6.4-1
|
||||||
|
- Update to version 3.6.4
|
||||||
|
|
||||||
* Mon Oct 09 2017 Charalampos Stratakis <cstratak@redhat.com> - 3.6.3-2
|
* Mon Oct 09 2017 Charalampos Stratakis <cstratak@redhat.com> - 3.6.3-2
|
||||||
- Fix memory corruption due to allocator mix
|
- Fix memory corruption due to allocator mix
|
||||||
Resolves: rhbz#1498207
|
Resolves: rhbz#1498207
|
||||||
|
|
2
sources
2
sources
|
@ -1 +1 @@
|
||||||
SHA512 (Python-3.6.3.tar.xz) = 32f24a3adcb7880003c7ecdc5e53e838e774adda76b308961d8215e28db630b2fa2828097817924c76afa4212b2df3362eb64d4e10f37c0147f512ec5aa8662b
|
SHA512 (Python-3.6.5.tar.xz) = 6b26fcd296b9bd8e67861eff10d14db7507711ddba947288d16d6def53135c39326b7f969c04bb2b2993f924d9e7ad3f5c5282a3915760bc0885cf0a8ea5eb51
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
Example usage of the Python systemtap tapset to show a nested view of all
|
|
||||||
Python function calls (and returns) across the whole system.
|
|
||||||
|
|
||||||
Run this using
|
|
||||||
stap systemtap-example.stp
|
|
||||||
to instrument all Python processes on the system, or (for example) using
|
|
||||||
stap systemtap-example.stp -c COMMAND
|
|
||||||
to instrument a specific program (implemented in Python)
|
|
||||||
*/
|
|
||||||
probe python.function.entry
|
|
||||||
{
|
|
||||||
printf("%s => %s in %s:%d\n", thread_indent(1), funcname, filename, lineno);
|
|
||||||
}
|
|
||||||
|
|
||||||
probe python.function.return
|
|
||||||
{
|
|
||||||
printf("%s <= %s in %s:%d\n", thread_indent(-1), funcname, filename, lineno);
|
|
||||||
}
|
|
Loading…
Reference in New Issue