Author: Mark Young <[email protected]> Branch: py3k Changeset: r85279:ae756a654002 Date: 2016-05-29 11:56 -0400 http://bitbucket.org/pypy/pypy/changeset/ae756a654002/
Log: Merge with upstream. diff too long, truncating to 2000 out of 3066 lines diff --git a/lib-python/3/ensurepip/__init__.py b/lib-python/3/ensurepip/__init__.py new file mode 100644 --- /dev/null +++ b/lib-python/3/ensurepip/__init__.py @@ -0,0 +1,210 @@ +import os +import os.path +import pkgutil +import sys +import tempfile + + +__all__ = ["version", "bootstrap"] + + +_SETUPTOOLS_VERSION = "21.2.1" + +_PIP_VERSION = "8.1.2" + +# pip currently requires ssl support, so we try to provide a nicer +# error message when that is missing (http://bugs.python.org/issue19744) +_MISSING_SSL_MESSAGE = ("pip {} requires SSL/TLS".format(_PIP_VERSION)) +try: + import ssl +except ImportError: + ssl = None + def _require_ssl_for_pip(): + raise RuntimeError(_MISSING_SSL_MESSAGE) +else: + def _require_ssl_for_pip(): + pass + +_PROJECTS = [ + ("setuptools", _SETUPTOOLS_VERSION), + ("pip", _PIP_VERSION), +] + + +def _run_pip(args, additional_paths=None): + # Add our bundled software to the sys.path so we can import it + if additional_paths is not None: + sys.path = additional_paths + sys.path + + # Install the bundled software + import pip + pip.main(args) + + +def version(): + """ + Returns a string specifying the bundled version of pip. + """ + return _PIP_VERSION + +def _disable_pip_configuration_settings(): + # We deliberately ignore all pip environment variables + # when invoking pip + # See http://bugs.python.org/issue19734 for details + keys_to_remove = [k for k in os.environ if k.startswith("PIP_")] + for k in keys_to_remove: + del os.environ[k] + # We also ignore the settings in the default pip configuration file + # See http://bugs.python.org/issue20053 for details + os.environ['PIP_CONFIG_FILE'] = os.devnull + + +def bootstrap(*, root=None, upgrade=False, user=False, + altinstall=False, default_pip=False, + verbosity=0): + """ + Bootstrap pip into the current Python installation (or the given root + directory). + + Note that calling this function will alter both sys.path and os.environ. + """ + if altinstall and default_pip: + raise ValueError("Cannot use altinstall and default_pip together") + + _require_ssl_for_pip() + _disable_pip_configuration_settings() + + # By default, installing pip and setuptools installs all of the + # following scripts (X.Y == running Python version): + # + # pip, pipX, pipX.Y, easy_install, easy_install-X.Y + # + # pip 1.5+ allows ensurepip to request that some of those be left out + if altinstall: + # omit pip, pipX and easy_install + os.environ["ENSUREPIP_OPTIONS"] = "altinstall" + elif not default_pip: + # omit pip and easy_install + os.environ["ENSUREPIP_OPTIONS"] = "install" + + 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)) + + # Construct the arguments to be passed to the pip command + args = ["install", "--no-index", "--find-links", tmpdir] + if root: + args += ["--root", root] + if upgrade: + args += ["--upgrade"] + if user: + args += ["--user"] + if verbosity: + args += ["-" + "v" * verbosity] + + _run_pip(args + [p[0] for p in _PROJECTS], additional_paths) + +def _uninstall_helper(*, verbosity=0): + """Helper to support a clean default uninstall process on Windows + + Note that calling this function may alter os.environ. + """ + # Nothing to do if pip was never installed, or has been removed + try: + import pip + except ImportError: + return + + # If the pip version doesn't match the bundled one, leave it alone + if pip.__version__ != _PIP_VERSION: + msg = ("ensurepip will only uninstall a matching version " + "({!r} installed, {!r} bundled)") + print(msg.format(pip.__version__, _PIP_VERSION), file=sys.stderr) + return + + _require_ssl_for_pip() + _disable_pip_configuration_settings() + + # Construct the arguments to be passed to the pip command + args = ["uninstall", "-y", "--disable-pip-version-check"] + if verbosity: + args += ["-" + "v" * verbosity] + + _run_pip(args + [p[0] for p in reversed(_PROJECTS)]) + + +def _main(argv=None): + if ssl is None: + print("Ignoring ensurepip failure: {}".format(_MISSING_SSL_MESSAGE), + file=sys.stderr) + return + + import argparse + parser = argparse.ArgumentParser(prog="python -m ensurepip") + parser.add_argument( + "--version", + action="version", + version="pip {}".format(version()), + help="Show the version of pip that is bundled with this Python.", + ) + parser.add_argument( + "-v", "--verbose", + action="count", + default=0, + dest="verbosity", + help=("Give more output. Option is additive, and can be used up to 3 " + "times."), + ) + parser.add_argument( + "-U", "--upgrade", + action="store_true", + default=False, + help="Upgrade pip and dependencies, even if already installed.", + ) + parser.add_argument( + "--user", + action="store_true", + default=False, + help="Install using the user scheme.", + ) + parser.add_argument( + "--root", + default=None, + help="Install everything relative to this alternate root directory.", + ) + parser.add_argument( + "--altinstall", + action="store_true", + default=False, + help=("Make an alternate install, installing only the X.Y versioned" + "scripts (Default: pipX, pipX.Y, easy_install-X.Y)"), + ) + parser.add_argument( + "--default-pip", + action="store_true", + default=False, + help=("Make a default pip install, installing the unqualified pip " + "and easy_install in addition to the versioned scripts"), + ) + + args = parser.parse_args(argv) + + bootstrap( + root=args.root, + upgrade=args.upgrade, + user=args.user, + verbosity=args.verbosity, + altinstall=args.altinstall, + default_pip=args.default_pip, + ) diff --git a/lib-python/3/ensurepip/__main__.py b/lib-python/3/ensurepip/__main__.py new file mode 100644 --- /dev/null +++ b/lib-python/3/ensurepip/__main__.py @@ -0,0 +1,4 @@ +import ensurepip + +if __name__ == "__main__": + ensurepip._main() diff --git a/lib-python/3/ensurepip/_bundled/pip-8.1.2-py2.py3-none-any.whl b/lib-python/3/ensurepip/_bundled/pip-8.1.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cc49227a0c7e13757f4863a9b7ace1eb56c3ce61 GIT binary patch [cut] diff --git a/lib-python/3/ensurepip/_bundled/setuptools-21.2.1-py2.py3-none-any.whl b/lib-python/3/ensurepip/_bundled/setuptools-21.2.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fe36464f79ba87960c33f3bdff817deb9e4e5f7c GIT binary patch [cut] diff --git a/lib-python/3/ensurepip/_uninstall.py b/lib-python/3/ensurepip/_uninstall.py new file mode 100644 --- /dev/null +++ b/lib-python/3/ensurepip/_uninstall.py @@ -0,0 +1,30 @@ +"""Basic pip uninstallation support, helper for the Windows uninstaller""" + +import argparse +import ensurepip + + +def _main(argv=None): + parser = argparse.ArgumentParser(prog="python -m ensurepip._uninstall") + parser.add_argument( + "--version", + action="version", + version="pip {}".format(ensurepip.version()), + help="Show the version of pip this will attempt to uninstall.", + ) + parser.add_argument( + "-v", "--verbose", + action="count", + default=0, + dest="verbosity", + help=("Give more output. Option is additive, and can be used up to 3 " + "times."), + ) + + args = parser.parse_args(argv) + + ensurepip._uninstall_helper(verbosity=args.verbosity) + + +if __name__ == "__main__": + _main() diff --git a/lib-python/3/importlib/_bootstrap.py b/lib-python/3/importlib/_bootstrap.py --- a/lib-python/3/importlib/_bootstrap.py +++ b/lib-python/3/importlib/_bootstrap.py @@ -768,7 +768,7 @@ else: registry_key = cls.REGISTRY_KEY key = registry_key.format(fullname=fullname, - sys_version=sys.version[:3]) + sys_version='%d.%d' % sys.version_info[:2]) try: with cls._open_registry(key) as hkey: filepath = _winreg.QueryValue(hkey, "") diff --git a/lib-python/3/subprocess.py b/lib-python/3/subprocess.py --- a/lib-python/3/subprocess.py +++ b/lib-python/3/subprocess.py @@ -976,15 +976,18 @@ c2pread, c2pwrite = -1, -1 errread, errwrite = -1, -1 + ispread = False if stdin is None: p2cread = _winapi.GetStdHandle(_winapi.STD_INPUT_HANDLE) if p2cread is None: p2cread, _ = _winapi.CreatePipe(None, 0) p2cread = Handle(p2cread) _winapi.CloseHandle(_) + ispread = True elif stdin == PIPE: p2cread, p2cwrite = _winapi.CreatePipe(None, 0) p2cread, p2cwrite = Handle(p2cread), Handle(p2cwrite) + ispread = True elif stdin == DEVNULL: p2cread = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stdin, int): @@ -992,17 +995,20 @@ else: # Assuming file-like object p2cread = msvcrt.get_osfhandle(stdin.fileno()) - p2cread = self._make_inheritable(p2cread) + p2cread = self._make_inheritable(p2cread, ispread) + ispwrite = False if stdout is None: c2pwrite = _winapi.GetStdHandle(_winapi.STD_OUTPUT_HANDLE) if c2pwrite is None: _, c2pwrite = _winapi.CreatePipe(None, 0) c2pwrite = Handle(c2pwrite) _winapi.CloseHandle(_) + ispwrite = True elif stdout == PIPE: c2pread, c2pwrite = _winapi.CreatePipe(None, 0) c2pread, c2pwrite = Handle(c2pread), Handle(c2pwrite) + ispwrite = True elif stdout == DEVNULL: c2pwrite = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stdout, int): @@ -1010,17 +1016,20 @@ else: # Assuming file-like object c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) - c2pwrite = self._make_inheritable(c2pwrite) + c2pwrite = self._make_inheritable(c2pwrite, ispwrite) + ispwrite = False if stderr is None: errwrite = _winapi.GetStdHandle(_winapi.STD_ERROR_HANDLE) if errwrite is None: _, errwrite = _winapi.CreatePipe(None, 0) errwrite = Handle(errwrite) _winapi.CloseHandle(_) + ispwrite = True elif stderr == PIPE: errread, errwrite = _winapi.CreatePipe(None, 0) errread, errwrite = Handle(errread), Handle(errwrite) + ispwrite = True elif stderr == STDOUT: errwrite = c2pwrite elif stderr == DEVNULL: @@ -1030,19 +1039,23 @@ else: # Assuming file-like object errwrite = msvcrt.get_osfhandle(stderr.fileno()) - errwrite = self._make_inheritable(errwrite) + errwrite = self._make_inheritable(errwrite, ispwrite) return (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) - def _make_inheritable(self, handle): + def _make_inheritable(self, handle, close=False): """Return a duplicate of handle, which is inheritable""" h = _winapi.DuplicateHandle( _winapi.GetCurrentProcess(), handle, _winapi.GetCurrentProcess(), 0, 1, _winapi.DUPLICATE_SAME_ACCESS) + # PyPy: If the initial handle was obtained with CreatePipe, + # close it. + if close: + handle.Close() return Handle(h) diff --git a/lib-python/3/test/test_ensurepip.py b/lib-python/3/test/test_ensurepip.py new file mode 100644 --- /dev/null +++ b/lib-python/3/test/test_ensurepip.py @@ -0,0 +1,360 @@ +import unittest +import unittest.mock +import test.support +import os +import os.path +import contextlib +import sys + +import ensurepip +import ensurepip._uninstall + +# pip currently requires ssl support, so we ensure we handle +# it being missing (http://bugs.python.org/issue19744) +ensurepip_no_ssl = test.support.import_fresh_module("ensurepip", + blocked=["ssl"]) +try: + import ssl +except ImportError: + def requires_usable_pip(f): + deco = unittest.skip(ensurepip._MISSING_SSL_MESSAGE) + return deco(f) +else: + def requires_usable_pip(f): + return f + +class TestEnsurePipVersion(unittest.TestCase): + + def test_returns_version(self): + self.assertEqual(ensurepip._PIP_VERSION, ensurepip.version()) + +class EnsurepipMixin: + + def setUp(self): + run_pip_patch = unittest.mock.patch("ensurepip._run_pip") + self.run_pip = run_pip_patch.start() + self.addCleanup(run_pip_patch.stop) + + # Avoid side effects on the actual os module + real_devnull = os.devnull + os_patch = unittest.mock.patch("ensurepip.os") + patched_os = os_patch.start() + self.addCleanup(os_patch.stop) + patched_os.devnull = real_devnull + patched_os.path = os.path + self.os_environ = patched_os.environ = os.environ.copy() + + +class TestBootstrap(EnsurepipMixin, unittest.TestCase): + + @requires_usable_pip + def test_basic_bootstrapping(self): + ensurepip.bootstrap() + + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", + unittest.mock.ANY, "setuptools", "pip", + ], + unittest.mock.ANY, + ) + + additional_paths = self.run_pip.call_args[0][1] + self.assertEqual(len(additional_paths), 2) + + @requires_usable_pip + def test_bootstrapping_with_root(self): + ensurepip.bootstrap(root="/foo/bar/") + + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", + unittest.mock.ANY, "--root", "/foo/bar/", + "setuptools", "pip", + ], + unittest.mock.ANY, + ) + + @requires_usable_pip + def test_bootstrapping_with_user(self): + ensurepip.bootstrap(user=True) + + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", + unittest.mock.ANY, "--user", "setuptools", "pip", + ], + unittest.mock.ANY, + ) + + @requires_usable_pip + def test_bootstrapping_with_upgrade(self): + ensurepip.bootstrap(upgrade=True) + + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", + unittest.mock.ANY, "--upgrade", "setuptools", "pip", + ], + unittest.mock.ANY, + ) + + @requires_usable_pip + def test_bootstrapping_with_verbosity_1(self): + ensurepip.bootstrap(verbosity=1) + + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", + unittest.mock.ANY, "-v", "setuptools", "pip", + ], + unittest.mock.ANY, + ) + + @requires_usable_pip + def test_bootstrapping_with_verbosity_2(self): + ensurepip.bootstrap(verbosity=2) + + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", + unittest.mock.ANY, "-vv", "setuptools", "pip", + ], + unittest.mock.ANY, + ) + + @requires_usable_pip + def test_bootstrapping_with_verbosity_3(self): + ensurepip.bootstrap(verbosity=3) + + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", + unittest.mock.ANY, "-vvv", "setuptools", "pip", + ], + unittest.mock.ANY, + ) + + @requires_usable_pip + def test_bootstrapping_with_regular_install(self): + ensurepip.bootstrap() + self.assertEqual(self.os_environ["ENSUREPIP_OPTIONS"], "install") + + @requires_usable_pip + def test_bootstrapping_with_alt_install(self): + ensurepip.bootstrap(altinstall=True) + self.assertEqual(self.os_environ["ENSUREPIP_OPTIONS"], "altinstall") + + @requires_usable_pip + def test_bootstrapping_with_default_pip(self): + ensurepip.bootstrap(default_pip=True) + self.assertNotIn("ENSUREPIP_OPTIONS", self.os_environ) + + def test_altinstall_default_pip_conflict(self): + with self.assertRaises(ValueError): + ensurepip.bootstrap(altinstall=True, default_pip=True) + self.assertFalse(self.run_pip.called) + + @requires_usable_pip + def test_pip_environment_variables_removed(self): + # ensurepip deliberately ignores all pip environment variables + # See http://bugs.python.org/issue19734 for details + self.os_environ["PIP_THIS_SHOULD_GO_AWAY"] = "test fodder" + ensurepip.bootstrap() + self.assertNotIn("PIP_THIS_SHOULD_GO_AWAY", self.os_environ) + + @requires_usable_pip + def test_pip_config_file_disabled(self): + # ensurepip deliberately ignores the pip config file + # See http://bugs.python.org/issue20053 for details + ensurepip.bootstrap() + self.assertEqual(self.os_environ["PIP_CONFIG_FILE"], os.devnull) + [email protected] +def fake_pip(version=ensurepip._PIP_VERSION): + if version is None: + pip = None + else: + class FakePip(): + __version__ = version + pip = FakePip() + sentinel = object() + orig_pip = sys.modules.get("pip", sentinel) + sys.modules["pip"] = pip + try: + yield pip + finally: + if orig_pip is sentinel: + del sys.modules["pip"] + else: + sys.modules["pip"] = orig_pip + +class TestUninstall(EnsurepipMixin, unittest.TestCase): + + def test_uninstall_skipped_when_not_installed(self): + with fake_pip(None): + ensurepip._uninstall_helper() + self.assertFalse(self.run_pip.called) + + def test_uninstall_skipped_with_warning_for_wrong_version(self): + with fake_pip("not a valid version"): + with test.support.captured_stderr() as stderr: + ensurepip._uninstall_helper() + warning = stderr.getvalue().strip() + self.assertIn("only uninstall a matching version", warning) + self.assertFalse(self.run_pip.called) + + + @requires_usable_pip + def test_uninstall(self): + with fake_pip(): + ensurepip._uninstall_helper() + + self.run_pip.assert_called_once_with( + [ + "uninstall", "-y", "--disable-pip-version-check", "pip", + "setuptools", + ] + ) + + @requires_usable_pip + def test_uninstall_with_verbosity_1(self): + with fake_pip(): + ensurepip._uninstall_helper(verbosity=1) + + self.run_pip.assert_called_once_with( + [ + "uninstall", "-y", "--disable-pip-version-check", "-v", "pip", + "setuptools", + ] + ) + + @requires_usable_pip + def test_uninstall_with_verbosity_2(self): + with fake_pip(): + ensurepip._uninstall_helper(verbosity=2) + + self.run_pip.assert_called_once_with( + [ + "uninstall", "-y", "--disable-pip-version-check", "-vv", "pip", + "setuptools", + ] + ) + + @requires_usable_pip + def test_uninstall_with_verbosity_3(self): + with fake_pip(): + ensurepip._uninstall_helper(verbosity=3) + + self.run_pip.assert_called_once_with( + [ + "uninstall", "-y", "--disable-pip-version-check", "-vvv", + "pip", "setuptools", + ] + ) + + @requires_usable_pip + def test_pip_environment_variables_removed(self): + # ensurepip deliberately ignores all pip environment variables + # See http://bugs.python.org/issue19734 for details + self.os_environ["PIP_THIS_SHOULD_GO_AWAY"] = "test fodder" + with fake_pip(): + ensurepip._uninstall_helper() + self.assertNotIn("PIP_THIS_SHOULD_GO_AWAY", self.os_environ) + + @requires_usable_pip + def test_pip_config_file_disabled(self): + # ensurepip deliberately ignores the pip config file + # See http://bugs.python.org/issue20053 for details + with fake_pip(): + ensurepip._uninstall_helper() + self.assertEqual(self.os_environ["PIP_CONFIG_FILE"], os.devnull) + + +class TestMissingSSL(EnsurepipMixin, unittest.TestCase): + + def setUp(self): + sys.modules["ensurepip"] = ensurepip_no_ssl + @self.addCleanup + def restore_module(): + sys.modules["ensurepip"] = ensurepip + super().setUp() + + def test_bootstrap_requires_ssl(self): + self.os_environ["PIP_THIS_SHOULD_STAY"] = "test fodder" + with self.assertRaisesRegex(RuntimeError, "requires SSL/TLS"): + ensurepip_no_ssl.bootstrap() + self.assertFalse(self.run_pip.called) + self.assertIn("PIP_THIS_SHOULD_STAY", self.os_environ) + + def test_uninstall_requires_ssl(self): + self.os_environ["PIP_THIS_SHOULD_STAY"] = "test fodder" + with self.assertRaisesRegex(RuntimeError, "requires SSL/TLS"): + with fake_pip(): + ensurepip_no_ssl._uninstall_helper() + self.assertFalse(self.run_pip.called) + self.assertIn("PIP_THIS_SHOULD_STAY", self.os_environ) + + def test_main_exits_early_with_warning(self): + with test.support.captured_stderr() as stderr: + ensurepip_no_ssl._main(["--version"]) + warning = stderr.getvalue().strip() + self.assertTrue(warning.endswith("requires SSL/TLS"), warning) + self.assertFalse(self.run_pip.called) + +# Basic testing of the main functions and their argument parsing + +EXPECTED_VERSION_OUTPUT = "pip " + ensurepip._PIP_VERSION + +class TestBootstrappingMainFunction(EnsurepipMixin, unittest.TestCase): + + @requires_usable_pip + def test_bootstrap_version(self): + with test.support.captured_stderr() as stdout: + with self.assertRaises(SystemExit): + ensurepip._main(["--version"]) + result = stdout.getvalue().strip() + self.assertEqual(result, EXPECTED_VERSION_OUTPUT) + self.assertFalse(self.run_pip.called) + + @requires_usable_pip + def test_basic_bootstrapping(self): + ensurepip._main([]) + + self.run_pip.assert_called_once_with( + [ + "install", "--no-index", "--find-links", + unittest.mock.ANY, "setuptools", "pip", + ], + unittest.mock.ANY, + ) + + additional_paths = self.run_pip.call_args[0][1] + self.assertEqual(len(additional_paths), 2) + +class TestUninstallationMainFunction(EnsurepipMixin, unittest.TestCase): + + def test_uninstall_version(self): + with test.support.captured_stderr() as stdout: + with self.assertRaises(SystemExit): + ensurepip._uninstall._main(["--version"]) + result = stdout.getvalue().strip() + self.assertEqual(result, EXPECTED_VERSION_OUTPUT) + self.assertFalse(self.run_pip.called) + + @requires_usable_pip + def test_basic_uninstall(self): + with fake_pip(): + ensurepip._uninstall._main([]) + + self.run_pip.assert_called_once_with( + [ + "uninstall", "-y", "--disable-pip-version-check", "pip", + "setuptools", + ] + ) + + + +if __name__ == "__main__": + unittest.main() diff --git a/lib-python/conftest.py b/lib-python/conftest.py --- a/lib-python/conftest.py +++ b/lib-python/conftest.py @@ -196,6 +196,7 @@ RegrTest('test_dummy_threading.py', core=True), RegrTest('test_dynamic.py'), RegrTest('test_email', skip="XXX is a directory"), + RegrTest('test_ensurepip.py'), RegrTest('test_enumerate.py', core=True), RegrTest('test_eof.py', core=True), RegrTest('test_epoll.py'), diff --git a/lib_pypy/_decimal.py b/lib_pypy/_decimal.py --- a/lib_pypy/_decimal.py +++ b/lib_pypy/_decimal.py @@ -161,6 +161,15 @@ _codecs.register_error('_decimal_encode', _handle_decimaldigits) +def _unsafe_check(name, lo, hi, value): + if not -_sys.maxsize-1 <= value <= _sys.maxsize: + raise OverflowError( + "Python int too large to convert to C ssize_t") + if not lo <= value <= hi: + raise ValueError("valid range for unsafe %s is [%d, %d]" % + (name, lo, hi)) + + # Decimal class _DEC_MINALLOC = 4 @@ -298,7 +307,8 @@ raise ValueError("exponent must be an integer") if not -_sys.maxsize-1 <= exponent <= _sys.maxsize: # Compatibility with CPython - raise OverflowError() + raise OverflowError( + "Python int too large to convert to C ssize_t") # coefficients if not digits and not is_special: @@ -1501,6 +1511,19 @@ _mpdec.mpd_free(output) return result.decode() + if _sys.maxsize < 2**63-1: + def _unsafe_setprec(self, value): + _unsafe_check('prec', 1, 1070000000, value) + self._ctx.prec = value + + def _unsafe_setemin(self, value): + _unsafe_check('emin', -1070000000, 0, value) + self._ctx.emin = value + + def _unsafe_setemax(self, value): + _unsafe_check('emax', 0, 1070000000, value) + self._ctx.emax = value + class _SignalDict(_collections.abc.MutableMapping): diff --git a/lib_pypy/_libmpdec/vccompat.h b/lib_pypy/_libmpdec/vccompat.h new file mode 100644 --- /dev/null +++ b/lib_pypy/_libmpdec/vccompat.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008-2016 Stefan Krah. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef VCCOMPAT_H +#define VCCOMPAT_H + + +/* Visual C fixes: no stdint.h, no snprintf ... */ +#ifdef _MSC_VER + #include "vcstdint.h" + #undef inline + #define inline __inline + #undef random + #define random rand + #undef srandom + #define srandom srand + #undef snprintf + #define snprintf sprintf_s + #define HAVE_SNPRINTF + #undef strncasecmp + #define strncasecmp _strnicmp + #undef strcasecmp + #define strcasecmp _stricmp + #undef strtoll + #define strtoll _strtoi64 + #define strdup _strdup + #define PRIi64 "I64i" + #define PRIu64 "I64u" + #define PRIi32 "I32i" + #define PRIu32 "I32u" +#endif + + +#endif /* VCCOMPAT_H */ + + + diff --git a/lib_pypy/_libmpdec/vcdiv64.asm b/lib_pypy/_libmpdec/vcdiv64.asm new file mode 100644 --- /dev/null +++ b/lib_pypy/_libmpdec/vcdiv64.asm @@ -0,0 +1,48 @@ +; +; Copyright (c) 2008-2016 Stefan Krah. All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. +; + + +PUBLIC _mpd_div_words +_TEXT SEGMENT +q$ = 8 +r$ = 16 +hi$ = 24 +lo$ = 32 +d$ = 40 +_mpd_div_words PROC + mov r10, rdx + mov rdx, r8 + mov rax, r9 + div QWORD PTR d$[rsp] + mov QWORD PTR [r10], rdx + mov QWORD PTR [rcx], rax + ret 0 +_mpd_div_words ENDP +_TEXT ENDS +END + + diff --git a/lib_pypy/_libmpdec/vcstdint.h b/lib_pypy/_libmpdec/vcstdint.h new file mode 100644 --- /dev/null +++ b/lib_pypy/_libmpdec/vcstdint.h @@ -0,0 +1,232 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include <limits.h> + +// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#if (_MSC_VER < 1300) && defined(__cplusplus) + extern "C++" { +#endif +# include <wchar.h> +#if (_MSC_VER < 1300) && defined(__cplusplus) + } +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/lib_pypy/_subprocess.py b/lib_pypy/_subprocess.py deleted file mode 100644 --- a/lib_pypy/_subprocess.py +++ /dev/null @@ -1,214 +0,0 @@ -""" -Support routines for subprocess module. -Currently, this extension module is only required when using the -subprocess module on Windows. -""" - - -# Declare external Win32 functions - -import ctypes - -_kernel32 = ctypes.WinDLL('kernel32') - -_CloseHandle = _kernel32.CloseHandle -_CloseHandle.argtypes = [ctypes.c_int] -_CloseHandle.restype = ctypes.c_int - -_CreatePipe = _kernel32.CreatePipe -_CreatePipe.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int), - ctypes.c_void_p, ctypes.c_int] -_CreatePipe.restype = ctypes.c_int - -_GetCurrentProcess = _kernel32.GetCurrentProcess -_GetCurrentProcess.argtypes = [] -_GetCurrentProcess.restype = ctypes.c_int - -GetVersion = _kernel32.GetVersion -GetVersion.argtypes = [] -GetVersion.restype = ctypes.c_int - -_DuplicateHandle = _kernel32.DuplicateHandle -_DuplicateHandle.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int, - ctypes.POINTER(ctypes.c_int), - ctypes.c_int, ctypes.c_int, ctypes.c_int] -_DuplicateHandle.restype = ctypes.c_int - -_WaitForSingleObject = _kernel32.WaitForSingleObject -_WaitForSingleObject.argtypes = [ctypes.c_int, ctypes.c_uint] -_WaitForSingleObject.restype = ctypes.c_int - -_GetExitCodeProcess = _kernel32.GetExitCodeProcess -_GetExitCodeProcess.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_int)] -_GetExitCodeProcess.restype = ctypes.c_int - -_TerminateProcess = _kernel32.TerminateProcess -_TerminateProcess.argtypes = [ctypes.c_int, ctypes.c_int] -_TerminateProcess.restype = ctypes.c_int - -_GetStdHandle = _kernel32.GetStdHandle -_GetStdHandle.argtypes = [ctypes.c_int] -_GetStdHandle.restype = ctypes.c_int - -class _STARTUPINFO(ctypes.Structure): - _fields_ = [('cb', ctypes.c_int), - ('lpReserved', ctypes.c_void_p), - ('lpDesktop', ctypes.c_char_p), - ('lpTitle', ctypes.c_char_p), - ('dwX', ctypes.c_int), - ('dwY', ctypes.c_int), - ('dwXSize', ctypes.c_int), - ('dwYSize', ctypes.c_int), - ('dwXCountChars', ctypes.c_int), - ('dwYCountChars', ctypes.c_int), - ("dwFillAttribute", ctypes.c_int), - ("dwFlags", ctypes.c_int), - ("wShowWindow", ctypes.c_short), - ("cbReserved2", ctypes.c_short), - ("lpReserved2", ctypes.c_void_p), - ("hStdInput", ctypes.c_int), - ("hStdOutput", ctypes.c_int), - ("hStdError", ctypes.c_int) - ] - -class _PROCESS_INFORMATION(ctypes.Structure): - _fields_ = [("hProcess", ctypes.c_int), - ("hThread", ctypes.c_int), - ("dwProcessID", ctypes.c_int), - ("dwThreadID", ctypes.c_int)] - -_CreateProcess = _kernel32.CreateProcessW -_CreateProcess.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_void_p, ctypes.c_void_p, - ctypes.c_int, ctypes.c_int, ctypes.c_wchar_p, ctypes.c_wchar_p, - ctypes.POINTER(_STARTUPINFO), ctypes.POINTER(_PROCESS_INFORMATION)] -_CreateProcess.restype = ctypes.c_int - -del ctypes - -# Now the _subprocess module implementation - -from ctypes import c_int as _c_int, byref as _byref, WinError as _WinError - -class _handle: - def __init__(self, handle): - self.handle = handle - - def __int__(self): - return self.handle - - def __del__(self): - if self.handle is not None: - _CloseHandle(self.handle) - - def Detach(self): - handle, self.handle = self.handle, None - return handle - - def Close(self): - if self.handle not in (-1, None): - _CloseHandle(self.handle) - self.handle = None - -def CreatePipe(attributes, size): - read = _c_int() - write = _c_int() - - res = _CreatePipe(_byref(read), _byref(write), None, size) - - if not res: - raise _WinError() - - return _handle(read.value), _handle(write.value) - -def GetCurrentProcess(): - return _handle(_GetCurrentProcess()) - -def DuplicateHandle(source_process, source, target_process, access, inherit, options=0): - target = _c_int() - - res = _DuplicateHandle(int(source_process), int(source), int(target_process), - _byref(target), - access, inherit, options) - - if not res: - raise _WinError() - - return _handle(target.value) - -def CreateProcess(name, command_line, process_attr, thread_attr, - inherit, flags, env, start_dir, startup_info): - si = _STARTUPINFO() - if startup_info is not None: - si.dwFlags = startup_info.dwFlags - si.wShowWindow = startup_info.wShowWindow - if startup_info.hStdInput: - si.hStdInput = int(startup_info.hStdInput) - if startup_info.hStdOutput: - si.hStdOutput = int(startup_info.hStdOutput) - if startup_info.hStdError: - si.hStdError = int(startup_info.hStdError) - - pi = _PROCESS_INFORMATION() - flags |= CREATE_UNICODE_ENVIRONMENT - - if env is not None: - envbuf = "" - for k, v in env.items(): - envbuf += "%s=%s\0" % (k, v) - envbuf += '\0' - else: - envbuf = None - - res = _CreateProcess(name, command_line, None, None, inherit, flags, envbuf, - start_dir, _byref(si), _byref(pi)) - - if not res: - raise _WinError() - - return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessID, pi.dwThreadID - -def WaitForSingleObject(handle, milliseconds): - res = _WaitForSingleObject(int(handle), milliseconds) - - if res < 0: - raise _WinError() - - return res - -def GetExitCodeProcess(handle): - code = _c_int() - - res = _GetExitCodeProcess(int(handle), _byref(code)) - - if not res: - raise _WinError() - - return code.value - -def TerminateProcess(handle, exitcode): - res = _TerminateProcess(int(handle), exitcode) - - if not res: - raise _WinError() - -def GetStdHandle(stdhandle): - res = _GetStdHandle(stdhandle) - - if not res: - return None - else: - return res - -STD_INPUT_HANDLE = -10 -STD_OUTPUT_HANDLE = -11 -STD_ERROR_HANDLE = -12 -DUPLICATE_SAME_ACCESS = 2 -STARTF_USESTDHANDLES = 0x100 -STARTF_USESHOWWINDOW = 0x001 -SW_HIDE = 0 -INFINITE = 0xffffffff -WAIT_OBJECT_0 = 0 -CREATE_NEW_CONSOLE = 0x010 -CREATE_NEW_PROCESS_GROUP = 0x200 -CREATE_UNICODE_ENVIRONMENT = 0x400 -STILL_ACTIVE = 259 diff --git a/lib_pypy/_winapi.py b/lib_pypy/_winapi.py new file mode 100644 --- /dev/null +++ b/lib_pypy/_winapi.py @@ -0,0 +1,237 @@ +""" +Support routines for subprocess module. +Currently, this extension module is only required when using the +subprocess module on Windows. +""" + +import sys +if sys.platform != 'win32': + raise ImportError("The '_subprocess' module is only available on Windows") + +# Declare external Win32 functions + +import ctypes + +_kernel32 = ctypes.WinDLL('kernel32') + +_CloseHandle = _kernel32.CloseHandle +_CloseHandle.argtypes = [ctypes.c_int] +_CloseHandle.restype = ctypes.c_int + +_CreatePipe = _kernel32.CreatePipe +_CreatePipe.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int), + ctypes.c_void_p, ctypes.c_int] +_CreatePipe.restype = ctypes.c_int + +_GetCurrentProcess = _kernel32.GetCurrentProcess +_GetCurrentProcess.argtypes = [] +_GetCurrentProcess.restype = ctypes.c_int + +GetVersion = _kernel32.GetVersion +GetVersion.argtypes = [] +GetVersion.restype = ctypes.c_int + +_DuplicateHandle = _kernel32.DuplicateHandle +_DuplicateHandle.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int, + ctypes.POINTER(ctypes.c_int), + ctypes.c_int, ctypes.c_int, ctypes.c_int] +_DuplicateHandle.restype = ctypes.c_int + +_WaitForSingleObject = _kernel32.WaitForSingleObject +_WaitForSingleObject.argtypes = [ctypes.c_int, ctypes.c_uint] +_WaitForSingleObject.restype = ctypes.c_int + +_GetExitCodeProcess = _kernel32.GetExitCodeProcess +_GetExitCodeProcess.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_int)] +_GetExitCodeProcess.restype = ctypes.c_int + +_TerminateProcess = _kernel32.TerminateProcess +_TerminateProcess.argtypes = [ctypes.c_int, ctypes.c_int] +_TerminateProcess.restype = ctypes.c_int + +_GetStdHandle = _kernel32.GetStdHandle +_GetStdHandle.argtypes = [ctypes.c_int] +_GetStdHandle.restype = ctypes.c_int + +_GetModuleFileNameW = _kernel32.GetModuleFileNameW +_GetModuleFileNameW.argtypes = [ctypes.c_int, ctypes.c_wchar_p, ctypes.c_uint] +_GetModuleFileNameW.restype = ctypes.c_int + +class _STARTUPINFO(ctypes.Structure): + _fields_ = [('cb', ctypes.c_int), + ('lpReserved', ctypes.c_void_p), + ('lpDesktop', ctypes.c_char_p), + ('lpTitle', ctypes.c_char_p), + ('dwX', ctypes.c_int), + ('dwY', ctypes.c_int), + ('dwXSize', ctypes.c_int), + ('dwYSize', ctypes.c_int), + ('dwXCountChars', ctypes.c_int), + ('dwYCountChars', ctypes.c_int), + ("dwFillAttribute", ctypes.c_int), + ("dwFlags", ctypes.c_int), + ("wShowWindow", ctypes.c_short), + ("cbReserved2", ctypes.c_short), + ("lpReserved2", ctypes.c_void_p), + ("hStdInput", ctypes.c_int), + ("hStdOutput", ctypes.c_int), + ("hStdError", ctypes.c_int) + ] + +class _PROCESS_INFORMATION(ctypes.Structure): + _fields_ = [("hProcess", ctypes.c_int), + ("hThread", ctypes.c_int), + ("dwProcessID", ctypes.c_int), + ("dwThreadID", ctypes.c_int)] + +_CreateProcess = _kernel32.CreateProcessW +_CreateProcess.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_void_p, ctypes.c_void_p, + ctypes.c_int, ctypes.c_int, ctypes.c_wchar_p, ctypes.c_wchar_p, + ctypes.POINTER(_STARTUPINFO), ctypes.POINTER(_PROCESS_INFORMATION)] +_CreateProcess.restype = ctypes.c_int + +del ctypes + +# Now the _winapi module implementation + +from ctypes import c_int as _c_int, byref as _byref, WinError as _WinError + +class _handle: + def __init__(self, handle): + self.handle = handle + + def __int__(self): + return self.handle + + def __del__(self): + if self.handle is not None: + _CloseHandle(self.handle) + + def Detach(self): + handle, self.handle = self.handle, None + return handle + + def Close(self): + if self.handle not in (-1, None): + _CloseHandle(self.handle) + self.handle = None + +def CreatePipe(attributes, size): + read = _c_int() + write = _c_int() + + res = _CreatePipe(_byref(read), _byref(write), None, size) + + if not res: + raise _WinError() + + return _handle(read.value), _handle(write.value) + +def GetCurrentProcess(): + return _handle(_GetCurrentProcess()) + +def DuplicateHandle(source_process, source, target_process, access, inherit, options=0): + target = _c_int() + + res = _DuplicateHandle(int(source_process), int(source), int(target_process), + _byref(target), + access, inherit, options) + + if not res: + raise _WinError() + + return _handle(target.value) + +def CreateProcess(name, command_line, process_attr, thread_attr, + inherit, flags, env, start_dir, startup_info): + si = _STARTUPINFO() + if startup_info is not None: + si.dwFlags = startup_info.dwFlags + si.wShowWindow = startup_info.wShowWindow + if startup_info.hStdInput: + si.hStdInput = int(startup_info.hStdInput) + if startup_info.hStdOutput: + si.hStdOutput = int(startup_info.hStdOutput) + if startup_info.hStdError: + si.hStdError = int(startup_info.hStdError) + + pi = _PROCESS_INFORMATION() + flags |= CREATE_UNICODE_ENVIRONMENT + + if env is not None: + envbuf = "" + for k, v in env.items(): + envbuf += "%s=%s\0" % (k, v) + envbuf += '\0' + else: + envbuf = None + + res = _CreateProcess(name, command_line, None, None, inherit, flags, envbuf, + start_dir, _byref(si), _byref(pi)) + + if not res: + raise _WinError() + + return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessID, pi.dwThreadID + +def WaitForSingleObject(handle, milliseconds): + res = _WaitForSingleObject(int(handle), milliseconds) + + if res < 0: + raise _WinError() + + return res + +def GetExitCodeProcess(handle): + code = _c_int() + + res = _GetExitCodeProcess(int(handle), _byref(code)) + + if not res: + raise _WinError() + + return code.value + +def TerminateProcess(handle, exitcode): + res = _TerminateProcess(int(handle), exitcode) + + if not res: + raise _WinError() + +def GetStdHandle(stdhandle): + res = _GetStdHandle(stdhandle) + + if not res: + return None + else: + return res + +def CloseHandle(handle): + res = _CloseHandle(handle) + + if not res: + raise _WinError() + +def GetModuleFileName(module): + buf = ctypes.create_unicode_buffer(_MAX_PATH) + res = _GetModuleFileNameW(module, buf, _MAX_PATH) + + if not res: + raise _WinError() + return buf.value + +STD_INPUT_HANDLE = -10 +STD_OUTPUT_HANDLE = -11 +STD_ERROR_HANDLE = -12 +DUPLICATE_SAME_ACCESS = 2 +STARTF_USESTDHANDLES = 0x100 +STARTF_USESHOWWINDOW = 0x001 +SW_HIDE = 0 +INFINITE = 0xffffffff +WAIT_OBJECT_0 = 0 +WAIT_TIMEOUT = 0x102 +CREATE_NEW_CONSOLE = 0x010 +CREATE_NEW_PROCESS_GROUP = 0x200 +CREATE_UNICODE_ENVIRONMENT = 0x400 +STILL_ACTIVE = 259 +_MAX_PATH = 260 diff --git a/lib_pypy/cffi/commontypes.py b/lib_pypy/cffi/commontypes.py --- a/lib_pypy/cffi/commontypes.py +++ b/lib_pypy/cffi/commontypes.py @@ -35,8 +35,11 @@ "you call ffi.set_unicode()" % (commontype,)) else: if commontype == cdecl: - raise api.FFIError("Unsupported type: %r. Please file a bug " - "if you think it should be." % (commontype,)) + raise api.FFIError( + "Unsupported type: %r. Please look at " + "http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations " + "and file an issue if you think this type should really " + "be supported." % (commontype,)) result, quals = parser.parse_type_and_quals(cdecl) # recursive assert isinstance(result, model.BaseTypeByIdentity) diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -1193,8 +1193,7 @@ elif flag == 'S': return False else: - return (self.lookup(w_obj, '__getitem__') is not None and - self.lookup(w_obj, '__getslice__') is None) + return self.lookup(w_obj, '__getitem__') is not None # The code below only works # for the simple case (new-style instance). diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py --- a/pypy/module/__builtin__/functional.py +++ b/pypy/module/__builtin__/functional.py @@ -117,8 +117,17 @@ else: compare = space.lt jitdriver = min_jitdriver + any_kwds = bool(args.keywords) args_w = args.arguments_w if len(args_w) > 1: + if unroll and len(args_w) == 2 and not any_kwds: + # a fast path for the common case, useful for interpreted + # mode and to reduce the length of the jit trace + w0, w1 = args_w + if space.is_true(compare(w1, w0)): + return w1 + else: + return w0 w_sequence = space.newtuple(args_w) elif len(args_w): w_sequence = args_w[0] @@ -127,8 +136,8 @@ "%s() expects at least one argument", implementation_of) w_key = None - kwds = args.keywords - if kwds: + if any_kwds: + kwds = args.keywords if kwds[0] == "key" and len(kwds) == 1: w_key = args.keywords_w[0] else: diff --git a/pypy/module/__builtin__/test/test_functional.py b/pypy/module/__builtin__/test/test_functional.py --- a/pypy/module/__builtin__/test/test_functional.py +++ b/pypy/module/__builtin__/test/test_functional.py @@ -585,6 +585,11 @@ assert min([1, 2, 3]) == 1 raises(TypeError, min, 1, 2, bar=2) raises(TypeError, min, 1, 2, key=lambda x: x, bar=2) + assert type(min(1, 1.0)) is int + assert type(min(1.0, 1)) is float + assert type(min(1, 1.0, 1L)) is int + assert type(min(1.0, 1L, 1)) is float + assert type(min(1L, 1, 1.0)) is long def test_max(self): assert max(1, 2) == 2 @@ -592,3 +597,8 @@ assert max([1, 2, 3]) == 3 raises(TypeError, max, 1, 2, bar=2) raises(TypeError, max, 1, 2, key=lambda x: x, bar=2) + assert type(max(1, 1.0)) is int + assert type(max(1.0, 1)) is float + assert type(max(1, 1.0, 1L)) is int + assert type(max(1.0, 1L, 1)) is float + assert type(max(1L, 1, 1.0)) is long diff --git a/pypy/module/_cffi_backend/lib_obj.py b/pypy/module/_cffi_backend/lib_obj.py --- a/pypy/module/_cffi_backend/lib_obj.py +++ b/pypy/module/_cffi_backend/lib_obj.py @@ -196,9 +196,13 @@ if is_getattr and attr == '__dict__': return self.full_dict_copy() if is_getattr and attr == '__class__': - return self.space.type(self) + # used to be space.type(self). But HAAAAAACK! + # That makes help() behave correctly. I couldn't + # find a more reasonable way. Urgh. + from pypy.interpreter.module import Module + return self.space.gettypeobject(Module.typedef) if is_getattr and attr == '__name__': - return self.descr_repr() + return self.space.wrap("%s.lib" % self.libname) raise oefmt(self.space.w_AttributeError, "cffi library '%s' has no function, constant " "or global variable named '%s'", diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py b/pypy/module/_cffi_backend/test/test_recompiler.py --- a/pypy/module/_cffi_backend/test/test_recompiler.py +++ b/pypy/module/_cffi_backend/test/test_recompiler.py @@ -1039,8 +1039,8 @@ assert MYFOO == 42 assert hasattr(lib, '__dict__') assert lib.__all__ == ['MYFOO', 'mybar'] # but not 'myvar' - assert lib.__name__ == repr(lib) - assert lib.__class__ is type(lib) + assert lib.__name__ == '_CFFI_test_import_from_lib.lib' + assert lib.__class__ is type(sys) # !! hack for help() def test_macro_var_callback(self): ffi, lib = self.prepare( diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py --- a/pypy/module/cpyext/cdatetime.py +++ b/pypy/module/cpyext/cdatetime.py @@ -1,4 +1,5 @@ from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rtyper.annlowlevel import llhelper from pypy.module.cpyext.pyobject import PyObject, make_ref from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields) @@ -16,6 +17,23 @@ ('TimeType', PyTypeObjectPtr), ('DeltaType', PyTypeObjectPtr), ('TZInfoType', PyTypeObjectPtr), + + ('Date_FromDate', lltype.Ptr(lltype.FuncType( + [rffi.INT_real, rffi.INT_real, rffi.INT_real, PyTypeObjectPtr], + PyObject))), + ('Time_FromTime', lltype.Ptr(lltype.FuncType( + [rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyObject, PyTypeObjectPtr], + PyObject))), + ('DateTime_FromDateAndTime', lltype.Ptr(lltype.FuncType( + [rffi.INT_real, rffi.INT_real, rffi.INT_real, + rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyObject, PyTypeObjectPtr], + PyObject))), + ('Delta_FromDelta', lltype.Ptr(lltype.FuncType( + [rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyTypeObjectPtr], + PyObject))), )) @cpython_api([], lltype.Ptr(PyDateTime_CAPI)) @@ -45,6 +63,19 @@ datetimeAPI.c_TZInfoType = rffi.cast( PyTypeObjectPtr, make_ref(space, w_type)) + datetimeAPI.c_Date_FromDate = llhelper( + _PyDate_FromDate.api_func.functype, + _PyDate_FromDate.api_func.get_wrapper(space)) + datetimeAPI.c_Time_FromTime = llhelper( + _PyTime_FromTime.api_func.functype, + _PyTime_FromTime.api_func.get_wrapper(space)) + datetimeAPI.c_DateTime_FromDateAndTime = llhelper( + _PyDateTime_FromDateAndTime.api_func.functype, + _PyDateTime_FromDateAndTime.api_func.get_wrapper(space)) + datetimeAPI.c_Delta_FromDelta = llhelper( + _PyDelta_FromDelta.api_func.functype, + _PyDelta_FromDelta.api_func.get_wrapper(space)) + return datetimeAPI PyDateTime_DateStruct = lltype.ForwardReference() @@ -94,36 +125,40 @@ make_check_function("PyDelta_Check", "timedelta") make_check_function("PyTZInfo_Check", "tzinfo") -# Constructors +# Constructors. They are better used as macros. -@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDate_FromDate(space, year, month, day): +@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, PyTypeObjectPtr], + PyObject) +def _PyDate_FromDate(space, year, month, day, w_type): """Return a datetime.date object with the specified year, month and day. """ year = rffi.cast(lltype.Signed, year) month = rffi.cast(lltype.Signed, month) day = rffi.cast(lltype.Signed, day) - w_datetime = PyImport_Import(space, space.wrap("datetime")) - return space.call_method( - w_datetime, "date", + return space.call_function( + w_type, space.wrap(year), space.wrap(month), space.wrap(day)) -@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyTime_FromTime(space, hour, minute, second, usecond): +@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyObject, PyTypeObjectPtr], PyObject) +def _PyTime_FromTime(space, hour, minute, second, usecond, w_tzinfo, w_type): """Return a ``datetime.time`` object with the specified hour, minute, second and microsecond.""" hour = rffi.cast(lltype.Signed, hour) minute = rffi.cast(lltype.Signed, minute) second = rffi.cast(lltype.Signed, second) usecond = rffi.cast(lltype.Signed, usecond) - w_datetime = PyImport_Import(space, space.wrap("datetime")) - return space.call_method( - w_datetime, "time", + return space.call_function( + w_type, space.wrap(hour), space.wrap(minute), space.wrap(second), - space.wrap(usecond)) + space.wrap(usecond), w_tzinfo) -@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDateTime_FromDateAndTime(space, year, month, day, hour, minute, second, usecond): +@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, + rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyObject, PyTypeObjectPtr], PyObject) +def _PyDateTime_FromDateAndTime(space, year, month, day, + hour, minute, second, usecond, + w_tzinfo, w_type): """Return a datetime.datetime object with the specified year, month, day, hour, minute, second and microsecond. """ @@ -134,12 +169,11 @@ minute = rffi.cast(lltype.Signed, minute) second = rffi.cast(lltype.Signed, second) usecond = rffi.cast(lltype.Signed, usecond) - w_datetime = PyImport_Import(space, space.wrap("datetime")) - return space.call_method( - w_datetime, "datetime", + return space.call_function( + w_type, space.wrap(year), space.wrap(month), space.wrap(day), space.wrap(hour), space.wrap(minute), space.wrap(second), - space.wrap(usecond)) + space.wrap(usecond), w_tzinfo) @cpython_api([PyObject], PyObject) def PyDateTime_FromTimestamp(space, w_args): @@ -161,8 +195,10 @@ w_method = space.getattr(w_type, space.wrap("fromtimestamp")) return space.call(w_method, w_args) -@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDelta_FromDSU(space, days, seconds, useconds): +@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyTypeObjectPtr], + PyObject) +def _PyDelta_FromDelta(space, days, seconds, useconds, normalize, w_type): """Return a datetime.timedelta object representing the given number of days, seconds and microseconds. Normalization is performed so that the resulting number of microseconds and seconds lie in the ranges documented for @@ -171,9 +207,8 @@ days = rffi.cast(lltype.Signed, days) seconds = rffi.cast(lltype.Signed, seconds) useconds = rffi.cast(lltype.Signed, useconds) - w_datetime = PyImport_Import(space, space.wrap("datetime")) - return space.call_method( - w_datetime, "timedelta", + return space.call_function( + w_type, space.wrap(days), space.wrap(seconds), space.wrap(useconds)) # Accessors diff --git a/pypy/module/cpyext/include/datetime.h b/pypy/module/cpyext/include/datetime.h --- a/pypy/module/cpyext/include/datetime.h +++ b/pypy/module/cpyext/include/datetime.h @@ -12,6 +12,13 @@ PyTypeObject *TimeType; PyTypeObject *DeltaType; PyTypeObject *TZInfoType; + + /* constructors */ + PyObject *(*Date_FromDate)(int, int, int, PyTypeObject*); + PyObject *(*DateTime_FromDateAndTime)(int, int, int, int, int, int, int, + PyObject*, PyTypeObject*); + PyObject *(*Time_FromTime)(int, int, int, int, PyObject*, PyTypeObject*); + PyObject *(*Delta_FromDelta)(int, int, int, int, PyTypeObject*); } PyDateTime_CAPI; PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI; @@ -41,6 +48,22 @@ PyObject_HEAD } PyDateTime_TZInfo; +/* Macros for accessing constructors in a simplified fashion. */ +#define PyDate_FromDate(year, month, day) \ + PyDateTimeAPI->Date_FromDate(year, month, day, PyDateTimeAPI->DateType) + +#define PyDateTime_FromDateAndTime(year, month, day, hour, min, sec, usec) \ + PyDateTimeAPI->DateTime_FromDateAndTime(year, month, day, hour, \ + min, sec, usec, Py_None, PyDateTimeAPI->DateTimeType) + +#define PyTime_FromTime(hour, minute, second, usecond) \ + PyDateTimeAPI->Time_FromTime(hour, minute, second, usecond, \ + Py_None, PyDateTimeAPI->TimeType) + +#define PyDelta_FromDSU(days, seconds, useconds) \ + PyDateTimeAPI->Delta_FromDelta(days, seconds, useconds, 1, \ + PyDateTimeAPI->DeltaType) + #ifdef __cplusplus } #endif diff --git a/pypy/module/cpyext/src/unicodeobject.c b/pypy/module/cpyext/src/unicodeobject.c --- a/pypy/module/cpyext/src/unicodeobject.c +++ b/pypy/module/cpyext/src/unicodeobject.c @@ -6,9 +6,6 @@ #define Py_ISDIGIT isdigit #define Py_ISALPHA isalpha -#define PyObject_Malloc malloc -#define PyObject_Free free - static void makefmt(char *fmt, int longflag, int longlongflag, int size_tflag, int zeropad, int width, int precision, char c) diff --git a/pypy/module/cpyext/test/test_datetime.py b/pypy/module/cpyext/test/test_datetime.py --- a/pypy/module/cpyext/test/test_datetime.py +++ b/pypy/module/cpyext/test/test_datetime.py @@ -4,7 +4,8 @@ class TestDatetime(BaseApiTest): def test_date(self, space, api): - w_date = api.PyDate_FromDate(2010, 06, 03) + date_api = api._PyDateTime_Import() + w_date = api._PyDate_FromDate(2010, 06, 03, date_api.c_DateType) assert space.unwrap(space.str(w_date)) == '2010-06-03' assert api.PyDate_Check(w_date) @@ -15,7 +16,9 @@ assert api.PyDateTime_GET_DAY(w_date) == 3 def test_time(self, space, api): - w_time = api.PyTime_FromTime(23, 15, 40, 123456) + date_api = api._PyDateTime_Import() + w_time = api._PyTime_FromTime(23, 15, 40, 123456, + space.w_None, date_api.c_TimeType) assert space.unwrap(space.str(w_time)) == '23:15:40.123456' assert api.PyTime_Check(w_time) @@ -27,8 +30,10 @@ assert api.PyDateTime_TIME_GET_MICROSECOND(w_time) == 123456 def test_datetime(self, space, api): - w_date = api.PyDateTime_FromDateAndTime( - 2010, 06, 03, 23, 15, 40, 123456) + date_api = api._PyDateTime_Import() + w_date = api._PyDateTime_FromDateAndTime( + 2010, 06, 03, 23, 15, 40, 123456, + space.w_None, date_api.c_DateTimeType) assert space.unwrap(space.str(w_date)) == '2010-06-03 23:15:40.123456' assert api.PyDateTime_Check(w_date) @@ -45,6 +50,7 @@ assert api.PyDateTime_DATE_GET_MICROSECOND(w_date) == 123456 def test_delta(self, space, api): + date_api = api._PyDateTime_Import() w_delta = space.appexec( [space.wrap(3), space.wrap(15)], """(days, seconds): from datetime import timedelta @@ -53,7 +59,7 @@ assert api.PyDelta_Check(w_delta) assert api.PyDelta_CheckExact(w_delta) - w_delta = api.PyDelta_FromDSU(10, 20, 30) + w_delta = api._PyDelta_FromDelta(10, 20, 30, True, date_api.c_DeltaType) assert api.PyDelta_Check(w_delta) assert api.PyDelta_CheckExact(w_delta) @@ -118,6 +124,31 @@ datetime.tzinfo) module.clear_types() + def test_constructors(self): + module = self.import_extension('foo', [ + ("new_date", "METH_NOARGS", _______________________________________________ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
