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):
|
||||
self.assertEqual(dirs[1], wanted)
|
||||
elif os.sep == '/':
|
||||
# OS X non-framwework builds, Linux, FreeBSD, etc
|
||||
# OS X non-framework builds, Linux, FreeBSD, etc
|
||||
- self.assertEqual(len(dirs), 1)
|
||||
- wanted = os.path.join('xoxo', 'lib',
|
||||
+ self.assertEqual(len(dirs), 2)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
diff --git a/Makefile.pre.in b/Makefile.pre.in
|
||||
index 70e5927..04c8e3d 100644
|
||||
index 4b093e3..1088435 100644
|
||||
--- a/Makefile.pre.in
|
||||
+++ b/Makefile.pre.in
|
||||
@@ -556,7 +556,7 @@ clinic: $(BUILDPYTHON) $(srcdir)/Modules/_blake2/blake2s_impl.c
|
||||
$(RUNSHARED) $(PYTHON_FOR_BUILD) ./Tools/clinic/clinic.py --make
|
||||
@@ -543,7 +543,7 @@ clinic: check-clean-src $(srcdir)/Modules/_blake2/blake2s_impl.c
|
||||
$(PYTHON_FOR_REGEN) ./Tools/clinic/clinic.py --make
|
||||
|
||||
# Build the interpreter
|
||||
-$(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)
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -30,7 +30,7 @@ index 70e5927..04c8e3d 100644
|
|||
libpython$(LDVERSION).so: $(LIBRARY_OBJS)
|
||||
if test $(INSTSONAME) != $(LDLIBRARY); then \
|
||||
$(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 "-----------------------------------------------"; \
|
||||
fi
|
||||
|
||||
|
@ -39,7 +39,7 @@ index 70e5927..04c8e3d 100644
|
|||
$(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; \
|
||||
fi; \
|
||||
done
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
diff -Nur Python-3.4.1/Lib/ensurepip/__init__.py Python-3.4.1-rewheel/Lib/ensurepip/__init__.py
|
||||
--- Python-3.4.1/Lib/ensurepip/__init__.py 2014-08-21 10:49:30.792695824 +0200
|
||||
+++ Python-3.4.1-rewheel/Lib/ensurepip/__init__.py 2014-08-21 10:10:41.958341726 +0200
|
||||
diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py
|
||||
index d69e09f..5cb12df 100644
|
||||
--- a/Lib/ensurepip/__init__.py
|
||||
+++ b/Lib/ensurepip/__init__.py
|
||||
@@ -1,8 +1,10 @@
|
||||
import os
|
||||
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"]
|
||||
@@ -38,6 +40,8 @@
|
||||
@@ -25,6 +27,8 @@ def _run_pip(args, additional_paths=None):
|
||||
|
||||
# Install the bundled software
|
||||
import pip
|
||||
+ if args[0] in ["install", "list", "wheel"]:
|
||||
+ 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
|
||||
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
|
||||
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
|
||||
--- 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/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
|
||||
@@ -0,0 +1,143 @@
|
||||
+import argparse
|
||||
+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
|
||||
+ return to_write, to_omit
|
||||
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-rewheel/Makefile.pre.in 2014-08-21 10:10:41.961341722 +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
|
||||
@@ -1145,7 +1145,7 @@
|
||||
test/test_asyncio \
|
||||
collections concurrent concurrent/futures encodings \
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
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
|
||||
+++ b/Lib/distutils/command/install.py
|
||||
@@ -424,8 +424,18 @@ class install(Command):
|
||||
@@ -418,8 +418,19 @@ class install(Command):
|
||||
raise DistutilsOptionError(
|
||||
"must not supply exec-prefix without prefix")
|
||||
|
||||
- self.prefix = os.path.normpath(sys.prefix)
|
||||
- self.exec_prefix = os.path.normpath(sys.exec_prefix)
|
||||
+ # self.prefix is set to sys.prefix + /local/
|
||||
+ # if the executable is /usr/bin/python* and RPM build
|
||||
+ # is not detected to make pip and distutils install into
|
||||
+ # the separate location.
|
||||
+ if (sys.executable.startswith("/usr/bin/python")
|
||||
+ and 'RPM_BUILD_ROOT' not in os.environ):
|
||||
+ # if neither RPM build nor virtual environment is
|
||||
+ # detected to make pip and distutils install packages
|
||||
+ # into the separate location.
|
||||
+ if (not (hasattr(sys, 'real_prefix') or
|
||||
+ sys.prefix != sys.base_prefix) and
|
||||
+ 'RPM_BUILD_ROOT' not in os.environ):
|
||||
+ addition = "/local"
|
||||
+ else:
|
||||
+ addition = ""
|
||||
|
@ -24,22 +25,21 @@ index 9d31d13..ed44a93 100644
|
|||
else:
|
||||
if self.exec_prefix is None:
|
||||
diff --git a/Lib/site.py b/Lib/site.py
|
||||
index 4744eb0..b5fe571 100644
|
||||
index 0fc9200..c95202e 100644
|
||||
--- a/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
|
||||
|
||||
def addsitepackages(known_paths, prefixes=None):
|
||||
- """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*
|
||||
+ and RPM build is not detected to make sudo pip installed packages visible.
|
||||
+ '/usr/local' is included in PREFIXES if RPM build is not detected
|
||||
+ to make packages installed into this location visible.
|
||||
+
|
||||
+ """
|
||||
+ if (ENABLE_USER_SITE and sys.executable.startswith("/usr/bin/python")
|
||||
+ and 'RPM_BUILD_ROOT' not in os.environ):
|
||||
+ if ENABLE_USER_SITE and 'RPM_BUILD_ROOT' not in os.environ:
|
||||
+ PREFIXES.insert(0, "/usr/local")
|
||||
for sitedir in getsitepackages(prefixes):
|
||||
if os.path.isdir(sitedir):
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
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
|
||||
+++ b/Doc/using/cmdline.rst
|
||||
@@ -713,6 +713,45 @@ conflict.
|
||||
@@ -711,6 +711,45 @@ conflict.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
|
||||
|
@ -500,37 +500,13 @@ index 0000000..635c98f
|
|||
+if __name__ == "__main__":
|
||||
+ test_main()
|
||||
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
|
||||
+++ b/Lib/test/test_capi.py
|
||||
@@ -369,14 +369,21 @@ class EmbeddingTests(unittest.TestCase):
|
||||
def tearDown(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):
|
||||
@@ -425,32 +425,21 @@ class EmbeddingTests(unittest.TestCase):
|
||||
def test_repeated_init_and_subinterpreters(self):
|
||||
# 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 > 1:
|
||||
print()
|
||||
|
@ -549,49 +525,23 @@ index 6c3625d..009f542 100644
|
|||
-
|
||||
def test_forced_io_encoding(self):
|
||||
# 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:
|
||||
+ env = dict(os.environ, PYTHONIOENCODING="utf-8:surrogateescape")
|
||||
+ out, err = self.run_embedded_interpreter("forced_io_encoding", env=env)
|
||||
+ if support.verbose > 1:
|
||||
print()
|
||||
print(out)
|
||||
print(err)
|
||||
- expected_errors = sys.__stdout__.errors
|
||||
- expected_stdin_encoding = sys.__stdin__.encoding
|
||||
expected_stream_encoding = "utf-8"
|
||||
expected_errors = "surrogateescape"
|
||||
- expected_pipe_encoding = self._get_default_pipe_encoding()
|
||||
+ expected_stream_encoding = "utf-8"
|
||||
+ expected_errors = "surrogateescape"
|
||||
expected_output = '\n'.join([
|
||||
"--- Use defaults ---",
|
||||
"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
|
||||
index ae2bcd4..0a302ff 100644
|
||||
--- a/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):
|
||||
env = os.environ.copy()
|
||||
# Use C locale to get ascii for the locale encoding
|
||||
|
@ -601,7 +551,7 @@ index ae2bcd4..0a302ff 100644
|
|||
b'import locale; '
|
||||
b'print(ascii("' + undecodable + b'"), '
|
||||
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
|
||||
+++ b/Lib/test/test_sys.py
|
||||
@@ -680,6 +680,7 @@ class SysModuleTest(unittest.TestCase):
|
||||
|
@ -613,7 +563,7 @@ index df9ebd4..63145e4 100644
|
|||
'import sys',
|
||||
'def dump(name):',
|
||||
diff --git a/Modules/main.c b/Modules/main.c
|
||||
index dd50211..f20cf24 100644
|
||||
index b0fb78f..0d8590a 100644
|
||||
--- a/Modules/main.c
|
||||
+++ b/Modules/main.c
|
||||
@@ -105,7 +105,11 @@ static const char usage_6[] =
|
||||
|
@ -630,16 +580,15 @@ index dd50211..f20cf24 100644
|
|||
static int
|
||||
usage(int exitcode, const wchar_t* program)
|
||||
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
|
||||
index 3968399..1bd2bbf 100644
|
||||
index b0f9087..da892bf 100644
|
||||
--- a/Programs/_testembed.c
|
||||
+++ b/Programs/_testembed.c
|
||||
@@ -1,4 +1,5 @@
|
||||
-#include <Python.h>
|
||||
+#include "Python.h"
|
||||
#include <Python.h>
|
||||
+#include "pyconfig.h"
|
||||
#include "pythread.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*********************************************************
|
||||
diff --git a/Programs/python.c b/Programs/python.c
|
||||
index a7afbc7..03f8295 100644
|
||||
--- a/Programs/python.c
|
||||
|
@ -713,7 +662,7 @@ index a7afbc7..03f8295 100644
|
|||
for (i = 0; i < argc; i++) {
|
||||
PyMem_RawFree(argv_copy2[i]);
|
||||
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
|
||||
index a4f7f82..3843297 100644
|
||||
index 640271f..2a22b24 100644
|
||||
--- a/Python/pylifecycle.c
|
||||
+++ b/Python/pylifecycle.c
|
||||
@@ -167,6 +167,7 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
|
||||
|
@ -929,7 +878,7 @@ index a4f7f82..3843297 100644
|
|||
#endif
|
||||
|
||||
if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0')
|
||||
@@ -1242,12 +1428,8 @@ initstdio(void)
|
||||
@@ -1251,12 +1437,8 @@ initstdio(void)
|
||||
}
|
||||
}
|
||||
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
|
||||
index 67dfba3..b9c9f04 100644
|
||||
index 601cc84..5cdc021 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -3279,6 +3279,40 @@ then
|
||||
@@ -3310,6 +3310,40 @@ then
|
||||
fi
|
||||
AC_MSG_RESULT($with_pymalloc)
|
||||
|
||||
|
@ -1068,23 +938,3 @@ index 67dfba3..b9c9f04 100644
|
|||
# Check for Valgrind support
|
||||
AC_MSG_CHECKING([for --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
|
||||
# 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()\
|
||||
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:]]' || :\
|
||||
py2_byte_compile () {\
|
||||
python_binary="%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}
|
||||
|
|
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,
|
||||
# remember to update the python3-docs package as well
|
||||
Version: %{pybasever}.3
|
||||
Release: 2%{?dist}
|
||||
Version: %{pybasever}.5
|
||||
Release: 1%{?dist}
|
||||
License: Python
|
||||
|
||||
|
||||
|
@ -47,9 +47,6 @@ License: Python
|
|||
# Support for the GDB debugger
|
||||
%bcond_without gdb_hooks
|
||||
|
||||
# Support for systemtap instrumentation
|
||||
%bcond_with systemtap
|
||||
|
||||
# The dbm.gnu module (key-value database)
|
||||
%bcond_without gdbm
|
||||
|
||||
|
@ -176,7 +173,7 @@ BuildRequires: expat-devel
|
|||
BuildRequires: findutils
|
||||
BuildRequires: gcc-c++
|
||||
%if %{with gdbm}
|
||||
BuildRequires: gdbm-devel
|
||||
BuildRequires: gdbm-devel >= 1:1.13
|
||||
%endif
|
||||
BuildRequires: glibc-devel
|
||||
BuildRequires: gmp-devel
|
||||
|
@ -192,12 +189,6 @@ BuildRequires: readline-devel
|
|||
BuildRequires: sqlite-devel
|
||||
BuildRequires: gdb
|
||||
|
||||
%if %{with systemtap}
|
||||
BuildRequires: systemtap-devel
|
||||
BuildRequires: systemtap-sdt-devel
|
||||
%global tapsetdir /usr/share/systemtap/tapset
|
||||
%endif
|
||||
|
||||
BuildRequires: tar
|
||||
BuildRequires: tcl-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:
|
||||
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
|
||||
# Run in check section with Python that is currently being built
|
||||
# Written by bkabrda
|
||||
|
@ -265,16 +243,9 @@ Source11: idle3.appdata.xml
|
|||
# Was Patch0 in ivazquez' python3000 specfile:
|
||||
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 #
|
||||
# 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.
|
||||
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
|
||||
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 #
|
||||
# Upstream uses Debian-style architecture naming. Change to match Fedora.
|
||||
Patch274: 00274-fix-arch-names.patch
|
||||
|
||||
# 00277 #
|
||||
# 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, which makes the koji builds hang.
|
||||
# Fixed upstream: https://github.com/python/cpython/commit/11045c9d8a21dd9bd182a3939189db02815f9783
|
||||
Patch277: 00277-fix-test-subprocess-hanging-tests.patch
|
||||
# 00292 #
|
||||
# Restore the public PyExc_RecursionErrorInst symbol that was removed
|
||||
# from the 3.6.4 release upstream.
|
||||
# Reported upstream: https://bugs.python.org/issue30697
|
||||
Patch292: 00292-restore-PyExc_RecursionErrorInst-symbol.patch
|
||||
|
||||
# 00279 #
|
||||
# Fix memory corruption due to allocator mix
|
||||
# Fixed upstream: https://bugs.python.org/issue31532
|
||||
Patch279: 00279-fix-memory-corruption-due-to-allocator-mix.patch
|
||||
# 00294 #
|
||||
# Define TLS cipher suite on build time depending
|
||||
# on the OpenSSL default cipher suite selection.
|
||||
# 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 ^^^)
|
||||
#
|
||||
|
@ -440,7 +406,7 @@ language, designed with an emphasis on code readibility.
|
|||
It includes an extensive standard library, and has a vast ecosystem of
|
||||
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.
|
||||
The majority of its standard library is provided in the %{name}-libs package,
|
||||
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
|
||||
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:
|
||||
Provides: system-python-libs = %{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
|
||||
%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.
|
||||
rm -r Modules/expat
|
||||
rm -r Modules/zlib
|
||||
|
||||
%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
|
||||
%endif
|
||||
|
||||
|
@ -609,10 +574,6 @@ sed -r -i s/'_PIP_VERSION = "[0-9.]+"'/'_PIP_VERSION = "%{pip_version}"'/ Lib/en
|
|||
#
|
||||
%patch1 -p1
|
||||
|
||||
%if %{with systemtap}
|
||||
%patch55 -p1 -b .systemtap
|
||||
%endif
|
||||
|
||||
%if "%{_lib}" == "lib64"
|
||||
%patch102 -p1
|
||||
%endif
|
||||
|
@ -631,15 +592,10 @@ sed -r -i s/'_PIP_VERSION = "[0-9.]+"'/'_PIP_VERSION = "%{pip_version}"'/ Lib/en
|
|||
%patch205 -p1
|
||||
%patch251 -p1
|
||||
%patch262 -p1
|
||||
|
||||
%ifarch aarch64
|
||||
%patch264 -p1
|
||||
%endif
|
||||
|
||||
%patch273 -p1
|
||||
%patch274 -p1
|
||||
%patch277 -p1
|
||||
%patch279 -p1
|
||||
%patch292 -p1
|
||||
%patch294 -p1
|
||||
%patch301 -p1
|
||||
|
||||
|
||||
# Remove files that should be generated by the build
|
||||
|
@ -711,9 +667,7 @@ BuildPython() {
|
|||
--enable-loadable-sqlite-extensions \
|
||||
--with-dtrace \
|
||||
--with-lto \
|
||||
%if %{with systemtap}
|
||||
--with-systemtap \
|
||||
%endif
|
||||
--with-ssl-default-suites=openssl \
|
||||
%if %{with valgrind}
|
||||
--with-valgrind \
|
||||
%endif
|
||||
|
@ -835,16 +789,6 @@ InstallPython() {
|
|||
#endif
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -919,9 +863,10 @@ sed -i -e "s/'pyconfig.h'/'%{_pyconfig_h}'/" \
|
|||
# so handle files named using other naming scheme separately.
|
||||
LD_LIBRARY_PATH=./build/optimized ./build/optimized/python \
|
||||
Tools/scripts/pathfix.py \
|
||||
-i "%{_bindir}/python%{pybasever}" \
|
||||
-i "%{_bindir}/python%{pybasever}" -pn \
|
||||
%{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:
|
||||
rm %{buildroot}%{pylibdir}/Tools/scripts/{2to3,idle3,pydoc3,pyvenv}
|
||||
|
||||
|
@ -1026,14 +971,6 @@ done
|
|||
# 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)
|
||||
CheckPython() {
|
||||
ConfName=$1
|
||||
|
@ -1241,7 +1178,6 @@ fi
|
|||
%{dynload_dir}/spwd.%{SOABI_optimized}.so
|
||||
%{dynload_dir}/syslog.%{SOABI_optimized}.so
|
||||
%{dynload_dir}/termios.%{SOABI_optimized}.so
|
||||
#%{dynload_dir}/time.%{SOABI_optimized}.so
|
||||
%{dynload_dir}/_testmultiphase.%{SOABI_optimized}.so
|
||||
%{dynload_dir}/unicodedata.%{SOABI_optimized}.so
|
||||
%{dynload_dir}/xxlimited.%{SOABI_optimized}.so
|
||||
|
@ -1332,12 +1268,6 @@ fi
|
|||
|
||||
%{_libdir}/%{py_INSTSONAME_optimized}
|
||||
%{_libdir}/libpython3.so
|
||||
%if %{with systemtap}
|
||||
%dir %(dirname %{tapsetdir})
|
||||
%dir %{tapsetdir}
|
||||
%{tapsetdir}/%{libpython_stp_optimized}
|
||||
%doc systemtap-example.stp pyfuntop.stp
|
||||
%endif
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root)
|
||||
|
@ -1477,7 +1407,6 @@ fi
|
|||
%{dynload_dir}/spwd.%{SOABI_debug}.so
|
||||
%{dynload_dir}/syslog.%{SOABI_debug}.so
|
||||
%{dynload_dir}/termios.%{SOABI_debug}.so
|
||||
#%{dynload_dir}/time.%{SOABI_debug}.so
|
||||
%{dynload_dir}/_testmultiphase.%{SOABI_debug}.so
|
||||
%{dynload_dir}/unicodedata.%{SOABI_debug}.so
|
||||
%{dynload_dir}/zlib.%{SOABI_debug}.so
|
||||
|
@ -1487,11 +1416,6 @@ fi
|
|||
# now; they're listed below, under "-devel":
|
||||
|
||||
%{_libdir}/%{py_INSTSONAME_debug}
|
||||
%if %{with systemtap}
|
||||
%dir %(dirname %{tapsetdir})
|
||||
%dir %{tapsetdir}
|
||||
%{tapsetdir}/%{libpython_stp_debug}
|
||||
%endif
|
||||
|
||||
# Analog of the -devel subpackage's files:
|
||||
%{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
|
||||
# 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
|
||||
# (/usr/src/debug) gets added to this file (via LISTFILES) in
|
||||
# /usr/lib/rpm/find-debuginfo.sh
|
||||
|
@ -1538,6 +1462,50 @@ fi
|
|||
# ======================================================
|
||||
|
||||
%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
|
||||
- Fix memory corruption due to allocator mix
|
||||
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