[pypy-commit] pypy py3k-clock_get_info: merge py3k
pjenvey
pypy.commits at gmail.com
Fri May 27 21:20:09 EDT 2016
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k-clock_get_info
Changeset: r84768:fa4ea2faa429
Date: 2016-05-27 18:16 -0700
http://bitbucket.org/pypy/pypy/changeset/fa4ea2faa429/
Log: merge py3k
diff too long, truncating to 2000 out of 2645 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)
+
+ at contextlib.contextmanager
+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.
- at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject)
-def PyDate_FromDate(space, year, month, day):
+ at 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))
- at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject)
-def PyTime_FromTime(space, hour, minute, second, usecond):
+ at 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)
- at 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):
+ at 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)
- at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject)
-def PyDelta_FromDSU(space, days, seconds, useconds):
+ at 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",
More information about the pypy-commit
mailing list