diff options
65 files changed, 652 insertions, 393 deletions
diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 323f017d65b..ac6fd0b53fc 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -199,8 +199,9 @@ type objects) *must* have the :attr:`ob_size` field. This field is deprecated. When it is defined, it should point to a function that acts the same as the :c:member:`~PyTypeObject.tp_getattro` function, but taking a C string - instead of a Python string object to give the attribute name. The signature is - the same as for :c:func:`PyObject_GetAttrString`. + instead of a Python string object to give the attribute name. The signature is :: + + PyObject * tp_getattr(PyObject *o, char *attr_name); This field is inherited by subtypes together with :c:member:`~PyTypeObject.tp_getattro`: a subtype inherits both :c:member:`~PyTypeObject.tp_getattr` and :c:member:`~PyTypeObject.tp_getattro` from its base type when @@ -213,10 +214,11 @@ type objects) *must* have the :attr:`ob_size` field. This field is deprecated. When it is defined, it should point to a function that acts the same as the :c:member:`~PyTypeObject.tp_setattro` function, but taking a C string - instead of a Python string object to give the attribute name. The signature is - the same as for :c:func:`PyObject_SetAttrString`, but setting - *v* to *NULL* to delete an attribute must be supported. + instead of a Python string object to give the attribute name. The signature is :: + + PyObject * tp_setattr(PyObject *o, char *attr_name, PyObject *v); + The *v* argument is set to *NULL* to delete the attribute. This field is inherited by subtypes together with :c:member:`~PyTypeObject.tp_setattro`: a subtype inherits both :c:member:`~PyTypeObject.tp_setattr` and :c:member:`~PyTypeObject.tp_setattro` from its base type when the subtype's :c:member:`~PyTypeObject.tp_setattr` and :c:member:`~PyTypeObject.tp_setattro` are both *NULL*. diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst index 4742d84dab9..eaab20ad975 100644 --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -1,3 +1,5 @@ +.. highlightlang:: c + ********************** Argument Clinic How-To ********************** @@ -78,17 +80,23 @@ Basic Concepts And Usage ======================== Argument Clinic ships with CPython; you'll find it in ``Tools/clinic/clinic.py``. -If you run that script, specifying a C file as an argument:: +If you run that script, specifying a C file as an argument: + +.. code-block:: shell-session - % python3 Tools/clinic/clinic.py foo.c + $ python3 Tools/clinic/clinic.py foo.c Argument Clinic will scan over the file looking for lines that -look exactly like this:: +look exactly like this: + +.. code-block:: none /*[clinic input] When it finds one, it reads everything up to a line that looks -exactly like this:: +exactly like this: + +.. code-block:: none [clinic start generated code]*/ @@ -99,7 +107,9 @@ lines, are collectively called an Argument Clinic "block". When Argument Clinic parses one of these blocks, it generates output. This output is rewritten into the C file immediately after the block, followed by a comment containing a checksum. -The Argument Clinic block now looks like this:: +The Argument Clinic block now looks like this: + +.. code-block:: none /*[clinic input] ... clinic input goes here ... @@ -375,15 +385,10 @@ Let's dive in! Write a pickled representation of obj to the open file. [clinic start generated code]*/ -12. Save and close the file, then run ``Tools/clinic/clinic.py`` on it. - With luck everything worked and your block now has output! Reopen - the file in your text editor to see:: - - /*[clinic input] - module _pickle - class _pickle.Pickler "PicklerObject *" "&Pickler_Type" - [clinic start generated code]*/ - /*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ +12. Save and close the file, then run ``Tools/clinic/clinic.py`` on + it. With luck everything worked---your block now has output, and + a ``.c.h`` file has been generated! Reopen the file in your + text editor to see:: /*[clinic input] _pickle.Pickler.dump @@ -395,18 +400,20 @@ Let's dive in! Write a pickled representation of obj to the open file. [clinic start generated code]*/ - PyDoc_STRVAR(_pickle_Pickler_dump__doc__, - "Write a pickled representation of obj to the open file.\n" - "\n" - ... static PyObject * - _pickle_Pickler_dump_impl(PicklerObject *self, PyObject *obj) - /*[clinic end generated code: checksum=3bd30745bf206a48f8b576a1da3d90f55a0a4187]*/ + _pickle_Pickler_dump(PicklerObject *self, PyObject *obj) + /*[clinic end generated code: output=87ecad1261e02ac7 input=552eb1c0f52260d9]*/ Obviously, if Argument Clinic didn't produce any output, it's because it found an error in your input. Keep fixing your errors and retrying until Argument Clinic processes your file without complaint. + For readability, most of the glue code has been generated to a ``.c.h`` + file. You'll need to include that in your original ``.c`` file, + typically right after the clinic module block:: + + #include "clinic/_pickle.c.h" + 13. Double-check that the argument-parsing code Argument Clinic generated looks basically the same as the existing code. @@ -1027,7 +1034,9 @@ that value, and an error has been set (``PyErr_Occurred()`` returns a true value), then the generated code will propagate the error. Otherwise it will encode the value you return like normal. -Currently Argument Clinic supports only a few return converters:: +Currently Argument Clinic supports only a few return converters: + +.. code-block:: none bool int @@ -1606,7 +1615,9 @@ code probably looks like this:: #endif /* HAVE_FUNCTIONNAME */ And then in the ``PyMethodDef`` structure at the bottom the existing code -will have:: +will have: + +.. code-block:: none #ifdef HAVE_FUNCTIONNAME {'functionname', ... }, @@ -1656,7 +1667,9 @@ extra code when using the "block" output preset? It can't go in the output bloc because that could be deactivated by the ``#ifdef``. (That's the whole point!) In this situation, Argument Clinic writes the extra code to the "buffer" destination. -This may mean that you get a complaint from Argument Clinic:: +This may mean that you get a complaint from Argument Clinic: + +.. code-block:: none Warning in file "Modules/posixmodule.c" on line 12357: Destination buffer 'buffer' not empty at end of file, emptying. @@ -1676,7 +1689,9 @@ wouldn't make any sense to the Python interpreter. But using Argument Clinic to run Python blocks lets you use Python as a Python preprocessor! Since Python comments are different from C comments, Argument Clinic -blocks embedded in Python files look slightly different. They look like this:: +blocks embedded in Python files look slightly different. They look like this: + +.. code-block:: python3 #/*[python input] #print("def foo(): pass") diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst index 712b4b76238..18b5c6556be 100644 --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -578,7 +578,7 @@ Footnotes This document was reviewed and revised by John Lee. .. [#] Google for example. -.. [#] Browser sniffing is a very bad practise for website design - building +.. [#] Browser sniffing is a very bad practice for website design - building sites using web standards is much more sensible. Unfortunately a lot of sites still send different versions to different browsers. .. [#] The user agent for MSIE 6 is diff --git a/Doc/library/pkgutil.rst b/Doc/library/pkgutil.rst index 90d69e40717..fba0ea641d9 100644 --- a/Doc/library/pkgutil.rst +++ b/Doc/library/pkgutil.rst @@ -224,4 +224,6 @@ support. If the package cannot be located or loaded, or it uses a :term:`loader` which does not support :meth:`get_data <importlib.abc.ResourceLoader.get_data>`, - then ``None`` is returned. + then ``None`` is returned. In particular, the :term:`loader` for + :term:`namespace packages <namespace package>` does not support + :meth:`get_data <importlib.abc.ResourceLoader.get_data>`. diff --git a/Doc/library/re.rst b/Doc/library/re.rst index a298d97c9c3..7ef4cbeee79 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -762,7 +762,7 @@ form. now are errors. .. deprecated-removed:: 3.5 3.7 - Unknown escapes in *repl* consist of ``'\'`` and ASCII letter now raise + Unknown escapes in *repl* consisting of ``'\'`` and an ASCII letter now raise a deprecation warning and will be forbidden in Python 3.7. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 122ed003876..1e665affb82 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1644,18 +1644,20 @@ expression support in the :mod:`re` module). Return true if all characters in the string are decimal characters and there is at least one character, false - otherwise. Decimal characters are those from general category "Nd". This category - includes digit characters, and all characters - that can be used to form decimal-radix numbers, e.g. U+0660, - ARABIC-INDIC DIGIT ZERO. + otherwise. Decimal characters are those that can be used to form + numbers in base 10, e.g. U+0660, ARABIC-INDIC DIGIT + ZERO. Formally a decimal character is a character in the Unicode + General Category "Nd". .. method:: str.isdigit() Return true if all characters in the string are digits and there is at least one character, false otherwise. Digits include decimal characters and digits that need - special handling, such as the compatibility superscript digits. Formally, a digit - is a character that has the property value Numeric_Type=Digit or Numeric_Type=Decimal. + special handling, such as the compatibility superscript digits. + This covers digits which cannot be used to form numbers in base 10, + like the Kharosthi numbers. Formally, a digit is a character that has the + property value Numeric_Type=Digit or Numeric_Type=Decimal. .. method:: str.isidentifier() @@ -2158,7 +2160,7 @@ The conversion types are: +------------+-----------------------------------------------------+-------+ | ``'o'`` | Signed octal value. | \(1) | +------------+-----------------------------------------------------+-------+ -| ``'u'`` | Obsolete type -- it is identical to ``'d'``. | \(7) | +| ``'u'`` | Obsolete type -- it is identical to ``'d'``. | \(6) | +------------+-----------------------------------------------------+-------+ | ``'x'`` | Signed hexadecimal (lowercase). | \(2) | +------------+-----------------------------------------------------+-------+ @@ -2199,15 +2201,12 @@ The conversion types are: Notes: (1) - The alternate form causes a leading zero (``'0'``) to be inserted between - left-hand padding and the formatting of the number if the leading character - of the result is not already a zero. + The alternate form causes a leading octal specifier (``'0o'``) to be + inserted before the first digit. (2) The alternate form causes a leading ``'0x'`` or ``'0X'`` (depending on whether - the ``'x'`` or ``'X'`` format was used) to be inserted between left-hand padding - and the formatting of the number if the leading character of the result is not - already a zero. + the ``'x'`` or ``'X'`` format was used) to be inserted before the first digit. (3) The alternate form causes the result to always contain a decimal point, even if @@ -2226,8 +2225,7 @@ Notes: (5) If precision is ``N``, the output is truncated to ``N`` characters. - -(7) +(6) See :pep:`237`. Since Python strings have an explicit length, ``%s`` conversions do not assume @@ -3303,15 +3301,12 @@ The conversion types are: Notes: (1) - The alternate form causes a leading zero (``'0'``) to be inserted between - left-hand padding and the formatting of the number if the leading character - of the result is not already a zero. + The alternate form causes a leading octal specifier (``'0o'``) to be + inserted before the first digit. (2) The alternate form causes a leading ``'0x'`` or ``'0X'`` (depending on whether - the ``'x'`` or ``'X'`` format was used) to be inserted between left-hand padding - and the formatting of the number if the leading character of the result is not - already a zero. + the ``'x'`` or ``'X'`` format was used) to be inserted before the first digit. (3) The alternate form causes the result to always contain a decimal point, even if diff --git a/Doc/tutorial/modules.rst b/Doc/tutorial/modules.rst index 35db305d9e1..1e3d5c01a47 100644 --- a/Doc/tutorial/modules.rst +++ b/Doc/tutorial/modules.rst @@ -501,7 +501,7 @@ when the ``from...import`` statement is executed. (This also works when ``__all__`` is defined.) Although certain modules are designed to export only names that follow certain -patterns when you use ``import *``, it is still considered bad practise in +patterns when you use ``import *``, it is still considered bad practice in production code. Remember, there is nothing wrong with using ``from Package import diff --git a/Include/patchlevel.h b/Include/patchlevel.h index f59e12ada13..49930e85565 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -19,11 +19,11 @@ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 6 #define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.6.0rc1+" +#define PY_VERSION "3.6.0+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/_pyio.py b/Lib/_pyio.py index d0947f06d51..2ebfb0576f5 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -277,7 +277,7 @@ class OpenWrapper: try: UnsupportedOperation = io.UnsupportedOperation except AttributeError: - class UnsupportedOperation(ValueError, OSError): + class UnsupportedOperation(OSError, ValueError): pass diff --git a/Lib/dbm/dumb.py b/Lib/dbm/dumb.py index e7c6440ee65..2296dbfd547 100644 --- a/Lib/dbm/dumb.py +++ b/Lib/dbm/dumb.py @@ -97,8 +97,9 @@ class _Database(collections.MutableMapping): try: f = _io.open(self._dirfile, 'r', encoding="Latin-1") except OSError: - pass + self._modified = not self._readonly else: + self._modified = False with f: for line in f: line = line.rstrip() @@ -113,7 +114,7 @@ class _Database(collections.MutableMapping): # CAUTION: It's vital that _commit() succeed, and _commit() can # be called from __del__(). Therefore we must never reference a # global in this routine. - if self._index is None: + if self._index is None or not self._modified: return # nothing to do try: @@ -197,6 +198,7 @@ class _Database(collections.MutableMapping): elif not isinstance(val, (bytes, bytearray)): raise TypeError("values must be bytes or strings") self._verify_open() + self._modified = True if key not in self._index: self._addkey(key, self._addval(val)) else: @@ -229,6 +231,7 @@ class _Database(collections.MutableMapping): if isinstance(key, str): key = key.encode('utf-8') self._verify_open() + self._modified = True # The blocks used by the associated value are lost. del self._index[key] # XXX It's unclear why we do a _commit() here (the code always diff --git a/Lib/distutils/command/wininst-14.0-amd64.exe b/Lib/distutils/command/wininst-14.0-amd64.exe Binary files differindex 22299543a97..253c2e2ecce 100644 --- a/Lib/distutils/command/wininst-14.0-amd64.exe +++ b/Lib/distutils/command/wininst-14.0-amd64.exe diff --git a/Lib/distutils/command/wininst-14.0.exe b/Lib/distutils/command/wininst-14.0.exe Binary files differindex 0dac1103d98..46f5f356676 100644 --- a/Lib/distutils/command/wininst-14.0.exe +++ b/Lib/distutils/command/wininst-14.0.exe diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index ab434460c26..9feec50842c 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -1440,6 +1440,4 @@ def _install(_bootstrap_module): _setup(_bootstrap_module) supported_loaders = _get_supported_file_loaders() sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)]) - if _os.__name__ == 'nt': - sys.meta_path.append(WindowsRegistryFinder) sys.meta_path.append(PathFinder) diff --git a/Lib/mailbox.py b/Lib/mailbox.py index 0e23987ce75..39f24f9a723 100644 --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -313,11 +313,12 @@ class Maildir(Mailbox): # final position in order to prevent race conditions with changes # from other programs try: - if hasattr(os, 'link'): + try: os.link(tmp_file.name, dest) - os.remove(tmp_file.name) - else: + except (AttributeError, PermissionError): os.rename(tmp_file.name, dest) + else: + os.remove(tmp_file.name) except OSError as e: os.remove(tmp_file.name) if e.errno == errno.EEXIST: @@ -1200,13 +1201,14 @@ class MH(Mailbox): for key in self.iterkeys(): if key - 1 != prev: changes.append((key, prev + 1)) - if hasattr(os, 'link'): + try: os.link(os.path.join(self._path, str(key)), os.path.join(self._path, str(prev + 1))) - os.unlink(os.path.join(self._path, str(key))) - else: + except (AttributeError, PermissionError): os.rename(os.path.join(self._path, str(key)), os.path.join(self._path, str(prev + 1))) + else: + os.unlink(os.path.join(self._path, str(key))) prev += 1 self._next_key = prev + 1 if len(changes) == 0: @@ -2076,13 +2078,14 @@ def _lock_file(f, dotlock=True): else: raise try: - if hasattr(os, 'link'): + try: os.link(pre_lock.name, f.name + '.lock') dotlock_done = True - os.unlink(pre_lock.name) - else: + except (AttributeError, PermissionError): os.rename(pre_lock.name, f.name + '.lock') dotlock_done = True + else: + os.unlink(pre_lock.name) except FileExistsError: os.remove(pre_lock.name) raise ExternalClashError('dot lock unavailable: %s' % diff --git a/Lib/multiprocessing/context.py b/Lib/multiprocessing/context.py index 09455e2ec77..623f6fb733a 100644 --- a/Lib/multiprocessing/context.py +++ b/Lib/multiprocessing/context.py @@ -196,7 +196,7 @@ class BaseContext(object): def get_start_method(self, allow_none=False): return self._name - def set_start_method(self, method=None): + def set_start_method(self, method, force=False): raise ValueError('cannot set start method of concrete context') @property diff --git a/Lib/multiprocessing/spawn.py b/Lib/multiprocessing/spawn.py index dfb9f652701..4aba372e48e 100644 --- a/Lib/multiprocessing/spawn.py +++ b/Lib/multiprocessing/spawn.py @@ -217,7 +217,7 @@ def prepare(data): process.ORIGINAL_DIR = data['orig_dir'] if 'start_method' in data: - set_start_method(data['start_method']) + set_start_method(data['start_method'], force=True) if 'init_main_from_name' in data: _fixup_main_from_name(data['init_main_from_name']) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index b78b1b1f4bb..5d4c86ce366 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -50,9 +50,13 @@ import copy import re try: - import grp, pwd + import pwd except ImportError: - grp = pwd = None + pwd = None +try: + import grp +except ImportError: + grp = None # os.symlink on Windows prior to 6.0 raises NotImplementedError symlink_exception = (AttributeError, NotImplementedError) @@ -2219,22 +2223,25 @@ class TarFile(object): def chown(self, tarinfo, targetpath, numeric_owner): """Set owner of targetpath according to tarinfo. If numeric_owner - is True, use .gid/.uid instead of .gname/.uname. + is True, use .gid/.uid instead of .gname/.uname. If numeric_owner + is False, fall back to .gid/.uid when the search based on name + fails. """ - if pwd and hasattr(os, "geteuid") and os.geteuid() == 0: + if hasattr(os, "geteuid") and os.geteuid() == 0: # We have to be root to do so. - if numeric_owner: - g = tarinfo.gid - u = tarinfo.uid - else: + g = tarinfo.gid + u = tarinfo.uid + if not numeric_owner: try: - g = grp.getgrnam(tarinfo.gname)[2] + if grp: + g = grp.getgrnam(tarinfo.gname)[2] except KeyError: - g = tarinfo.gid + pass try: - u = pwd.getpwnam(tarinfo.uname)[2] + if pwd: + u = pwd.getpwnam(tarinfo.uname)[2] except KeyError: - u = tarinfo.uid + pass try: if tarinfo.issym() and hasattr(os, "lchown"): os.lchown(targetpath, u, g) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index c00846c7b0f..b5f47825466 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3818,6 +3818,19 @@ class TestStartMethod(unittest.TestCase): self.assertTrue(methods == ['fork', 'spawn'] or methods == ['fork', 'spawn', 'forkserver']) + def test_preload_resources(self): + if multiprocessing.get_start_method() != 'forkserver': + self.skipTest("test only relevant for 'forkserver' method") + name = os.path.join(os.path.dirname(__file__), 'mp_preload.py') + rc, out, err = test.support.script_helper.assert_python_ok(name) + out = out.decode() + err = err.decode() + if out.rstrip() != 'ok' or err != '': + print(out) + print(err) + self.fail("failed spawning forkserver or grandchild") + + # # Check that killing process does not leak named semaphores # diff --git a/Lib/test/eintrdata/eintr_tester.py b/Lib/test/eintrdata/eintr_tester.py index 9fbe04de9c5..d194e775eae 100644 --- a/Lib/test/eintrdata/eintr_tester.py +++ b/Lib/test/eintrdata/eintr_tester.py @@ -20,6 +20,7 @@ import time import unittest from test import support +android_not_root = support.android_not_root @contextlib.contextmanager def kill_on_error(proc): @@ -311,6 +312,7 @@ class SocketEINTRTest(EINTRBaseTest): # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=203162 @support.requires_freebsd_version(10, 3) @unittest.skipUnless(hasattr(os, 'mkfifo'), 'needs mkfifo()') + @unittest.skipIf(android_not_root, "mkfifo not allowed, non root user") def _test_open(self, do_open_close_reader, do_open_close_writer): filename = support.TESTFN diff --git a/Lib/test/mp_preload.py b/Lib/test/mp_preload.py new file mode 100644 index 00000000000..5314e8f0b21 --- /dev/null +++ b/Lib/test/mp_preload.py @@ -0,0 +1,18 @@ +import multiprocessing + +multiprocessing.Lock() + + +def f(): + print("ok") + + +if __name__ == "__main__": + ctx = multiprocessing.get_context("forkserver") + modname = "test.mp_preload" + # Make sure it's importable + __import__(modname) + ctx.set_forkserver_preload([modname]) + proc = ctx.Process(target=f) + proc.start() + proc.join() diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 52c908e0284..15d8fc849b9 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -93,8 +93,10 @@ __all__ = [ "check__all__", "requires_android_level", "requires_multiprocessing_queue", # sys "is_jython", "is_android", "check_impl_detail", "unix_shell", + "setswitchinterval", "android_not_root", # network "HOST", "IPV6_ENABLED", "find_unused_port", "bind_port", "open_urlresource", + "bind_unix_socket", # processes 'temp_umask', "reap_children", # logging @@ -360,9 +362,9 @@ if sys.platform.startswith("win"): mode = 0 if stat.S_ISDIR(mode): _waitfor(_rmtree_inner, fullname, waitall=True) - _force_run(path, os.rmdir, fullname) + _force_run(fullname, os.rmdir, fullname) else: - _force_run(path, os.unlink, fullname) + _force_run(fullname, os.unlink, fullname) _waitfor(_rmtree_inner, path, waitall=True) _waitfor(lambda p: _force_run(p, os.rmdir, p), path) else: @@ -707,6 +709,15 @@ def bind_port(sock, host=HOST): port = sock.getsockname()[1] return port +def bind_unix_socket(sock, addr): + """Bind a unix socket, raising SkipTest if PermissionError is raised.""" + assert sock.family == socket.AF_UNIX + try: + sock.bind(addr) + except PermissionError: + sock.close() + raise unittest.SkipTest('cannot bind AF_UNIX sockets') + def _is_ipv6_enabled(): """Check whether IPv6 is enabled on this host.""" if socket.has_ipv6: @@ -768,6 +779,7 @@ is_jython = sys.platform.startswith('java') _ANDROID_API_LEVEL = sysconfig.get_config_var('ANDROID_API_LEVEL') is_android = (_ANDROID_API_LEVEL is not None and _ANDROID_API_LEVEL > 0) +android_not_root = (is_android and os.geteuid() != 0) if sys.platform != 'win32': unix_shell = '/system/bin/sh' if is_android else '/bin/sh' @@ -1054,9 +1066,16 @@ def make_bad_fd(): file.close() unlink(TESTFN) -def check_syntax_error(testcase, statement): - testcase.assertRaises(SyntaxError, compile, statement, - '<test string>', 'exec') +def check_syntax_error(testcase, statement, *, lineno=None, offset=None): + with testcase.assertRaises(SyntaxError) as cm: + compile(statement, '<test string>', 'exec') + err = cm.exception + testcase.assertIsNotNone(err.lineno) + if lineno is not None: + testcase.assertEqual(err.lineno, lineno) + testcase.assertIsNotNone(err.offset) + if offset is not None: + testcase.assertEqual(err.offset, offset) def open_urlresource(url, *args, **kw): import urllib.request, urllib.parse @@ -2547,3 +2566,18 @@ def missing_compiler_executable(cmd_names=[]): continue if spawn.find_executable(cmd[0]) is None: return cmd[0] + + +_is_android_emulator = None +def setswitchinterval(interval): + # Setting a very low gil interval on the Android emulator causes python + # to hang (issue #26939). + minimum_interval = 1e-5 + if is_android and interval < minimum_interval: + global _is_android_emulator + if _is_android_emulator is None: + _is_android_emulator = (subprocess.check_output( + ['getprop', 'ro.kernel.qemu']).strip() == b'1') + if _is_android_emulator: + interval = minimum_interval + return sys.setswitchinterval(interval) diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py index dbee593c544..51c65737a44 100644 --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -95,7 +95,9 @@ def bind_af_aware(sock, addr): if HAS_UNIX_SOCKETS and sock.family == socket.AF_UNIX: # Make sure the path doesn't exist. support.unlink(addr) - sock.bind(addr) + support.bind_unix_socket(sock, addr) + else: + sock.bind(addr) class HelperFunctionTests(unittest.TestCase): diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index b71bb9f7ee5..ae2bcd43754 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -8,7 +8,7 @@ import shutil import sys import subprocess import tempfile -from test.support import script_helper +from test.support import script_helper, is_android from test.support.script_helper import (spawn_python, kill_python, assert_python_ok, assert_python_failure) @@ -178,15 +178,16 @@ class CmdLineTest(unittest.TestCase): if not stdout.startswith(pattern): raise AssertionError("%a doesn't start with %a" % (stdout, pattern)) - @unittest.skipUnless(sys.platform == 'darwin', 'test specific to Mac OS X') - def test_osx_utf8(self): + @unittest.skipUnless((sys.platform == 'darwin' or + is_android), 'test specific to Mac OS X and Android') + def test_osx_android_utf8(self): def check_output(text): decoded = text.decode('utf-8', 'surrogateescape') expected = ascii(decoded).encode('ascii') + b'\n' env = os.environ.copy() # C locale gives ASCII locale encoding, but Python uses UTF-8 - # to parse the command line arguments on Mac OS X + # to parse the command line arguments on Mac OS X and Android. env['LC_ALL'] = 'C' p = subprocess.Popen( diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py index 2d77f078b76..df531d64e48 100644 --- a/Lib/test/test_dbm_dumb.py +++ b/Lib/test/test_dbm_dumb.py @@ -5,6 +5,7 @@ import io import operator import os +import stat import unittest import warnings import dbm.dumb as dumbdbm @@ -259,6 +260,21 @@ class DumbDBMTestCase(unittest.TestCase): f = dumbdbm.open(_fname, flag) f.close() + @unittest.skipUnless(hasattr(os, 'chmod'), 'test needs os.chmod()') + def test_readonly_files(self): + with support.temp_dir() as dir: + fname = os.path.join(dir, 'db') + with dumbdbm.open(fname, 'n') as f: + self.assertEqual(list(f.keys()), []) + for key in self._dict: + f[key] = self._dict[key] + os.chmod(fname + ".dir", stat.S_IRUSR) + os.chmod(fname + ".dat", stat.S_IRUSR) + os.chmod(dir, stat.S_IRUSR|stat.S_IXUSR) + with dumbdbm.open(fname, 'r') as f: + self.assertEqual(sorted(f.keys()), sorted(self._dict)) + f.close() # don't write + def tearDown(self): _delete_files() diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 1e08ed92cec..c5bff7718dc 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -7,6 +7,7 @@ import pickle import sys import types import unittest +import warnings import weakref from copy import deepcopy @@ -1661,6 +1662,77 @@ order (MRO) for bases """ self.assertEqual(b.foo, 3) self.assertEqual(b.__class__, D) + @unittest.expectedFailure + def test_bad_new(self): + self.assertRaises(TypeError, object.__new__) + self.assertRaises(TypeError, object.__new__, '') + self.assertRaises(TypeError, list.__new__, object) + self.assertRaises(TypeError, object.__new__, list) + class C(object): + __new__ = list.__new__ + self.assertRaises(TypeError, C) + class C(list): + __new__ = object.__new__ + self.assertRaises(TypeError, C) + + def test_object_new(self): + class A(object): + pass + object.__new__(A) + self.assertRaises(TypeError, object.__new__, A, 5) + object.__init__(A()) + self.assertRaises(TypeError, object.__init__, A(), 5) + + class A(object): + def __init__(self, foo): + self.foo = foo + object.__new__(A) + object.__new__(A, 5) + object.__init__(A(3)) + self.assertRaises(TypeError, object.__init__, A(3), 5) + + class A(object): + def __new__(cls, foo): + return object.__new__(cls) + object.__new__(A) + self.assertRaises(TypeError, object.__new__, A, 5) + object.__init__(A(3)) + object.__init__(A(3), 5) + + class A(object): + def __new__(cls, foo): + return object.__new__(cls) + def __init__(self, foo): + self.foo = foo + object.__new__(A) + self.assertRaises(TypeError, object.__new__, A, 5) + object.__init__(A(3)) + self.assertRaises(TypeError, object.__init__, A(3), 5) + + @unittest.expectedFailure + def test_restored_object_new(self): + class A(object): + def __new__(cls, *args, **kwargs): + raise AssertionError + self.assertRaises(AssertionError, A) + class B(A): + __new__ = object.__new__ + def __init__(self, foo): + self.foo = foo + with warnings.catch_warnings(): + warnings.simplefilter('error', DeprecationWarning) + b = B(3) + self.assertEqual(b.foo, 3) + self.assertEqual(b.__class__, B) + del B.__new__ + self.assertRaises(AssertionError, B) + del A.__new__ + with warnings.catch_warnings(): + warnings.simplefilter('error', DeprecationWarning) + b = B(3) + self.assertEqual(b.foo, 3) + self.assertEqual(b.__class__, B) + def test_altmro(self): # Testing mro() and overriding it... class A(object): @@ -3522,6 +3594,24 @@ order (MRO) for bases """ self.assertIsInstance(d, D) self.assertEqual(d.foo, 1) + class C(object): + @staticmethod + def __new__(*args): + return args + self.assertEqual(C(1, 2), (C, 1, 2)) + class D(C): + pass + self.assertEqual(D(1, 2), (D, 1, 2)) + + class C(object): + @classmethod + def __new__(*args): + return args + self.assertEqual(C(1, 2), (C, C, 1, 2)) + class D(C): + pass + self.assertEqual(D(1, 2), (D, D, 1, 2)) + def test_imul_bug(self): # Testing for __imul__ problems... # SF bug 544647 diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py index 8afd5b8f1fa..5471be21b5e 100644 --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -200,42 +200,28 @@ class FormatTest(unittest.TestCase): testcommon("%#+37.34o", big, "+0o0012345670123456701234567012345670") # next one gets one leading zero from precision testcommon("%.33o", big, "012345670123456701234567012345670") - # base marker shouldn't change that, since "0" is redundant + # base marker added in spite of leading zero (different to Python 2) testcommon("%#.33o", big, "0o012345670123456701234567012345670") - # but reduce precision, and base marker should add a zero + # reduce precision, and base marker is always added testcommon("%#.32o", big, "0o12345670123456701234567012345670") - # one leading zero from precision, and another from "0" flag & width - testcommon("%034.33o", big, "0012345670123456701234567012345670") - # base marker shouldn't change that - testcommon("%0#34.33o", big, "0o012345670123456701234567012345670") + # one leading zero from precision, plus two from "0" flag & width + testcommon("%035.33o", big, "00012345670123456701234567012345670") + # base marker shouldn't change the size + testcommon("%0#35.33o", big, "0o012345670123456701234567012345670") # Some small ints, in both Python int and flavors). testcommon("%d", 42, "42") testcommon("%d", -42, "-42") - testcommon("%d", 42, "42") - testcommon("%d", -42, "-42") testcommon("%d", 42.0, "42") testcommon("%#x", 1, "0x1") - testcommon("%#x", 1, "0x1") - testcommon("%#X", 1, "0X1") testcommon("%#X", 1, "0X1") testcommon("%#o", 1, "0o1") - testcommon("%#o", 1, "0o1") - testcommon("%#o", 0, "0o0") testcommon("%#o", 0, "0o0") testcommon("%o", 0, "0") - testcommon("%o", 0, "0") testcommon("%d", 0, "0") - testcommon("%d", 0, "0") - testcommon("%#x", 0, "0x0") testcommon("%#x", 0, "0x0") testcommon("%#X", 0, "0X0") - testcommon("%#X", 0, "0X0") testcommon("%x", 0x42, "42") testcommon("%x", -0x42, "-42") - testcommon("%x", 0x42, "42") - testcommon("%x", -0x42, "-42") - testcommon("%o", 0o42, "42") - testcommon("%o", -0o42, "-42") testcommon("%o", 0o42, "42") testcommon("%o", -0o42, "-42") # alternate float formatting diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index 82050835f6a..708ed25b526 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -70,18 +70,18 @@ f'{a * x()}'""" # Make sure x was called. self.assertTrue(x.called) - def test_literal_eval(self): - # With no expressions, an f-string is okay. - self.assertEqual(ast.literal_eval("f'x'"), 'x') - self.assertEqual(ast.literal_eval("f'x' 'y'"), 'xy') - - # But this should raise an error. - with self.assertRaisesRegex(ValueError, 'malformed node or string'): - ast.literal_eval("f'x{3}'") + def test_docstring(self): + def f(): + f'''Not a docstring''' + self.assertIsNone(f.__doc__) + def g(): + '''Not a docstring''' \ + f'' + self.assertIsNone(g.__doc__) - # As should this, which uses a different ast node + def test_literal_eval(self): with self.assertRaisesRegex(ValueError, 'malformed node or string'): - ast.literal_eval("f'{3}'") + ast.literal_eval("f'x'") def test_ast_compile_time_concat(self): x = [''] diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 75427dfad34..ba2a52fb734 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1322,7 +1322,7 @@ class TestLRU: f.cache_clear() orig_si = sys.getswitchinterval() - sys.setswitchinterval(1e-6) + support.setswitchinterval(1e-6) try: # create n threads in order to fill cache threads = [threading.Thread(target=full, args=[k]) diff --git a/Lib/test/test_future.py b/Lib/test/test_future.py index 213b2ba0755..2f1c410b1bf 100644 --- a/Lib/test/test_future.py +++ b/Lib/test/test_future.py @@ -2,6 +2,7 @@ import unittest from test import support +import os import re rx = re.compile(r'\((\S+).py, line (\d+)') @@ -12,6 +13,12 @@ def get_error_location(msg): class FutureTest(unittest.TestCase): + def check_syntax_error(self, err, basename, lineno, offset=0): + self.assertIn('%s.py, line %d' % (basename, lineno), str(err)) + self.assertEqual(os.path.basename(err.filename), basename + '.py') + self.assertEqual(err.lineno, lineno) + self.assertEqual(err.offset, offset) + def test_future1(self): with support.CleanImport('future_test1'): from test import future_test1 @@ -27,68 +34,44 @@ class FutureTest(unittest.TestCase): from test import test_future3 def test_badfuture3(self): - try: + with self.assertRaises(SyntaxError) as cm: from test import badsyntax_future3 - except SyntaxError as msg: - self.assertEqual(get_error_location(msg), ("badsyntax_future3", '3')) - else: - self.fail("expected exception didn't occur") + self.check_syntax_error(cm.exception, "badsyntax_future3", 3) def test_badfuture4(self): - try: + with self.assertRaises(SyntaxError) as cm: from test import badsyntax_future4 - except SyntaxError as msg: - self.assertEqual(get_error_location(msg), ("badsyntax_future4", '3')) - else: - self.fail("expected exception didn't occur") + self.check_syntax_error(cm.exception, "badsyntax_future4", 3) def test_badfuture5(self): - try: + with self.assertRaises(SyntaxError) as cm: from test import badsyntax_future5 - except SyntaxError as msg: - self.assertEqual(get_error_location(msg), ("badsyntax_future5", '4')) - else: - self.fail("expected exception didn't occur") + self.check_syntax_error(cm.exception, "badsyntax_future5", 4) def test_badfuture6(self): - try: + with self.assertRaises(SyntaxError) as cm: from test import badsyntax_future6 - except SyntaxError as msg: - self.assertEqual(get_error_location(msg), ("badsyntax_future6", '3')) - else: - self.fail("expected exception didn't occur") + self.check_syntax_error(cm.exception, "badsyntax_future6", 3) def test_badfuture7(self): - try: + with self.assertRaises(SyntaxError) as cm: from test import badsyntax_future7 - except SyntaxError as msg: - self.assertEqual(get_error_location(msg), ("badsyntax_future7", '3')) - else: - self.fail("expected exception didn't occur") + self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 53) def test_badfuture8(self): - try: + with self.assertRaises(SyntaxError) as cm: from test import badsyntax_future8 - except SyntaxError as msg: - self.assertEqual(get_error_location(msg), ("badsyntax_future8", '3')) - else: - self.fail("expected exception didn't occur") + self.check_syntax_error(cm.exception, "badsyntax_future8", 3) def test_badfuture9(self): - try: + with self.assertRaises(SyntaxError) as cm: from test import badsyntax_future9 - except SyntaxError as msg: - self.assertEqual(get_error_location(msg), ("badsyntax_future9", '3')) - else: - self.fail("expected exception didn't occur") + self.check_syntax_error(cm.exception, "badsyntax_future9", 3, 0) def test_badfuture10(self): - try: + with self.assertRaises(SyntaxError) as cm: from test import badsyntax_future10 - except SyntaxError as msg: - self.assertEqual(get_error_location(msg), ("badsyntax_future10", '3')) - else: - self.fail("expected exception didn't occur") + self.check_syntax_error(cm.exception, "badsyntax_future10", 3, 0) def test_parserhack(self): # test that the parser.c::future_hack function works as expected diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py index 2bd4457e616..60f1d928467 100644 --- a/Lib/test/test_gdb.py +++ b/Lib/test/test_gdb.py @@ -679,7 +679,7 @@ class StackNavigationTests(DebuggerTests): def test_pyup_command(self): 'Verify that the "py-up" command works' bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-up']) + cmds_after_breakpoint=['py-up', 'py-up']) self.assertMultilineMatches(bt, r'''^.* #[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\) @@ -698,7 +698,7 @@ $''') def test_up_at_top(self): 'Verify handling of "py-up" at the top of the stack' bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-up'] * 4) + cmds_after_breakpoint=['py-up'] * 5) self.assertEndsWith(bt, 'Unable to find an older python frame\n') @@ -708,7 +708,7 @@ $''') def test_up_then_down(self): 'Verify "py-up" followed by "py-down"' bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-up', 'py-down']) + cmds_after_breakpoint=['py-up', 'py-up', 'py-down']) self.assertMultilineMatches(bt, r'''^.* #[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\) @@ -727,6 +727,7 @@ class PyBtTests(DebuggerTests): self.assertMultilineMatches(bt, r'''^.* Traceback \(most recent call first\): + <built-in method id of module object .*> File ".*gdb_sample.py", line 10, in baz id\(42\) File ".*gdb_sample.py", line 7, in bar @@ -815,7 +816,6 @@ id(42) ) self.assertIn('Garbage-collecting', gdb_output) - @unittest.skip("FIXME: builtin method is not shown in py-bt and py-bt-full") @unittest.skipIf(python_is_optimized(), "Python was compiled with optimizations") # Some older versions of gdb will fail with @@ -854,7 +854,7 @@ class PyPrintTests(DebuggerTests): def test_basic_command(self): 'Verify that the "py-print" command works' bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-print args']) + cmds_after_breakpoint=['py-up', 'py-print args']) self.assertMultilineMatches(bt, r".*\nlocal 'args' = \(1, 2, 3\)\n.*") @@ -863,7 +863,7 @@ class PyPrintTests(DebuggerTests): @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") def test_print_after_up(self): bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-up', 'py-print c', 'py-print b', 'py-print a']) + cmds_after_breakpoint=['py-up', 'py-up', 'py-print c', 'py-print b', 'py-print a']) self.assertMultilineMatches(bt, r".*\nlocal 'c' = 3\nlocal 'b' = 2\nlocal 'a' = 1\n.*") @@ -871,7 +871,7 @@ class PyPrintTests(DebuggerTests): "Python was compiled with optimizations") def test_printing_global(self): bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-print __name__']) + cmds_after_breakpoint=['py-up', 'py-print __name__']) self.assertMultilineMatches(bt, r".*\nglobal '__name__' = '__main__'\n.*") @@ -879,7 +879,7 @@ class PyPrintTests(DebuggerTests): "Python was compiled with optimizations") def test_printing_builtin(self): bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-print len']) + cmds_after_breakpoint=['py-up', 'py-print len']) self.assertMultilineMatches(bt, r".*\nbuiltin 'len' = <built-in method len of module object at remote 0x-?[0-9a-f]+>\n.*") @@ -888,7 +888,7 @@ class PyLocalsTests(DebuggerTests): "Python was compiled with optimizations") def test_basic_command(self): bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-locals']) + cmds_after_breakpoint=['py-up', 'py-locals']) self.assertMultilineMatches(bt, r".*\nargs = \(1, 2, 3\)\n.*") @@ -897,7 +897,7 @@ class PyLocalsTests(DebuggerTests): "Python was compiled with optimizations") def test_locals_after_up(self): bt = self.get_stack_trace(script=self.get_sample_script(), - cmds_after_breakpoint=['py-up', 'py-locals']) + cmds_after_breakpoint=['py-up', 'py-up', 'py-locals']) self.assertMultilineMatches(bt, r".*\na = 1\nb = 2\nc = 3\n.*") diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py index ae5dd6a5f7c..f698e13f68a 100644 --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -8,6 +8,7 @@ import sys import unittest import warnings from test import support +android_not_root = support.android_not_root def create_file(filename, data=b'foo'): @@ -212,6 +213,7 @@ class GenericTest: def test_samefile_on_symlink(self): self._test_samefile_on_link_func(os.symlink) + @unittest.skipIf(android_not_root, "hard links not allowed, non root user") def test_samefile_on_link(self): self._test_samefile_on_link_func(os.link) @@ -251,6 +253,7 @@ class GenericTest: def test_samestat_on_symlink(self): self._test_samestat_on_link_func(os.symlink) + @unittest.skipIf(android_not_root, "hard links not allowed, non root user") def test_samestat_on_link(self): self._test_samestat_on_link_func(os.link) diff --git a/Lib/test/test_global.py b/Lib/test/test_global.py index 37ec67255a5..9eeccf12506 100644 --- a/Lib/test/test_global.py +++ b/Lib/test/test_global.py @@ -24,7 +24,7 @@ def wrong1(): global a global b """ - check_syntax_error(self, prog_text_1) + check_syntax_error(self, prog_text_1, lineno=4, offset=4) def test2(self): prog_text_2 = """\ @@ -32,7 +32,7 @@ def wrong2(): print(x) global x """ - check_syntax_error(self, prog_text_2) + check_syntax_error(self, prog_text_2, lineno=3, offset=4) def test3(self): prog_text_3 = """\ @@ -41,7 +41,7 @@ def wrong3(): x = 2 global x """ - check_syntax_error(self, prog_text_3) + check_syntax_error(self, prog_text_3, lineno=4, offset=4) def test4(self): prog_text_4 = """\ diff --git a/Lib/test/test_importlib/test_locks.py b/Lib/test/test_importlib/test_locks.py index b2aadff289b..dbce9c2dfdf 100644 --- a/Lib/test/test_importlib/test_locks.py +++ b/Lib/test/test_importlib/test_locks.py @@ -57,7 +57,7 @@ if threading is not None: def setUp(self): try: self.old_switchinterval = sys.getswitchinterval() - sys.setswitchinterval(0.000001) + support.setswitchinterval(0.000001) except AttributeError: self.old_switchinterval = None diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py index aeabdbb2b5e..2ba944335ae 100644 --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -2137,9 +2137,9 @@ class MaildirTestCase(unittest.TestCase): if mbox: fp.write(FROM_) fp.write(DUMMY_MESSAGE) - if hasattr(os, "link"): + try: os.link(tmpname, newname) - else: + except (AttributeError, PermissionError): with open(newname, "w") as fp: fp.write(DUMMY_MESSAGE) self._msgfiles.append(newname) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index f98c1febb5c..ce1ca153ed0 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -10,6 +10,7 @@ import tempfile import unittest from test import support +android_not_root = support.android_not_root TESTFN = support.TESTFN try: @@ -1864,6 +1865,7 @@ class _BasePathTest(object): self.assertFalse((P / 'fileA' / 'bah').is_fifo()) @unittest.skipUnless(hasattr(os, "mkfifo"), "os.mkfifo() required") + @unittest.skipIf(android_not_root, "mkfifo not allowed, non root user") def test_is_fifo_true(self): P = self.cls(BASE, 'myfifo') os.mkfifo(str(P)) @@ -1886,7 +1888,8 @@ class _BasePathTest(object): try: sock.bind(str(P)) except OSError as e: - if "AF_UNIX path too long" in str(e): + if (isinstance(e, PermissionError) or + "AF_UNIX path too long" in str(e)): self.skipTest("cannot bind Unix socket: " + str(e)) self.assertTrue(P.is_socket()) self.assertFalse(P.is_fifo()) @@ -2080,6 +2083,8 @@ class PosixPathTest(_BasePathTest, unittest.TestCase): self.assertEqual(given, expect) self.assertEqual(set(p.rglob("FILEd*")), set()) + @unittest.skipUnless(hasattr(pwd, 'getpwall'), + 'pwd module does not expose getpwall()') def test_expanduser(self): P = self.cls support.import_module('pwd') diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 63c74cd80da..029d0815e94 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1,6 +1,7 @@ "Test posix functions" from test import support +android_not_root = support.android_not_root # Skip these tests if there is no posix module. posix = support.import_module('posix') @@ -422,6 +423,7 @@ class PosixTester(unittest.TestCase): posix.stat, list(os.fsencode(support.TESTFN))) @unittest.skipUnless(hasattr(posix, 'mkfifo'), "don't have mkfifo()") + @unittest.skipIf(android_not_root, "mkfifo not allowed, non root user") def test_mkfifo(self): support.unlink(support.TESTFN) posix.mkfifo(support.TESTFN, stat.S_IRUSR | stat.S_IWUSR) @@ -429,6 +431,7 @@ class PosixTester(unittest.TestCase): @unittest.skipUnless(hasattr(posix, 'mknod') and hasattr(stat, 'S_IFIFO'), "don't have mknod()/S_IFIFO") + @unittest.skipIf(android_not_root, "mknod not allowed, non root user") def test_mknod(self): # Test using mknod() to create a FIFO (the only use specified # by POSIX). @@ -907,6 +910,7 @@ class PosixTester(unittest.TestCase): posix.close(f) @unittest.skipUnless(os.link in os.supports_dir_fd, "test needs dir_fd support in os.link()") + @unittest.skipIf(android_not_root, "hard link not allowed, non root user") def test_link_dir_fd(self): f = posix.open(posix.getcwd(), posix.O_RDONLY) try: @@ -930,6 +934,7 @@ class PosixTester(unittest.TestCase): @unittest.skipUnless((os.mknod in os.supports_dir_fd) and hasattr(stat, 'S_IFIFO'), "test requires both stat.S_IFIFO and dir_fd support for os.mknod()") + @unittest.skipIf(android_not_root, "mknod not allowed, non root user") def test_mknod_dir_fd(self): # Test using mknodat() to create a FIFO (the only use specified # by POSIX). @@ -1013,6 +1018,7 @@ class PosixTester(unittest.TestCase): posix.close(f) @unittest.skipUnless(os.mkfifo in os.supports_dir_fd, "test needs dir_fd support in os.mkfifo()") + @unittest.skipIf(android_not_root, "mkfifo not allowed, non root user") def test_mkfifo_dir_fd(self): support.unlink(support.TESTFN) f = posix.open(posix.getcwd(), posix.O_RDONLY) diff --git a/Lib/test/test_pwd.py b/Lib/test/test_pwd.py index b7b1a4a5f64..ac9cff789ee 100644 --- a/Lib/test/test_pwd.py +++ b/Lib/test/test_pwd.py @@ -4,10 +4,19 @@ from test import support pwd = support.import_module('pwd') +def _getpwall(): + # Android does not have getpwall. + if hasattr(pwd, 'getpwall'): + return pwd.getpwall() + elif hasattr(pwd, 'getpwuid'): + return [pwd.getpwuid(0)] + else: + return [] + class PwdTest(unittest.TestCase): def test_values(self): - entries = pwd.getpwall() + entries = _getpwall() for e in entries: self.assertEqual(len(e), 7) @@ -33,7 +42,7 @@ class PwdTest(unittest.TestCase): # and check afterwards (done in test_values_extended) def test_values_extended(self): - entries = pwd.getpwall() + entries = _getpwall() entriesbyname = {} entriesbyuid = {} @@ -57,12 +66,13 @@ class PwdTest(unittest.TestCase): self.assertRaises(TypeError, pwd.getpwuid, 3.14) self.assertRaises(TypeError, pwd.getpwnam) self.assertRaises(TypeError, pwd.getpwnam, 42) - self.assertRaises(TypeError, pwd.getpwall, 42) + if hasattr(pwd, 'getpwall'): + self.assertRaises(TypeError, pwd.getpwall, 42) # try to get some errors bynames = {} byuids = {} - for (n, p, u, g, gecos, d, s) in pwd.getpwall(): + for (n, p, u, g, gecos, d, s) in _getpwall(): bynames[n] = u byuids[u] = n @@ -96,13 +106,17 @@ class PwdTest(unittest.TestCase): # loop, say), pwd.getpwuid() might still be able to find data for that # uid. Using sys.maxint 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 self.assertNotIn(fakeuid, byuids) - self.assertRaises(KeyError, pwd.getpwuid, fakeuid) + if not support.is_android: + self.assertRaises(KeyError, pwd.getpwuid, fakeuid) # -1 shouldn't be a valid uid because it has a special meaning in many # uid-related functions - self.assertRaises(KeyError, pwd.getpwuid, -1) + if not support.is_android: + self.assertRaises(KeyError, pwd.getpwuid, -1) # should be out of uid_t range self.assertRaises(KeyError, pwd.getpwuid, 2**128) self.assertRaises(KeyError, pwd.getpwuid, -2**128) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index af5f00fdf0d..46e2c57746d 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -22,7 +22,8 @@ import tarfile import warnings from test import support -from test.support import TESTFN, check_warnings, captured_stdout, requires_zlib +from test.support import (TESTFN, check_warnings, captured_stdout, + requires_zlib, android_not_root) try: import bz2 @@ -787,6 +788,7 @@ class TestShutil(unittest.TestCase): @unittest.skipIf(os.name == 'nt', 'temporarily disabled on Windows') @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link') + @unittest.skipIf(android_not_root, "hard links not allowed, non root user") def test_dont_copy_file_onto_link_to_itself(self): # bug 851123. os.mkdir(TESTFN) @@ -839,6 +841,7 @@ class TestShutil(unittest.TestCase): # Issue #3002: copyfile and copytree block indefinitely on named pipes @unittest.skipUnless(hasattr(os, "mkfifo"), 'requires os.mkfifo()') + @unittest.skipIf(android_not_root, "mkfifo not allowed, non root user") def test_copyfile_named_pipe(self): os.mkfifo(TESTFN) try: @@ -849,6 +852,7 @@ class TestShutil(unittest.TestCase): finally: os.remove(TESTFN) + @unittest.skipIf(android_not_root, "mkfifo not allowed, non root user") @unittest.skipUnless(hasattr(os, "mkfifo"), 'requires os.mkfifo()') @support.skip_unless_symlink def test_copytree_named_pipe(self): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 59564c9063d..6b29e182348 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -278,8 +278,14 @@ class ThreadableTest: def clientRun(self, test_func): self.server_ready.wait() - self.clientSetUp() - self.client_ready.set() + try: + self.clientSetUp() + except BaseException as e: + self.queue.put(e) + self.clientTearDown() + return + finally: + self.client_ready.set() if self.server_crashed: self.clientTearDown() return @@ -520,8 +526,11 @@ class ConnectedStreamTestMixin(SocketListeningTestMixin, self.serv_conn = self.cli def clientTearDown(self): - self.serv_conn.close() - self.serv_conn = None + try: + self.serv_conn.close() + self.serv_conn = None + except AttributeError: + pass super().clientTearDown() @@ -540,7 +549,7 @@ class UnixSocketTestBase(SocketTestBase): def bindSock(self, sock): path = tempfile.mktemp(dir=self.dir_path) - sock.bind(path) + support.bind_unix_socket(sock, path) self.addCleanup(support.unlink, path) class UnixStreamBase(UnixSocketTestBase): @@ -4631,7 +4640,7 @@ class TestUnixDomain(unittest.TestCase): def bind(self, sock, path): # Bind the socket try: - sock.bind(path) + support.bind_unix_socket(sock, path) except OSError as e: if str(e) == "AF_UNIX path too long": self.skipTest( diff --git a/Lib/test/test_stat.py b/Lib/test/test_stat.py index f1a5938a39f..cd02a6ee374 100644 --- a/Lib/test/test_stat.py +++ b/Lib/test/test_stat.py @@ -1,7 +1,7 @@ import unittest import os import sys -from test.support import TESTFN, import_fresh_module +from test.support import TESTFN, import_fresh_module, android_not_root c_stat = import_fresh_module('stat', fresh=['_stat']) py_stat = import_fresh_module('stat', blocked=['_stat']) @@ -168,6 +168,7 @@ class TestFilemode: self.assertS_IS("LNK", st_mode) @unittest.skipUnless(hasattr(os, 'mkfifo'), 'os.mkfifo not available') + @unittest.skipIf(android_not_root, "mkfifo not allowed, non root user") def test_fifo(self): os.mkfifo(TESTFN, 0o700) st_mode, modestr = self.get_mode() diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index 553822b5823..e83a4d6426a 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -240,7 +240,7 @@ class TestSupport(unittest.TestCase): self.assertEqual(cm.exception.errno, errno.EBADF) def test_check_syntax_error(self): - support.check_syntax_error(self, "def class") + support.check_syntax_error(self, "def class", lineno=1, offset=9) with self.assertRaises(AssertionError): support.check_syntax_error(self, "x=1") diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index 30471653c36..dfaee173ef7 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -159,15 +159,17 @@ class SymtableTest(unittest.TestCase): def test_filename_correct(self): ### Bug tickler: SyntaxError file name correct whether error raised ### while parsing or building symbol table. - def checkfilename(brokencode): + def checkfilename(brokencode, offset): try: symtable.symtable(brokencode, "spam", "exec") except SyntaxError as e: self.assertEqual(e.filename, "spam") + self.assertEqual(e.lineno, 1) + self.assertEqual(e.offset, offset) else: self.fail("no SyntaxError for %r" % (brokencode,)) - checkfilename("def f(x): foo)(") # parse-time - checkfilename("def f(x): global x") # symtable-build-time + checkfilename("def f(x): foo)(", 14) # parse-time + checkfilename("def f(x): global x", 10) # symtable-build-time symtable.symtable("pass", b"spam", "exec") with self.assertWarns(DeprecationWarning), \ self.assertRaises(TypeError): diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 80e36fd46e5..7f7e6dafcf9 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -544,7 +544,7 @@ from test import support class SyntaxTestCase(unittest.TestCase): def _check_error(self, code, errtext, - filename="<testcase>", mode="exec", subclass=None): + filename="<testcase>", mode="exec", subclass=None, lineno=None, offset=None): """Check that compiling code raises SyntaxError with errtext. errtest is a regular expression that must be present in the @@ -559,6 +559,11 @@ class SyntaxTestCase(unittest.TestCase): mo = re.search(errtext, str(err)) if mo is None: self.fail("SyntaxError did not contain '%r'" % (errtext,)) + self.assertEqual(err.filename, filename) + if lineno is not None: + self.assertEqual(err.lineno, lineno) + if offset is not None: + self.assertEqual(err.offset, offset) else: self.fail("compile() did not raise SyntaxError") @@ -569,7 +574,7 @@ class SyntaxTestCase(unittest.TestCase): self._check_error("del f()", "delete") def test_global_err_then_warn(self): - # Bug tickler: The SyntaxError raised for one global statement + # Bug #763201: The SyntaxError raised for one global statement # shouldn't be clobbered by a SyntaxWarning issued for a later one. source = """if 1: def error(a): diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 091e90522de..355bc614da3 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -385,7 +385,9 @@ class TestSysConfig(unittest.TestCase): self.assertIsNotNone(vars['SO']) self.assertEqual(vars['SO'], vars['EXT_SUFFIX']) - @unittest.skipUnless(sys.platform == 'linux', 'Linux-specific test') + @unittest.skipUnless(sys.platform == 'linux' and + hasattr(sys.implementation, '_multiarch'), + 'multiarch-specific test') def test_triplet_in_ext_suffix(self): import ctypes, platform, re machine = platform.machine() @@ -395,7 +397,6 @@ class TestSysConfig(unittest.TestCase): if re.match('(i[3-6]86|x86_64)$', machine): if ctypes.sizeof(ctypes.c_char_p()) == 4: self.assertTrue(suffix.endswith('i386-linux-gnu.so') or - suffix.endswith('i686-linux-android.so') or suffix.endswith('x86_64-linux-gnux32.so'), suffix) else: # 8 byte pointer size diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 845e7d4bd40..2c2914fd6d8 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -462,7 +462,7 @@ class ThreadTests(BaseTestCase): self.addCleanup(sys.setswitchinterval, old_interval) # Make the bug more likely to manifest. - sys.setswitchinterval(1e-6) + test.support.setswitchinterval(1e-6) for i in range(20): t = threading.Thread(target=lambda: None) diff --git a/Makefile.pre.in b/Makefile.pre.in index cd7d33d2304..48b5180b074 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -858,8 +858,8 @@ UNICODE_DEPS = \ $(srcdir)/Objects/stringlib/unicode_format.h \ $(srcdir)/Objects/stringlib/unicodedefs.h +Objects/bytes_methods.o: $(srcdir)/Objects/bytes_methods.c $(BYTESTR_DEPS) Objects/bytesobject.o: $(srcdir)/Objects/bytesobject.c $(BYTESTR_DEPS) - Objects/bytearrayobject.o: $(srcdir)/Objects/bytearrayobject.c $(BYTESTR_DEPS) Objects/unicodeobject.o: $(srcdir)/Objects/unicodeobject.c $(UNICODE_DEPS) diff --git a/Misc/NEWS b/Misc/NEWS index 5cf929f21f8..477dc9ba146 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,7 +2,7 @@ Python News +++++++++++ -What's New in Python 3.6.0 release candidate 2 +What's New in Python 3.6.1 release candidate 1 ============================================== *Release date: XXXX-XX-XX* @@ -10,19 +10,62 @@ What's New in Python 3.6.0 release candidate 2 Core and Builtins ----------------- +- Issue #26919: On Android, operating system data is now always encoded/decoded + to/from UTF-8, instead of the locale encoding to avoid inconsistencies with + os.fsencode() and os.fsdecode() which are already using UTF-8. + - Issue #28147: Fix a memory leak in split-table dictionaries: setattr() must not convert combined table into split table. Patch written by INADA Naoki. +- Issue #28739: f-string expressions no longer accepted as docstrings and + by ast.literal_eval() even if they do not include expressions. + +- Issue #28512: Fixed setting the offset attribute of SyntaxError by + PyErr_SyntaxLocationEx() and PyErr_SyntaxLocationObject(). + +- Issue #28918: Fix the cross compilation of xxlimited when Python has been + built with Py_DEBUG defined. + +- Issue #28731: Optimize _PyDict_NewPresized() to create correct size dict. + Improve speed of dict literal with constant keys up to 30%. + +Library +------- + +- Issue #28779: multiprocessing.set_forkserver_preload() would crash the + forkserver process if a preloaded module instantiated some + multiprocessing objects such as locks. + +- Issue #28847: dbm.dumb now supports reading read-only files and no longer + writes the index file when it is not changed. + +- Issue #26937: The chown() method of the tarfile.TarFile class does not fail + now when the grp module cannot be imported, as for example on Android + platforms. + Windows ------- -- Issue #28896: Deprecate WindowsRegistryFinder +- Issue #28896: Deprecate WindowsRegistryFinder and disable it by default. + +Tests +----- + +- Issue #28683: Fix the tests that bind() a unix socket and raise + PermissionError on Android for a non-root user. + +- Issue #26939: Add the support.setswitchinterval() function to fix + test_functools hanging on the Android armv7 qemu emulator. Build ----- -- Issue #28898: Prevent gdb build errors due to HAVE_LONG_LONG redefinition. +- Issue #20211: Do not add the directory for installing C header files and the + directory for installing object code libraries to the cross compilation + search paths. Original patch by Thomas Petazzoni. + +- Issue #28849: Do not define sys.implementation._multiarch on Android. What's New in Python 3.6.0 release candidate 1 diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 4e8f74a3c94..fff90468a59 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -1327,7 +1327,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop) return -1; } - res = _PyObject_CallMethodId(all_tasks, &PyId_add, "O", self, NULL); + res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_add, self, NULL); if (res == NULL) { return -1; } @@ -1838,8 +1838,8 @@ task_call_wakeup(TaskObj *task, PyObject *fut) } else { /* `task` is a subclass of Task */ - return _PyObject_CallMethodId( - (PyObject*)task, &PyId__wakeup, "O", fut, NULL); + return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup, + fut, NULL); } } @@ -1854,8 +1854,8 @@ task_call_step(TaskObj *task, PyObject *arg) if (arg == NULL) { arg = Py_None; } - return _PyObject_CallMethodId( - (PyObject*)task, &PyId__step, "O", arg, NULL); + return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step, + arg, NULL); } } @@ -1869,8 +1869,8 @@ task_call_step_soon(TaskObj *task, PyObject *arg) return -1; } - handle = _PyObject_CallMethodId( - task->task_loop, &PyId_call_soon, "O", cb, NULL); + handle = _PyObject_CallMethodIdObjArgs(task->task_loop, &PyId_call_soon, + cb, NULL); Py_DECREF(cb); if (handle == NULL) { return -1; @@ -2135,8 +2135,9 @@ task_step_impl(TaskObj *task, PyObject *exc) if (wrapper == NULL) { goto fail; } - res = _PyObject_CallMethodId( - result, &PyId_add_done_callback, "O", wrapper, NULL); + res = _PyObject_CallMethodIdObjArgs(result, + &PyId_add_done_callback, + wrapper, NULL); Py_DECREF(wrapper); if (res == NULL) { goto fail; diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 60f8b549a82..f4d3cbd49f8 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -683,7 +683,7 @@ PyInit__io(void) /* UnsupportedOperation inherits from ValueError and IOError */ state->unsupported_operation = PyObject_CallFunction( (PyObject *)&PyType_Type, "s(OO){}", - "UnsupportedOperation", PyExc_ValueError, PyExc_IOError); + "UnsupportedOperation", PyExc_OSError, PyExc_ValueError); if (state->unsupported_operation == NULL) goto fail; Py_INCREF(state->unsupported_operation); diff --git a/Modules/timemodule.c b/Modules/timemodule.c index db0ab5805c5..ebd44ad525b 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -398,7 +398,7 @@ time_localtime(PyObject *self, PyObject *args) struct tm local = buf; char zone[100]; int gmtoff; - strftime(zone, sizeof(buf), "%Z", &buf); + strftime(zone, sizeof(zone), "%Z", &buf); gmtoff = timegm(&buf) - when; return tmtotuple(&local, zone, gmtoff); } diff --git a/Objects/abstract.c b/Objects/abstract.c index f9afece815b..d838856d452 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2325,7 +2325,7 @@ exit: return result; } -/* Positional arguments are obj followed args. */ +/* Positional arguments are obj followed by args. */ PyObject * _PyObject_Call_Prepend(PyObject *func, PyObject *obj, PyObject *args, PyObject *kwargs) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 20b6f2f52e4..5fff34b1194 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -388,7 +388,7 @@ dk_set_index(PyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix) * This can be used to reserve enough size to insert n entries without * resizing. */ -#define ESTIMATE_SIZE(n) (((n)*3) >> 1) +#define ESTIMATE_SIZE(n) (((n)*3+1) >> 1) /* Alternative fraction that is otherwise close enough to 2n/3 to make * little difference. 8 * 2/3 == 8 * 5/8 == 5. 16 * 2/3 == 16 * 5/8 == 10. @@ -1359,12 +1359,26 @@ make_keys_shared(PyObject *op) PyObject * _PyDict_NewPresized(Py_ssize_t minused) { + const Py_ssize_t max_presize = 128 * 1024; Py_ssize_t newsize; PyDictKeysObject *new_keys; - for (newsize = PyDict_MINSIZE; - newsize <= minused && newsize > 0; - newsize <<= 1) - ; + + /* There are no strict guarantee that returned dict can contain minused + * items without resize. So we create medium size dict instead of very + * large dict or MemoryError. + */ + if (minused > USABLE_FRACTION(max_presize)) { + newsize = max_presize; + } + else { + Py_ssize_t minsize = ESTIMATE_SIZE(minused); + newsize = PyDict_MINSIZE; + while (newsize < minsize) { + newsize <<= 1; + } + } + assert(IS_POWER_OF_2(newsize)); + new_keys = new_keys_object(newsize); if (new_keys == NULL) return NULL; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 9c998f7ab3e..44911671a0e 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5083,10 +5083,10 @@ onError: return NULL; } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__ANDROID__) /* Simplified UTF-8 decoder using surrogateescape error handler, - used to decode the command line arguments on Mac OS X. + used to decode the command line arguments on Mac OS X and Android. Return a pointer to a newly allocated wide character string (use PyMem_RawFree() to free the memory), or NULL on memory allocation error. */ @@ -5137,7 +5137,7 @@ _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size) return unicode; } -#endif /* __APPLE__ */ +#endif /* __APPLE__ or __ANDROID__ */ /* Primary internal function which creates utf8 encoded bytes objects. diff --git a/PC/bdist_wininst/install.c b/PC/bdist_wininst/install.c index fd977f5a554..17cc30d25cf 100644 --- a/PC/bdist_wininst/install.c +++ b/PC/bdist_wininst/install.c @@ -154,7 +154,7 @@ HANDLE hBitmap; char *bitmap_bytes; static const char *REGISTRY_SUFFIX_6432 = -#ifdef MS_WIN64 +#ifdef _WIN64 ""; #else "-32"; diff --git a/PCbuild/_freeze_importlib.vcxproj b/PCbuild/_freeze_importlib.vcxproj index f7714c003af..c73266301e8 100644 --- a/PCbuild/_freeze_importlib.vcxproj +++ b/PCbuild/_freeze_importlib.vcxproj @@ -76,31 +76,44 @@ </ProjectReference> </ItemGroup> <ItemGroup> - <None Include="..\Lib\importlib\_bootstrap.py" /> + <None Include="..\Lib\importlib\_bootstrap.py"> + <IntFile>$(IntDir)importlib.g.h</IntFile> + <OutFile>$(PySourcePath)Python\importlib.h</OutFile> + </None> + <None Include="..\Lib\importlib\_bootstrap_external.py"> + <IntFile>$(IntDir)importlib_external.g.h</IntFile> + <OutFile>$(PySourcePath)Python\importlib_external.h</OutFile> + </None> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> - <Target Name="RebuildImportLib" AfterTargets="AfterBuild" Condition="$(Configuration) == 'Debug' or $(Configuration) == 'Release'"> - <Exec Command='"$(TargetPath)" "$(PySourcePath)Lib\importlib\_bootstrap.py" "$(IntDir)importlib.g.h"' /> + <Target Name="_RebuildImportLib"> + <Exec Command='"$(TargetPath)" "%(None.FullPath)" "%(None.IntFile)"' /> <PropertyGroup> - <_OldContent Condition="Exists('$(PySourcePath)Python\importlib.h')">$([System.IO.File]::ReadAllText('$(PySourcePath)Python\importlib.h').Replace(`
`, `
`))</_OldContent> - <_NewContent Condition="Exists('$(IntDir)importlib.g.h')">$([System.IO.File]::ReadAllText('$(IntDir)importlib.g.h').Replace(`
`, `
`))</_NewContent> + <_OldContent Condition="Exists($(OutTargetPath))"></_OldContent> + <_NewContent Condition="Exists($(IntTargetPath))">$([System.IO.File]::ReadAllText($(IntTargetPath)).Replace(`
`, `
`))</_NewContent> </PropertyGroup> - <Copy SourceFiles="$(IntDir)importlib.g.h" - DestinationFiles="$(PySourcePath)Python\importlib.h" - Condition="Exists('$(IntDir)importlib.g.h') and '$(_OldContent)' != '$(_NewContent)'" /> + <Copy SourceFiles="%(None.IntFile)" + DestinationFiles="%(None.OutFile)" + Condition="!Exists(%(None.OutFile)) or (Exists(%(None.IntFile)) and '$([System.IO.File]::ReadAllText(%(None.OutFile)).Replace(`
`, `
`))' != '$([System.IO.File]::ReadAllText(%(None.IntFile)).Replace(`
`, `
`))')"> + <Output TaskParameter="CopiedFiles" ItemName="_Updated" /> + </Copy> - <Warning Text="importlib.h has been updated. You will need to rebuild pythoncore to see the changes." - Condition="Exists('$(IntDir)importlib.g.h') and '$(_OldContent)' != '$(_NewContent)' and $(Configuration) == 'Debug'" /> - <Error Text="importlib.h has been updated. You will need to rebuild pythoncore to see the changes." - Condition="Exists('$(IntDir)importlib.g.h') and '$(_OldContent)' != '$(_NewContent)' and $(Configuration) == 'Release'" /> + <Warning Text="@(_Updated->'%(Filename)%(Extension)',', ') updated. You will need to rebuild pythoncore to see the changes." + Condition="'@(_Updated)' != '' and $(Configuration) == 'Debug'" /> + <Error Text="@(_Updated->'%(Filename)%(Extension)',', ') updated. You will need to rebuild pythoncore to see the changes." + Condition="'@(_Updated)' != '' and $(Configuration) == 'Release'" /> + </Target> + <Target Name="RebuildImportLib" AfterTargets="AfterBuild" Condition="$(Configuration) == 'Debug' or $(Configuration) == 'Release'" + DependsOnTargets="_RebuildImportLib"> </Target> <Target Name="_CleanImportLib" BeforeTargets="CoreClean"> <ItemGroup> <Clean Include="$(IntDir)importlib.g.h" /> + <Clean Include="$(IntDir)importlib_external.g.h" /> </ItemGroup> </Target> </Project> diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj index e0e6e93fc0a..c6b8487c0a2 100644 --- a/PCbuild/pcbuild.proj +++ b/PCbuild/pcbuild.proj @@ -28,7 +28,7 @@ <BuildTarget>Build</BuildTarget> <CleanTarget>Clean</CleanTarget> <CleanAllTarget>CleanAll</CleanAllTarget> - <BuildInParallel>true</BuildInParallel> + <BuildInParallel>false</BuildInParallel> </Projects2> </ItemDefinitionGroup> <ItemGroup> @@ -48,8 +48,6 @@ <Projects Include="pylauncher.vcxproj;pywlauncher.vcxproj" /> <!-- pyshellext.dll --> <Projects Include="pyshellext.vcxproj" /> - <!-- _freeze_importlib --> - <Projects Include="_freeze_importlib.vcxproj" /> <!-- Extension modules --> <ExtensionModules Include="_asyncio;_ctypes;_decimal;_elementtree;_msi;_multiprocessing;_overlapped;pyexpat;select;unicodedata;winsound" /> <!-- Extension modules that require external sources --> @@ -68,10 +66,10 @@ <BuildInParallel>false</BuildInParallel> </Projects> + <!-- _freeze_importlib --> + <Projects2 Include="_freeze_importlib.vcxproj" /> <!-- python[w].exe --> - <Projects2 Include="python.vcxproj;pythonw.vcxproj"> - <BuildInParallel>false</BuildInParallel> - </Projects2> + <Projects2 Include="python.vcxproj;pythonw.vcxproj" /> </ItemGroup> <Target Name="Build"> diff --git a/Python/ast.c b/Python/ast.c index 82f4529bf91..217ea14bf31 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -4789,6 +4789,7 @@ ExprList_Finish(ExprList *l, PyArena *arena) typedef struct { PyObject *last_str; ExprList expr_list; + int fmode; } FstringParser; #ifdef NDEBUG @@ -4807,6 +4808,7 @@ static void FstringParser_Init(FstringParser *state) { state->last_str = NULL; + state->fmode = 0; ExprList_Init(&state->expr_list); FstringParser_check_invariants(state); } @@ -4869,6 +4871,7 @@ FstringParser_ConcatFstring(FstringParser *state, const char **str, struct compiling *c, const node *n) { FstringParser_check_invariants(state); + state->fmode = 1; /* Parse the f-string. */ while (1) { @@ -4960,7 +4963,8 @@ FstringParser_Finish(FstringParser *state, struct compiling *c, /* If we're just a constant string with no expressions, return that. */ - if(state->expr_list.size == 0) { + if (!state->fmode) { + assert(!state->expr_list.size); if (!state->last_str) { /* Create a zero length string. */ state->last_str = PyUnicode_FromStringAndSize(NULL, 0); @@ -4984,11 +4988,6 @@ FstringParser_Finish(FstringParser *state, struct compiling *c, if (!seq) goto error; - /* If there's only one expression, return it. Otherwise, we need - to join them together. */ - if (seq->size == 1) - return seq->elements[0]; - return JoinedStr(seq, LINENO(n), n->n_col_offset, c->c_arena); error: diff --git a/Python/compile.c b/Python/compile.c index 35151cdd590..0e160758524 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3415,7 +3415,8 @@ static int compiler_joined_str(struct compiler *c, expr_ty e) { VISIT_SEQ(c, expr, e->v.JoinedStr.values); - ADDOP_I(c, BUILD_STRING, asdl_seq_LEN(e->v.JoinedStr.values)); + if (asdl_seq_LEN(e->v.JoinedStr.values) != 1) + ADDOP_I(c, BUILD_STRING, asdl_seq_LEN(e->v.JoinedStr.values)); return 1; } diff --git a/Python/errors.c b/Python/errors.c index 7b25a2202c2..fd6c42fd27f 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1059,16 +1059,15 @@ PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset) PyErr_Clear(); Py_DECREF(tmp); } + tmp = NULL; if (col_offset >= 0) { tmp = PyLong_FromLong(col_offset); if (tmp == NULL) PyErr_Clear(); - else { - if (_PyObject_SetAttrId(v, &PyId_offset, tmp)) - PyErr_Clear(); - Py_DECREF(tmp); - } } + if (_PyObject_SetAttrId(v, &PyId_offset, tmp ? tmp : Py_None)) + PyErr_Clear(); + Py_XDECREF(tmp); if (filename != NULL) { if (_PyObject_SetAttrId(v, &PyId_filename, filename)) PyErr_Clear(); @@ -1080,9 +1079,6 @@ PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset) Py_DECREF(tmp); } } - if (_PyObject_SetAttrId(v, &PyId_offset, Py_None)) { - PyErr_Clear(); - } if (exc != PyExc_SyntaxError) { if (!_PyObject_HasAttrId(v, &PyId_msg)) { tmp = PyObject_Str(v); diff --git a/Python/fileutils.c b/Python/fileutils.c index 6a32c42c80a..e84d66e99a4 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -20,7 +20,7 @@ extern int winerror_to_errno(int); #include <fcntl.h> #endif /* HAVE_FCNTL_H */ -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__ANDROID__) extern wchar_t* _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size); #endif @@ -273,7 +273,7 @@ decode_ascii_surrogateescape(const char *arg, size_t *size) wchar_t* Py_DecodeLocale(const char* arg, size_t *size) { -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__ANDROID__) wchar_t *wstr; wstr = _Py_DecodeUTF8_surrogateescape(arg, strlen(arg)); if (size != NULL) { @@ -406,7 +406,7 @@ oom: if (size != NULL) *size = (size_t)-1; return NULL; -#endif /* __APPLE__ */ +#endif /* __APPLE__ or __ANDROID__ */ } /* Encode a wide character string to the locale encoding with the @@ -424,7 +424,7 @@ oom: char* Py_EncodeLocale(const wchar_t *text, size_t *error_pos) { -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__ANDROID__) Py_ssize_t len; PyObject *unicode, *bytes = NULL; char *cpath; @@ -522,7 +522,7 @@ Py_EncodeLocale(const wchar_t *text, size_t *error_pos) bytes = result; } return result; -#endif /* __APPLE__ */ +#endif /* __APPLE__ or __ANDROID__ */ } diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 1b767c5a9ba..2f40978fb78 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -2334,7 +2334,7 @@ const unsigned char _Py_M__importlib_external[] = { 111,111,116,115,116,114,97,112,32,109,111,100,117,108,101,46, 10,10,32,32,32,32,114,52,0,0,0,114,63,0,0,0, 218,8,98,117,105,108,116,105,110,115,114,140,0,0,0,90, - 5,112,111,115,105,120,250,1,47,218,2,110,116,250,1,92, + 5,112,111,115,105,120,250,1,47,90,2,110,116,250,1,92, 99,1,0,0,0,0,0,0,0,2,0,0,0,3,0,0, 0,115,0,0,0,115,26,0,0,0,124,0,93,18,125,1, 116,0,124,1,131,1,100,0,107,2,86,0,1,0,113,2, @@ -2376,61 +2376,58 @@ const unsigned char _Py_M__importlib_external[] = { 1,10,1,4,2,2,1,10,1,6,1,14,1,12,2,8, 1,12,1,12,1,18,3,2,1,14,1,16,2,10,1,12, 3,10,1,12,3,10,1,10,1,12,3,14,1,14,1,10, - 1,10,1,10,1,114,32,1,0,0,99,1,0,0,0,0, + 1,10,1,10,1,114,31,1,0,0,99,1,0,0,0,0, 0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,115, - 72,0,0,0,116,0,124,0,131,1,1,0,116,1,131,0, + 50,0,0,0,116,0,124,0,131,1,1,0,116,1,131,0, 125,1,116,2,106,3,106,4,116,5,106,6,124,1,142,0, - 103,1,131,1,1,0,116,7,106,8,100,1,107,2,114,56, - 116,2,106,9,106,10,116,11,131,1,1,0,116,2,106,9, - 106,10,116,12,131,1,1,0,100,2,83,0,41,3,122,41, - 73,110,115,116,97,108,108,32,116,104,101,32,112,97,116,104, - 45,98,97,115,101,100,32,105,109,112,111,114,116,32,99,111, - 109,112,111,110,101,110,116,115,46,114,27,1,0,0,78,41, - 13,114,32,1,0,0,114,159,0,0,0,114,8,0,0,0, - 114,253,0,0,0,114,147,0,0,0,114,5,1,0,0,114, - 18,1,0,0,114,3,0,0,0,114,109,0,0,0,218,9, - 109,101,116,97,95,112,97,116,104,114,161,0,0,0,114,166, - 0,0,0,114,248,0,0,0,41,2,114,31,1,0,0,90, - 17,115,117,112,112,111,114,116,101,100,95,108,111,97,100,101, - 114,115,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,218,8,95,105,110,115,116,97,108,108,158,5,0,0,115, - 12,0,0,0,0,2,8,1,6,1,20,1,10,1,12,1, - 114,34,1,0,0,41,1,114,0,0,0,0,41,2,114,1, - 0,0,0,114,2,0,0,0,41,1,114,49,0,0,0,41, - 1,78,41,3,78,78,78,41,3,78,78,78,41,2,114,62, - 0,0,0,114,62,0,0,0,41,1,78,41,1,78,41,58, - 114,111,0,0,0,114,12,0,0,0,90,37,95,67,65,83, - 69,95,73,78,83,69,78,83,73,84,73,86,69,95,80,76, - 65,84,70,79,82,77,83,95,66,89,84,69,83,95,75,69, - 89,114,11,0,0,0,114,13,0,0,0,114,19,0,0,0, - 114,21,0,0,0,114,30,0,0,0,114,40,0,0,0,114, - 41,0,0,0,114,45,0,0,0,114,46,0,0,0,114,48, - 0,0,0,114,58,0,0,0,218,4,116,121,112,101,218,8, - 95,95,99,111,100,101,95,95,114,142,0,0,0,114,17,0, - 0,0,114,132,0,0,0,114,16,0,0,0,114,20,0,0, - 0,90,17,95,82,65,87,95,77,65,71,73,67,95,78,85, - 77,66,69,82,114,77,0,0,0,114,76,0,0,0,114,88, - 0,0,0,114,78,0,0,0,90,23,68,69,66,85,71,95, - 66,89,84,69,67,79,68,69,95,83,85,70,70,73,88,69, - 83,90,27,79,80,84,73,77,73,90,69,68,95,66,89,84, - 69,67,79,68,69,95,83,85,70,70,73,88,69,83,114,83, - 0,0,0,114,89,0,0,0,114,95,0,0,0,114,99,0, - 0,0,114,101,0,0,0,114,120,0,0,0,114,127,0,0, - 0,114,139,0,0,0,114,145,0,0,0,114,148,0,0,0, - 114,153,0,0,0,218,6,111,98,106,101,99,116,114,160,0, - 0,0,114,165,0,0,0,114,166,0,0,0,114,181,0,0, - 0,114,191,0,0,0,114,207,0,0,0,114,215,0,0,0, - 114,220,0,0,0,114,226,0,0,0,114,221,0,0,0,114, - 227,0,0,0,114,246,0,0,0,114,248,0,0,0,114,5, - 1,0,0,114,23,1,0,0,114,159,0,0,0,114,32,1, - 0,0,114,34,1,0,0,114,4,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,6,0,0,0,218,8,60,109,111, - 100,117,108,101,62,8,0,0,0,115,108,0,0,0,4,16, - 4,1,4,1,2,1,6,3,8,17,8,5,8,5,8,6, - 8,12,8,10,8,9,8,5,8,7,10,22,10,123,16,1, - 12,2,4,1,4,2,6,2,6,2,8,2,16,45,8,34, - 8,19,8,12,8,12,8,28,8,17,10,55,10,12,10,10, - 8,14,6,3,4,1,14,67,14,64,14,29,16,110,14,41, - 18,45,18,16,4,3,18,53,14,60,14,42,14,127,0,5, - 14,127,0,22,10,23,8,11,8,68, + 103,1,131,1,1,0,116,2,106,7,106,8,116,9,131,1, + 1,0,100,1,83,0,41,2,122,41,73,110,115,116,97,108, + 108,32,116,104,101,32,112,97,116,104,45,98,97,115,101,100, + 32,105,109,112,111,114,116,32,99,111,109,112,111,110,101,110, + 116,115,46,78,41,10,114,31,1,0,0,114,159,0,0,0, + 114,8,0,0,0,114,253,0,0,0,114,147,0,0,0,114, + 5,1,0,0,114,18,1,0,0,218,9,109,101,116,97,95, + 112,97,116,104,114,161,0,0,0,114,248,0,0,0,41,2, + 114,30,1,0,0,90,17,115,117,112,112,111,114,116,101,100, + 95,108,111,97,100,101,114,115,114,4,0,0,0,114,4,0, + 0,0,114,6,0,0,0,218,8,95,105,110,115,116,97,108, + 108,158,5,0,0,115,8,0,0,0,0,2,8,1,6,1, + 20,1,114,33,1,0,0,41,1,114,0,0,0,0,41,2, + 114,1,0,0,0,114,2,0,0,0,41,1,114,49,0,0, + 0,41,1,78,41,3,78,78,78,41,3,78,78,78,41,2, + 114,62,0,0,0,114,62,0,0,0,41,1,78,41,1,78, + 41,58,114,111,0,0,0,114,12,0,0,0,90,37,95,67, + 65,83,69,95,73,78,83,69,78,83,73,84,73,86,69,95, + 80,76,65,84,70,79,82,77,83,95,66,89,84,69,83,95, + 75,69,89,114,11,0,0,0,114,13,0,0,0,114,19,0, + 0,0,114,21,0,0,0,114,30,0,0,0,114,40,0,0, + 0,114,41,0,0,0,114,45,0,0,0,114,46,0,0,0, + 114,48,0,0,0,114,58,0,0,0,218,4,116,121,112,101, + 218,8,95,95,99,111,100,101,95,95,114,142,0,0,0,114, + 17,0,0,0,114,132,0,0,0,114,16,0,0,0,114,20, + 0,0,0,90,17,95,82,65,87,95,77,65,71,73,67,95, + 78,85,77,66,69,82,114,77,0,0,0,114,76,0,0,0, + 114,88,0,0,0,114,78,0,0,0,90,23,68,69,66,85, + 71,95,66,89,84,69,67,79,68,69,95,83,85,70,70,73, + 88,69,83,90,27,79,80,84,73,77,73,90,69,68,95,66, + 89,84,69,67,79,68,69,95,83,85,70,70,73,88,69,83, + 114,83,0,0,0,114,89,0,0,0,114,95,0,0,0,114, + 99,0,0,0,114,101,0,0,0,114,120,0,0,0,114,127, + 0,0,0,114,139,0,0,0,114,145,0,0,0,114,148,0, + 0,0,114,153,0,0,0,218,6,111,98,106,101,99,116,114, + 160,0,0,0,114,165,0,0,0,114,166,0,0,0,114,181, + 0,0,0,114,191,0,0,0,114,207,0,0,0,114,215,0, + 0,0,114,220,0,0,0,114,226,0,0,0,114,221,0,0, + 0,114,227,0,0,0,114,246,0,0,0,114,248,0,0,0, + 114,5,1,0,0,114,23,1,0,0,114,159,0,0,0,114, + 31,1,0,0,114,33,1,0,0,114,4,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,6,0,0,0,218,8,60, + 109,111,100,117,108,101,62,8,0,0,0,115,108,0,0,0, + 4,16,4,1,4,1,2,1,6,3,8,17,8,5,8,5, + 8,6,8,12,8,10,8,9,8,5,8,7,10,22,10,123, + 16,1,12,2,4,1,4,2,6,2,6,2,8,2,16,45, + 8,34,8,19,8,12,8,12,8,28,8,17,10,55,10,12, + 10,10,8,14,6,3,4,1,14,67,14,64,14,29,16,110, + 14,41,18,45,18,16,4,3,18,53,14,60,14,42,14,127, + 0,5,14,127,0,22,10,23,8,11,8,68, }; diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index e4d2c1ec4c3..798b062c6bc 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -1492,23 +1492,38 @@ class Frame(object): ''' if self.is_waiting_for_gil(): return 'Waiting for the GIL' - elif self.is_gc_collect(): + + if self.is_gc_collect(): return 'Garbage-collecting' - else: - # Detect invocations of PyCFunction instances: - older = self.older() - if older and older._gdbframe.name() == 'PyCFunction_Call': - # Within that frame: - # "func" is the local containing the PyObject* of the - # PyCFunctionObject instance - # "f" is the same value, but cast to (PyCFunctionObject*) - # "self" is the (PyObject*) of the 'self' - try: - # Use the prettyprinter for the func: - func = older._gdbframe.read_var('func') - return str(func) - except RuntimeError: - return 'PyCFunction invocation (unable to read "func")' + + # Detect invocations of PyCFunction instances: + older = self.older() + if not older: + return False + + caller = older._gdbframe.name() + if not caller: + return False + + if caller == 'PyCFunction_Call': + # Within that frame: + # "func" is the local containing the PyObject* of the + # PyCFunctionObject instance + # "f" is the same value, but cast to (PyCFunctionObject*) + # "self" is the (PyObject*) of the 'self' + try: + # Use the prettyprinter for the func: + func = older._gdbframe.read_var('func') + return str(func) + except RuntimeError: + return 'PyCFunction invocation (unable to read "func")' + + elif caller == '_PyCFunction_FastCallDict': + try: + func = older._gdbframe.read_var('func_obj') + return str(func) + except RuntimeError: + return 'PyCFunction invocation (unable to read "func_obj")' # This frame isn't worth reporting: return False diff --git a/configure b/configure index cf95b2705a9..43f342e6fc2 100755 --- a/configure +++ b/configure @@ -5218,29 +5218,7 @@ cat >> conftest.c <<EOF #undef sparc #undef unix #if defined(__ANDROID__) -# if defined(__x86_64__) && defined(__LP64__) - x86_64-linux-android -# elif defined(__i386__) - i686-linux-android -# elif defined(__aarch64__) && defined(__AARCH64EL__) -# if defined(__ILP32__) - aarch64_ilp32-linux-android -# else - aarch64-linux-android -# endif -# elif defined(__ARM_EABI__) && defined(__ARMEL__) - arm-linux-androideabi -# elif defined(__mips_hard_float) && defined(_MIPSEL) -# if _MIPS_SIM == _ABIO32 - mipsel-linux-android -# elif _MIPS_SIM == _ABI64 - mips64el-linux-android -# else -# error unknown platform triplet -# endif -# else -# error unknown platform triplet -# endif + # Android is not a multiarch system. #elif defined(__linux__) # if defined(__x86_64__) && defined(__LP64__) x86_64-linux-gnu @@ -15712,7 +15690,9 @@ fi # first curses header check ac_save_cppflags="$CPPFLAGS" -CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw" +if test "$cross_compiling" = no; then + CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw" +fi for ac_header in curses.h ncurses.h do : diff --git a/configure.ac b/configure.ac index 1d63813977e..af540923ac3 100644 --- a/configure.ac +++ b/configure.ac @@ -770,29 +770,7 @@ cat >> conftest.c <<EOF #undef sparc #undef unix #if defined(__ANDROID__) -# if defined(__x86_64__) && defined(__LP64__) - x86_64-linux-android -# elif defined(__i386__) - i686-linux-android -# elif defined(__aarch64__) && defined(__AARCH64EL__) -# if defined(__ILP32__) - aarch64_ilp32-linux-android -# else - aarch64-linux-android -# endif -# elif defined(__ARM_EABI__) && defined(__ARMEL__) - arm-linux-androideabi -# elif defined(__mips_hard_float) && defined(_MIPSEL) -# if _MIPS_SIM == _ABIO32 - mipsel-linux-android -# elif _MIPS_SIM == _ABI64 - mips64el-linux-android -# else -# error unknown platform triplet -# endif -# else -# error unknown platform triplet -# endif + # Android is not a multiarch system. #elif defined(__linux__) # if defined(__x86_64__) && defined(__LP64__) x86_64-linux-gnu @@ -4907,7 +4885,9 @@ fi # first curses header check ac_save_cppflags="$CPPFLAGS" -CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw" +if test "$cross_compiling" = no; then + CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw" +fi AC_CHECK_HEADERS(curses.h ncurses.h) @@ -532,8 +532,9 @@ class PyBuildExt(build_ext): for directory in reversed(options.dirs): add_dir_to_list(dir_list, directory) - if os.path.normpath(sys.base_prefix) != '/usr' \ - and not sysconfig.get_config_var('PYTHONFRAMEWORK'): + if (not cross_compiling and + os.path.normpath(sys.base_prefix) != '/usr' and + not sysconfig.get_config_var('PYTHONFRAMEWORK')): # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework # (PYTHONFRAMEWORK is set) to avoid # linking problems when # building a framework with different architectures than @@ -1349,7 +1350,8 @@ class PyBuildExt(build_ext): panel_library = 'panel' if curses_library == 'ncursesw': curses_defines.append(('HAVE_NCURSESW', '1')) - curses_includes.append('/usr/include/ncursesw') + if not cross_compiling: + curses_includes.append('/usr/include/ncursesw') # Bug 1464056: If _curses.so links with ncursesw, # _curses_panel.so must link with panelw. panel_library = 'panelw' @@ -1630,7 +1632,7 @@ class PyBuildExt(build_ext): ## ext = Extension('xx', ['xxmodule.c']) ## self.extensions.append(ext) - if 'd' not in sys.abiflags: + if 'd' not in sysconfig.get_config_var('ABIFLAGS'): ext = Extension('xxlimited', ['xxlimited.c'], define_macros=[('Py_LIMITED_API', '0x03050000')]) self.extensions.append(ext) |