diff --git a/python3/001-3.4-dbm-cygwin.patch b/python3/001-3.4-dbm-cygwin.patch index cad61435..27a89aa5 100644 --- a/python3/001-3.4-dbm-cygwin.patch +++ b/python3/001-3.4-dbm-cygwin.patch @@ -1,6 +1,6 @@ --- Python-3.4.3/setup.py.orig 2015-02-25 05:27:46.000000000 -0600 +++ Python-3.4.3/setup.py 2015-05-05 11:18:04.030880000 -0500 -@@ -1165,7 +1165,7 @@ class PyBuildExt(build_ext): +@@ -1241,7 +1241,7 @@ class PyBuildExt(build_ext): dbm_setup_debug = False # verbose debug prints from this script? dbm_order = ['gdbm'] # The standard Unix dbm module: @@ -9,7 +9,7 @@ config_args = [arg.strip("'") for arg in sysconfig.get_config_var("CONFIG_ARGS").split()] dbm_args = [arg for arg in config_args -@@ -1220,6 +1220,15 @@ class PyBuildExt(build_ext): +@@ -1296,6 +1296,15 @@ class PyBuildExt(build_ext): ], libraries = gdbm_libs) break diff --git a/python3/00146-hashlib-fips.patch b/python3/00146-hashlib-fips.patch new file mode 100644 index 00000000..0bbcea90 --- /dev/null +++ b/python3/00146-hashlib-fips.patch @@ -0,0 +1,640 @@ +diff --git a/Lib/hashlib.py b/Lib/hashlib.py +index 316cece..b7ad879 100644 +--- a/Lib/hashlib.py ++++ b/Lib/hashlib.py +@@ -24,6 +24,16 @@ the zlib module. + Choose your hash function wisely. Some have known collision weaknesses. + sha384 and sha512 will be slow on 32 bit platforms. + ++If the underlying implementation supports "FIPS mode", and this is enabled, it ++may restrict the available hashes to only those that are compliant with FIPS ++regulations. For example, it may deny the use of MD5, on the grounds that this ++is not secure for uses such as authentication, system integrity checking, or ++digital signatures. If you need to use such a hash for non-security purposes ++(such as indexing into a data structure for speed), you can override the keyword ++argument "usedforsecurity" from True to False to signify that your code is not ++relying on the hash for security purposes, and this will allow the hash to be ++usable even in FIPS mode. ++ + Hash objects have these methods: + - update(arg): Update the hash object with the bytes in arg. Repeated calls + are equivalent to a single call with the concatenation of all +@@ -67,6 +77,18 @@ algorithms_available = set(__always_supported) + __all__ = __always_supported + ('new', 'algorithms_guaranteed', + 'algorithms_available', 'pbkdf2_hmac') + ++import functools ++def __ignore_usedforsecurity(func): ++ """Used for sha3_* functions. Until OpenSSL implements them, we want ++ to use them from Python _sha3 module, but we want them to accept ++ usedforsecurity argument too.""" ++ # TODO: remove this function when OpenSSL implements sha3 ++ @functools.wraps(func) ++ def inner(*args, **kwargs): ++ if 'usedforsecurity' in kwargs: ++ kwargs.pop('usedforsecurity') ++ return func(*args, **kwargs) ++ return inner + + __builtin_constructor_cache = {} + +@@ -100,31 +122,39 @@ def __get_openssl_constructor(name): + f = getattr(_hashlib, 'openssl_' + name) + # Allow the C module to raise ValueError. The function will be + # defined but the hash not actually available thanks to OpenSSL. +- f() ++ # We pass "usedforsecurity=False" to disable FIPS-based restrictions: ++ # at this stage we're merely seeing if the function is callable, ++ # rather than using it for actual work. ++ f(usedforsecurity=False) + # Use the C function directly (very fast) + return f + except (AttributeError, ValueError): ++ # TODO: We want to just raise here when OpenSSL implements sha3 ++ # because we want to make sure that Fedora uses everything from OpenSSL + return __get_builtin_constructor(name) + + +-def __py_new(name, data=b''): +- """new(name, data=b'') - Return a new hashing object using the named algorithm; +- optionally initialized with data (which must be bytes). ++def __py_new(name, data=b'', usedforsecurity=True): ++ """new(name, data=b'', usedforsecurity=True) - Return a new hashing object using ++ the named algorithm; optionally initialized with data (which must be bytes). ++ The 'usedforsecurity' keyword argument does nothing, and is for compatibilty ++ with the OpenSSL implementation + """ + return __get_builtin_constructor(name)(data) + + +-def __hash_new(name, data=b''): +- """new(name, data=b'') - Return a new hashing object using the named algorithm; +- optionally initialized with data (which must be bytes). ++def __hash_new(name, data=b'', usedforsecurity=True): ++ """new(name, data=b'', usedforsecurity=True) - Return a new hashing object using ++ the named algorithm; optionally initialized with data (which must be bytes). ++ ++ Override 'usedforsecurity' to False when using for non-security purposes in ++ a FIPS environment + """ + try: +- return _hashlib.new(name, data) ++ return _hashlib.new(name, data, usedforsecurity) + except ValueError: +- # If the _hashlib module (OpenSSL) doesn't support the named +- # hash, try using our builtin implementations. +- # This allows for SHA224/256 and SHA384/512 support even though +- # the OpenSSL library prior to 0.9.8 doesn't provide them. ++ # TODO: We want to just raise here when OpenSSL implements sha3 ++ # because we want to make sure that Fedora uses everything from OpenSSL + return __get_builtin_constructor(name)(data) + + +@@ -207,7 +237,10 @@ for __func_name in __always_supported: + # try them all, some may not work due to the OpenSSL + # version not supporting that algorithm. + try: +- globals()[__func_name] = __get_hash(__func_name) ++ func = __get_hash(__func_name) ++ if 'sha3_' in __func_name: ++ func = __ignore_usedforsecurity(func) ++ globals()[__func_name] = func + except ValueError: + import logging + logging.exception('code for hash %s was not found.', __func_name) +@@ -215,3 +248,4 @@ for __func_name in __always_supported: + # Cleanup locals() + del __always_supported, __func_name, __get_hash + del __py_new, __hash_new, __get_openssl_constructor ++del __ignore_usedforsecurity +\ No newline at end of file +diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py +index c9b113e..60e2392 100644 +--- a/Lib/test/test_hashlib.py ++++ b/Lib/test/test_hashlib.py +@@ -24,7 +24,22 @@ from test.support import _4G, bigmemtest, import_fresh_module + COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount') + + c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib']) +-py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib']) ++# skipped on Fedora, since we always use OpenSSL implementation ++# py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib']) ++ ++def openssl_enforces_fips(): ++ # Use the "openssl" command (if present) to try to determine if the local ++ # OpenSSL is configured to enforce FIPS ++ from subprocess import Popen, PIPE ++ try: ++ p = Popen(['openssl', 'md5'], ++ stdin=PIPE, stdout=PIPE, stderr=PIPE) ++ except OSError: ++ # "openssl" command not found ++ return False ++ stdout, stderr = p.communicate(input=b'abc') ++ return b'unknown cipher' in stderr ++OPENSSL_ENFORCES_FIPS = openssl_enforces_fips() + + def hexstr(s): + assert isinstance(s, bytes), repr(s) +@@ -34,6 +49,16 @@ def hexstr(s): + r += h[(i >> 4) & 0xF] + h[i & 0xF] + return r + ++# hashlib and _hashlib-based functions support a "usedforsecurity" keyword ++# argument, and FIPS mode requires that it be used overridden with a False ++# value for these selftests to work. Other cryptographic code within Python ++# doesn't support this keyword. ++# Modify a function to one in which "usedforsecurity=False" is added to the ++# keyword arguments: ++def suppress_fips(f): ++ def g(*args, **kwargs): ++ return f(*args, usedforsecurity=False, **kwargs) ++ return g + + class HashLibTestCase(unittest.TestCase): + supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1', +@@ -63,11 +88,11 @@ class HashLibTestCase(unittest.TestCase): + # For each algorithm, test the direct constructor and the use + # of hashlib.new given the algorithm name. + for algorithm, constructors in self.constructors_to_test.items(): +- constructors.add(getattr(hashlib, algorithm)) ++ constructors.add(suppress_fips(getattr(hashlib, algorithm))) + def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm): + if data is None: +- return hashlib.new(_alg) +- return hashlib.new(_alg, data) ++ return suppress_fips(hashlib.new)(_alg) ++ return suppress_fips(hashlib.new)(_alg, data) + constructors.add(_test_algorithm_via_hashlib_new) + + _hashlib = self._conditional_import_module('_hashlib') +@@ -79,27 +104,12 @@ class HashLibTestCase(unittest.TestCase): + for algorithm, constructors in self.constructors_to_test.items(): + constructor = getattr(_hashlib, 'openssl_'+algorithm, None) + if constructor: +- constructors.add(constructor) ++ constructors.add(suppress_fips(constructor)) + + def add_builtin_constructor(name): + constructor = getattr(hashlib, "__get_builtin_constructor")(name) + self.constructors_to_test[name].add(constructor) + +- _md5 = self._conditional_import_module('_md5') +- if _md5: +- add_builtin_constructor('md5') +- _sha1 = self._conditional_import_module('_sha1') +- if _sha1: +- add_builtin_constructor('sha1') +- _sha256 = self._conditional_import_module('_sha256') +- if _sha256: +- add_builtin_constructor('sha224') +- add_builtin_constructor('sha256') +- _sha512 = self._conditional_import_module('_sha512') +- if _sha512: +- add_builtin_constructor('sha384') +- add_builtin_constructor('sha512') +- + super(HashLibTestCase, self).__init__(*args, **kwargs) + + @property +@@ -148,9 +158,6 @@ class HashLibTestCase(unittest.TestCase): + else: + del sys.modules['_md5'] + self.assertRaises(TypeError, get_builtin_constructor, 3) +- constructor = get_builtin_constructor('md5') +- self.assertIs(constructor, _md5.md5) +- self.assertEqual(sorted(builtin_constructor_cache), ['MD5', 'md5']) + + def test_hexdigest(self): + for cons in self.hash_constructors: +@@ -433,6 +440,64 @@ class HashLibTestCase(unittest.TestCase): + + self.assertEqual(expected_hash, hasher.hexdigest()) + ++ def test_issue9146(self): ++ # Ensure that various ways to use "MD5" from "hashlib" don't segfault: ++ m = hashlib.md5(usedforsecurity=False) ++ m.update(b'abc\n') ++ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1") ++ ++ m = hashlib.new('md5', usedforsecurity=False) ++ m.update(b'abc\n') ++ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1") ++ ++ m = hashlib.md5(b'abc\n', usedforsecurity=False) ++ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1") ++ ++ m = hashlib.new('md5', b'abc\n', usedforsecurity=False) ++ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1") ++ ++ @unittest.skipUnless(OPENSSL_ENFORCES_FIPS, ++ 'FIPS enforcement required for this test.') ++ def test_hashlib_fips_mode(self): ++ # Ensure that we raise a ValueError on vanilla attempts to use MD5 ++ # in hashlib in a FIPS-enforced setting: ++ with self.assertRaisesRegexp(ValueError, '.*unknown cipher'): ++ m = hashlib.md5() ++ ++ if not self._conditional_import_module('_md5'): ++ with self.assertRaisesRegexp(ValueError, '.*unknown cipher'): ++ m = hashlib.new('md5') ++ ++ @unittest.skipUnless(OPENSSL_ENFORCES_FIPS, ++ 'FIPS enforcement required for this test.') ++ def test_hashopenssl_fips_mode(self): ++ # Verify the _hashlib module's handling of md5: ++ _hashlib = self._conditional_import_module('_hashlib') ++ if _hashlib: ++ assert hasattr(_hashlib, 'openssl_md5') ++ ++ # Ensure that _hashlib raises a ValueError on vanilla attempts to ++ # use MD5 in a FIPS-enforced setting: ++ with self.assertRaisesRegexp(ValueError, '.*unknown cipher'): ++ m = _hashlib.openssl_md5() ++ with self.assertRaisesRegexp(ValueError, '.*unknown cipher'): ++ m = _hashlib.new('md5') ++ ++ # Ensure that in such a setting we can whitelist a callsite with ++ # usedforsecurity=False and have it succeed: ++ m = _hashlib.openssl_md5(usedforsecurity=False) ++ m.update(b'abc\n') ++ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1") ++ ++ m = _hashlib.new('md5', usedforsecurity=False) ++ m.update(b'abc\n') ++ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1") ++ ++ m = _hashlib.openssl_md5(b'abc\n', usedforsecurity=False) ++ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1") ++ ++ m = _hashlib.new('md5', b'abc\n', usedforsecurity=False) ++ self.assertEquals(m.hexdigest(), "0bee89b07a248e27c83fc3d5951213c1") + + class KDFTests(unittest.TestCase): + +@@ -516,7 +581,7 @@ class KDFTests(unittest.TestCase): + out = pbkdf2(hash_name='sha1', password=b'password', salt=b'salt', + iterations=1, dklen=None) + self.assertEqual(out, self.pbkdf2_results['sha1'][0][0]) +- ++ @unittest.skip('skipped on Fedora, as we always use OpenSSL pbkdf2_hmac') + def test_pbkdf2_hmac_py(self): + self._test_pbkdf2_hmac(py_hashlib.pbkdf2_hmac) + +diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c +index 44765ac..b8cf490 100644 +--- a/Modules/_hashopenssl.c ++++ b/Modules/_hashopenssl.c +@@ -20,6 +20,8 @@ + + + /* EVP is the preferred interface to hashing in OpenSSL */ ++#include ++#include + #include + #include + /* We use the object interface to discover what hashes OpenSSL supports. */ +@@ -45,11 +47,19 @@ typedef struct { + + static PyTypeObject EVPtype; + ++/* Struct to hold all the cached information we need on a specific algorithm. ++ We have one of these per algorithm */ ++typedef struct { ++ PyObject *name_obj; ++ EVP_MD_CTX ctxs[2]; ++ /* ctx_ptrs will point to ctxs unless an error occurred, when it will ++ be NULL: */ ++ EVP_MD_CTX *ctx_ptrs[2]; ++ PyObject *error_msgs[2]; ++} EVPCachedInfo; + +-#define DEFINE_CONSTS_FOR_NEW(Name) \ +- static PyObject *CONST_ ## Name ## _name_obj = NULL; \ +- static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \ +- static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL; ++#define DEFINE_CONSTS_FOR_NEW(Name) \ ++ static EVPCachedInfo cached_info_ ##Name; + + DEFINE_CONSTS_FOR_NEW(md5) + DEFINE_CONSTS_FOR_NEW(sha1) +@@ -92,6 +102,48 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len) + } + } + ++static void ++mc_ctx_init(EVP_MD_CTX *ctx, int usedforsecurity) ++{ ++ EVP_MD_CTX_init(ctx); ++ ++ /* ++ If the user has declared that this digest is being used in a ++ non-security role (e.g. indexing into a data structure), set ++ the exception flag for openssl to allow it ++ */ ++ if (!usedforsecurity) { ++#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW ++ EVP_MD_CTX_set_flags(ctx, ++ EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); ++#endif ++ } ++} ++ ++/* Get an error msg for the last error as a PyObject */ ++static PyObject * ++error_msg_for_last_error(void) ++{ ++ char *errstr; ++ ++ errstr = ERR_error_string(ERR_peek_last_error(), NULL); ++ ERR_clear_error(); ++ ++ return PyUnicode_FromString(errstr); /* Can be NULL */ ++} ++ ++static void ++set_evp_exception(void) ++{ ++ char *errstr; ++ ++ errstr = ERR_error_string(ERR_peek_last_error(), NULL); ++ ERR_clear_error(); ++ ++ PyErr_SetString(PyExc_ValueError, errstr); ++} ++ ++ + /* Internal methods for a hash object */ + + static void +@@ -259,15 +311,16 @@ EVP_repr(EVPobject *self) + static int + EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds) + { +- static char *kwlist[] = {"name", "string", NULL}; ++ static char *kwlist[] = {"name", "string", "usedforsecurity", NULL}; + PyObject *name_obj = NULL; + PyObject *data_obj = NULL; ++ int usedforsecurity = 1; + Py_buffer view; + char *nameStr; + const EVP_MD *digest; + +- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:HASH", kwlist, +- &name_obj, &data_obj)) { ++ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:HASH", kwlist, ++ &name_obj, &data_obj, &usedforsecurity)) { + return -1; + } + +@@ -288,7 +341,12 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds) + PyBuffer_Release(&view); + return -1; + } +- EVP_DigestInit(&self->ctx, digest); ++ mc_ctx_init(&self->ctx, usedforsecurity); ++ if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) { ++ set_evp_exception(); ++ PyBuffer_Release(&view); ++ return -1; ++ } + + self->name = name_obj; + Py_INCREF(self->name); +@@ -372,7 +430,8 @@ static PyTypeObject EVPtype = { + static PyObject * + EVPnew(PyObject *name_obj, + const EVP_MD *digest, const EVP_MD_CTX *initial_ctx, +- const unsigned char *cp, Py_ssize_t len) ++ const unsigned char *cp, Py_ssize_t len, ++ int usedforsecurity) + { + EVPobject *self; + +@@ -387,7 +446,12 @@ EVPnew(PyObject *name_obj, + if (initial_ctx) { + EVP_MD_CTX_copy(&self->ctx, initial_ctx); + } else { +- EVP_DigestInit(&self->ctx, digest); ++ mc_ctx_init(&self->ctx, usedforsecurity); ++ if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) { ++ set_evp_exception(); ++ Py_DECREF(self); ++ return NULL; ++ } + } + + if (cp && len) { +@@ -411,21 +475,29 @@ PyDoc_STRVAR(EVP_new__doc__, + An optional string argument may be provided and will be\n\ + automatically hashed.\n\ + \n\ +-The MD5 and SHA1 algorithms are always supported.\n"); ++The MD5 and SHA1 algorithms are always supported.\n\ ++\n\ ++An optional \"usedforsecurity=True\" keyword argument is provided for use in\n\ ++environments that enforce FIPS-based restrictions. Some implementations of\n\ ++OpenSSL can be configured to prevent the usage of non-secure algorithms (such\n\ ++as MD5). If you have a non-security use for these algorithms (e.g. a hash\n\ ++table), you can override this argument by marking the callsite as\n\ ++\"usedforsecurity=False\"."); + + static PyObject * + EVP_new(PyObject *self, PyObject *args, PyObject *kwdict) + { +- static char *kwlist[] = {"name", "string", NULL}; ++ static char *kwlist[] = {"name", "string", "usedforsecurity", NULL}; + PyObject *name_obj = NULL; + PyObject *data_obj = NULL; ++ int usedforsecurity = 1; + Py_buffer view = { 0 }; + PyObject *ret_obj; + char *name; + const EVP_MD *digest; + +- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|O:new", kwlist, +- &name_obj, &data_obj)) { ++ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|Oi:new", kwlist, ++ &name_obj, &data_obj, &usedforsecurity)) { + return NULL; + } + +@@ -439,7 +511,8 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict) + + digest = EVP_get_digestbyname(name); + +- ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf, view.len); ++ ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf, view.len, ++ usedforsecurity); + + if (data_obj) + PyBuffer_Release(&view); +@@ -722,57 +795,114 @@ generate_hash_name_list(void) + + + /* +- * This macro generates constructor function definitions for specific +- * hash algorithms. These constructors are much faster than calling +- * the generic one passing it a python string and are noticably +- * faster than calling a python new() wrapper. Thats important for ++ * This macro and function generates a family of constructor function ++ * definitions for specific hash algorithms. These constructors are much ++ * faster than calling the generic one passing it a python string and are ++ * noticably faster than calling a python new() wrapper. That's important for + * code that wants to make hashes of a bunch of small strings. + */ + #define GEN_CONSTRUCTOR(NAME) \ + static PyObject * \ +- EVP_new_ ## NAME (PyObject *self, PyObject *args) \ ++ EVP_new_ ## NAME (PyObject *self, PyObject *args, PyObject *kwdict) \ + { \ +- PyObject *data_obj = NULL; \ +- Py_buffer view = { 0 }; \ +- PyObject *ret_obj; \ +- \ +- if (!PyArg_ParseTuple(args, "|O:" #NAME , &data_obj)) { \ +- return NULL; \ +- } \ +- \ +- if (data_obj) \ +- GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); \ +- \ +- ret_obj = EVPnew( \ +- CONST_ ## NAME ## _name_obj, \ +- NULL, \ +- CONST_new_ ## NAME ## _ctx_p, \ +- (unsigned char*)view.buf, \ +- view.len); \ +- \ +- if (data_obj) \ +- PyBuffer_Release(&view); \ +- return ret_obj; \ ++ return implement_specific_EVP_new(self, args, kwdict, \ ++ "|Oi:" #NAME, \ ++ &cached_info_ ## NAME ); \ + } + ++static PyObject * ++implement_specific_EVP_new(PyObject *self, PyObject *args, PyObject *kwdict, ++ const char *format, ++ EVPCachedInfo *cached_info) ++{ ++ static char *kwlist[] = {"string", "usedforsecurity", NULL}; ++ PyObject *data_obj = NULL; ++ Py_buffer view = { 0 }; ++ int usedforsecurity = 1; ++ int idx; ++ PyObject *ret_obj = NULL; ++ ++ assert(cached_info); ++ ++ if (!PyArg_ParseTupleAndKeywords(args, kwdict, format, kwlist, ++ &data_obj, &usedforsecurity)) { ++ return NULL; ++ } ++ ++ if (data_obj) ++ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); ++ ++ idx = usedforsecurity ? 1 : 0; ++ ++ /* ++ * If an error occurred during creation of the global content, the ctx_ptr ++ * will be NULL, and the error_msg will hopefully be non-NULL: ++ */ ++ if (cached_info->ctx_ptrs[idx]) { ++ /* We successfully initialized this context; copy it: */ ++ ret_obj = EVPnew(cached_info->name_obj, ++ NULL, ++ cached_info->ctx_ptrs[idx], ++ (unsigned char*)view.buf, view.len, ++ usedforsecurity); ++ } else { ++ /* Some kind of error happened initializing the global context for ++ this (digest, usedforsecurity) pair. ++ Raise an exception with the saved error message: */ ++ if (cached_info->error_msgs[idx]) { ++ PyErr_SetObject(PyExc_ValueError, cached_info->error_msgs[idx]); ++ } else { ++ PyErr_SetString(PyExc_ValueError, "Error initializing hash"); ++ } ++ } ++ ++ if (data_obj) ++ PyBuffer_Release(&view); ++ ++ return ret_obj; ++} ++ + /* a PyMethodDef structure for the constructor */ + #define CONSTRUCTOR_METH_DEF(NAME) \ +- {"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_VARARGS, \ ++ {"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, \ ++ METH_VARARGS|METH_KEYWORDS, \ + PyDoc_STR("Returns a " #NAME \ + " hash object; optionally initialized with a string") \ + } + +-/* used in the init function to setup a constructor: initialize OpenSSL +- constructor constants if they haven't been initialized already. */ +-#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \ +- if (CONST_ ## NAME ## _name_obj == NULL) { \ +- CONST_ ## NAME ## _name_obj = PyUnicode_FromString(#NAME); \ +- if (EVP_get_digestbyname(#NAME)) { \ +- CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \ +- EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \ +- } \ +- } \ ++/* ++ Macro/function pair to set up the constructors. ++ ++ Try to initialize a context for each hash twice, once with ++ EVP_MD_CTX_FLAG_NON_FIPS_ALLOW and once without. ++ ++ Any that have errors during initialization will end up with a NULL ctx_ptrs ++ entry, and err_msgs will be set (unless we're very low on memory) ++*/ ++#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \ ++ init_constructor_constant(&cached_info_ ## NAME, #NAME); \ + } while (0); ++static void ++init_constructor_constant(EVPCachedInfo *cached_info, const char *name) ++{ ++ assert(cached_info); ++ cached_info->name_obj = PyUnicode_FromString(name); ++ if (EVP_get_digestbyname(name)) { ++ int i; ++ for (i=0; i<2; i++) { ++ mc_ctx_init(&cached_info->ctxs[i], i); ++ if (EVP_DigestInit_ex(&cached_info->ctxs[i], ++ EVP_get_digestbyname(name), NULL)) { ++ /* Success: */ ++ cached_info->ctx_ptrs[i] = &cached_info->ctxs[i]; ++ } else { ++ /* Failure: */ ++ cached_info->ctx_ptrs[i] = NULL; ++ cached_info->error_msgs[i] = error_msg_for_last_error(); ++ } ++ } ++ } ++} + + GEN_CONSTRUCTOR(md5) + GEN_CONSTRUCTOR(sha1) +@@ -819,13 +949,10 @@ PyInit__hashlib(void) + { + PyObject *m, *openssl_md_meth_names; + +- OpenSSL_add_all_digests(); +- ERR_load_crypto_strings(); ++ SSL_load_error_strings(); ++ SSL_library_init(); + +- /* TODO build EVP_functions openssl_* entries dynamically based +- * on what hashes are supported rather than listing many +- * but having some be unsupported. Only init appropriate +- * constants. */ ++ OpenSSL_add_all_digests(); + + Py_TYPE(&EVPtype) = &PyType_Type; + if (PyType_Ready(&EVPtype) < 0) diff --git a/python3/00155-avoid-ctypes-thunks.patch b/python3/00155-avoid-ctypes-thunks.patch new file mode 100644 index 00000000..edb6028a --- /dev/null +++ b/python3/00155-avoid-ctypes-thunks.patch @@ -0,0 +1,15 @@ +diff -up Python-3.2.3/Lib/ctypes/__init__.py.rhbz814391 Python-3.2.3/Lib/ctypes/__init__.py +--- Python-3.2.3/Lib/ctypes/__init__.py.rhbz814391 2012-04-20 15:12:49.017867692 -0400 ++++ Python-3.2.3/Lib/ctypes/__init__.py 2012-04-20 15:15:09.501111408 -0400 +@@ -266,11 +266,6 @@ def _reset_cache(): + # _SimpleCData.c_char_p_from_param + POINTER(c_char).from_param = c_char_p.from_param + _pointer_type_cache[None] = c_void_p +- # XXX for whatever reasons, creating the first instance of a callback +- # function is needed for the unittests on Win64 to succeed. This MAY +- # be a compiler bug, since the problem occurs only when _ctypes is +- # compiled with the MS SDK compiler. Or an uninitialized variable? +- CFUNCTYPE(c_int)(lambda: None) + + def create_unicode_buffer(init, size=None): + """create_unicode_buffer(aString) -> character array diff --git a/python3/00157-uid-gid-overflows.patch b/python3/00157-uid-gid-overflows.patch new file mode 100644 index 00000000..03f3e021 --- /dev/null +++ b/python3/00157-uid-gid-overflows.patch @@ -0,0 +1,68 @@ +diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py +index e9fdb07..ea60e6e 100644 +--- a/Lib/test/test_os.py ++++ b/Lib/test/test_os.py +@@ -1723,30 +1723,36 @@ class PosixUidGidTests(unittest.TestCase): + def test_setuid(self): + if os.getuid() != 0: + self.assertRaises(OSError, os.setuid, 0) ++ self.assertRaises(TypeError, os.setuid, 'not an int') + self.assertRaises(OverflowError, os.setuid, 1<<32) + + @unittest.skipUnless(hasattr(os, 'setgid'), 'test needs os.setgid()') + def test_setgid(self): + if os.getuid() != 0 and not HAVE_WHEEL_GROUP: + self.assertRaises(OSError, os.setgid, 0) ++ self.assertRaises(TypeError, os.setgid, 'not an int') + self.assertRaises(OverflowError, os.setgid, 1<<32) + + @unittest.skipUnless(hasattr(os, 'seteuid'), 'test needs os.seteuid()') + def test_seteuid(self): + if os.getuid() != 0: + self.assertRaises(OSError, os.seteuid, 0) ++ self.assertRaises(TypeError, os.seteuid, 'not an int') + self.assertRaises(OverflowError, os.seteuid, 1<<32) + + @unittest.skipUnless(hasattr(os, 'setegid'), 'test needs os.setegid()') + def test_setegid(self): + if os.getuid() != 0 and not HAVE_WHEEL_GROUP: + self.assertRaises(OSError, os.setegid, 0) ++ self.assertRaises(TypeError, os.setegid, 'not an int') + self.assertRaises(OverflowError, os.setegid, 1<<32) + + @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()') + def test_setreuid(self): + if os.getuid() != 0: + self.assertRaises(OSError, os.setreuid, 0, 0) ++ self.assertRaises(TypeError, os.setreuid, 'not an int', 0) ++ self.assertRaises(TypeError, os.setreuid, 0, 'not an int') + self.assertRaises(OverflowError, os.setreuid, 1<<32, 0) + self.assertRaises(OverflowError, os.setreuid, 0, 1<<32) + +@@ -1762,6 +1768,8 @@ class PosixUidGidTests(unittest.TestCase): + def test_setregid(self): + if os.getuid() != 0 and not HAVE_WHEEL_GROUP: + self.assertRaises(OSError, os.setregid, 0, 0) ++ self.assertRaises(TypeError, os.setregid, 'not an int', 0) ++ self.assertRaises(TypeError, os.setregid, 0, 'not an int') + self.assertRaises(OverflowError, os.setregid, 1<<32, 0) + self.assertRaises(OverflowError, os.setregid, 0, 1<<32) + +diff --git a/Lib/test/test_pwd.py b/Lib/test/test_pwd.py +index ac9cff7..db98159 100644 +--- a/Lib/test/test_pwd.py ++++ b/Lib/test/test_pwd.py +@@ -104,11 +104,11 @@ class PwdTest(unittest.TestCase): + # In some cases, byuids isn't a complete list of all users in the + # system, so if we try to pick a value not in byuids (via a perturbing + # loop, say), pwd.getpwuid() might still be able to find data for that +- # uid. Using sys.maxint may provoke the same problems, but hopefully ++ # uid. Using 2**32 - 2 may provoke the same problems, but hopefully + # it will be a more repeatable failure. + # Android accepts a very large span of uids including sys.maxsize and + # -1; it raises KeyError with 1 or 2 for example. +- fakeuid = sys.maxsize ++ fakeuid = 2**32 - 2 + self.assertNotIn(fakeuid, byuids) + if not support.is_android: + self.assertRaises(KeyError, pwd.getpwuid, fakeuid) diff --git a/python3/00170-gc-assertions.patch b/python3/00170-gc-assertions.patch new file mode 100644 index 00000000..9190fb9e --- /dev/null +++ b/python3/00170-gc-assertions.patch @@ -0,0 +1,310 @@ +diff --git a/Include/object.h b/Include/object.h +index 0c88603..e3413e8 100644 +--- a/Include/object.h ++++ b/Include/object.h +@@ -1071,6 +1071,49 @@ PyAPI_FUNC(void) + _PyObject_DebugTypeStats(FILE *out); + #endif /* ifndef Py_LIMITED_API */ + ++/* ++ Define a pair of assertion macros. ++ ++ These work like the regular C assert(), in that they will abort the ++ process with a message on stderr if the given condition fails to hold, ++ but compile away to nothing if NDEBUG is defined. ++ ++ However, before aborting, Python will also try to call _PyObject_Dump() on ++ the given object. This may be of use when investigating bugs in which a ++ particular object is corrupt (e.g. buggy a tp_visit method in an extension ++ module breaking the garbage collector), to help locate the broken objects. ++ ++ The WITH_MSG variant allows you to supply an additional message that Python ++ will attempt to print to stderr, after the object dump. ++*/ ++#ifdef NDEBUG ++/* No debugging: compile away the assertions: */ ++#define PyObject_ASSERT_WITH_MSG(obj, expr, msg) ((void)0) ++#else ++/* With debugging: generate checks: */ ++#define PyObject_ASSERT_WITH_MSG(obj, expr, msg) \ ++ ((expr) \ ++ ? (void)(0) \ ++ : _PyObject_AssertFailed((obj), \ ++ (msg), \ ++ (__STRING(expr)), \ ++ (__FILE__), \ ++ (__LINE__), \ ++ (__PRETTY_FUNCTION__))) ++#endif ++ ++#define PyObject_ASSERT(obj, expr) \ ++ PyObject_ASSERT_WITH_MSG(obj, expr, NULL) ++ ++/* ++ Declare and define the entrypoint even when NDEBUG is defined, to avoid ++ causing compiler/linker errors when building extensions without NDEBUG ++ against a Python built with NDEBUG defined ++*/ ++PyAPI_FUNC(void) _PyObject_AssertFailed(PyObject *, const char *, ++ const char *, const char *, int, ++ const char *); ++ + #ifdef __cplusplus + } + #endif +diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py +index e727499..6efcafb 100644 +--- a/Lib/test/test_gc.py ++++ b/Lib/test/test_gc.py +@@ -1,10 +1,11 @@ + import unittest + from test.support import (verbose, refcount_test, run_unittest, + strip_python_stderr, cpython_only, start_threads, +- temp_dir, requires_type_collecting) ++ temp_dir, import_module, requires_type_collecting) + from test.support.script_helper import assert_python_ok, make_script + + import sys ++import sysconfig + import time + import gc + import weakref +@@ -50,6 +51,8 @@ class GC_Detector(object): + # gc collects it. + self.wr = weakref.ref(C1055820(666), it_happened) + ++BUILD_WITH_NDEBUG = ('-DNDEBUG' in sysconfig.get_config_vars()['PY_CFLAGS']) ++ + @with_tp_del + class Uncollectable(object): + """Create a reference cycle with multiple __del__ methods. +@@ -862,6 +865,50 @@ class GCCallbackTests(unittest.TestCase): + self.assertEqual(len(gc.garbage), 0) + + ++ @unittest.skipIf(BUILD_WITH_NDEBUG, ++ 'built with -NDEBUG') ++ def test_refcount_errors(self): ++ self.preclean() ++ # Verify the "handling" of objects with broken refcounts ++ import_module("ctypes") #skip if not supported ++ ++ import subprocess ++ code = '''if 1: ++ a = [] ++ b = [a] ++ ++ # Simulate the refcount of "a" being too low (compared to the ++ # references held on it by live data), but keeping it above zero ++ # (to avoid deallocating it): ++ import ctypes ++ ctypes.pythonapi.Py_DecRef(ctypes.py_object(a)) ++ ++ # The garbage collector should now have a fatal error when it reaches ++ # the broken object: ++ import gc ++ gc.collect() ++ ''' ++ p = subprocess.Popen([sys.executable, "-c", code], ++ stdout=subprocess.PIPE, ++ stderr=subprocess.PIPE) ++ stdout, stderr = p.communicate() ++ p.stdout.close() ++ p.stderr.close() ++ # Verify that stderr has a useful error message: ++ self.assertRegex(stderr, ++ b'Modules/gcmodule.c:[0-9]+: visit_decref: Assertion "\(\(gc\)->gc.gc_refs >> \(1\)\) != 0" failed.') ++ self.assertRegex(stderr, ++ b'refcount was too small') ++ self.assertRegex(stderr, ++ b'object : \[\]') ++ self.assertRegex(stderr, ++ b'type : list') ++ self.assertRegex(stderr, ++ b'refcount: 1') ++ self.assertRegex(stderr, ++ b'address : 0x[0-9a-f]+') ++ ++ + class GCTogglingTests(unittest.TestCase): + def setUp(self): + gc.enable() +diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c +index 0c6f444..87edd5a 100644 +--- a/Modules/gcmodule.c ++++ b/Modules/gcmodule.c +@@ -342,7 +342,8 @@ update_refs(PyGC_Head *containers) + { + PyGC_Head *gc = containers->gc.gc_next; + for (; gc != containers; gc = gc->gc.gc_next) { +- assert(_PyGCHead_REFS(gc) == GC_REACHABLE); ++ PyObject_ASSERT(FROM_GC(gc), ++ _PyGCHead_REFS(gc) == GC_REACHABLE); + _PyGCHead_SET_REFS(gc, Py_REFCNT(FROM_GC(gc))); + /* Python's cyclic gc should never see an incoming refcount + * of 0: if something decref'ed to 0, it should have been +@@ -362,7 +363,8 @@ update_refs(PyGC_Head *containers) + * so serious that maybe this should be a release-build + * check instead of an assert? + */ +- assert(_PyGCHead_REFS(gc) != 0); ++ PyObject_ASSERT(FROM_GC(gc), ++ _PyGCHead_REFS(gc) != 0); + } + } + +@@ -377,7 +379,9 @@ visit_decref(PyObject *op, void *data) + * generation being collected, which can be recognized + * because only they have positive gc_refs. + */ +- assert(_PyGCHead_REFS(gc) != 0); /* else refcount was too small */ ++ PyObject_ASSERT_WITH_MSG(FROM_GC(gc), ++ _PyGCHead_REFS(gc) != 0, ++ "refcount was too small"); /* else refcount was too small */ + if (_PyGCHead_REFS(gc) > 0) + _PyGCHead_DECREF(gc); + } +@@ -437,9 +441,10 @@ visit_reachable(PyObject *op, PyGC_Head *reachable) + * If gc_refs == GC_UNTRACKED, it must be ignored. + */ + else { +- assert(gc_refs > 0 +- || gc_refs == GC_REACHABLE +- || gc_refs == GC_UNTRACKED); ++ PyObject_ASSERT(FROM_GC(gc), ++ gc_refs > 0 ++ || gc_refs == GC_REACHABLE ++ || gc_refs == GC_UNTRACKED); + } + } + return 0; +@@ -481,7 +486,7 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable) + */ + PyObject *op = FROM_GC(gc); + traverseproc traverse = Py_TYPE(op)->tp_traverse; +- assert(_PyGCHead_REFS(gc) > 0); ++ PyObject_ASSERT(op, _PyGCHead_REFS(gc) > 0); + _PyGCHead_SET_REFS(gc, GC_REACHABLE); + (void) traverse(op, + (visitproc)visit_reachable, +@@ -544,7 +549,7 @@ move_legacy_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers) + for (gc = unreachable->gc.gc_next; gc != unreachable; gc = next) { + PyObject *op = FROM_GC(gc); + +- assert(IS_TENTATIVELY_UNREACHABLE(op)); ++ PyObject_ASSERT(op, IS_TENTATIVELY_UNREACHABLE(op)); + next = gc->gc.gc_next; + + if (has_legacy_finalizer(op)) { +@@ -620,7 +625,7 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) + PyWeakReference **wrlist; + + op = FROM_GC(gc); +- assert(IS_TENTATIVELY_UNREACHABLE(op)); ++ PyObject_ASSERT(op, IS_TENTATIVELY_UNREACHABLE(op)); + next = gc->gc.gc_next; + + if (! PyType_SUPPORTS_WEAKREFS(Py_TYPE(op))) +@@ -641,9 +646,9 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) + * the callback pointer intact. Obscure: it also + * changes *wrlist. + */ +- assert(wr->wr_object == op); ++ PyObject_ASSERT(wr->wr_object, wr->wr_object == op); + _PyWeakref_ClearRef(wr); +- assert(wr->wr_object == Py_None); ++ PyObject_ASSERT(wr->wr_object, wr->wr_object == Py_None); + if (wr->wr_callback == NULL) + continue; /* no callback */ + +@@ -677,7 +682,7 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) + */ + if (IS_TENTATIVELY_UNREACHABLE(wr)) + continue; +- assert(IS_REACHABLE(wr)); ++ PyObject_ASSERT(op, IS_REACHABLE(wr)); + + /* Create a new reference so that wr can't go away + * before we can process it again. +@@ -686,7 +691,8 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) + + /* Move wr to wrcb_to_call, for the next pass. */ + wrasgc = AS_GC(wr); +- assert(wrasgc != next); /* wrasgc is reachable, but ++ PyObject_ASSERT(op, wrasgc != next); ++ /* wrasgc is reachable, but + next isn't, so they can't + be the same */ + gc_list_move(wrasgc, &wrcb_to_call); +@@ -702,11 +708,11 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) + + gc = wrcb_to_call.gc.gc_next; + op = FROM_GC(gc); +- assert(IS_REACHABLE(op)); +- assert(PyWeakref_Check(op)); ++ PyObject_ASSERT(op, IS_REACHABLE(op)); ++ PyObject_ASSERT(op, PyWeakref_Check(op)); + wr = (PyWeakReference *)op; + callback = wr->wr_callback; +- assert(callback != NULL); ++ PyObject_ASSERT(op, callback != NULL); + + /* copy-paste of weakrefobject.c's handle_callback() */ + temp = PyObject_CallFunctionObjArgs(callback, wr, NULL); +@@ -823,12 +829,14 @@ check_garbage(PyGC_Head *collectable) + for (gc = collectable->gc.gc_next; gc != collectable; + gc = gc->gc.gc_next) { + _PyGCHead_SET_REFS(gc, Py_REFCNT(FROM_GC(gc))); +- assert(_PyGCHead_REFS(gc) != 0); ++ PyObject_ASSERT(FROM_GC(gc), ++ _PyGCHead_REFS(gc) != 0); + } + subtract_refs(collectable); + for (gc = collectable->gc.gc_next; gc != collectable; + gc = gc->gc.gc_next) { +- assert(_PyGCHead_REFS(gc) >= 0); ++ PyObject_ASSERT(FROM_GC(gc), ++ _PyGCHead_REFS(gc) >= 0); + if (_PyGCHead_REFS(gc) != 0) + return -1; + } +diff --git a/Objects/object.c b/Objects/object.c +index 559794f..a47d47f 100644 +--- a/Objects/object.c ++++ b/Objects/object.c +@@ -2025,6 +2025,35 @@ _PyTrash_thread_destroy_chain(void) + } + } + ++PyAPI_FUNC(void) ++_PyObject_AssertFailed(PyObject *obj, const char *msg, const char *expr, ++ const char *file, int line, const char *function) ++{ ++ fprintf(stderr, ++ "%s:%d: %s: Assertion \"%s\" failed.\n", ++ file, line, function, expr); ++ if (msg) { ++ fprintf(stderr, "%s\n", msg); ++ } ++ ++ fflush(stderr); ++ ++ if (obj) { ++ /* This might succeed or fail, but we're about to abort, so at least ++ try to provide any extra info we can: */ ++ _PyObject_Dump(obj); ++ } ++ else { ++ fprintf(stderr, "NULL object\n"); ++ } ++ ++ fflush(stdout); ++ fflush(stderr); ++ ++ /* Terminate the process: */ ++ abort(); ++} ++ + #ifndef Py_TRACE_REFS + /* For Py_LIMITED_API, we need an out-of-line version of _Py_Dealloc. + Define this here, so we can undefine the macro. */ diff --git a/python3/00178-dont-duplicate-flags-in-sysconfig.patch b/python3/00178-dont-duplicate-flags-in-sysconfig.patch new file mode 100644 index 00000000..4b84e05f --- /dev/null +++ b/python3/00178-dont-duplicate-flags-in-sysconfig.patch @@ -0,0 +1,30 @@ +diff -r 39b9b05c3085 Lib/distutils/sysconfig.py +--- a/Lib/distutils/sysconfig.py Wed Apr 10 00:27:23 2013 +0200 ++++ b/Lib/distutils/sysconfig.py Wed Apr 10 10:14:18 2013 +0200 +@@ -370,7 +370,10 @@ + done[n] = item = "" + if found: + after = value[m.end():] +- value = value[:m.start()] + item + after ++ value = value[:m.start()] ++ if item.strip() not in value: ++ value += item ++ value += after + if "$" in after: + notdone[name] = value + else: +diff -r 39b9b05c3085 Lib/sysconfig.py +--- a/Lib/sysconfig.py Wed Apr 10 00:27:23 2013 +0200 ++++ b/Lib/sysconfig.py Wed Apr 10 10:14:18 2013 +0200 +@@ -294,7 +294,10 @@ + + if found: + after = value[m.end():] +- value = value[:m.start()] + item + after ++ value = value[:m.start()] ++ if item.strip() not in value: ++ value += item ++ value += after + if "$" in after: + notdone[name] = value + else: diff --git a/python3/00188-fix-lib2to3-tests-when-hashlib-doesnt-compile-properly.patch b/python3/00188-fix-lib2to3-tests-when-hashlib-doesnt-compile-properly.patch new file mode 100644 index 00000000..90af30db --- /dev/null +++ b/python3/00188-fix-lib2to3-tests-when-hashlib-doesnt-compile-properly.patch @@ -0,0 +1,11 @@ +diff -r 28c04e954bb6 Lib/lib2to3/main.py +--- a/Lib/lib2to3/main.py Tue Oct 29 22:25:55 2013 -0400 ++++ b/Lib/lib2to3/main.py Wed Nov 06 14:33:07 2013 +0100 +@@ -213,6 +213,7 @@ + + # Set up logging handler + level = logging.DEBUG if options.verbose else logging.INFO ++ logging.root.handlers = [] + logging.basicConfig(format='%(name)s: %(message)s', level=level) + logger = logging.getLogger('lib2to3.main') + diff --git a/python3/00189-add-rewheel-module.patch b/python3/00189-add-rewheel-module.patch new file mode 100644 index 00000000..d504e92a --- /dev/null +++ b/python3/00189-add-rewheel-module.patch @@ -0,0 +1,232 @@ +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 +@@ -1,8 +1,10 @@ + import os + import os.path + import pkgutil ++import shutil + import sys + import tempfile ++from ensurepip import rewheel + + + __all__ = ["version", "bootstrap"] +@@ -25,6 +27,8 @@ + + # Install the bundled software + import pip ++ if args[0] in ["install", "list", "wheel"]: ++ args.append('--pre') + pip.main(args) + + +@@ -73,20 +77,39 @@ + # omit pip and easy_install + os.environ["ENSUREPIP_OPTIONS"] = "install" + ++ whls = [] ++ rewheel_dir = None ++ # try to see if we have system-wide versions of _PROJECTS ++ dep_records = rewheel.find_system_records([p[0] for p in _PROJECTS]) ++ # TODO: check if system-wide versions are the newest ones ++ # if --upgrade is used? ++ if all(dep_records): ++ # if we have all _PROJECTS installed system-wide, we'll recreate ++ # wheels from them and install those ++ rewheel_dir = tempfile.TemporaryDirectory() ++ for dr in dep_records: ++ new_whl = rewheel.rewheel_from_record(dr, rewheel_dir.name) ++ whls.append(os.path.join(rewheel_dir.name, new_whl)) ++ else: ++ # if we don't have all the _PROJECTS installed system-wide, ++ # let's just fall back to bundled wheels ++ for project, version in _PROJECTS: ++ whl = os.path.join( ++ os.path.dirname(__file__), ++ "_bundled", ++ "{}-{}-py2.py3-none-any.whl".format(project, version) ++ ) ++ whls.append(whl) ++ + with tempfile.TemporaryDirectory() as tmpdir: + # Put our bundled wheels into a temporary directory and construct the + # additional paths that need added to sys.path + additional_paths = [] +- for project, version in _PROJECTS: +- wheel_name = "{}-{}-py2.py3-none-any.whl".format(project, version) +- whl = pkgutil.get_data( +- "ensurepip", +- "_bundled/{}".format(wheel_name), +- ) +- with open(os.path.join(tmpdir, wheel_name), "wb") as fp: +- fp.write(whl) +- +- additional_paths.append(os.path.join(tmpdir, wheel_name)) ++ for whl in whls: ++ shutil.copy(whl, tmpdir) ++ additional_paths.append(os.path.join(tmpdir, os.path.basename(whl))) ++ if rewheel_dir: ++ rewheel_dir.cleanup() + + # 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 +@@ -0,0 +1,143 @@ ++import argparse ++import codecs ++import csv ++import email.parser ++import os ++import io ++import re ++import site ++import subprocess ++import sys ++import zipfile ++ ++def run(): ++ parser = argparse.ArgumentParser(description='Recreate wheel of package with given RECORD.') ++ parser.add_argument('record_path', ++ help='Path to RECORD file') ++ parser.add_argument('-o', '--output-dir', ++ help='Dir where to place the wheel, defaults to current working dir.', ++ dest='outdir', ++ default=os.path.curdir) ++ ++ ns = parser.parse_args() ++ retcode = 0 ++ try: ++ print(rewheel_from_record(**vars(ns))) ++ except BaseException as e: ++ print('Failed: {}'.format(e)) ++ retcode = 1 ++ sys.exit(1) ++ ++def find_system_records(projects): ++ """Return list of paths to RECORD files for system-installed projects. ++ ++ If a project is not installed, the resulting list contains None instead ++ of a path to its RECORD ++ """ ++ records = [] ++ # get system site-packages dirs ++ sys_sitepack = site.getsitepackages([sys.base_prefix, sys.base_exec_prefix]) ++ sys_sitepack = [sp for sp in sys_sitepack if os.path.exists(sp)] ++ # try to find all projects in all system site-packages ++ for project in projects: ++ path = None ++ for sp in sys_sitepack: ++ dist_info_re = os.path.join(sp, project) + r'-[^\{0}]+\.dist-info'.format(os.sep) ++ candidates = [os.path.join(sp, p) for p in os.listdir(sp)] ++ # filter out candidate dirs based on the above regexp ++ filtered = [c for c in candidates if re.match(dist_info_re, c)] ++ # if we have 0 or 2 or more dirs, something is wrong... ++ if len(filtered) == 1: ++ path = filtered[0] ++ if path is not None: ++ records.append(os.path.join(path, 'RECORD')) ++ else: ++ records.append(None) ++ return records ++ ++def rewheel_from_record(record_path, outdir): ++ """Recreates a whee of package with given record_path and returns path ++ to the newly created wheel.""" ++ site_dir = os.path.dirname(os.path.dirname(record_path)) ++ record_relpath = record_path[len(site_dir):].strip(os.path.sep) ++ to_write, to_omit = get_records_to_pack(site_dir, record_relpath) ++ new_wheel_name = get_wheel_name(record_path) ++ new_wheel_path = os.path.join(outdir, new_wheel_name + '.whl') ++ ++ new_wheel = zipfile.ZipFile(new_wheel_path, mode='w', compression=zipfile.ZIP_DEFLATED) ++ # we need to write a new record with just the files that we will write, ++ # e.g. not binaries and *.pyc/*.pyo files ++ new_record = io.StringIO() ++ writer = csv.writer(new_record) ++ ++ # handle files that we can write straight away ++ for f, sha_hash, size in to_write: ++ new_wheel.write(os.path.join(site_dir, f), arcname=f) ++ writer.writerow([f, sha_hash,size]) ++ ++ # rewrite the old wheel file with a new computed one ++ writer.writerow([record_relpath, '', '']) ++ new_wheel.writestr(record_relpath, new_record.getvalue()) ++ ++ new_wheel.close() ++ ++ return new_wheel.filename ++ ++def get_wheel_name(record_path): ++ """Return proper name of the wheel, without .whl.""" ++ ++ wheel_info_path = os.path.join(os.path.dirname(record_path), 'WHEEL') ++ with codecs.open(wheel_info_path, encoding='utf-8') as wheel_info_file: ++ wheel_info = email.parser.Parser().parsestr(wheel_info_file.read()) ++ ++ metadata_path = os.path.join(os.path.dirname(record_path), 'METADATA') ++ with codecs.open(metadata_path, encoding='utf-8') as metadata_file: ++ metadata = email.parser.Parser().parsestr(metadata_file.read()) ++ ++ # construct name parts according to wheel spec ++ distribution = metadata.get('Name') ++ version = metadata.get('Version') ++ build_tag = '' # nothing for now ++ lang_tag = [] ++ for t in wheel_info.get_all('Tag'): ++ lang_tag.append(t.split('-')[0]) ++ lang_tag = '.'.join(lang_tag) ++ abi_tag, plat_tag = wheel_info.get('Tag').split('-')[1:3] ++ # leave out build tag, if it is empty ++ to_join = filter(None, [distribution, version, build_tag, lang_tag, abi_tag, plat_tag]) ++ return '-'.join(list(to_join)) ++ ++def get_records_to_pack(site_dir, record_relpath): ++ """Accepts path of sitedir and path of RECORD file relative to it. ++ Returns two lists: ++ - list of files that can be written to new RECORD straight away ++ - list of files that shouldn't be written or need some processing ++ (pyc and pyo files, scripts) ++ """ ++ record_file_path = os.path.join(site_dir, record_relpath) ++ with codecs.open(record_file_path, encoding='utf-8') as record_file: ++ record_contents = record_file.read() ++ # temporary fix for https://github.com/pypa/pip/issues/1376 ++ # we need to ignore files under ".data" directory ++ data_dir = os.path.dirname(record_relpath).strip(os.path.sep) ++ data_dir = data_dir[:-len('dist-info')] + 'data' ++ ++ to_write = [] ++ to_omit = [] ++ for l in record_contents.splitlines(): ++ spl = l.split(',') ++ if len(spl) == 3: ++ # new record will omit (or write differently): ++ # - abs paths, paths with ".." (entry points), ++ # - pyc+pyo files ++ # - the old RECORD file ++ # TODO: is there any better way to recognize an entry point? ++ if os.path.isabs(spl[0]) or spl[0].startswith('..') or \ ++ spl[0].endswith('.pyc') or spl[0].endswith('.pyo') or \ ++ spl[0] == record_relpath or spl[0].startswith(data_dir): ++ to_omit.append(spl) ++ else: ++ to_write.append(spl) ++ else: ++ 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 +@@ -1227,7 +1227,7 @@ + test/test_asyncio \ + collections concurrent concurrent/futures encodings \ + email email/mime test/test_email test/test_email/data \ +- ensurepip ensurepip/_bundled \ ++ ensurepip ensurepip/_bundled ensurepip/rewheel \ + html json test/test_json http dbm xmlrpc \ + sqlite3 sqlite3/test \ + logging csv wsgiref urllib \ diff --git a/python3/002-3.1-enable-new-dtags.patch b/python3/002-3.1-enable-new-dtags.patch index 89a2d17c..05954faf 100644 --- a/python3/002-3.1-enable-new-dtags.patch +++ b/python3/002-3.1-enable-new-dtags.patch @@ -2,7 +2,7 @@ Cygwin ld (as of binutils-2.19.51) does not understand --enable-new-dtags. --- Python-3.1/Lib/distutils/unixccompiler.py.orig 2009-05-09 06:55:12.000000000 -0500 +++ Python-3.1/Lib/distutils/unixccompiler.py 2009-08-19 22:46:55.222993300 -0500 -@@ -279,7 +279,7 @@ class UnixCCompiler(CCompiler): +@@ -224,7 +224,7 @@ class UnixCCompiler(CCompiler): # the configuration data stored in the Python installation, so # we use this hack. compiler = os.path.basename(sysconfig.get_config_var("CC")) @@ -10,4 +10,4 @@ Cygwin ld (as of binutils-2.19.51) does not understand --enable-new-dtags. + if sys.platform[:6] == "darwin" or sys.platform[:6] == "cygwin": # MacOSX's linker doesn't understand the -R flag at all return "-L" + dir - elif sys.platform[:5] == "hp-ux": + elif sys.platform[:7] == "freebsd": diff --git a/python3/00206-remove-hf-from-arm-triplet.patch b/python3/00206-remove-hf-from-arm-triplet.patch new file mode 100644 index 00000000..8e494866 --- /dev/null +++ b/python3/00206-remove-hf-from-arm-triplet.patch @@ -0,0 +1,15 @@ +diff -up Python-3.5.0/configure.ac Python-3.5.0/configure.ac +--- Python-3.5.0/configure.ac 2015-09-23 13:52:20.756909744 +0200 ++++ Python-3.5.0/configure.ac 2015-09-23 13:52:46.859163629 +0200 +@@ -799,9 +799,9 @@ cat >> conftest.c <> conftest.c <> conftest.c <> conftest.c <> conftest.c < $@.tmp diff --git a/python3/00252-add-executable-option.patch b/python3/00252-add-executable-option.patch new file mode 100644 index 00000000..1f54cc5b --- /dev/null +++ b/python3/00252-add-executable-option.patch @@ -0,0 +1,45 @@ +diff --git a/Lib/distutils/cmd.py b/Lib/distutils/cmd.py +index c89d5ef..dd61621 100644 +--- a/Lib/distutils/cmd.py ++++ b/Lib/distutils/cmd.py +@@ -296,7 +296,8 @@ class Command: + finalized command object. + """ + cmd_obj = self.distribution.get_command_obj(command, create) +- cmd_obj.ensure_finalized() ++ if cmd_obj is not None: ++ cmd_obj.ensure_finalized() + return cmd_obj + + # XXX rename to 'get_reinitialized_command()'? (should do the +diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py +index 8174192..30ca739 100644 +--- a/Lib/distutils/command/install.py ++++ b/Lib/distutils/command/install.py +@@ -122,6 +122,8 @@ class install(Command): + "force installation (overwrite any existing files)"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), ++ ('executable=', 'e', ++ "specify final destination interpreter path (install.py)"), + + # Where to install documentation (eventually!) + #('doc-format=', None, "format of documentation to generate"), +@@ -195,6 +197,7 @@ class install(Command): + # directory not in sys.path. + self.force = 0 + self.skip_build = 0 ++ self.executable = None + self.warn_dir = 1 + + # These are only here as a conduit from the 'build' command to the +@@ -367,6 +370,9 @@ class install(Command): + ('build_base', 'build_base'), + ('build_lib', 'build_lib')) + ++ if self.executable is None: ++ self.executable = os.path.normpath(sys.executable) ++ + # Punt on doc directories for now -- after all, we're punting on + # documentation completely! + diff --git a/python3/00260-require-setuptools-dependencies.patch b/python3/00260-require-setuptools-dependencies.patch new file mode 100644 index 00000000..8bbb9407 --- /dev/null +++ b/python3/00260-require-setuptools-dependencies.patch @@ -0,0 +1,183 @@ +diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py +index 9f5d151..4dfa8a1 100644 +--- a/Lib/ensurepip/__init__.py ++++ b/Lib/ensurepip/__init__.py +@@ -10,13 +10,25 @@ import tempfile + __all__ = ["version", "bootstrap"] + + +-_SETUPTOOLS_VERSION = "28.8.0" ++_SETUPTOOLS_VERSION = "34.2.0" + + _PIP_VERSION = "9.0.1" + ++_SIX_VERSION = "1.10.0" ++ ++_APPDIRS_VERSION = "1.4.0" ++ ++_PACKAGING_VERSION = "16.8" ++ ++_PYPARSING_VERSION = "2.1.10" ++ + _PROJECTS = [ +- ("setuptools", _SETUPTOOLS_VERSION), +- ("pip", _PIP_VERSION), ++ ("setuptools", _SETUPTOOLS_VERSION), ++ ("pip", _PIP_VERSION), ++ ("six", _SIX_VERSION), ++ ("appdirs", _APPDIRS_VERSION), ++ ("packaging", _PACKAGING_VERSION), ++ ("pyparsing", _PYPARSING_VERSION) + ] + + +diff --git a/Lib/test/test_ensurepip.py b/Lib/test/test_ensurepip.py +index 9b04c18..23664c4 100644 +--- a/Lib/test/test_ensurepip.py ++++ b/Lib/test/test_ensurepip.py +@@ -40,13 +40,14 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase): + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", +- unittest.mock.ANY, "setuptools", "pip", ++ unittest.mock.ANY, ++ "setuptools", "pip", "six", "appdirs", "packaging", "pyparsing", + ], + unittest.mock.ANY, + ) + + additional_paths = self.run_pip.call_args[0][1] +- self.assertEqual(len(additional_paths), 2) ++ self.assertEqual(len(additional_paths), 6) + + def test_bootstrapping_with_root(self): + ensurepip.bootstrap(root="/foo/bar/") +@@ -55,7 +56,7 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase): + [ + "install", "--no-index", "--find-links", + unittest.mock.ANY, "--root", "/foo/bar/", +- "setuptools", "pip", ++ "setuptools", "pip", "six", "appdirs", "packaging", "pyparsing", + ], + unittest.mock.ANY, + ) +@@ -66,7 +67,8 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase): + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", +- unittest.mock.ANY, "--user", "setuptools", "pip", ++ unittest.mock.ANY, "--user", ++ "setuptools", "pip", "six", "appdirs", "packaging", "pyparsing", + ], + unittest.mock.ANY, + ) +@@ -77,7 +79,8 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase): + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", +- unittest.mock.ANY, "--upgrade", "setuptools", "pip", ++ unittest.mock.ANY, "--upgrade", ++ "setuptools", "pip", "six", "appdirs", "packaging", "pyparsing", + ], + unittest.mock.ANY, + ) +@@ -88,7 +91,8 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase): + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", +- unittest.mock.ANY, "-v", "setuptools", "pip", ++ unittest.mock.ANY, "-v", ++ "setuptools", "pip", "six", "appdirs", "packaging", "pyparsing", + ], + unittest.mock.ANY, + ) +@@ -99,7 +103,8 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase): + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", +- unittest.mock.ANY, "-vv", "setuptools", "pip", ++ unittest.mock.ANY, "-vv", ++ "setuptools", "pip", "six", "appdirs", "packaging", "pyparsing", + ], + unittest.mock.ANY, + ) +@@ -110,7 +115,8 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase): + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", +- unittest.mock.ANY, "-vvv", "setuptools", "pip", ++ unittest.mock.ANY, "-vvv", ++ "setuptools", "pip", "six", "appdirs", "packaging", "pyparsing", + ], + unittest.mock.ANY, + ) +@@ -186,8 +192,8 @@ class TestUninstall(EnsurepipMixin, unittest.TestCase): + + self.run_pip.assert_called_once_with( + [ +- "uninstall", "-y", "--disable-pip-version-check", "pip", +- "setuptools", ++ "uninstall", "-y", "--disable-pip-version-check", ++ "pyparsing", "packaging", "appdirs", "six", "pip", "setuptools", + ] + ) + +@@ -197,8 +203,8 @@ class TestUninstall(EnsurepipMixin, unittest.TestCase): + + self.run_pip.assert_called_once_with( + [ +- "uninstall", "-y", "--disable-pip-version-check", "-v", "pip", +- "setuptools", ++ "uninstall", "-y", "--disable-pip-version-check", "-v", ++ "pyparsing", "packaging", "appdirs", "six", "pip", "setuptools", + ] + ) + +@@ -208,8 +214,8 @@ class TestUninstall(EnsurepipMixin, unittest.TestCase): + + self.run_pip.assert_called_once_with( + [ +- "uninstall", "-y", "--disable-pip-version-check", "-vv", "pip", +- "setuptools", ++ "uninstall", "-y", "--disable-pip-version-check", "-vv", ++ "pyparsing", "packaging", "appdirs", "six", "pip", "setuptools", + ] + ) + +@@ -220,7 +226,7 @@ class TestUninstall(EnsurepipMixin, unittest.TestCase): + self.run_pip.assert_called_once_with( + [ + "uninstall", "-y", "--disable-pip-version-check", "-vvv", +- "pip", "setuptools", ++ "pyparsing", "packaging", "appdirs", "six", "pip", "setuptools", + ] + ) + +@@ -260,13 +266,14 @@ class TestBootstrappingMainFunction(EnsurepipMixin, unittest.TestCase): + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", +- unittest.mock.ANY, "setuptools", "pip", ++ unittest.mock.ANY, ++ "setuptools", "pip", "six", "appdirs", "packaging", "pyparsing", + ], + unittest.mock.ANY, + ) + + additional_paths = self.run_pip.call_args[0][1] +- self.assertEqual(len(additional_paths), 2) ++ self.assertEqual(len(additional_paths), 6) + + class TestUninstallationMainFunction(EnsurepipMixin, unittest.TestCase): + +@@ -284,8 +291,8 @@ class TestUninstallationMainFunction(EnsurepipMixin, unittest.TestCase): + + self.run_pip.assert_called_once_with( + [ +- "uninstall", "-y", "--disable-pip-version-check", "pip", +- "setuptools", ++ "uninstall", "-y", "--disable-pip-version-check", "pyparsing", "packaging", ++ "appdirs", "six", "pip", "setuptools", + ] + ) + diff --git a/python3/00261-use-proper-command-line-parsing-in-_testembed.patch b/python3/00261-use-proper-command-line-parsing-in-_testembed.patch new file mode 100644 index 00000000..49db110a --- /dev/null +++ b/python3/00261-use-proper-command-line-parsing-in-_testembed.patch @@ -0,0 +1,104 @@ +diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py +index 6c3625d..2a53f3d 100644 +--- a/Lib/test/test_capi.py ++++ b/Lib/test/test_capi.py +@@ -385,7 +385,7 @@ class EmbeddingTests(unittest.TestCase): + + def test_subinterps(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: + print() + print(out) +diff --git a/Programs/_testembed.c b/Programs/_testembed.c +index 3968399..a68d4fa 100644 +--- a/Programs/_testembed.c ++++ b/Programs/_testembed.c +@@ -33,7 +33,7 @@ static void print_subinterp(void) + ); + } + +-static void test_repeated_init_and_subinterpreters(void) ++static int test_repeated_init_and_subinterpreters(void) + { + PyThreadState *mainstate, *substate; + #ifdef WITH_THREAD +@@ -70,6 +70,7 @@ static void test_repeated_init_and_subinterpreters(void) + PyEval_RestoreThread(mainstate); + Py_Finalize(); + } ++ return 0; + } + + /***************************************************** +@@ -103,7 +104,7 @@ static void check_stdio_details(const char *encoding, const char * errors) + Py_Finalize(); + } + +-static void test_forced_io_encoding(void) ++static int test_forced_io_encoding(void) + { + /* Check various combinations */ + printf("--- Use defaults ---\n"); +@@ -122,19 +123,51 @@ static void test_forced_io_encoding(void) + printf("Unexpected success calling Py_SetStandardStreamEncoding"); + } + Py_Finalize(); ++ return 0; + } + +-/* Different embedding tests */ +-int main(int argc, char *argv[]) ++/* ********************************************************* ++ * List of test cases and the function that implements it. ++ * ++ * Names are compared case-sensitively with the first ++ * argument. If no match is found, or no first argument was ++ * provided, the names of all test cases are printed and ++ * the exit code will be -1. ++ * ++ * The int returned from test functions is used as the exit ++ * code, and test_capi treats all non-zero exit codes as a ++ * failed test. ++ *********************************************************/ ++struct TestCase + { ++ const char *name; ++ int (*func)(void); ++}; ++ ++static struct TestCase TestCases[] = { ++ { "forced_io_encoding", test_forced_io_encoding }, ++ { "repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters }, ++ { NULL, NULL } ++}; + +- /* TODO: Check the argument string to allow for more test cases */ ++int main(int argc, char *argv[]) ++{ + if (argc > 1) { +- /* For now: assume "forced_io_encoding */ +- test_forced_io_encoding(); +- } else { +- /* Run the original embedding test case by default */ +- test_repeated_init_and_subinterpreters(); ++ for (struct TestCase *tc = TestCases; tc && tc->name; tc++) { ++ if (strcmp(argv[1], tc->name) == 0) ++ return (*tc->func)(); ++ } + } +- return 0; ++ ++ /* No match found, or no test name provided, so display usage */ ++ printf("Python " PY_VERSION " _testembed executable for embedded interpreter tests\n" ++ "Normally executed via 'EmbeddingTests' in Lib/test/test_capi.py\n\n" ++ "Usage: %s TESTNAME\n\nAll available tests:\n", argv[0]); ++ for (struct TestCase *tc = TestCases; tc && tc->name; tc++) { ++ printf(" %s\n", tc->name); ++ } ++ ++ /* Non-zero exit code will cause test_capi.py tests to fail. ++ This is intentional. */ ++ return -1; + } diff --git a/python3/00262-pep538_coerce_legacy_c_locale.patch b/python3/00262-pep538_coerce_legacy_c_locale.patch new file mode 100644 index 00000000..462f2aa2 --- /dev/null +++ b/python3/00262-pep538_coerce_legacy_c_locale.patch @@ -0,0 +1,683 @@ +diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst +index 195f63f..0d0a127 100644 +--- a/Doc/using/cmdline.rst ++++ b/Doc/using/cmdline.rst +@@ -713,6 +713,40 @@ conflict. + + .. versionadded:: 3.6 + ++ ++.. envvar:: PYTHONCOERCECLOCALE ++ ++ If set to the value ``0``, causes the main Python command line application ++ to skip coercing the legacy ASCII-based C locale to a more capable UTF-8 ++ based alternative. Note that this setting is checked even when the ++ :option:`-E` or :option:`-I` options are used, as it is handled prior to ++ the processing of command line options. ++ ++ If this variable is *not* set, or is set to a value other than ``0``, and ++ the current locale reported for the ``LC_CTYPE`` category is the default ++ ``C`` locale, then the Python CLI will attempt to configure one of the ++ following locales for the given locale categories before loading the ++ interpreter runtime: ++ ++ * ``C.UTF-8`` (``LC_ALL``) ++ * ``C.utf8`` (``LC_ALL``) ++ * ``UTF-8`` (``LC_CTYPE``) ++ ++ If setting one of these locale categories succeeds, then the matching ++ environment variables will be set (both ``LC_ALL`` and ``LANG`` for the ++ ``LC_ALL`` category, and ``LC_CTYPE`` for the ``LC_CTYPE`` category) in ++ the current process environment before the Python runtime is initialized. ++ ++ Configuring one of these locales (either explicitly or via the above ++ implicit locale coercion) will automatically set the error handler for ++ :data:`sys.stdin` and :data:`sys.stdout` to ``surrogateescape``. This ++ behavior can be overridden using :envvar:`PYTHONIOENCODING` as usual. ++ ++ Availability: \*nix ++ ++ .. versionadded:: 3.7 ++ See :pep:`538` for more details. ++ + Debug-mode variables + ~~~~~~~~~~~~~~~~~~~~ + +diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py +index ca5f9c2..7aa460b 100644 +--- a/Lib/test/support/script_helper.py ++++ b/Lib/test/support/script_helper.py +@@ -51,8 +51,35 @@ def interpreter_requires_environment(): + return __cached_interp_requires_environment + + +-_PythonRunResult = collections.namedtuple("_PythonRunResult", +- ("rc", "out", "err")) ++class _PythonRunResult(collections.namedtuple("_PythonRunResult", ++ ("rc", "out", "err"))): ++ """Helper for reporting Python subprocess run results""" ++ def fail(self, cmd_line): ++ """Provide helpful details about failed subcommand runs""" ++ # Limit to 80 lines to ASCII characters ++ maxlen = 80 * 100 ++ out, err = self.out, self.err ++ if len(out) > maxlen: ++ out = b'(... truncated stdout ...)' + out[-maxlen:] ++ if len(err) > maxlen: ++ err = b'(... truncated stderr ...)' + err[-maxlen:] ++ out = out.decode('ascii', 'replace').rstrip() ++ err = err.decode('ascii', 'replace').rstrip() ++ raise AssertionError("Process return code is %d\n" ++ "command line: %r\n" ++ "\n" ++ "stdout:\n" ++ "---\n" ++ "%s\n" ++ "---\n" ++ "\n" ++ "stderr:\n" ++ "---\n" ++ "%s\n" ++ "---" ++ % (self.rc, cmd_line, ++ out, ++ err)) + + + # Executing the interpreter in a subprocess +@@ -110,30 +137,7 @@ def run_python_until_end(*args, **env_vars): + def _assert_python(expected_success, *args, **env_vars): + res, cmd_line = run_python_until_end(*args, **env_vars) + if (res.rc and expected_success) or (not res.rc and not expected_success): +- # Limit to 80 lines to ASCII characters +- maxlen = 80 * 100 +- out, err = res.out, res.err +- if len(out) > maxlen: +- out = b'(... truncated stdout ...)' + out[-maxlen:] +- if len(err) > maxlen: +- err = b'(... truncated stderr ...)' + err[-maxlen:] +- out = out.decode('ascii', 'replace').rstrip() +- err = err.decode('ascii', 'replace').rstrip() +- raise AssertionError("Process return code is %d\n" +- "command line: %r\n" +- "\n" +- "stdout:\n" +- "---\n" +- "%s\n" +- "---\n" +- "\n" +- "stderr:\n" +- "---\n" +- "%s\n" +- "---" +- % (res.rc, cmd_line, +- out, +- err)) ++ res.fail(cmd_line) + return res + + def assert_python_ok(*args, **env_vars): +diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py +index 2a53f3d..391ca15 100644 +--- a/Lib/test/test_capi.py ++++ b/Lib/test/test_capi.py +@@ -369,14 +369,15 @@ 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) + 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,7 +387,7 @@ class EmbeddingTests(unittest.TestCase): + def test_subinterps(self): + # This is just a "don't crash" test + out, err = self.run_embedded_interpreter("repeated_init_and_subinterpreters") +- if support.verbose: ++ if support.verbose > 1: + print() + print(out) + print(err) +@@ -403,13 +404,14 @@ class EmbeddingTests(unittest.TestCase): + + def test_forced_io_encoding(self): + # Checks forced configuration of embedded interpreter IO streams +- out, err = self.run_embedded_interpreter("forced_io_encoding") +- if support.verbose: ++ env = {"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_errors = "surrogateescape" ++ expected_stdin_encoding = "UTF-8" + expected_pipe_encoding = self._get_default_pipe_encoding() + expected_output = '\n'.join([ + "--- Use defaults ---", +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 + env['LC_ALL'] = 'C' ++ env['PYTHONCOERCECLOCALE'] = '0' + code = ( + 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 +--- a/Lib/test/test_sys.py ++++ b/Lib/test/test_sys.py +@@ -680,6 +680,7 @@ class SysModuleTest(unittest.TestCase): + # Force the POSIX locale + env = os.environ.copy() + env["LC_ALL"] = "C" ++ env["PYTHONCOERCECLOCALE"] = "0" + code = '\n'.join(( + 'import sys', + 'def dump(name):', +diff --git a/Programs/_testembed.c b/Programs/_testembed.c +index a68d4fa..e28de1c 100644 +--- a/Programs/_testembed.c ++++ b/Programs/_testembed.c +@@ -1,4 +1,5 @@ +-#include ++#include "Python.h" ++#include "pyconfig.h" + #include + + /********************************************************* +@@ -126,6 +127,20 @@ static int test_forced_io_encoding(void) + return 0; + } + ++static int test_c_locale_warning(void) ++{ ++#ifdef PY_WARN_ON_C_LOCALE ++ /* Force use of the C locale */ ++ setenv("LC_ALL", "C", 1); ++ ++ _testembed_Py_Initialize(); ++ Py_Finalize(); ++#else ++ printf("C locale compatibility warning disabled at compile time\n"); ++#endif ++ return 0; ++} ++ + /* ********************************************************* + * List of test cases and the function that implements it. + * +@@ -147,6 +162,7 @@ struct TestCase + static struct TestCase TestCases[] = { + { "forced_io_encoding", test_forced_io_encoding }, + { "repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters }, ++ { "c_locale_warning", test_c_locale_warning }, + { NULL, NULL } + }; + +diff --git a/Programs/python.c b/Programs/python.c +index a7afbc7..03f8295 100644 +--- a/Programs/python.c ++++ b/Programs/python.c +@@ -15,6 +15,21 @@ wmain(int argc, wchar_t **argv) + } + #else + ++/* Access private pylifecycle helper API to better handle the legacy C locale ++ * ++ * The legacy C locale assumes ASCII as the default text encoding, which ++ * causes problems not only for the CPython runtime, but also other ++ * components like GNU readline. ++ * ++ * Accordingly, when the CLI detects it, it attempts to coerce it to a ++ * more capable UTF-8 based alternative. ++ * ++ * See the documentation of the PYTHONCOERCECLOCALE setting for more details. ++ * ++ */ ++extern int _Py_LegacyLocaleDetected(void); ++extern void _Py_CoerceLegacyLocale(void); ++ + int + main(int argc, char **argv) + { +@@ -25,7 +40,11 @@ main(int argc, char **argv) + char *oldloc; + + /* Force malloc() allocator to bootstrap Python */ ++#ifdef Py_DEBUG ++ (void)_PyMem_SetupAllocators("malloc_debug"); ++# else + (void)_PyMem_SetupAllocators("malloc"); ++# endif + + argv_copy = (wchar_t **)PyMem_RawMalloc(sizeof(wchar_t*) * (argc+1)); + argv_copy2 = (wchar_t **)PyMem_RawMalloc(sizeof(wchar_t*) * (argc+1)); +@@ -49,7 +68,21 @@ main(int argc, char **argv) + return 1; + } + ++#ifdef __ANDROID__ ++ /* Passing "" to setlocale() on Android requests the C locale rather ++ * than checking environment variables, so request C.UTF-8 explicitly ++ */ ++ setlocale(LC_ALL, "C.UTF-8"); ++#else ++ /* Reconfigure the locale to the default for this process */ + setlocale(LC_ALL, ""); ++#endif ++ ++ if (_Py_LegacyLocaleDetected()) { ++ _Py_CoerceLegacyLocale(); ++ } ++ ++ /* Convert from char to wchar_t based on the locale settings */ + for (i = 0; i < argc; i++) { + argv_copy[i] = Py_DecodeLocale(argv[i], NULL); + if (!argv_copy[i]) { +@@ -70,7 +103,11 @@ main(int argc, char **argv) + + /* Force again malloc() allocator to release memory blocks allocated + before Py_Main() */ ++#ifdef Py_DEBUG ++ (void)_PyMem_SetupAllocators("malloc_debug"); ++# else + (void)_PyMem_SetupAllocators("malloc"); ++# endif + + for (i = 0; i < argc; i++) { + PyMem_RawFree(argv_copy2[i]); +diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c +index a4f7f82..261ed34 100644 +--- a/Python/pylifecycle.c ++++ b/Python/pylifecycle.c +@@ -167,6 +167,7 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors) + return 0; + } + ++ + /* Global initializations. Can be undone by Py_FinalizeEx(). Don't + call this twice without an intervening Py_FinalizeEx() call. When + initializations fail, a fatal error is issued and the function does +@@ -301,6 +302,173 @@ import_init(PyInterpreterState *interp, PyObject *sysmod) + } + + ++/* Helper functions to better handle the legacy C locale ++ * ++ * The legacy C locale assumes ASCII as the default text encoding, which ++ * causes problems not only for the CPython runtime, but also other ++ * components like GNU readline. ++ * ++ * Accordingly, when the CLI detects it, it attempts to coerce it to a ++ * more capable UTF-8 based alternative as follows: ++ * ++ * if (_Py_LegacyLocaleDetected()) { ++ * _Py_CoerceLegacyLocale(); ++ * } ++ * ++ * See the documentation of the PYTHONCOERCECLOCALE setting for more details. ++ * ++ * Locale coercion also impacts the default error handler for the standard ++ * streams: while the usual default is "strict", the default for the legacy ++ * C locale and for any of the coercion target locales is "surrogateescape". ++ */ ++ ++int ++_Py_LegacyLocaleDetected(void) ++{ ++ const char *ctype_loc = setlocale(LC_CTYPE, NULL); ++ return ctype_loc != NULL && strcmp(ctype_loc, "C") == 0; ++} ++ ++typedef struct _CandidateLocale { ++ const char *locale_name; ++ int category; ++} _LocaleCoercionTarget; ++ ++static _LocaleCoercionTarget _TARGET_LOCALES[] = { ++ { "C.UTF-8", LC_ALL }, ++ { "C.utf8", LC_ALL }, ++ { "UTF-8", LC_CTYPE }, ++ { NULL, 0 } ++}; ++ ++static char * ++get_default_standard_stream_error_handler(void) ++{ ++ const char *ctype_loc = setlocale(LC_CTYPE, NULL); ++ if (ctype_loc != NULL) { ++ /* "surrogateescape" is the default in the legacy C locale */ ++ if (strcmp(ctype_loc, "C") == 0) { ++ return "surrogateescape"; ++ } ++ ++ /* "surrogateescape" is the default in locale coercion target locales */ ++ const _LocaleCoercionTarget *target = NULL; ++ for (target = _TARGET_LOCALES; target->locale_name; target++) { ++ if (strcmp(ctype_loc, target->locale_name) == 0) { ++ return "surrogateescape"; ++ } ++ } ++ } ++ ++ /* Otherwise return NULL to request the typical default error handler */ ++ return NULL; ++} ++ ++#ifdef PY_COERCE_C_LOCALE ++static const char *_C_LOCALE_COERCION_WARNING = ++ "Python detected LC_CTYPE=C: %.20s coerced to %.20s (set another locale " ++ "or PYTHONCOERCECLOCALE=0 to disable this locale coercion behavior).\n"; ++ ++static void ++_coerce_default_locale_settings(const _LocaleCoercionTarget *target) ++{ ++ const char *newloc = target->locale_name; ++ int category = target->category; ++ ++ /* Reset locale back to currently configured defaults */ ++ setlocale(LC_ALL, ""); ++ ++ /* Set the relevant locale environment variables */ ++ if (category == LC_ALL) { ++ const char *env_vars_updated = "LC_ALL & LANG"; ++ if (setenv("LC_ALL", newloc, 1)) { ++ fprintf(stderr, ++ "Error setting LC_ALL, skipping C locale coercion\n"); ++ return; ++ } ++ if (setenv("LANG", newloc, 1)) { ++ fprintf(stderr, ++ "Error setting LANG during C locale coercion\n"); ++ env_vars_updated = "LC_ALL"; ++ } ++ fprintf(stderr, _C_LOCALE_COERCION_WARNING, env_vars_updated, newloc); ++ } else if (category == LC_CTYPE) { ++ if (setenv("LC_CTYPE", newloc, 1)) { ++ fprintf(stderr, ++ "Error setting LC_CTYPE, skipping C locale coercion\n"); ++ return; ++ } ++ fprintf(stderr, _C_LOCALE_COERCION_WARNING, "LC_CTYPE", newloc); ++ } else { ++ fprintf(stderr, "Locale coercion must target LC_ALL or LC_CTYPE\n"); ++ return; ++ } ++ ++ /* Reconfigure with the overridden environment variables */ ++ setlocale(LC_ALL, ""); ++} ++ ++static int ++c_locale_coercion_is_expected(void) ++{ ++ /* This may be called prior to Py_Initialize, so we don't call any other ++ * Python APIs, and we ignore the -E and -I flags ++ */ ++ const char *coerce_c_locale = getenv("PYTHONCOERCECLOCALE"); ++ if (coerce_c_locale == NULL || strncmp(coerce_c_locale, "0", 2) != 0) { ++ return 1; ++ } ++ return 0; ++} ++#endif ++ ++void ++_Py_CoerceLegacyLocale(void) ++{ ++#ifdef PY_COERCE_C_LOCALE ++ /* We ignore the Python -E and -I flags here, as the CLI needs to sort out ++ * the locale settings *before* we try to do anything with the command ++ * line arguments. For cross-platform debugging purposes, we also need ++ * to give end users a way to force even scripts that are otherwise ++ * isolated from their environment to use the legacy ASCII-centric C ++ * locale. ++ */ ++ if (c_locale_coercion_is_expected()) { ++ /* PYTHONCOERCECLOCALE is not set, or is not set to exactly "0" */ ++ const _LocaleCoercionTarget *target = NULL; ++ for (target = _TARGET_LOCALES; target->locale_name; target++) { ++ const char *reconfigured_locale = setlocale(target->category, ++ target->locale_name); ++ if (reconfigured_locale != NULL) { ++ /* Successfully configured locale, so make it the default */ ++ _coerce_default_locale_settings(target); ++ return; ++ } ++ } ++ } ++ /* No C locale warning here, as Py_Initialize will emit one later */ ++#endif ++} ++ ++ ++#ifdef PY_WARN_ON_C_LOCALE ++static const char *_C_LOCALE_WARNING = ++ "Python runtime initialized with LC_CTYPE=C (a locale with default ASCII " ++ "encoding), which may cause Unicode compatibility problems. Using C.UTF-8, " ++ "C.utf8, or UTF-8 (if available) as alternative Unicode-compatible " ++ "locales is recommended.\n"; ++ ++static void ++_emit_stderr_warning_for_c_locale(void) ++{ ++ if (c_locale_coercion_is_expected()) { ++ if (_Py_LegacyLocaleDetected()) { ++ fprintf(stderr, "%s", _C_LOCALE_WARNING); ++ } ++ } ++} ++#endif ++ + void + _Py_InitializeEx_Private(int install_sigs, int install_importlib) + { +@@ -315,11 +483,19 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) + initialized = 1; + _Py_Finalizing = NULL; + +-#ifdef HAVE_SETLOCALE ++#ifdef __ANDROID__ ++ /* Passing "" to setlocale() on Android requests the C locale rather ++ * than checking environment variables, so request C.UTF-8 explicitly ++ */ ++ setlocale(LC_CTYPE, "C.UTF-8"); ++#else + /* Set up the LC_CTYPE locale, so we can obtain + the locale's charset without having to switch + locales. */ + setlocale(LC_CTYPE, ""); ++#ifdef PY_WARN_ON_C_LOCALE ++ _emit_stderr_warning_for_c_locale(); ++#endif + #endif + + if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0') +@@ -1242,12 +1418,8 @@ initstdio(void) + } + } + if (!errors && !(pythonioencoding && *pythonioencoding)) { +- /* When the LC_CTYPE locale is the POSIX locale ("C locale"), +- stdin and stdout use the surrogateescape error handler by +- default, instead of the strict error handler. */ +- char *loc = setlocale(LC_CTYPE, NULL); +- if (loc != NULL && strcmp(loc, "C") == 0) +- errors = "surrogateescape"; ++ /* Choose the default error handler based on the current locale */ ++ errors = get_default_standard_stream_error_handler(); + } + } + +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 +--- a/configure.ac ++++ b/configure.ac +@@ -3279,6 +3279,40 @@ then + fi + AC_MSG_RESULT($with_pymalloc) + ++# Check for --with-c-locale-coercion ++AC_MSG_CHECKING(for --with-c-locale-coercion) ++AC_ARG_WITH(c-locale-coercion, ++ AS_HELP_STRING([--with(out)-c-locale-coercion], ++ [disable/enable C locale coercion to a UTF-8 based locale])) ++ ++if test -z "$with_c_locale_coercion" ++then ++ with_c_locale_coercion="yes" ++fi ++if test "$with_c_locale_coercion" != "no" ++then ++ AC_DEFINE(PY_COERCE_C_LOCALE, 1, ++ [Define if you want to coerce the C locale to a UTF-8 based locale]) ++fi ++AC_MSG_RESULT($with_c_locale_coercion) ++ ++# Check for --with-c-locale-warning ++AC_MSG_CHECKING(for --with-c-locale-warning) ++AC_ARG_WITH(c-locale-warning, ++ AS_HELP_STRING([--with(out)-c-locale-warning], ++ [disable/enable locale compatibility warning in the C locale])) ++ ++if test -z "$with_c_locale_warning" ++then ++ with_c_locale_warning="yes" ++fi ++if test "$with_c_locale_warning" != "no" ++then ++ AC_DEFINE(PY_WARN_ON_C_LOCALE, 1, ++ [Define to emit a locale compatibility warning in the C locale]) ++fi ++AC_MSG_RESULT($with_c_locale_warning) ++ + # 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 + diff --git a/python3/00264-skip-test-failing-on-aarch64.patch b/python3/00264-skip-test-failing-on-aarch64.patch new file mode 100644 index 00000000..edda219b --- /dev/null +++ b/python3/00264-skip-test-failing-on-aarch64.patch @@ -0,0 +1,12 @@ +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): diff --git a/python3/003-3.4-tkinter-cygwin.patch b/python3/003-3.4-tkinter-cygwin.patch index 675e0ec3..9b116dd6 100644 --- a/python3/003-3.4-tkinter-cygwin.patch +++ b/python3/003-3.4-tkinter-cygwin.patch @@ -1,6 +1,6 @@ --- Python-3.4.3/setup.py.orig 2015-02-25 05:27:46.000000000 -0600 +++ Python-3.4.3/setup.py 2015-05-05 11:18:04.030880000 -0500 -@@ -1763,12 +1772,6 @@ class PyBuildExt(build_ext): +@@ -1849,12 +1849,6 @@ class PyBuildExt(build_ext): include_dirs.append('/usr/X11/include') added_lib_dirs.append('/usr/X11/lib') @@ -13,7 +13,7 @@ # Check for BLT extension if self.compiler.find_library_file(lib_dirs + added_lib_dirs, 'BLT8.0'): -@@ -1786,9 +1789,8 @@ class PyBuildExt(build_ext): +@@ -1872,9 +1866,8 @@ class PyBuildExt(build_ext): if host_platform in ['aix3', 'aix4']: libs.append('ld') diff --git a/python3/004-3.4-ctypes-cygwin.patch b/python3/004-3.4-ctypes-cygwin.patch index a4afb787..7da657bb 100644 --- a/python3/004-3.4-ctypes-cygwin.patch +++ b/python3/004-3.4-ctypes-cygwin.patch @@ -1,7 +1,7 @@ --- Python-3.4.3/Lib/ctypes/__init__.py.orig 2015-02-25 05:27:44.000000000 -0600 +++ Python-3.4.3/Lib/ctypes/__init__.py 2015-05-05 11:39:39.945940300 -0500 -@@ -434,7 +434,8 @@ pydll = LibraryLoader(PyDLL) - if _os.name in ("nt", "ce"): +@@ -431,7 +431,8 @@ pydll = LibraryLoader(PyDLL) + if _os.name == "nt": pythonapi = PyDLL("python dll", None, _sys.dllhandle) elif _sys.platform == "cygwin": - pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2]) @@ -12,7 +12,7 @@ --- Python-3.4.3/Lib/ctypes/util.py.orig 2015-02-25 05:27:44.000000000 -0600 +++ Python-3.4.3/Lib/ctypes/util.py 2015-05-05 11:10:45.202655900 -0500 -@@ -83,6 +83,25 @@ if os.name == "posix" and sys.platform = +@@ -80,6 +80,25 @@ if os.name == "posix" and sys.platform = continue return None @@ -38,7 +38,7 @@ elif os.name == "posix": # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump import re, tempfile -@@ -258,6 +277,10 @@ def test(): +@@ -328,6 +347,10 @@ def test(): print(cdll.LoadLibrary("libcrypto.dylib")) print(cdll.LoadLibrary("libSystem.dylib")) print(cdll.LoadLibrary("System.framework/System")) diff --git a/python3/005-3.1-PATH_MAX.patch b/python3/005-3.1-PATH_MAX.patch deleted file mode 100644 index a25235a6..00000000 --- a/python3/005-3.1-PATH_MAX.patch +++ /dev/null @@ -1,16 +0,0 @@ -Avoid redefine error. - ---- Python-3.1/Modules/main.c.orig 2009-02-12 09:55:38.000000000 -0600 -+++ Python-3.1/Modules/main.c 2009-07-22 22:50:19.981100800 -0500 -@@ -14,9 +14,11 @@ - #include - #ifdef HAVE_FCNTL_H - #include -+#ifndef PATH_MAX - #define PATH_MAX MAXPATHLEN - #endif - #endif -+#endif - - #ifdef _MSC_VER - #include diff --git a/python3/005-3.6-PATH_MAX.patch b/python3/005-3.6-PATH_MAX.patch new file mode 100644 index 00000000..b9903c1c --- /dev/null +++ b/python3/005-3.6-PATH_MAX.patch @@ -0,0 +1,12 @@ +--- Python-3.6.0/Modules/main.c.orig 2017-02-08 04:28:31.840450700 -0500 ++++ Python-3.6.0/Modules/main.c 2017-02-08 04:31:01.757513100 -0500 +@@ -12,6 +12,9 @@ + #endif + #ifdef HAVE_FCNTL_H + #include ++#ifndef PATH_MAX ++#define PATH_MAX MAXPATHLEN ++#endif + #endif + #endif + diff --git a/python3/007-3.2-export-PySignal_SetWakeupFd.patch b/python3/007-3.2-export-PySignal_SetWakeupFd.patch index ec6aeb25..70dd247a 100644 --- a/python3/007-3.2-export-PySignal_SetWakeupFd.patch +++ b/python3/007-3.2-export-PySignal_SetWakeupFd.patch @@ -1,6 +1,6 @@ --- Python-3.2/Include/pyerrors.h.orig +++ Python-3.2/Include/pyerrors.h -@@ -244,7 +244,7 @@ PyAPI_FUNC(int) PyErr_CheckSignals(void) +@@ -358,7 +358,7 @@ PyAPI_FUNC(int) PyErr_CheckSignals(void) /* In signalmodule.c */ #ifndef Py_LIMITED_API diff --git a/python3/008-3.4-distutils-soname.patch b/python3/008-3.4-distutils-soname.patch index 179e1ab4..cf1a7b7a 100644 --- a/python3/008-3.4-distutils-soname.patch +++ b/python3/008-3.4-distutils-soname.patch @@ -1,6 +1,6 @@ --- Python-3.4.3/Lib/distutils/command/build_ext.py.orig 2015-02-25 05:27:44.000000000 -0600 +++ Python-3.4.3/Lib/distutils/command/build_ext.py 2015-05-05 11:15:40.666175000 -0500 -@@ -696,9 +696,9 @@ class build_ext(Command): +@@ -716,9 +716,9 @@ class build_ext(Command): else: return ext.libraries elif sys.platform[:6] == "cygwin": @@ -14,7 +14,7 @@ return ext.libraries + [pythonlib] --- Python-3.4.3/Makefile.pre.in.orig 2015-02-25 05:27:45.000000000 -0600 +++ Python-3.4.3/Makefile.pre.in 2015-05-05 11:15:40.672175700 -0500 -@@ -638,7 +638,7 @@ $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION +@@ -674,7 +674,7 @@ $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION # This rule builds the Cygwin Python DLL and import library if configured # for a shared core library; otherwise, this rule is a noop. @@ -25,7 +25,7 @@ $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST); \ --- Python-3.4.3/Modules/makesetup.orig 2015-02-25 05:27:46.000000000 -0600 +++ Python-3.4.3/Modules/makesetup 2015-05-05 11:15:40.676676300 -0500 -@@ -91,7 +91,7 @@ CYGWIN*) if test $libdir = . +@@ -92,7 +92,7 @@ CYGWIN*) if test $libdir = . else ExtraLibDir='$(LIBPL)' fi @@ -36,7 +36,7 @@ # Main loop --- Python-3.4.3/configure.ac.orig 2015-02-25 05:27:46.000000000 -0600 +++ Python-3.4.3/configure.ac 2015-05-05 11:24:25.915873200 -0500 -@@ -944,6 +944,7 @@ if test $enable_shared = "yes"; then +@@ -1144,6 +1144,7 @@ if test $enable_shared = "yes"; then case $ac_sys_system in CYGWIN*) LDLIBRARY='libpython$(LDVERSION).dll.a' diff --git a/python3/009-3.2-distutils-shlibext.patch b/python3/009-3.2-distutils-shlibext.patch index 7275449b..9fb2697d 100644 --- a/python3/009-3.2-distutils-shlibext.patch +++ b/python3/009-3.2-distutils-shlibext.patch @@ -3,7 +3,7 @@ an implib but no static lib (e.g. sqlite3). --- Python-3.2.3/Lib/distutils/cygwinccompiler.py.orig 2012-04-11 01:54:02.000000000 -0500 +++ Python-3.2.3/Lib/distutils/cygwinccompiler.py 2012-06-22 19:37:11.740576800 -0500 -@@ -88,9 +88,7 @@ class CygwinCCompiler(UnixCCompiler): +@@ -92,9 +92,7 @@ class CygwinCCompiler(UnixCCompiler): compiler_type = 'cygwin' obj_extension = ".o" static_lib_extension = ".a" @@ -16,8 +16,8 @@ an implib but no static lib (e.g. sqlite3). def __init__(self, verbose=0, dry_run=0, force=0): --- Python-3.2.5/Lib/distutils/unixccompiler.py.orig 2013-07-30 16:39:21.092550800 -0500 +++ Python-3.2.5/Lib/distutils/unixccompiler.py 2013-07-30 20:01:52.168552600 -0500 -@@ -79,6 +79,7 @@ class UnixCCompiler(CCompiler): - static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s" +@@ -81,6 +81,7 @@ class UnixCCompiler(CCompiler): + xcode_stub_lib_format = dylib_lib_format if sys.platform == "cygwin": exe_extension = ".exe" + dylib_lib_extension = ".dll.a" diff --git a/python3/010-3.4-pep3149-cygwin.patch b/python3/010-3.6-pep3149-cygwin.patch similarity index 68% rename from python3/010-3.4-pep3149-cygwin.patch rename to python3/010-3.6-pep3149-cygwin.patch index 2b547e93..685ec1e0 100644 --- a/python3/010-3.4-pep3149-cygwin.patch +++ b/python3/010-3.6-pep3149-cygwin.patch @@ -9,14 +9,14 @@ ".dll", #else /* !__CYGWIN__ */ "." SOABI ".so", ---- Python-3.4.3/configure.ac.orig 2015-02-25 05:27:46.000000000 -0600 -+++ Python-3.4.3/configure.ac 2015-05-05 11:24:25.915873200 -0500 -@@ -4096,7 +4097,7 @@ AC_MSG_RESULT($SOABI) +--- Python-3.6.0/configure.ac.orig 2017-02-08 04:39:39.793333600 -0500 ++++ Python-3.6.0/configure.ac 2017-02-08 04:45:44.649752400 -0500 +@@ -4614,7 +4614,7 @@ AC_SUBST(EXT_SUFFIX) case $ac_sys_system in -- Linux*|GNU*) -+ Linux*|GNU*|CYGWIN*) +- Linux*|GNU*|Darwin) ++ Linux*|GNU*|Darwin|CYGWIN*) EXT_SUFFIX=.${SOABI}${SHLIB_SUFFIX};; *) EXT_SUFFIX=${SHLIB_SUFFIX};; diff --git a/python3/011-3.4-thread-cygwin64.patch b/python3/011-3.6-thread-cygwin64.patch similarity index 50% rename from python3/011-3.4-thread-cygwin64.patch rename to python3/011-3.6-thread-cygwin64.patch index 2725086e..e3dcc21f 100644 --- a/python3/011-3.4-thread-cygwin64.patch +++ b/python3/011-3.6-thread-cygwin64.patch @@ -1,7 +1,7 @@ --- Python-3.4.3/Include/pythread.h.orig 2015-02-25 05:27:44.000000000 -0600 +++ Python-3.4.3/Include/pythread.h 2015-05-05 11:27:20.117994100 -0500 -@@ -77,11 +77,11 @@ PyAPI_FUNC(int) PyThread_set_stacksize(s - PyAPI_FUNC(PyObject*) PyThread_GetInfo(void); +@@ -74,11 +74,11 @@ PyAPI_FUNC(int) PyThread_set_stacksize(s + #endif /* Thread Local Storage (TLS) API */ -PyAPI_FUNC(int) PyThread_create_key(void); @@ -17,20 +17,38 @@ /* Cleanup after a fork */ PyAPI_FUNC(void) PyThread_ReInitTLS(void); ---- Python-3.4.3/Python/pystate.c.orig 2015-02-25 05:27:46.000000000 -0600 -+++ Python-3.4.3/Python/pystate.c 2015-05-05 11:27:20.122994700 -0500 -@@ -37,7 +37,7 @@ static PyThread_type_lock head_mutex = N +--- Python-3.6.0/Python/pystate.c.orig 2017-02-08 04:54:10.265051500 -0500 ++++ Python-3.6.0/Python/pystate.c 2017-02-08 05:00:43.539089400 -0500 +@@ -47,7 +47,7 @@ GILState implementation */ static PyInterpreterState *autoInterpreterState = NULL; --static int autoTLSkey = 0; -+static long autoTLSkey = 0L; +-static int autoTLSkey = -1; ++static long autoTLSkey = -1L; #else #define HEAD_INIT() /* Nothing */ #define HEAD_LOCK() /* Nothing */ ---- Python-3.4.3/Python/thread_pthread.h.orig 2015-02-25 05:27:46.000000000 -0600 -+++ Python-3.4.3/Python/thread_pthread.h 2015-05-05 11:27:20.126495200 -0500 -@@ -603,28 +603,28 @@ _pythread_pthread_set_stacksize(size_t s +@@ -713,7 +713,7 @@ _PyGILState_Init(PyInterpreterState *i, + { + assert(i && t); /* must init with valid states */ + autoTLSkey = PyThread_create_key(); +- if (autoTLSkey == -1) ++ if (autoTLSkey == -1L) + Py_FatalError("Could not allocate TLS entry"); + autoInterpreterState = i; + assert(PyThread_get_key_value(autoTLSkey) == NULL); +@@ -745,7 +745,7 @@ _PyGILState_Reinit(void) + { + PyThreadState *tstate = PyGILState_GetThisThreadState(); + PyThread_delete_key(autoTLSkey); +- if ((autoTLSkey = PyThread_create_key()) == -1) ++ if ((autoTLSkey = PyThread_create_key()) == -1L) + Py_FatalError("Could not allocate TLS entry"); + + /* If the thread had an associated auto thread state, reassociate it with +--- Python-3.6.0/Python/thread_pthread.h.orig 2016-12-22 21:21:22.000000000 -0500 ++++ Python-3.6.0/Python/thread_pthread.h 2017-02-08 05:18:45.791168100 -0500 +@@ -603,36 +603,36 @@ #define Py_HAVE_NATIVE_TLS @@ -40,8 +58,19 @@ { pthread_key_t key; int fail = pthread_key_create(&key, NULL); -- return fail ? -1 : key; -+ return fail ? -1L : (long) key; + if (fail) +- return -1; +- if (key > INT_MAX) { ++ return -1L; ++ if (key > LONG_MAX) { + /* Issue #22206: handle integer overflow */ + pthread_key_delete(key); + errno = ENOMEM; +- return -1; ++ return -1L; + } +- return (int)key; ++ return (long)key; } void @@ -64,7 +93,7 @@ { int fail; fail = pthread_setspecific(key, value); -@@ -632,7 +632,7 @@ PyThread_set_key_value(int key, void *va +@@ -640,7 +640,7 @@ PyThread_set_key_value(int key, void *va } void * diff --git a/python3/012-3.2-getpath-exe-extension.patch b/python3/012-3.2-getpath-exe-extension.patch index b1ae18eb..ebd43f97 100644 --- a/python3/012-3.2-getpath-exe-extension.patch +++ b/python3/012-3.2-getpath-exe-extension.patch @@ -1,6 +1,6 @@ --- Python-3.2.3/Modules/getpath.c.orig 2012-04-11 02:54:07.000000000 -0400 +++ Python-3.2.3/Modules/getpath.c 2012-06-14 13:33:30.179375000 -0400 -@@ -491,6 +491,28 @@ +@@ -551,6 +551,28 @@ if (isxfile(progpath)) break; diff --git a/python3/013-3.4-select-cygwin.patch b/python3/013-3.4-select-cygwin.patch index b2063e75..48686858 100644 --- a/python3/013-3.4-select-cygwin.patch +++ b/python3/013-3.4-select-cygwin.patch @@ -1,8 +1,8 @@ --- Python-3.4.3/Modules/selectmodule.c.orig 2015-02-25 05:27:46.000000000 -0600 +++ Python-3.4.3/Modules/selectmodule.c 2015-05-05 13:58:58.914394500 -0500 -@@ -4,6 +4,16 @@ - have any value except INVALID_SOCKET. - */ +@@ -8,6 +8,16 @@ + #define _GNU_SOURCE + #endif +/* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined. + 64 is too small (too many people have bumped into that limit). @@ -17,7 +17,7 @@ #include "Python.h" #include -@@ -22,16 +32,6 @@ +@@ -26,16 +36,6 @@ #undef HAVE_BROKEN_POLL #endif diff --git a/python3/014-3.4-signal-cygwin.patch b/python3/014-3.4-signal-cygwin.patch index 1fdceab9..4db4fad9 100644 --- a/python3/014-3.4-signal-cygwin.patch +++ b/python3/014-3.4-signal-cygwin.patch @@ -1,6 +1,6 @@ --- Python-3.4.3/Modules/signalmodule.c.orig 2015-02-25 05:27:46.000000000 -0600 +++ Python-3.4.3/Modules/signalmodule.c 2015-05-05 16:10:10.357940900 -0500 -@@ -741,7 +741,11 @@ fill_siginfo(siginfo_t *si) +@@ -957,7 +957,11 @@ fill_siginfo(siginfo_t *si) PyStructSequence_SET_ITEM(result, 4, _PyLong_FromUid(si->si_uid)); PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong((long)(si->si_status))); diff --git a/python3/015-3.4-struct-cygwin.patch b/python3/015-3.4-struct-cygwin.patch index 4205e85a..4380119d 100644 --- a/python3/015-3.4-struct-cygwin.patch +++ b/python3/015-3.4-struct-cygwin.patch @@ -1,6 +1,6 @@ --- Python-3.4.3/Modules/_struct.c.orig 2015-02-25 05:27:45.000000000 -0600 +++ Python-3.4.3/Modules/_struct.c 2015-05-05 16:17:01.509150400 -0500 -@@ -1627,7 +1627,7 @@ unpackiter_iternext(unpackiterobject *se +@@ -1650,7 +1650,7 @@ unpackiter_iternext(unpackiterobject *se } static PyTypeObject unpackiter_type = { diff --git a/python3/016-3.6-mpdec-cygwin.patch b/python3/016-3.6-mpdec-cygwin.patch new file mode 100644 index 00000000..3787d502 --- /dev/null +++ b/python3/016-3.6-mpdec-cygwin.patch @@ -0,0 +1,11 @@ +--- a/setup.py ++++ b/setup.py +@@ -2061,7 +2061,7 @@ class PyBuildExt(build_ext): + undef_macros = [] + if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"): + include_dirs = [] +- libraries = [':libmpdec.so.2'] ++ libraries = [':libmpdec.dll.a'] + sources = ['_decimal/_decimal.c'] + depends = ['_decimal/docstrings.h'] + else: diff --git a/python3/017-3.4-shebang.patch b/python3/017-3.4-shebang.patch deleted file mode 100644 index 8ed092e5..00000000 --- a/python3/017-3.4-shebang.patch +++ /dev/null @@ -1,16 +0,0 @@ ---- Python-3.4.4/Lib/cgi.py 2015-12-21 00:00:58.000000000 -0600 -+++ Python-3.4.4/Lib/cgi.py 2016-05-24 00:33:59.673777200 -0500 -@@ -1,4 +1,4 @@ --#!/usr/bin/python -+#!/usr/bin/python3 - - # NOTE: the above "/usr/local/bin/python" is NOT a mistake. It is - # intentionally NOT "/usr/bin/env python". On many systems ---- Python-3.4.4/Lib/encodings/rot_13.py 2015-12-21 00:00:58.000000000 -0600 -+++ Python-3.4.4/Lib/encodings/rot_13.py 2016-05-24 00:34:13.983796900 -0500 -@@ -1,4 +1,4 @@ --#!/usr/bin/env python -+#!/usr/bin/env python3 - """ Python Character Mapping Codec for ROT13. - - This codec de/encodes from str to str. diff --git a/python3/025-MINGW-compiler-customize-mingw-cygwin-compilers.patch b/python3/025-MINGW-compiler-customize-mingw-cygwin-compilers.patch index e886f230..d2dc8ab4 100644 --- a/python3/025-MINGW-compiler-customize-mingw-cygwin-compilers.patch +++ b/python3/025-MINGW-compiler-customize-mingw-cygwin-compilers.patch @@ -1,7 +1,7 @@ diff -urN a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py --- a/Lib/distutils/sysconfig.py 2014-10-11 14:19:27.487874300 +0100 +++ b/Lib/distutils/sysconfig.py 2014-10-11 14:19:30.049020800 +0100 -@@ -165,7 +165,23 @@ +@@ -156,7 +156,23 @@ Mainly needed on Unix, so we can plug in the information that varies across Unices and is stored in Python's Makefile. """ @@ -26,7 +26,7 @@ diff -urN a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py if sys.platform == "darwin": # Perform first-time customization of compiler-related # config vars on OS X now that we know we need a compiler. -@@ -175,7 +191,6 @@ +@@ -166,7 +182,6 @@ # that Python itself was built on. Also the user OS # version and build tools may not support the same set # of CPU architectures for universal builds. diff --git a/python3/3.6-ftm.patch b/python3/3.6-ftm.patch new file mode 100644 index 00000000..69575fad --- /dev/null +++ b/python3/3.6-ftm.patch @@ -0,0 +1,14 @@ +--- origsrc/Python-3.6.1rc1/configure.ac 2017-03-12 14:28:34.395001700 -0500 ++++ src/Python-3.6.1rc1/configure.ac 2017-03-21 00:27:44.595584900 -0500 +@@ -138,11 +138,6 @@ AC_DEFINE(_GNU_SOURCE, 1, [Define on Lin + AC_DEFINE(_NETBSD_SOURCE, 1, [Define on NetBSD to activate all library features]) + + # The later defininition of _XOPEN_SOURCE and _POSIX_C_SOURCE disables +-# certain features on FreeBSD, so we need __BSD_VISIBLE to re-enable +-# them. +-AC_DEFINE(__BSD_VISIBLE, 1, [Define on FreeBSD to activate all library features]) +- +-# The later defininition of _XOPEN_SOURCE and _POSIX_C_SOURCE disables + # u_int on Irix 5.3. Defining _BSD_TYPES brings it back. + AC_DEFINE(_BSD_TYPES, 1, [Define on Irix to enable u_int]) + diff --git a/python3/3.6-getrandom.patch b/python3/3.6-getrandom.patch new file mode 100644 index 00000000..3c3e93af --- /dev/null +++ b/python3/3.6-getrandom.patch @@ -0,0 +1,19 @@ +getrandom(2) without GRND_RANDOM is broken prior to Cygwin 2.8.0: + +https://sourceware.org/git/?p=newlib-cygwin.git;a=commitdiff;h=6c420fa + +--- origsrc/Python-3.6.1/configure.ac 2017-03-21 21:36:53.153779000 -0500 ++++ src/Python-3.6.1/configure.ac 2017-03-21 21:42:30.270960000 -0500 +@@ -5372,6 +5372,12 @@ AC_MSG_CHECKING(for the getrandom() func + AC_LINK_IFELSE( + [ + AC_LANG_SOURCE([[ ++ #ifdef __CYGWIN__ ++ #include ++ #if CYGWIN_VERSION_DLL_MAJOR < 2008 ++ #error getrandom(2) is broken prior to Cygwin 2.8.0 ++ #endif ++ #endif + #include + + int main() { diff --git a/python3/900-msysize.patch b/python3/900-msysize.patch index 051bafac..1c44f4c8 100644 --- a/python3/900-msysize.patch +++ b/python3/900-msysize.patch @@ -11,10 +11,10 @@ diff -Naur Python-3.4.3-orig/config.guess Python-3.4.3/config.guess p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; -diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac ---- Python-3.4.3-orig/configure.ac 2015-05-07 09:55:44.998000000 +0300 -+++ Python-3.4.3/configure.ac 2015-05-07 09:58:31.825600000 +0300 -@@ -373,6 +373,9 @@ +diff -Naur Python-3.6.0/configure.ac.orig Python-3.6.0/configure.ac +--- Python-3.6.0/configure.ac.orig 2017-02-08 09:14:49.544766100 -0500 ++++ Python-3.6.0/configure.ac 2017-02-08 09:23:26.742594900 -0500 +@@ -383,6 +383,9 @@ *-*-cygwin*) ac_sys_system=Cygwin ;; @@ -24,7 +24,7 @@ diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac *) # for now, limit cross builds to known configurations MACHDEP="unknown" -@@ -397,6 +400,7 @@ +@@ -407,6 +410,7 @@ case $MACHDEP in linux*) MACHDEP="linux";; cygwin*) MACHDEP="cygwin";; @@ -32,7 +32,7 @@ diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac darwin*) MACHDEP="darwin";; irix646) MACHDEP="irix6";; '') MACHDEP="unknown";; -@@ -418,6 +422,9 @@ +@@ -428,6 +432,9 @@ *-*-cygwin*) _host_cpu= ;; @@ -42,16 +42,16 @@ diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac *) # for now, limit cross builds to known configurations MACHDEP="unknown" -@@ -892,7 +899,7 @@ +@@ -1087,7 +1094,7 @@ if test -z "$enable_shared" - then + then case $ac_sys_system in - CYGWIN*) + CYGWIN*|MSYS*) enable_shared="yes";; *) enable_shared="no";; -@@ -947,6 +954,11 @@ +@@ -1142,6 +1149,11 @@ BLDLIBRARY='-L. -lpython$(LDVERSION)' DLLLIBRARY='libpython$(LDVERSION).dll' ;; @@ -63,7 +63,7 @@ diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac SunOS*) LDLIBRARY='libpython$(LDVERSION).so' BLDLIBRARY='-Wl,-R,$(LIBDIR) -L. -lpython$(LDVERSION)' -@@ -998,7 +1010,7 @@ +@@ -1188,7 +1200,7 @@ else # shared is disabled PY_ENABLE_SHARED=0 case $ac_sys_system in @@ -72,7 +72,7 @@ diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac BLDLIBRARY='$(LIBRARY)' LDLIBRARY='libpython$(LDVERSION).dll.a' ;; -@@ -1056,7 +1068,7 @@ +@@ -1238,7 +1250,7 @@ AC_SUBST(LN) if test -z "$LN" ; then case $ac_sys_system in @@ -81,7 +81,7 @@ diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac *) LN=ln;; esac fi -@@ -1962,7 +1974,7 @@ +@@ -2380,7 +2392,7 @@ *) SHLIB_SUFFIX=.sl;; esac ;; @@ -90,7 +90,7 @@ diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac *) SHLIB_SUFFIX=.so;; esac fi -@@ -2100,7 +2112,7 @@ +@@ -2518,7 +2530,7 @@ SCO_SV*) LDSHARED='$(CC) -Wl,-G,-Bexport' LDCXXSHARED='$(CXX) -Wl,-G,-Bexport';; @@ -99,7 +99,7 @@ diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac LDSHARED="gcc -shared -Wl,--enable-auto-image-base" LDCXXSHARED="g++ -shared -Wl,--enable-auto-image-base";; *) LDSHARED="ld";; -@@ -2186,7 +2198,7 @@ +@@ -2606,7 +2618,7 @@ LINKFORSHARED="-Xlinker --export-dynamic" fi;; esac;; @@ -108,7 +108,7 @@ diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac if test $enable_shared = "no" then LINKFORSHARED='-Wl,--out-implib=$(LDLIBRARY)' -@@ -2208,7 +2220,7 @@ +@@ -2628,7 +2640,7 @@ if test ! "$LIBRARY" = "$LDLIBRARY" then case $ac_sys_system in @@ -117,7 +117,7 @@ diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac # Cygwin needs CCSHARED when building extension DLLs # but not when building the interpreter DLL. CFLAGSFORSHARED='';; -@@ -2637,7 +2649,7 @@ +@@ -3061,7 +3073,7 @@ fi AC_CHECK_FUNCS(pthread_sigmask, [case $ac_sys_system in @@ -126,19 +126,28 @@ diff -Naur Python-3.4.3-orig/configure.ac Python-3.4.3/configure.ac AC_DEFINE(HAVE_BROKEN_PTHREAD_SIGMASK, 1, [Define if pthread_sigmask() does not work on your system.]) ;; -@@ -4097,7 +4109,7 @@ +@@ -4609,7 +4621,7 @@ AC_SUBST(EXT_SUFFIX) case $ac_sys_system in -- Linux*|GNU*|CYGWIN*) -+ Linux*|GNU*|CYGWIN*|MSYS*) +- Linux*|GNU*|Darwin|CYGWIN*) ++ Linux*|GNU*|Darwin|CYGWIN*|MSYS*) EXT_SUFFIX=.${SOABI}${SHLIB_SUFFIX};; *) EXT_SUFFIX=${SHLIB_SUFFIX};; -diff -Naur Python-3.4.3-orig/Lib/asyncio/base_events.py Python-3.4.3/Lib/asyncio/base_events.py ---- Python-3.4.3-orig/Lib/asyncio/base_events.py 2015-02-25 14:27:44.000000000 +0300 -+++ Python-3.4.3/Lib/asyncio/base_events.py 2015-05-07 09:58:31.825600000 +0300 -@@ -784,7 +784,7 @@ +diff -Naur Python-3.6.0/Lib/asyncio/base_events.py.orig Python-3.6.0/Lib/asyncio/base_events.py +--- Python-3.6.0/Lib/asyncio/base_events.py.orig 2016-12-22 21:21:19.000000000 -0500 ++++ Python-3.6.0/Lib/asyncio/base_events.py 2017-02-08 08:59:15.247005800 -0500 +@@ -895,7 +895,7 @@ + exceptions = [] + + if reuse_address is None: +- reuse_address = os.name == 'posix' and sys.platform != 'cygwin' ++ reuse_address = os.name == 'posix' and sys.platform != 'cygwin' and sys.platform != 'msys' + + for ((family, proto), + (local_address, remote_address)) in addr_pairs_info: +@@ -997,7 +997,7 @@ AF_INET6 = getattr(socket, 'AF_INET6', 0) if reuse_address is None: @@ -146,7 +155,7 @@ diff -Naur Python-3.4.3-orig/Lib/asyncio/base_events.py Python-3.4.3/Lib/asyncio + reuse_address = os.name == 'posix' and sys.platform != 'cygwin' and sys.platform != 'msys' sockets = [] if host == '': - host = None + hosts = [None] diff -Naur Python-3.4.3-orig/Lib/ctypes/__init__.py Python-3.4.3/Lib/ctypes/__init__.py --- Python-3.4.3-orig/Lib/ctypes/__init__.py 2015-05-07 09:55:34.078000000 +0300 +++ Python-3.4.3/Lib/ctypes/__init__.py 2015-05-07 09:58:31.825600000 +0300 @@ -158,9 +167,9 @@ diff -Naur Python-3.4.3-orig/Lib/ctypes/__init__.py Python-3.4.3/Lib/ctypes/__in __version__ = "1.1.0" -@@ -433,9 +433,8 @@ +@@ -430,9 +430,8 @@ - if _os.name in ("nt", "ce"): + if _os.name == "nt": pythonapi = PyDLL("python dll", None, _sys.dllhandle) -elif _sys.platform == "cygwin": - pythonapi = PyDLL("libpython%d.%d%s.dll" % \ @@ -173,8 +182,8 @@ diff -Naur Python-3.4.3-orig/Lib/ctypes/__init__.py Python-3.4.3/Lib/ctypes/__in diff -Naur Python-3.4.3-orig/Lib/ctypes/test/test_loading.py Python-3.4.3/Lib/ctypes/test/test_loading.py --- Python-3.4.3-orig/Lib/ctypes/test/test_loading.py 2015-02-25 14:27:44.000000000 +0300 +++ Python-3.4.3/Lib/ctypes/test/test_loading.py 2015-05-07 09:58:31.841200000 +0300 -@@ -15,6 +15,8 @@ - libc_name = "coredll" +@@ -13,6 +13,8 @@ + libc_name = find_library("c") elif sys.platform == "cygwin": libc_name = "cygwin1.dll" + elif sys.platform == "msys": @@ -185,7 +194,7 @@ diff -Naur Python-3.4.3-orig/Lib/ctypes/test/test_loading.py Python-3.4.3/Lib/ct diff -Naur Python-3.4.3-orig/Lib/ctypes/util.py Python-3.4.3/Lib/ctypes/util.py --- Python-3.4.3-orig/Lib/ctypes/util.py 2015-05-07 09:55:34.078000000 +0300 +++ Python-3.4.3/Lib/ctypes/util.py 2015-05-07 10:01:40.261800000 +0300 -@@ -83,7 +83,7 @@ +@@ -80,7 +80,7 @@ continue return None @@ -194,7 +203,7 @@ diff -Naur Python-3.4.3-orig/Lib/ctypes/util.py Python-3.4.3/Lib/ctypes/util.py def find_library(name): for libdir in ['/usr/lib', '/usr/local/lib']: for libext in ['lib%s.dll.a' % name, 'lib%s.a' % name]: -@@ -281,6 +281,10 @@ +@@ -351,6 +351,10 @@ print(cdll.LoadLibrary("cygbz2-1.dll")) print(cdll.LoadLibrary("cygcrypt-0.dll")) print(find_library("crypt")) @@ -228,7 +237,7 @@ diff -Naur Python-3.4.3-orig/Lib/distutils/ccompiler.py Python-3.4.3/Lib/distuti diff -Naur Python-3.4.3-orig/Lib/distutils/command/build_ext.py Python-3.4.3/Lib/distutils/command/build_ext.py --- Python-3.4.3-orig/Lib/distutils/command/build_ext.py 2015-05-07 09:55:34.811200000 +0300 +++ Python-3.4.3/Lib/distutils/command/build_ext.py 2015-05-07 09:58:31.856800000 +0300 -@@ -223,7 +223,7 @@ +@@ -217,7 +217,7 @@ # for extensions under Cygwin and AtheOS Python's library directory must be # appended to library_dirs @@ -237,7 +246,7 @@ diff -Naur Python-3.4.3-orig/Lib/distutils/command/build_ext.py Python-3.4.3/Lib if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")): # building third party extensions self.library_dirs.append(os.path.join(sys.prefix, "lib", -@@ -695,7 +695,7 @@ +@@ -715,7 +715,7 @@ return ext.libraries + [pythonlib] else: return ext.libraries @@ -258,7 +267,7 @@ diff -Naur Python-3.4.3-orig/Lib/distutils/cygwinccompiler.py Python-3.4.3/Lib/d diff -Naur Python-3.4.3-orig/Lib/distutils/sysconfig.py Python-3.4.3/Lib/distutils/sysconfig.py --- Python-3.4.3-orig/Lib/distutils/sysconfig.py 2015-05-07 09:55:46.604800000 +0300 +++ Python-3.4.3/Lib/distutils/sysconfig.py 2015-05-07 10:07:03.222600000 +0300 -@@ -166,7 +166,7 @@ +@@ -157,7 +157,7 @@ varies across Unices and is stored in Python's Makefile. """ global _config_vars @@ -267,7 +276,7 @@ diff -Naur Python-3.4.3-orig/Lib/distutils/sysconfig.py Python-3.4.3/Lib/distuti # Note that cygwin use posix build and 'unix' compiler. # If build is not based on posix then we must predefine # some environment variables corresponding to posix -@@ -181,7 +181,7 @@ +@@ -172,7 +172,7 @@ _config_vars['AR'] = "ar" _config_vars['ARFLAGS'] = "rc" @@ -288,19 +297,19 @@ diff -Naur Python-3.4.3-orig/Lib/distutils/tests/support.py Python-3.4.3/Lib/dis def mkdtemp(self): """Create a temporary directory that will be cleaned up. -diff -Naur Python-3.4.3-orig/Lib/distutils/unixccompiler.py Python-3.4.3/Lib/distutils/unixccompiler.py ---- Python-3.4.3-orig/Lib/distutils/unixccompiler.py 2015-05-07 09:55:44.108800000 +0300 -+++ Python-3.4.3/Lib/distutils/unixccompiler.py 2015-05-07 09:58:31.856800000 +0300 -@@ -77,7 +77,7 @@ - shared_lib_extension = ".so" - dylib_lib_extension = ".dylib" +diff -Naur Python-3.6.0/Lib/distutils/unixccompiler.py.orig Python-3.6.0/Lib/distutils/unixccompiler.py +--- Python-3.6.0/Lib/distutils/unixccompiler.py.orig 2017-02-08 08:22:40.592815800 -0500 ++++ Python-3.6.0/Lib/distutils/unixccompiler.py 2017-02-08 08:32:38.946960100 -0500 +@@ -79,7 +79,7 @@ + xcode_stub_lib_extension = ".tbd" static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s" + xcode_stub_lib_format = dylib_lib_format - if sys.platform == "cygwin": + if sys.platform in ["cygwin", "msys"]: exe_extension = ".exe" dylib_lib_extension = ".dll.a" -@@ -223,7 +223,7 @@ +@@ -225,7 +225,7 @@ # the configuration data stored in the Python installation, so # we use this hack. compiler = os.path.basename(sysconfig.get_config_var("CC")) @@ -308,7 +317,7 @@ diff -Naur Python-3.4.3-orig/Lib/distutils/unixccompiler.py Python-3.4.3/Lib/dis + if sys.platform[:6] == "darwin" or sys.platform[:6] == "cygwin" or sys.platform[:4] == "msys": # MacOSX's linker doesn't understand the -R flag at all return "-L" + dir - elif sys.platform[:5] == "hp-ux": + elif sys.platform[:7] == "freebsd": diff -Naur Python-3.4.3-orig/Lib/distutils/util.py Python-3.4.3/Lib/distutils/util.py --- Python-3.4.3-orig/Lib/distutils/util.py 2015-02-25 14:27:44.000000000 +0300 +++ Python-3.4.3/Lib/distutils/util.py 2015-05-07 09:58:31.872400000 +0300 @@ -325,22 +334,22 @@ diff -Naur Python-3.4.3-orig/Lib/distutils/util.py Python-3.4.3/Lib/distutils/ut elif osname[:6] == "darwin": import _osx_support, distutils.sysconfig osname, release, machine = _osx_support.get_platform_osx( -diff -Naur Python-3.4.3-orig/Lib/importlib/_bootstrap.py Python-3.4.3/Lib/importlib/_bootstrap.py ---- Python-3.4.3-orig/Lib/importlib/_bootstrap.py 2015-02-25 14:27:44.000000000 +0300 -+++ Python-3.4.3/Lib/importlib/_bootstrap.py 2015-05-07 09:58:31.872400000 +0300 +diff -Naur Python-3.6.0/Lib/importlib/_bootstrap_external.py.orig Python-3.6.0/Lib/importlib/_bootstrap_external.py +--- Python-3.6.0/Lib/importlib/_bootstrap_external.py.orig 2017-02-08 08:43:48.316520300 -0500 ++++ Python-3.6.0/Lib/importlib/_bootstrap_external.py 2017-02-08 08:44:28.339129300 -0500 @@ -22,7 +22,7 @@ # Bootstrap-related code ###################################################### - --_CASE_INSENSITIVE_PLATFORMS = 'win', 'cygwin', 'darwin' -+_CASE_INSENSITIVE_PLATFORMS = 'win', 'cygwin', 'msys', 'darwin' - - - def _make_relax_case(): + _CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win', +-_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin' ++_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'msys', 'darwin' + _CASE_INSENSITIVE_PLATFORMS = (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY + + _CASE_INSENSITIVE_PLATFORMS_STR_KEY) + diff -Naur Python-3.4.3-orig/Lib/sysconfig.py Python-3.4.3/Lib/sysconfig.py --- Python-3.4.3-orig/Lib/sysconfig.py 2015-02-25 14:27:44.000000000 +0300 +++ Python-3.4.3/Lib/sysconfig.py 2015-05-07 09:58:34.087600000 +0300 -@@ -671,6 +671,13 @@ +@@ -683,6 +683,13 @@ m = rel_re.match(release) if m: release = m.group() @@ -357,7 +366,7 @@ diff -Naur Python-3.4.3-orig/Lib/sysconfig.py Python-3.4.3/Lib/sysconfig.py diff -Naur Python-3.4.3-orig/Lib/tempfile.py Python-3.4.3/Lib/tempfile.py --- Python-3.4.3-orig/Lib/tempfile.py 2015-02-25 14:27:44.000000000 +0300 +++ Python-3.4.3/Lib/tempfile.py 2015-05-07 09:58:35.086000000 +0300 -@@ -467,7 +467,7 @@ +@@ -557,7 +557,7 @@ _os.close(fd) raise @@ -369,19 +378,19 @@ diff -Naur Python-3.4.3-orig/Lib/tempfile.py Python-3.4.3/Lib/tempfile.py diff -Naur Python-3.4.3-orig/Lib/test/test_curses.py Python-3.4.3/Lib/test/test_curses.py --- Python-3.4.3-orig/Lib/test/test_curses.py 2015-02-25 14:27:45.000000000 +0300 +++ Python-3.4.3/Lib/test/test_curses.py 2015-05-07 09:58:35.086000000 +0300 -@@ -33,6 +33,8 @@ +@@ -40,6 +40,8 @@ "$TERM=%r, calling initscr() may cause exit" % term) @unittest.skipIf(sys.platform == "cygwin", "cygwin's curses mostly just hangs") +@unittest.skipIf(sys.platform == "msys", + "msys's curses mostly just hangs") class TestCurses(unittest.TestCase): + @classmethod - def setUpClass(cls): diff -Naur Python-3.4.3-orig/Lib/test/test_importlib/util.py Python-3.4.3/Lib/test/test_importlib/util.py --- Python-3.4.3-orig/Lib/test/test_importlib/util.py 2015-02-25 14:27:45.000000000 +0300 +++ Python-3.4.3/Lib/test/test_importlib/util.py 2015-05-07 09:58:35.086000000 +0300 -@@ -31,7 +31,7 @@ +@@ -85,7 +85,7 @@ CASE_INSENSITIVE_FS = True # Windows is the only OS that is *always* case-insensitive # (OS X *can* be case-sensitive). @@ -393,7 +402,7 @@ diff -Naur Python-3.4.3-orig/Lib/test/test_importlib/util.py Python-3.4.3/Lib/te diff -Naur Python-3.4.3-orig/Lib/test/test_mailbox.py Python-3.4.3/Lib/test/test_mailbox.py --- Python-3.4.3-orig/Lib/test/test_mailbox.py 2015-02-25 14:27:45.000000000 +0300 +++ Python-3.4.3/Lib/test/test_mailbox.py 2015-05-07 09:58:35.086000000 +0300 -@@ -596,7 +596,7 @@ +@@ -591,7 +591,7 @@ def setUp(self): TestMailbox.setUp(self) @@ -417,7 +426,7 @@ diff -Naur Python-3.4.3-orig/Lib/test/test_netrc.py Python-3.4.3/Lib/test/test_n diff -Naur Python-3.4.3-orig/Lib/test/test_shutil.py Python-3.4.3/Lib/test/test_shutil.py --- Python-3.4.3-orig/Lib/test/test_shutil.py 2015-02-25 14:27:45.000000000 +0300 +++ Python-3.4.3/Lib/test/test_shutil.py 2015-05-07 09:58:35.117200000 +0300 -@@ -99,7 +99,7 @@ +@@ -97,7 +97,7 @@ super(TestShutil, self).tearDown() while self.tempdirs: d = self.tempdirs.pop() @@ -426,7 +435,7 @@ diff -Naur Python-3.4.3-orig/Lib/test/test_shutil.py Python-3.4.3/Lib/test/test_ def mkdtemp(self): -@@ -200,7 +200,7 @@ +@@ -196,7 +196,7 @@ @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.chmod()') @@ -450,8 +459,8 @@ diff -Naur Python-3.4.3-orig/Lib/tkinter/test/test_tkinter/test_loadtk.py Python diff -Naur Python-3.4.3-orig/Modules/makesetup Python-3.4.3/Modules/makesetup --- Python-3.4.3-orig/Modules/makesetup 2015-05-07 09:55:42.954400000 +0300 +++ Python-3.4.3/Modules/makesetup 2015-05-07 09:58:35.132800000 +0300 -@@ -85,7 +85,7 @@ - # Setup to link with extra libraries when makeing shared extensions. +@@ -86,7 +86,7 @@ + # Setup to link with extra libraries when making shared extensions. # Currently, only Cygwin needs this baggage. case `uname -s` in -CYGWIN*) if test $libdir = . @@ -462,7 +471,7 @@ diff -Naur Python-3.4.3-orig/Modules/makesetup Python-3.4.3/Modules/makesetup diff -Naur Python-3.4.3-orig/setup.py Python-3.4.3/setup.py --- Python-3.4.3-orig/setup.py 2015-05-07 09:55:33.329200000 +0300 +++ Python-3.4.3/setup.py 2015-05-07 09:58:35.132800000 +0300 -@@ -317,7 +317,7 @@ +@@ -361,7 +361,7 @@ # Workaround for Cygwin: Cygwin currently has fork issues when many # modules have been imported @@ -471,7 +480,7 @@ diff -Naur Python-3.4.3-orig/setup.py Python-3.4.3/setup.py self.announce('WARNING: skipping import check for Cygwin-based "%s"' % ext.name) return -@@ -1263,7 +1263,7 @@ +@@ -1339,7 +1339,7 @@ exts.append( Extension('resource', ['resource.c']) ) # Sun yellow pages. Some systems have the functions in libc. @@ -480,7 +489,7 @@ diff -Naur Python-3.4.3-orig/setup.py Python-3.4.3/setup.py find_file('rpcsvc/yp_prot.h', inc_dirs, []) is not None): if (self.compiler.find_library_file(lib_dirs, 'nsl')): libs = ['nsl'] -@@ -1500,6 +1500,10 @@ +@@ -1577,6 +1577,10 @@ macros = dict() libraries = [] @@ -491,3 +500,15 @@ diff -Naur Python-3.4.3-orig/setup.py Python-3.4.3/setup.py elif host_platform in ('freebsd4', 'freebsd5', 'freebsd6', 'freebsd7', 'freebsd8'): # FreeBSD's P1003.1b semaphore support is very experimental # and has many known problems. (as of June 2008) +diff -aur Python-3.6.0/Lib/test/test_asyncio/test_base_events.py.orig Python-3.6.0/Lib/test/test_asyncio/test_base_events.py +--- Python-3.6.0/Lib/test/test_asyncio/test_base_events.py.orig 2017-02-08 15:03:29.184676300 -0500 ++++ Python-3.6.0/Lib/test/test_asyncio/test_base_events.py 2017-02-08 15:49:05.932013200 -0500 +@@ -1576,7 +1576,7 @@ + sock = transport.get_extra_info('socket') + + reuse_address_default_on = ( +- os.name == 'posix' and sys.platform != 'cygwin') ++ os.name == 'posix' and sys.platform != 'cygwin' and sys.platform != 'msys') + reuseport_supported = hasattr(socket, 'SO_REUSEPORT') + + if reuse_address_default_on: diff --git a/python3/920-allow-win-drives-in-os-path-isabs.patch b/python3/920-allow-win-drives-in-os-path-isabs.patch index 1f4656e1..a09f1628 100644 --- a/python3/920-allow-win-drives-in-os-path-isabs.patch +++ b/python3/920-allow-win-drives-in-os-path-isabs.patch @@ -1,6 +1,6 @@ --- a/Lib/posixpath.py 2013-11-27 06:57:57.000000000 +0000 +++ b/Lib/posixpath.py 2014-02-21 10:43:34.423932700 +0000 -@@ -41,6 +41,12 @@ +@@ -42,6 +42,12 @@ else: return '/' @@ -13,9 +13,9 @@ # Normalize the case of a pathname. Trivial in Posix, string.lower on Mac. # On MS-DOS this may also turn slashes into backslashes; however, other # normalizations (such as optimizing '../' away) are not allowed -@@ -61,7 +67,12 @@ - def isabs(s): +@@ -63,7 +69,12 @@ """Test whether a path is absolute""" + s = os.fspath(s) sep = _get_sep(s) - return s.startswith(sep) + altsep = _get_altsep(s) diff --git a/python3/PKGBUILD b/python3/PKGBUILD index aa5baacc..63fb60d4 100644 --- a/python3/PKGBUILD +++ b/python3/PKGBUILD @@ -2,15 +2,15 @@ # Contributor: Ray Donnelly pkgname=python -pkgver=3.4.5 +pkgver=3.6.1 pkgrel=1 -_pybasever=3.4 +_pybasever=3.6 pkgdesc="Next generation of the python high-level scripting language" arch=('i686' 'x86_64') license=('custom') url="https://www.python.org/" -depends=('libbz2' 'libexpat' 'libffi' 'liblzma' 'ncurses' 'libopenssl' 'libreadline' 'libsqlite' 'zlib') -makedepends=('libbz2-devel' 'libexpat-devel' 'libsqlite-devel' 'libffi-devel' 'ncurses-devel' 'libreadline-devel' 'liblzma-devel' 'openssl-devel' 'zlib-devel') +depends=('libbz2' 'libexpat' 'libffi' 'liblzma' 'ncurses' 'libopenssl' 'libreadline' 'mpdecimal' 'libsqlite' 'zlib') +makedepends=('libbz2-devel' 'libexpat-devel' 'mpdecimal-devel' 'libsqlite-devel' 'libffi-devel' 'ncurses-devel' 'libreadline-devel' 'liblzma-devel' 'openssl-devel' 'zlib-devel') #optdepends=('tk: for tkinter' 'sqlite') provides=('python3') replaces=('python3') @@ -20,43 +20,77 @@ source=(https://www.python.org/ftp/python/${pkgver%rc*}/Python-${pkgver}.tar.xz 002-3.1-enable-new-dtags.patch 003-3.4-tkinter-cygwin.patch 004-3.4-ctypes-cygwin.patch - 005-3.1-PATH_MAX.patch + 005-3.6-PATH_MAX.patch 006-3.1-ncurses-abi6.patch 007-3.2-export-PySignal_SetWakeupFd.patch 008-3.4-distutils-soname.patch 009-3.2-distutils-shlibext.patch - 010-3.4-pep3149-cygwin.patch - 011-3.4-thread-cygwin64.patch + 010-3.6-pep3149-cygwin.patch + 011-3.6-thread-cygwin64.patch 012-3.2-getpath-exe-extension.patch 013-3.4-select-cygwin.patch 014-3.4-signal-cygwin.patch 015-3.4-struct-cygwin.patch - 017-3.4-shebang.patch - 025-MINGW-compiler-customize-mingw-cygwin-compilers.patch - 900-msysize.patch - 910-libffi-msys2.patch - 920-allow-win-drives-in-os-path-isabs.patch) -sha256sums=('ee64b1c8a47461009abf25252332d29a4e587cb4f0c1c96aa793a3732e9d898a' - '4fadf48332d86266c0fa30548dba56ca295d936d556b879972aea81290ad7520' - '4db598b2bf7ae3767a7ab84501ba9cc0d2b26d2b94e6c2652884143b40bf9820' - 'fc27003dda4a96cc5154faec447183c325cb7508339de58e7152207ecd19bfa5' - '7b688e9103af3eed42999c418c29a26c973020eec89cfc35c5a63c03c42ec9d9' - 'bb5a438ecb655e1e2e54372e3980abafc667c2e229dda0f269eccd79ed72ed4e' + 3.6-ftm.patch + 3.6-getrandom.patch + 025-MINGW-compiler-customize-mingw-cygwin-compilers.patch + 900-msysize.patch + 910-libffi-msys2.patch + 920-allow-win-drives-in-os-path-isabs.patch + dont-make-libpython-readonly.patch + 00155-avoid-ctypes-thunks.patch + 00157-uid-gid-overflows.patch + 00170-gc-assertions.patch + 00178-dont-duplicate-flags-in-sysconfig.patch + 00188-fix-lib2to3-tests-when-hashlib-doesnt-compile-properly.patch + 00189-add-rewheel-module.patch + 00206-remove-hf-from-arm-triplet.patch + 00243-fix-mips64-triplet.patch + 00249-fix-out-of-tree-dtrace-builds.patch + 00252-add-executable-option.patch + 00260-require-setuptools-dependencies.patch + 00261-use-proper-command-line-parsing-in-_testembed.patch + 00264-skip-test-failing-on-aarch64.patch + python3-powerppc-arch.patch + 016-3.6-mpdec-cygwin.patch) +sha256sums=('a01810ddfcec216bcdb357a84bfaafdfaa0ca42bbdaa4cb7ff74f5a9961e4041' + 'de52e4722a6902e09dd6f343fdac0e7d45339f89386c8096b9c582c31aeb82e7' + 'b5a787f02811f46800f98bf242448770492643a4431771bb4283e6ae97016263' + '4d7601b62e73c04553d22d480a873983a28b11df1f06be6898014453ce04afc3' + 'edf33a790c7c0903b8edbc8e68baf91cf2d34c13e607503d1cc7f270186ea76c' + '85499ca7f1016087df48223e4712db60930aa97a2eae634d2d955fb71bdfc864' '8a138293fa5ad3a7522e00194994fecc8967c6a71822127391e4d756b2280e74' - '8e8c554e5f2e3a5765a3487e1b80f03c4e377f878548730fe43f0860a9dc0108' - '3e557cbd67246c33da738e80de59e56352e0822ce604cee8d12df50c311f7c12' - '8e1ea7683ccd3f4b45f97075c125be86f28d4db9a342a257ea2f138936fd80a4' - 'df1e72d5dc55c480d15a039dfe7ba2b73700e6ec6fac860ed2e6152e55ca9f29' - 'a5250b1d4b38d90b8bb03ba93642c1b6d44b51d76c3659c9360363610b7cc698' - 'e7e3aa7adbee914a30aad34dcc6fe0beb036580edcefdfae596c55b408c450c9' - '63189f7e171eaa082af1f6315f14cc1aebb4b3b431ec0e120d1b7b178263c39f' - '98ec5d02475388ff899bd59566b37996895cd2a049c40d2845c052816e4875ff' - '4d2331bf3af0beb8528c0aad4669b4d58093481f4f8120e80a71645d98565495' - '46e37c95e4acd527fd60168ae1513553f7d466ec30f0c7ba4a4a1d1ee5344311' - '0f96dc585398d3d04e2f02e5e398f2d81f65cbd6544999e5acf38d985975caba' - 'e21c674a9454f3ff441ca2d298889616ec126defaa29fc7469e74427b1df44bb' + '1ab20d38926aa85e638317620c29c484fcbbc228cd7cdf9543c29b750556d23f' + '7a7425b5fa28b7692bafff226981650748d7f40a42a711378b9a9c8b23a98060' + '6ead37259110c28b16e35e05c93c82b46aa0fbb5152ff61bdaf1eea5f1ad01da' + 'f5b67408d39d3fda539ea90b12c48a05bd950b38460ec3e6a688e3377b071ed3' + '73083aebc0ed9ce34bd52b1aeef73f7bcb3b27dff81967276562101e41dfaa5a' + 'c09d3612d748852def0bcd1cb36dda7bd24366ed6b386743c800c7cb21eb0298' + 'e668b749e5f0bc584262add2cd7fffb2f6f32393a14918029d791012eda930f3' + '30564663c1f2cd7d0d10a2b07eceb139534f17bc3a38dc8daafad0d5111e8bbc' + '505c736e35772835b06597de552217e4838052b759d1350b65b4cb079b6403f3' + '7c4774d40b18d5a4ef4f3e05d53cc2d4d0ca3d0f970b3af7f7164ac8be0a4c56' + 'd1f4b04c59bce82532f5ff5fdae4dda7f03f87b2ab03da61bee008915ce2ddc9' + '5b1083e9b50e149d623d863dee38ac1fb8d142f1bb78c8a01dcb09bfd97f4118' + '9bbe2921b16ba689472a54de8aa5921cbf7eb9a3921ae1c9697d44ffaf8f414f' '7e587d145db24fbee1c7c7b96a4d7f247d132315384d551005ffb39b51f41906' - 'a1edaeda01466268cd75eb50c440b1ee76eafea334b14515b3cfb66c1e38d0e9') + '387a2b7931fb4958e2526991760d85677f44fa13cff0aeb0f41a267f1f7fd214' + 'f8b15d7079bfa1707e5bea78f600a0fca2077c25428c2bac5793b19b408f276e' + '7a3f8f43b9c9eecb65d80b60c875344950a8b55082401830599d091548a3a985' + '13519ee9358cc5378b3fab60501b9db4d56e86d0b69da8b9841989d437492c7e' + 'e70369c7096b8204b0af968679d493bf272996df637e53ca6fad4a236f1a2b02' + '4e7ce358f0650545ee9ae112b26cee4dce8f763eac5612f556e975ad38056fb8' + 'd04b7bec35418c699358c8140a7213efe1a133772972715800b7a6101e0d699a' + 'f093014bf6c0b64a662ea7d41812e6bbe33726af2b607062a3dbae226691948f' + 'd61273d74f734bcdef933531cbd3cc77cf79b5826837cbd40cd48e5b1bc76072' + 'f81a0a0907e65a00bff1a1ede4827a33984a6f2aee3aed2ce6a2423decdfd26d' + '8fa156c7c3615f1e9affb51b536d568c69811852a3f6c9afa43746365c8a9486' + '735257fc216be2300b35dab8a97ff76199cc98d69b0bce36f099d476fb0f30e5' + 'df334d534d225587a1a90e143be7f788cc2a1b8ae30f6d378cef0ef83ef3ced4' + 'bb21618672c91f549e9ba3c9fd63f419670f9e3aa051f23e773fc08fbecac80f' + '843c26c4325f1d42f30f6e1fac5e6ff06122903bd37aa67683838ae49609e276' + '0de3e6e67d86f7e3593c504385399537b42920aca94329424cc8b1d65ae2ac4f' + 'e3ef181333d5c9d20297849a46a68271a2190b7fc611c40c68c1ae240fa7ec36') prepare() { cd "${srcdir}/Python-${pkgver}" @@ -67,23 +101,44 @@ prepare() { patch -p1 -i ${srcdir}/002-3.1-enable-new-dtags.patch patch -p1 -i ${srcdir}/003-3.4-tkinter-cygwin.patch patch -p1 -i ${srcdir}/004-3.4-ctypes-cygwin.patch - patch -p1 -i ${srcdir}/005-3.1-PATH_MAX.patch + patch -p1 -i ${srcdir}/005-3.6-PATH_MAX.patch patch -p1 -i ${srcdir}/006-3.1-ncurses-abi6.patch patch -p1 -i ${srcdir}/007-3.2-export-PySignal_SetWakeupFd.patch patch -p1 -i ${srcdir}/008-3.4-distutils-soname.patch patch -p1 -i ${srcdir}/009-3.2-distutils-shlibext.patch - patch -p1 -i ${srcdir}/010-3.4-pep3149-cygwin.patch - patch -p1 -i ${srcdir}/011-3.4-thread-cygwin64.patch + patch -p1 -i ${srcdir}/010-3.6-pep3149-cygwin.patch + patch -p1 -i ${srcdir}/011-3.6-thread-cygwin64.patch patch -p1 -i ${srcdir}/012-3.2-getpath-exe-extension.patch patch -p1 -i ${srcdir}/013-3.4-select-cygwin.patch patch -p1 -i ${srcdir}/014-3.4-signal-cygwin.patch patch -p1 -i ${srcdir}/015-3.4-struct-cygwin.patch - patch -p1 -i ${srcdir}/017-3.4-shebang.patch + patch -p2 -i ${srcdir}/3.6-ftm.patch + patch -p2 -i ${srcdir}/3.6-getrandom.patch patch -p1 -i ${srcdir}/025-MINGW-compiler-customize-mingw-cygwin-compilers.patch patch -p1 -i ${srcdir}/900-msysize.patch patch -p1 -i ${srcdir}/910-libffi-msys2.patch patch -p1 -i ${srcdir}/920-allow-win-drives-in-os-path-isabs.patch + #archlinux + patch -p1 -i ${srcdir}/dont-make-libpython-readonly.patch + #fedora + patch -p1 -i ${srcdir}/00155-avoid-ctypes-thunks.patch + patch -p1 -i ${srcdir}/00157-uid-gid-overflows.patch + patch -p1 -i ${srcdir}/00170-gc-assertions.patch + patch -p1 -i ${srcdir}/00178-dont-duplicate-flags-in-sysconfig.patch + patch -p1 -i ${srcdir}/00188-fix-lib2to3-tests-when-hashlib-doesnt-compile-properly.patch + patch -p1 -i ${srcdir}/00189-add-rewheel-module.patch + patch -p1 -i ${srcdir}/00206-remove-hf-from-arm-triplet.patch + patch -p1 -i ${srcdir}/00243-fix-mips64-triplet.patch + patch -p1 -i ${srcdir}/00249-fix-out-of-tree-dtrace-builds.patch + patch -p1 -i ${srcdir}/00252-add-executable-option.patch + patch -p1 -i ${srcdir}/00260-require-setuptools-dependencies.patch + patch -p1 -i ${srcdir}/00261-use-proper-command-line-parsing-in-_testembed.patch + patch -p1 -i ${srcdir}/00264-skip-test-failing-on-aarch64.patch + patch -p1 -i ${srcdir}/python3-powerppc-arch.patch + #PiotrVV + patch -p1 -i ${srcdir}/016-3.6-mpdec-cygwin.patch + # Incomplete patch from Ray Donnelly # patch -p1 -i ${srcdir}/3.3.2-allow-windows-paths-for-executable.patch @@ -92,7 +147,7 @@ prepare() { rm -r Modules/expat rm -r Modules/zlib rm -r Modules/_ctypes/{darwin,libffi}* - + rm -r Modules/_decimal/libmpdec autoreconf -fiv } @@ -115,10 +170,13 @@ build() { --with-system-expat \ --with-system-ffi \ --with-threads \ + --with-system-libmpdec \ + --enable-loadable-sqlite-extensions \ --without-ensurepip \ + ac_cv_func_bind_textdomain_codeset=yes - make + LC_CTYPE=en_US.UTF-8 make EXTRA_CFLAGS="$CFLAGS" } check() { @@ -128,13 +186,14 @@ check() { package() { cd "${srcdir}/Python-${pkgver}" - make DESTDIR="${pkgdir}" install maninstall + make DESTDIR="${pkgdir}" EXTRA_CFLAGS="$CFLAGS" install maninstall # Why are these not done by default... ln -sf python3 "${pkgdir}"/usr/bin/python.exe ln -sf python3-config "${pkgdir}"/usr/bin/python-config ln -sf idle3 "${pkgdir}"/usr/bin/idle ln -sf pydoc3 "${pkgdir}"/usr/bin/pydoc + ln -sf pyvenv-${_pybasever} "${pkgdir}"/usr/bin/pyvenv3 ln -sf python${_pybasever}.1 "${pkgdir}"/usr/share/man/man1/python3.1 ln -sf python${_pybasever}.1 "${pkgdir}"/usr/share/man/man1/python.1 @@ -142,7 +201,7 @@ package() { cp -f "${pkgdir}"/usr/lib/python${_pybasever}/config-${_pybasever}m/libpython${_pybasever}m.dll.a "${pkgdir}"/usr/lib/libpython${_pybasever}m.dll.a # Clean-up reference to build directory - sed -i "s|$srcdir/Python-${pkgver}:||" "$pkgdir/usr/lib/python${_pybasever}/config-${_pybasever}m/Makefile" + sed -i "s|$srcdir/Python-${pkgver}:||" "${pkgdir}/usr/lib/python${_pybasever}/config-${_pybasever}m/Makefile" # License install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" diff --git a/python3/dont-make-libpython-readonly.patch b/python3/dont-make-libpython-readonly.patch new file mode 100644 index 00000000..cbf9cf5e --- /dev/null +++ b/python3/dont-make-libpython-readonly.patch @@ -0,0 +1,13 @@ +diff --git a/Makefile.pre.in b/Makefile.pre.in +index ce2c0aa..7d6dcf7 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -70,7 +70,7 @@ INSTALL_DATA= @INSTALL_DATA@ + # Shared libraries must be installed with executable mode on some systems; + # rather than figuring out exactly which, we always give them executable mode. + # Also, making them read-only seems to be a good idea... +-INSTALL_SHARED= ${INSTALL} -m 555 ++INSTALL_SHARED= ${INSTALL} -m 755 + + MKDIR_P= @MKDIR_P@ + diff --git a/python3/python3-powerppc-arch.patch b/python3/python3-powerppc-arch.patch new file mode 100644 index 00000000..754b2469 --- /dev/null +++ b/python3/python3-powerppc-arch.patch @@ -0,0 +1,30 @@ +diff -up Python-3.5.0/configure.ac.than Python-3.5.0/configure.ac +--- Python-3.5.0/configure.ac.than 2015-11-13 11:51:32.039560172 -0500 ++++ Python-3.5.0/configure.ac 2015-11-13 11:52:11.670168157 -0500 +@@ -841,9 +841,9 @@ cat >> conftest.c <> conftest.c <