From 25c6e4544ab19d0e22a9079ced85160ee68ea34e Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 10 2018 05:15:11 +0000 Subject: import python-2.7.5-68.el7 --- diff --git a/SOURCES/00240-increase-smtplib-tests-timeouts.patch b/SOURCES/00240-increase-smtplib-tests-timeouts.patch new file mode 100644 index 0000000..ae61b18 --- /dev/null +++ b/SOURCES/00240-increase-smtplib-tests-timeouts.patch @@ -0,0 +1,66 @@ +diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py +index 14d0060d8ec..1bb66901880 100644 +--- a/Lib/test/test_smtplib.py ++++ b/Lib/test/test_smtplib.py +@@ -179,31 +179,31 @@ def tearDown(self): + + def testBasic(self): + # connect +- smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) ++ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) + smtp.quit() + + def testNOOP(self): +- smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) ++ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) + expected = (250, 'Ok') + self.assertEqual(smtp.noop(), expected) + smtp.quit() + + def testRSET(self): +- smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) ++ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) + expected = (250, 'Ok') + self.assertEqual(smtp.rset(), expected) + smtp.quit() + + def testNotImplemented(self): + # EHLO isn't implemented in DebuggingServer +- smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) ++ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) + expected = (502, 'Error: command "EHLO" not implemented') + self.assertEqual(smtp.ehlo(), expected) + smtp.quit() + + def testVRFY(self): + # VRFY isn't implemented in DebuggingServer +- smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) ++ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) + expected = (502, 'Error: command "VRFY" not implemented') + self.assertEqual(smtp.vrfy('nobody@nowhere.com'), expected) + self.assertEqual(smtp.verify('nobody@nowhere.com'), expected) +@@ -212,21 +212,21 @@ def testVRFY(self): + def testSecondHELO(self): + # check that a second HELO returns a message that it's a duplicate + # (this behavior is specific to smtpd.SMTPChannel) +- smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) ++ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) + smtp.helo() + expected = (503, 'Duplicate HELO/EHLO') + self.assertEqual(smtp.helo(), expected) + smtp.quit() + + def testHELP(self): +- smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) ++ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) + self.assertEqual(smtp.help(), 'Error: command "HELP" not implemented') + smtp.quit() + + def testSend(self): + # connect and send mail + m = 'A test message' +- smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) ++ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) + smtp.sendmail('John', 'Sally', m) + # XXX(nnorwitz): this test is flaky and dies with a bad file descriptor + # in asyncore. This sleep might help, but should really be fixed diff --git a/SOURCES/00275-fix-fnctl-with-integer-on-big-endian.patch b/SOURCES/00275-fix-fnctl-with-integer-on-big-endian.patch new file mode 100644 index 0000000..c14b981 --- /dev/null +++ b/SOURCES/00275-fix-fnctl-with-integer-on-big-endian.patch @@ -0,0 +1,22 @@ +diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c +index 997867a..2bd2f55 100644 +--- a/Modules/fcntlmodule.c ++++ b/Modules/fcntlmodule.c +@@ -34,7 +34,7 @@ fcntl_fcntl(PyObject *self, PyObject *args) + { + int fd; + int code; +- long arg; ++ int arg; + int ret; + char *str; + Py_ssize_t len; +@@ -61,7 +61,7 @@ fcntl_fcntl(PyObject *self, PyObject *args) + PyErr_Clear(); + arg = 0; + if (!PyArg_ParseTuple(args, +- "O&i|l;fcntl requires a file or file descriptor," ++ "O&i|I;fcntl requires a file or file descriptor," + " an integer and optionally a third integer or a string", + conv_descriptor, &fd, &code, &arg)) { + return NULL; diff --git a/SOURCES/00276-increase-imaplib-MAXLINE.patch b/SOURCES/00276-increase-imaplib-MAXLINE.patch new file mode 100644 index 0000000..34da36b --- /dev/null +++ b/SOURCES/00276-increase-imaplib-MAXLINE.patch @@ -0,0 +1,22 @@ +diff --git a/Lib/imaplib.py b/Lib/imaplib.py +index 4586fb3..d8243e5 100644 +--- a/Lib/imaplib.py ++++ b/Lib/imaplib.py +@@ -37,11 +37,12 @@ AllowedVersions = ('IMAP4REV1', 'IMAP4') # Most recent first + + # Maximal line length when calling readline(). This is to prevent + # reading arbitrary length lines. RFC 3501 and 2060 (IMAP 4rev1) +-# don't specify a line length. RFC 2683 however suggests limiting client +-# command lines to 1000 octets and server command lines to 8000 octets. +-# We have selected 10000 for some extra margin and since that is supposedly +-# also what UW and Panda IMAP does. +-_MAXLINE = 10000 ++# don't specify a line length. RFC 2683 suggests limiting client ++# command lines to 1000 octets and that servers should be prepared ++# to accept command lines up to 8000 octets, so we used to use 10K here. ++# In the modern world (eg: gmail) the response to, for example, a ++# search command can be quite large, so we now use 1M. ++_MAXLINE = 1000000 + + + # Commands diff --git a/SOURCES/00281-add-context-parameter-to-xmlrpclib.ServerProxy.patch b/SOURCES/00281-add-context-parameter-to-xmlrpclib.ServerProxy.patch new file mode 100644 index 0000000..282437f --- /dev/null +++ b/SOURCES/00281-add-context-parameter-to-xmlrpclib.ServerProxy.patch @@ -0,0 +1,91 @@ + +# HG changeset patch +# User Benjamin Peterson +# Date 1417319735 18000 +# Node ID 62bd574e95d5ec4b37ca8f72ae6523ea7d6c11cd +# Parent 1ac5aec658f6972c3372f139ce69ee6799dc0b2e +add context parameter to xmlrpclib.ServerProxy (#22960) + +Patch from Alex Gaynor. + +diff --git a/Doc/library/xmlrpclib.rst b/Doc/library/xmlrpclib.rst +--- a/Doc/library/xmlrpclib.rst ++++ b/Doc/library/xmlrpclib.rst +@@ -39,7 +39,7 @@ between conformable Python objects and X + For https URIs, :mod:`xmlrpclib` now performs all the necessary certificate + and hostname checks by default + +-.. class:: ServerProxy(uri[, transport[, encoding[, verbose[, allow_none[, use_datetime]]]]]) ++.. class:: ServerProxy(uri[, transport[, encoding[, verbose[, allow_none[, use_datetime[, context]]]]]]) + + A :class:`ServerProxy` instance is an object that manages communication with a + remote XML-RPC server. The required first argument is a URI (Uniform Resource +@@ -57,11 +57,13 @@ between conformable Python objects and X + :class:`datetime.datetime` objects may be passed to calls. + + Both the HTTP and HTTPS transports support the URL syntax extension for HTTP +- Basic Authentication: ``http://user:pass@host:port/path``. The ``user:pass`` ++ Basic Authentication: ``http://user:pass@host:port/path``. The ``user:pass`` + portion will be base64-encoded as an HTTP 'Authorization' header, and sent to + the remote server as part of the connection process when invoking an XML-RPC + method. You only need to use this if the remote server requires a Basic +- Authentication user and password. ++ Authentication user and password. If an HTTPS url is provided, *context* may ++ be :class:`ssl.SSLContext` and configures the SSL settings of the underlying ++ HTTPS connection. + + The returned instance is a proxy object with methods that can be used to invoke + corresponding RPC calls on the remote server. If the remote server supports the +@@ -131,6 +133,9 @@ between conformable Python objects and X + *__dict__* attribute and don't have a base class that is marshalled in a + special way. + ++ .. versionchanged:: 2.7.9 ++ Added the *context* argument. ++ + + .. seealso:: + +diff --git a/Lib/xmlrpclib.py b/Lib/xmlrpclib.py +--- a/Lib/xmlrpclib.py ++++ b/Lib/xmlrpclib.py +@@ -1478,6 +1478,10 @@ class Transport: + class SafeTransport(Transport): + """Handles an HTTPS transaction to an XML-RPC server.""" + ++ def __init__(self, use_datetime=0, context=None): ++ Transport.__init__(self, use_datetime=use_datetime) ++ self.context = context ++ + # FIXME: mostly untested + + def make_connection(self, host): +@@ -1493,7 +1497,7 @@ class SafeTransport(Transport): + ) + else: + chost, self._extra_headers, x509 = self.get_host_info(host) +- self._connection = host, HTTPS(chost, None, **(x509 or {})) ++ self._connection = host, HTTPS(chost, None, context=self.context, **(x509 or {})) + return self._connection[1] + + ## +@@ -1536,7 +1540,7 @@ class ServerProxy: + """ + + def __init__(self, uri, transport=None, encoding=None, verbose=0, +- allow_none=0, use_datetime=0): ++ allow_none=0, use_datetime=0, context=None): + # establish a "logical" server connection + + if isinstance(uri, unicode): +@@ -1553,7 +1557,7 @@ class ServerProxy: + + if transport is None: + if type == "https": +- transport = SafeTransport(use_datetime=use_datetime) ++ transport = SafeTransport(use_datetime=use_datetime, context=context) + else: + transport = Transport(use_datetime=use_datetime) + self.__transport = transport + + diff --git a/SOURCES/00282-obmalloc-mmap-threshold.patch b/SOURCES/00282-obmalloc-mmap-threshold.patch new file mode 100644 index 0000000..fde9c3f --- /dev/null +++ b/SOURCES/00282-obmalloc-mmap-threshold.patch @@ -0,0 +1,157 @@ +Make it more likely for the system allocator to release free()d memory arenas on glibc-based systems. +Patch by Charles-François Natali. +https://bugs.python.org/issue20494 + +diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c +--- a/Objects/obmalloc.c ++++ b/Objects/obmalloc.c +@@ -2,6 +2,13 @@ + + #ifdef WITH_PYMALLOC + ++#ifdef HAVE_MMAP ++ #include ++ #ifdef MAP_ANONYMOUS ++ #define ARENAS_USE_MMAP ++ #endif ++#endif ++ + #ifdef WITH_VALGRIND + #include + +@@ -75,7 +82,8 @@ static int running_on_valgrind = -1; + * Allocation strategy abstract: + * + * For small requests, the allocator sub-allocates blocks of memory. +- * Requests greater than 256 bytes are routed to the system's allocator. ++ * Requests greater than SMALL_REQUEST_THRESHOLD bytes are routed to the ++ * system's allocator. + * + * Small requests are grouped in size classes spaced 8 bytes apart, due + * to the required valid alignment of the returned address. Requests of +@@ -107,10 +115,11 @@ static int running_on_valgrind = -1; + * 57-64 64 7 + * 65-72 72 8 + * ... ... ... +- * 241-248 248 30 +- * 249-256 256 31 ++ * 497-504 504 62 ++ * 505-512 512 63 + * +- * 0, 257 and up: routed to the underlying allocator. ++ * 0, SMALL_REQUEST_THRESHOLD + 1 and up: routed to the underlying ++ * allocator. + */ + + /*==========================================================================*/ +@@ -143,10 +152,13 @@ static int running_on_valgrind = -1; + * 1) ALIGNMENT <= SMALL_REQUEST_THRESHOLD <= 256 + * 2) SMALL_REQUEST_THRESHOLD is evenly divisible by ALIGNMENT + * ++ * Note: a size threshold of 512 guarantees that newly created dictionaries ++ * will be allocated from preallocated memory pools on 64-bit. ++ * + * Although not required, for better performance and space efficiency, + * it is recommended that SMALL_REQUEST_THRESHOLD is set to a power of 2. + */ +-#define SMALL_REQUEST_THRESHOLD 256 ++#define SMALL_REQUEST_THRESHOLD 512 + #define NB_SMALL_SIZE_CLASSES (SMALL_REQUEST_THRESHOLD / ALIGNMENT) + + /* +@@ -174,15 +186,15 @@ static int running_on_valgrind = -1; + /* + * The allocator sub-allocates blocks of memory (called arenas) aligned + * on a page boundary. This is a reserved virtual address space for the +- * current process (obtained through a malloc call). In no way this means +- * that the memory arenas will be used entirely. A malloc() is usually +- * an address range reservation for bytes, unless all pages within this +- * space are referenced subsequently. So malloc'ing big blocks and not using +- * them does not mean "wasting memory". It's an addressable range wastage... ++ * current process (obtained through a malloc()/mmap() call). In no way this ++ * means that the memory arenas will be used entirely. A malloc() is ++ * usually an address range reservation for bytes, unless all pages within ++ * this space are referenced subsequently. So malloc'ing big blocks and not ++ * using them does not mean "wasting memory". It's an addressable range ++ * wastage... + * +- * Therefore, allocating arenas with malloc is not optimal, because there is +- * some address space wastage, but this is the most portable way to request +- * memory from the system across various platforms. ++ * Arenas are allocated with mmap() on systems supporting anonymous memory ++ * mappings to reduce heap fragmentation. + */ + #define ARENA_SIZE (256 << 10) /* 256KB */ + +@@ -440,6 +452,9 @@ static poolp usedpools[2 * ((NB_SMALL_SI + , PT(48), PT(49), PT(50), PT(51), PT(52), PT(53), PT(54), PT(55) + #if NB_SMALL_SIZE_CLASSES > 56 + , PT(56), PT(57), PT(58), PT(59), PT(60), PT(61), PT(62), PT(63) ++#if NB_SMALL_SIZE_CLASSES > 64 ++#error "NB_SMALL_SIZE_CLASSES should be less than 64" ++#endif /* NB_SMALL_SIZE_CLASSES > 64 */ + #endif /* NB_SMALL_SIZE_CLASSES > 56 */ + #endif /* NB_SMALL_SIZE_CLASSES > 48 */ + #endif /* NB_SMALL_SIZE_CLASSES > 40 */ +@@ -577,7 +592,12 @@ new_arena(void) + arenaobj = unused_arena_objects; + unused_arena_objects = arenaobj->nextarena; + assert(arenaobj->address == 0); ++#ifdef ARENAS_USE_MMAP ++ arenaobj->address = (uptr)mmap(NULL, ARENA_SIZE, PROT_READ|PROT_WRITE, ++ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); ++#else + arenaobj->address = (uptr)malloc(ARENA_SIZE); ++#endif + if (arenaobj->address == 0) { + /* The allocation failed: return NULL after putting the + * arenaobj back. +@@ -1054,7 +1074,11 @@ PyObject_Free(void *p) + unused_arena_objects = ao; + + /* Free the entire arena. */ ++#ifdef ARENAS_USE_MMAP ++ munmap((void *)ao->address, ARENA_SIZE); ++#else + free((void *)ao->address); ++#endif + ao->address = 0; /* mark unassociated */ + --narenas_currently_allocated; + +diff --git a/configure b/configure +--- a/configure ++++ b/configure +@@ -10164,7 +10164,7 @@ for ac_func in alarm setitimer getitimer + clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \ + gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ + getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ +- initgroups kill killpg lchmod lchown lstat mkfifo mknod mktime \ ++ initgroups kill killpg lchmod lchown lstat mkfifo mknod mktime mmap \ + mremap nice pathconf pause plock poll pthread_init \ + putenv readlink realpath \ + select sem_open sem_timedwait sem_getvalue sem_unlink setegid seteuid \ +diff --git a/configure.ac b/configure.ac +--- a/configure.ac ++++ b/configure.ac +@@ -2905,7 +2905,7 @@ AC_CHECK_FUNCS(alarm setitimer getitimer + clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \ + gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ + getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ +- initgroups kill killpg lchmod lchown lstat mkfifo mknod mktime \ ++ initgroups kill killpg lchmod lchown lstat mkfifo mknod mktime mmap \ + mremap nice pathconf pause plock poll pthread_init \ + putenv readlink realpath \ + select sem_open sem_timedwait sem_getvalue sem_unlink setegid seteuid \ +diff --git a/pyconfig.h.in b/pyconfig.h.in +--- a/pyconfig.h.in ++++ b/pyconfig.h.in +@@ -475,6 +475,9 @@ + /* Define to 1 if you have the `mktime' function. */ + #undef HAVE_MKTIME + ++/* Define to 1 if you have the `mmap' function. */ ++#undef HAVE_MMAP ++ + /* Define to 1 if you have the `mremap' function. */ + #undef HAVE_MREMAP + diff --git a/SOURCES/00287-fix-thread-hanging-on-inaccessible-nfs-server.patch b/SOURCES/00287-fix-thread-hanging-on-inaccessible-nfs-server.patch new file mode 100644 index 0000000..1dbb62f --- /dev/null +++ b/SOURCES/00287-fix-thread-hanging-on-inaccessible-nfs-server.patch @@ -0,0 +1,135 @@ +diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c +index 4a71a57ec0d..2b40ada195a 100644 +--- a/Modules/_io/fileio.c ++++ b/Modules/_io/fileio.c +@@ -146,9 +146,15 @@ dircheck(fileio* self, PyObject *nameobj) + { + #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR) + struct stat buf; ++ int res; + if (self->fd < 0) + return 0; +- if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) { ++ ++ Py_BEGIN_ALLOW_THREADS ++ res = fstat(self->fd, &buf); ++ Py_END_ALLOW_THREADS ++ ++ if (res == 0 && S_ISDIR(buf.st_mode)) { + errno = EISDIR; + PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj); + return -1; +@@ -162,17 +168,34 @@ check_fd(int fd) + { + #if defined(HAVE_FSTAT) + struct stat buf; +- if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) { +- PyObject *exc; +- char *msg = strerror(EBADF); +- exc = PyObject_CallFunction(PyExc_OSError, "(is)", +- EBADF, msg); +- PyErr_SetObject(PyExc_OSError, exc); +- Py_XDECREF(exc); +- return -1; ++ int res; ++ PyObject *exc; ++ char *msg; ++ ++ if (!_PyVerify_fd(fd)) { ++ goto badfd; + } +-#endif ++ ++ Py_BEGIN_ALLOW_THREADS ++ res = fstat(fd, &buf); ++ Py_END_ALLOW_THREADS ++ ++ if (res < 0 && errno == EBADF) { ++ goto badfd; ++ } ++ + return 0; ++ ++badfd: ++ msg = strerror(EBADF); ++ exc = PyObject_CallFunction(PyExc_OSError, "(is)", ++ EBADF, msg); ++ PyErr_SetObject(PyExc_OSError, exc); ++ Py_XDECREF(exc); ++ return -1; ++#else ++ return 0; ++#endif + } + + +@@ -519,9 +542,19 @@ new_buffersize(fileio *self, size_t currentsize) + #ifdef HAVE_FSTAT + off_t pos, end; + struct stat st; +- if (fstat(self->fd, &st) == 0) { ++ int res; ++ ++ Py_BEGIN_ALLOW_THREADS ++ res = fstat(self->fd, &st); ++ Py_END_ALLOW_THREADS ++ ++ if (res == 0) { + end = st.st_size; ++ ++ Py_BEGIN_ALLOW_THREADS + pos = lseek(self->fd, 0L, SEEK_CUR); ++ Py_END_ALLOW_THREADS ++ + /* Files claiming a size smaller than SMALLCHUNK may + actually be streaming pseudo-files. In this case, we + apply the more aggressive algorithm below. +diff --git a/Objects/fileobject.c b/Objects/fileobject.c +index 2f63c374d1e..8d1c5812f0d 100644 +--- a/Objects/fileobject.c ++++ b/Objects/fileobject.c +@@ -121,10 +121,15 @@ dircheck(PyFileObject* f) + { + #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR) + struct stat buf; ++ int res; + if (f->f_fp == NULL) + return f; +- if (fstat(fileno(f->f_fp), &buf) == 0 && +- S_ISDIR(buf.st_mode)) { ++ ++ Py_BEGIN_ALLOW_THREADS ++ res = fstat(fileno(f->f_fp), &buf); ++ Py_END_ALLOW_THREADS ++ ++ if (res == 0 && S_ISDIR(buf.st_mode)) { + char *msg = strerror(EISDIR); + PyObject *exc = PyObject_CallFunction(PyExc_IOError, "(isO)", + EISDIR, msg, f->f_name); +@@ -1010,7 +1015,13 @@ new_buffersize(PyFileObject *f, size_t currentsize) + #ifdef HAVE_FSTAT + off_t pos, end; + struct stat st; +- if (fstat(fileno(f->f_fp), &st) == 0) { ++ int res; ++ ++ Py_BEGIN_ALLOW_THREADS ++ res = fstat(fileno(f->f_fp), &st); ++ Py_END_ALLOW_THREADS ++ ++ if (res == 0) { + end = st.st_size; + /* The following is not a bug: we really need to call lseek() + *and* ftell(). The reason is that some stdio libraries +@@ -1021,7 +1032,11 @@ new_buffersize(PyFileObject *f, size_t currentsize) + works. We can't use the lseek() value either, because we + need to take the amount of buffered data into account. + (Yet another reason why stdio stinks. :-) */ ++ ++ Py_BEGIN_ALLOW_THREADS + pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR); ++ Py_END_ALLOW_THREADS ++ + if (pos >= 0) { + pos = ftell(f->f_fp); + } diff --git a/SOURCES/00295-fix-https-behind-proxy.patch b/SOURCES/00295-fix-https-behind-proxy.patch new file mode 100644 index 0000000..2d54592 --- /dev/null +++ b/SOURCES/00295-fix-https-behind-proxy.patch @@ -0,0 +1,250 @@ +diff --git a/Lib/httplib.py b/Lib/httplib.py +index 592ee57..b69145b 100644 +--- a/Lib/httplib.py ++++ b/Lib/httplib.py +@@ -735,25 +735,40 @@ class HTTPConnection: + self._tunnel_host = None + self._tunnel_port = None + self._tunnel_headers = {} +- +- self._set_hostport(host, port) + if strict is not None: + self.strict = strict + ++ (self.host, self.port) = self._get_hostport(host, port) ++ ++ # This is stored as an instance variable to allow unittests ++ # to replace with a suitable mock ++ self._create_connection = socket.create_connection ++ + def set_tunnel(self, host, port=None, headers=None): +- """ Sets up the host and the port for the HTTP CONNECT Tunnelling. ++ """ Set up host and port for HTTP CONNECT tunnelling. ++ ++ In a connection that uses HTTP Connect tunneling, the host passed to the ++ constructor is used as proxy server that relays all communication to the ++ endpoint passed to set_tunnel. This is done by sending a HTTP CONNECT ++ request to the proxy server when the connection is established. ++ ++ This method must be called before the HTTP connection has been ++ established. + + The headers argument should be a mapping of extra HTTP headers + to send with the CONNECT request. + """ +- self._tunnel_host = host +- self._tunnel_port = port ++ # Verify if this is required. ++ if self.sock: ++ raise RuntimeError("Can't setup tunnel for established connection.") ++ ++ self._tunnel_host, self._tunnel_port = self._get_hostport(host, port) + if headers: + self._tunnel_headers = headers + else: + self._tunnel_headers.clear() + +- def _set_hostport(self, host, port): ++ def _get_hostport(self, host, port): + if port is None: + i = host.rfind(':') + j = host.rfind(']') # ipv6 addresses have [...] +@@ -770,15 +785,14 @@ class HTTPConnection: + port = self.default_port + if host and host[0] == '[' and host[-1] == ']': + host = host[1:-1] +- self.host = host +- self.port = port ++ return (host, port) + + def set_debuglevel(self, level): + self.debuglevel = level + + def _tunnel(self): +- self._set_hostport(self._tunnel_host, self._tunnel_port) +- self.send("CONNECT %s:%d HTTP/1.0\r\n" % (self.host, self.port)) ++ self.send("CONNECT %s:%d HTTP/1.0\r\n" % (self._tunnel_host, ++ self._tunnel_port)) + for header, value in self._tunnel_headers.iteritems(): + self.send("%s: %s\r\n" % (header, value)) + self.send("\r\n") +@@ -803,8 +817,8 @@ class HTTPConnection: + + def connect(self): + """Connect to the host and port specified in __init__.""" +- self.sock = socket.create_connection((self.host,self.port), +- self.timeout, self.source_address) ++ self.sock = self._create_connection((self.host,self.port), ++ self.timeout, self.source_address) + + if self._tunnel_host: + self._tunnel() +@@ -942,17 +956,24 @@ class HTTPConnection: + netloc_enc = netloc.encode("idna") + self.putheader('Host', netloc_enc) + else: ++ if self._tunnel_host: ++ host = self._tunnel_host ++ port = self._tunnel_port ++ else: ++ host = self.host ++ port = self.port ++ + try: +- host_enc = self.host.encode("ascii") ++ host_enc = host.encode("ascii") + except UnicodeEncodeError: +- host_enc = self.host.encode("idna") ++ host_enc = host.encode("idna") + # Wrap the IPv6 Host Header with [] (RFC 2732) + if host_enc.find(':') >= 0: + host_enc = "[" + host_enc + "]" +- if self.port == self.default_port: ++ if port == self.default_port: + self.putheader('Host', host_enc) + else: +- self.putheader('Host', "%s:%s" % (host_enc, self.port)) ++ self.putheader('Host', "%s:%s" % (host_enc, port)) + + # note: we are assuming that clients will not attempt to set these + # headers since *this* library must deal with the +@@ -1141,7 +1162,7 @@ class HTTP: + "Accept arguments to set the host/port, since the superclass doesn't." + + if host is not None: +- self._conn._set_hostport(host, port) ++ (self._conn.host, self._conn.port) = self._conn._get_hostport(host, port) + self._conn.connect() + + def getfile(self): +diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py +index 29af589..9db30cc 100644 +--- a/Lib/test/test_httplib.py ++++ b/Lib/test/test_httplib.py +@@ -21,10 +21,12 @@ CERT_selfsigned_pythontestdotnet = os.path.join(here, 'selfsigned_pythontestdotn + HOST = test_support.HOST + + class FakeSocket: +- def __init__(self, text, fileclass=StringIO.StringIO): ++ def __init__(self, text, fileclass=StringIO.StringIO, host=None, port=None): + self.text = text + self.fileclass = fileclass + self.data = '' ++ self.host = host ++ self.port = port + + def sendall(self, data): + self.data += ''.join(data) +@@ -34,6 +36,9 @@ class FakeSocket: + raise httplib.UnimplementedFileMode() + return self.fileclass(self.text) + ++ def close(self): ++ pass ++ + class EPipeSocket(FakeSocket): + + def __init__(self, text, pipe_trigger): +@@ -487,7 +492,11 @@ class OfflineTest(TestCase): + self.assertEqual(httplib.responses[httplib.NOT_FOUND], "Not Found") + + +-class SourceAddressTest(TestCase): ++class TestServerMixin: ++ """A limited socket server mixin. ++ ++ This is used by test cases for testing http connection end points. ++ """ + def setUp(self): + self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.port = test_support.bind_port(self.serv) +@@ -502,6 +511,7 @@ class SourceAddressTest(TestCase): + self.serv.close() + self.serv = None + ++class SourceAddressTest(TestServerMixin, TestCase): + def testHTTPConnectionSourceAddress(self): + self.conn = httplib.HTTPConnection(HOST, self.port, + source_address=('', self.source_port)) +@@ -518,6 +528,24 @@ class SourceAddressTest(TestCase): + # for an ssl_wrapped connect() to actually return from. + + ++class HTTPTest(TestServerMixin, TestCase): ++ def testHTTPConnection(self): ++ self.conn = httplib.HTTP(host=HOST, port=self.port, strict=None) ++ self.conn.connect() ++ self.assertEqual(self.conn._conn.host, HOST) ++ self.assertEqual(self.conn._conn.port, self.port) ++ ++ def testHTTPWithConnectHostPort(self): ++ testhost = 'unreachable.test.domain' ++ testport = '80' ++ self.conn = httplib.HTTP(host=testhost, port=testport) ++ self.conn.connect(host=HOST, port=self.port) ++ self.assertNotEqual(self.conn._conn.host, testhost) ++ self.assertNotEqual(self.conn._conn.port, testport) ++ self.assertEqual(self.conn._conn.host, HOST) ++ self.assertEqual(self.conn._conn.port, self.port) ++ ++ + class TimeoutTest(TestCase): + PORT = None + +@@ -716,13 +744,54 @@ class HTTPSTest(TestCase): + c = httplib.HTTPSConnection(hp, context=context) + self.assertEqual(h, c.host) + self.assertEqual(p, c.port) +- ++ ++class TunnelTests(TestCase): ++ def test_connect(self): ++ response_text = ( ++ 'HTTP/1.0 200 OK\r\n\r\n' # Reply to CONNECT ++ 'HTTP/1.1 200 OK\r\n' # Reply to HEAD ++ 'Content-Length: 42\r\n\r\n' ++ ) ++ ++ def create_connection(address, timeout=None, source_address=None): ++ return FakeSocket(response_text, host=address[0], port=address[1]) ++ ++ conn = httplib.HTTPConnection('proxy.com') ++ conn._create_connection = create_connection ++ ++ # Once connected, we should not be able to tunnel anymore ++ conn.connect() ++ self.assertRaises(RuntimeError, conn.set_tunnel, 'destination.com') ++ ++ # But if close the connection, we are good. ++ conn.close() ++ conn.set_tunnel('destination.com') ++ conn.request('HEAD', '/', '') ++ ++ self.assertEqual(conn.sock.host, 'proxy.com') ++ self.assertEqual(conn.sock.port, 80) ++ self.assertIn('CONNECT destination.com', conn.sock.data) ++ # issue22095 ++ self.assertNotIn('Host: destination.com:None', conn.sock.data) ++ # issue22095 ++ ++ self.assertNotIn('Host: proxy.com', conn.sock.data) ++ ++ conn.close() ++ ++ conn.request('PUT', '/', '') ++ self.assertEqual(conn.sock.host, 'proxy.com') ++ self.assertEqual(conn.sock.port, 80) ++ self.assertTrue('CONNECT destination.com' in conn.sock.data) ++ self.assertTrue('Host: destination.com' in conn.sock.data) ++ + + + @test_support.reap_threads + def test_main(verbose=None): + test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest, +- HTTPSTest, SourceAddressTest) ++ HTTPTest, HTTPSTest, SourceAddressTest, ++ TunnelTests) + + if __name__ == '__main__': + test_main() diff --git a/SOURCES/00296-Readd-the-private-_set_hostport-api-to-httplib.patch b/SOURCES/00296-Readd-the-private-_set_hostport-api-to-httplib.patch new file mode 100644 index 0000000..56c3952 --- /dev/null +++ b/SOURCES/00296-Readd-the-private-_set_hostport-api-to-httplib.patch @@ -0,0 +1,26 @@ +From 8a91bb4ea0a7f50d024fe55014c2e86e36e67751 Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Mon, 19 Feb 2018 14:42:13 +0100 +Subject: [PATCH] Readd the private `_set_hostport` api to httplib + +--- + Lib/httplib.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Lib/httplib.py b/Lib/httplib.py +index b69145b..da2f346 100644 +--- a/Lib/httplib.py ++++ b/Lib/httplib.py +@@ -787,6 +787,9 @@ class HTTPConnection: + host = host[1:-1] + return (host, port) + ++ def _set_hostport(self, host, port): ++ (self.host, self.port) = self._get_hostport(host, port) ++ + def set_debuglevel(self, level): + self.debuglevel = level + +-- +2.13.6 + diff --git a/SPECS/python.spec b/SPECS/python.spec index a9fd32f..c70c0da 100644 --- a/SPECS/python.spec +++ b/SPECS/python.spec @@ -106,7 +106,7 @@ Summary: An interpreted, interactive, object-oriented programming language Name: %{python} # Remember to also rebase python-docs when changing this: Version: 2.7.5 -Release: 58%{?dist} +Release: 68%{?dist} License: Python Group: Development/Languages Requires: %{python}-libs%{?_isa} = %{version}-%{release} @@ -205,7 +205,7 @@ Source9: python.conf # Supply various useful macros for building Python components: # NOTE: The %%python_provide macro is copied directly from Fedora/EPEL, but the -# %{python3_pkgversion} and %{python3_other_pkgversion} macros used within it +# %%{python3_pkgversion} and %%{python3_other_pkgversion} macros used within it # are missing in RHEL. However, in their absence the lua code will run fine for # Python 2 packages and will print an error only if invoked for Python 3 # packages (unless the python-srpm-macros package from EPEL is installed). That @@ -357,7 +357,7 @@ Patch55: 00055-systemtap.patch # Upstream as of Python 2.7.4 # Patch101: 00101-lib64-regex.patch -# Only used when "%{_lib}" == "lib64" +# Only used when "%%{_lib}" == "lib64" # Fixup various paths throughout the build and in distutils from "lib" to "lib64", # and add the /usr/lib64/pythonMAJOR.MINOR/site-packages to sitedirs, in front of # /usr/lib/pythonMAJOR.MINOR/site-packages @@ -371,7 +371,7 @@ Patch102: python-2.7.3-lib64.patch Patch103: python-2.7-lib64-sysconfig.patch # 00104 # -# Only used when "%{_lib}" == "lib64" +# Only used when "%%{_lib}" == "lib64" # Another lib64 fix, for distutils/tests/test_install.py; not upstream: Patch104: 00104-lib64-fix-for-test_install.patch @@ -1103,6 +1103,13 @@ Patch237: 00237-CVE-2016-0772-smtplib.patch # Resolves: rhbz#1346357 Patch238: 00238-CVE-2016-5699-httplib.patch +# 00240 # +# Increase the timeouts of test_smtplib +# as there are failures on various powerpc architectures. +# FIXED UPSTREAM: https://github.com/python/cpython/commit/1122236c89770466c629aa0f0b0de2b2731b82ee +# Resolves: rhbz#1497795 +Patch240: 00240-increase-smtplib-tests-timeouts.patch + # 00241 # # CVE-2016-5636: http://seclists.org/oss-sec/2016/q2/560 # https://hg.python.org/cpython/rev/985fc64c60d6/ @@ -1170,6 +1177,57 @@ Patch266: 00266-fix-shutil.make_archive-ignoring-empty-dirs.patch # Resolves: rhbz#1432003 Patch268: 00268-set-stream-name-to-None.patch +# 00275 # +# Fixe fcntl() with integer argument on 64-bit big-endian platforms. +# FIXED UPSTREAM: https://bugs.python.org/issue22821 +# Resolves: rhbz#1489858 +Patch275: 00275-fix-fnctl-with-integer-on-big-endian.patch + +# 00276 # +# Increase imaplib's MAXLINE to accommodate modern mailbox sizes. +# FIXED UPSTREAM: https://bugs.python.org/issue23647 +# Resolves: rhbz#1485808 +Patch276: 00276-increase-imaplib-MAXLINE.patch + +# 00281 # +# Add context parameter to xmlrpclib.ServerProxy +# FIXED UPSTREAM: https://bugs.python.org/issue22960 +# Resolves: rhbz#1490392 +Patch281: 00281-add-context-parameter-to-xmlrpclib.ServerProxy.patch + +# 00282 # +# Make it more likely for the system allocator to release free()d memory arenas +# - Use mmap for arena allocation +# - Increase SMALL_REQUEST_THRESHOLD so that small dictionaries use +# pre-allocated arena pools +# FIXED UPSTREAM: https://bugs.python.org/issue20494 +# Resolves: rhbz#1468410 +Patch282: 00282-obmalloc-mmap-threshold.patch + +# 00287 # +# On the creation of io.FileIO() and builtin file() objects the GIL is now released +# when checking the file descriptor. io.FileIO.readall(), io.FileIO.read(), and +# file.read() also now release the GIL when getting the file size, which fixes hanging +# of all threads when trying to access an inaccessible NFS server. +# FIXED UPSTREAM: https://bugs.python.org/issue32186 +# Resolves: rhbz#1520068 +Patch287: 00287-fix-thread-hanging-on-inaccessible-nfs-server.patch + +# 00295 # +# Fix http.client.HTTPConnection tunneling and HTTPConnection.set_tunnel with default port, +# which was breaking https connections behind a proxy. +# FIXED UPSTREAM: https://bugs.python.org/issue7776 +# https://bugs.python.org/issue22095 +# https://bugs.python.org/issue23300 +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1483438 +Patch295: 00295-fix-https-behind-proxy.patch + +# 00296 # +# Re-add the private `_set_hostport` api to httplib +# DOWNSTREAM ONLY: backwards compatibility backport +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1546351 +Patch296: 00296-Readd-the-private-_set_hostport-api-to-httplib.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora 17 onwards, @@ -1191,7 +1249,7 @@ Patch268: 00268-set-stream-name-to-None.patch # applied to both versions. # This is the generated patch to "configure"; see the description of -# %{regenerate_autotooling_patch} +# %%{regenerate_autotooling_patch} # above: Patch5000: 05000-autotool-intermediates.patch @@ -1252,6 +1310,12 @@ implementation is within the "python-libs" package. Summary: Runtime libraries for Python Group: Applications/System +# New behaviour of httplib (patch 295) doesn't play well with really old pip +# version (1.4.1) bundled in the old virtualenv package. This new version of +# virtualenv updated bundled pip to 9.0.1 which works fine. +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1483438 +Conflicts: python-virtualenv < 15.1.0-1 + # Needed for ctypes, to load libraries, worked around for Live CDs size # Requires: binutils @@ -1571,6 +1635,7 @@ mv Modules/cryptmodule.c Modules/_cryptmodule.c %patch236 -p1 %patch237 -p1 %patch238 -p1 +%patch240 -p1 %patch241 -p1 %patch242 -p1 %patch255 -p1 @@ -1580,6 +1645,13 @@ mv Modules/cryptmodule.c Modules/_cryptmodule.c %patch265 -p1 %patch266 -p1 %patch268 -p1 +%patch275 -p1 +%patch276 -p1 +%patch281 -p1 +%patch282 -p1 +%patch287 -p1 +%patch295 -p1 +%patch296 -p1 # This shouldn't be necesarry, but is right now (2.2a3) @@ -2021,7 +2093,9 @@ sed -i "s|^#\!.\?/usr/bin.*$|#\! %{__python}|" \ # rhbz#1046276 /usr/bin/chmod 755 %{buildroot}%{dynload_dir}/*.so /usr/bin/chmod 755 %{buildroot}%{_libdir}/libpython%{pybasever}.so.1.0 +%if 0%{?with_debug_build} /usr/bin/chmod 755 %{buildroot}%{_libdir}/libpython%{pybasever}_d.so.1.0 +%endif # with_debug_build mkdir %{buildroot}%{_tmpfilesdir} cp %{SOURCE9} %{buildroot}%{_tmpfilesdir}/python.conf @@ -2451,6 +2525,47 @@ rm -fr %{buildroot} # ====================================================== %changelog +* Mon Feb 19 2018 Tomas Orsava - 2.7.5-68 +- Add Conflicts tag with old virtualenv versions due to new behaviour of + httplib (patch 295) +Resolves: rhbz#1483438 + +* Mon Feb 19 2018 Tomas Orsava - 2.7.5-67 +- Re-add the private `_set_hostport` api to httplib (Patch 296) +Resolves: rhbz#1546351 + +* Fri Feb 09 2018 Charalampos Stratakis - 2.7.5-66 +- Fix https connections behind a proxy. +Resolves: rhbz#1483438 + +* Fri Dec 08 2017 Charalampos Stratakis - 2.7.5-65 +- Fix hanging of all threads when trying to access an inaccessible NFS server. +Resolves: rhbz#1520068 + +* Tue Oct 17 2017 Charalampos Stratakis - 2.7.5-64 +- Fix an issue with the context parameter addition to xmlrpclib.ServerProxy +Resolves: rhbz#1490392 + +* Fri Oct 13 2017 Petr Viktorin - 2.7.5-63 +- Make it more likely for the system allocator to release free()d memory arenas +Resolves: rhbz#1468410 + +* Wed Oct 11 2017 Charalampos Stratakis - 2.7.5-62 +- Add context parameter to xmlrpclib.ServerProxy +Resolves: rhbz#1490392 + +* Tue Oct 03 2017 Charalampos Stratakis - 2.7.5-61 +- Increase imaplib's MAXLINE to accommodate modern mailbox sizes. +Resolves: rhbz#1489858 + +* Tue Oct 03 2017 Charalampos Stratakis - 2.7.5-60 +- Fix fcntl() with integer argument on 64-bit big-endian platforms. +Resolves: rhbz#1489858 + +* Tue Oct 03 2017 Charalampos Stratakis - 2.7.5-59 +- Increase timeouts in test_smtplib. +Resolves: rhbz#1497795 + * Wed May 03 2017 Charalampos Stratakis - 2.7.5-58 - Set stream to None in case an _open() fails. Resolves: rhbz#1432003