[Python-checkins] cpython (merge default -> default): Merged 3.4.0b1 release head back into trunk.

larry.hastings python-checkins at python.org
Sun Nov 24 23:07:23 CET 2013


http://hg.python.org/cpython/rev/0d2ac94fa389
changeset:   87524:0d2ac94fa389
parent:      87523:b89a2430ad78
parent:      87520:694e2708b4a8
user:        Larry Hastings <larry at hastings.org>
date:        Sun Nov 24 14:05:57 2013 -0800
summary:
  Merged 3.4.0b1 release head back into trunk.

files:
  Doc/Makefile                          |    1 +
  Doc/library/email.contentmanager.rst  |    4 +-
  Doc/library/email.message.rst         |    2 +-
  Doc/library/gettext.rst               |    6 +-
  Doc/library/unittest.rst              |    4 +-
  Doc/tools/sphinxext/susp-ignored.csv  |   16 +-
  Doc/whatsnew/3.4.rst                  |    2 +-
  Lib/_strptime.py                      |    2 +-
  Lib/asyncio/windows_events.py         |   11 +-
  Lib/decimal.py                        |    1 +
  Lib/fileinput.py                      |    2 +-
  Lib/test/test_codecs.py               |    4 +-
  Lib/test/test_decimal.py              |    1 +
  Lib/test/test_fileinput.py            |    8 +-
  Lib/test/test_gdb.py                  |    1 +
  Lib/test/test_io.py                   |    3 +-
  Lib/test/test_strptime.py             |    4 +
  Lib/test/test_time.py                 |    4 +
  Lib/test/test_zipfile.py              |   29 +-
  Misc/NEWS                             |   23 +-
  Modules/_decimal/_decimal.c           |    8 +-
  Modules/_decimal/libmpdec/mpdecimal.c |  260 +++
  Modules/_decimal/libmpdec/mpdecimal.h |   94 +-
  Modules/_elementtree.c                |   21 +-
  Modules/_pickle.c                     |  977 +++++++++----
  Modules/posixmodule.c                 |   47 +-
  setup.py                              |    2 +-
  27 files changed, 1151 insertions(+), 386 deletions(-)


diff --git a/Doc/Makefile b/Doc/Makefile
--- a/Doc/Makefile
+++ b/Doc/Makefile
@@ -186,6 +186,7 @@
 autobuild-dev:
 	make update
 	make dist SPHINXOPTS='-A daily=1 -A versionswitcher=1'
+	-make suspicious
 
 # for quick rebuilds (HTML only)
 autobuild-html:
diff --git a/Doc/library/email.contentmanager.rst b/Doc/library/email.contentmanager.rst
--- a/Doc/library/email.contentmanager.rst
+++ b/Doc/library/email.contentmanager.rst
@@ -96,7 +96,7 @@
       only it when looking for candidate matches.  Otherwise consider only the
       first (default root) part of the ``multipart/related``.
 
-      If a part has a :mailheader:``Content-Disposition`` header, only consider
+      If a part has a :mailheader:`Content-Disposition` header, only consider
       the part a candidate match if the value of the header is ``inline``.
 
       If none of the candidates matches any of the preferences in
@@ -134,7 +134,7 @@
 
       Return an iterator over all of the immediate sub-parts of the message,
       which will be empty for a non-``multipart``.  (See also
-      :meth:``~email.message.walk``.)
+      :meth:`~email.message.walk`.)
 
 
    .. method:: get_content(*args, content_manager=None, **kw)
diff --git a/Doc/library/email.message.rst b/Doc/library/email.message.rst
--- a/Doc/library/email.message.rst
+++ b/Doc/library/email.message.rst
@@ -35,7 +35,7 @@
 
    If *policy* is specified (it must be an instance of a :mod:`~email.policy`
    class) use the rules it specifies to udpate and serialize the representation
-   of the message.  If *policy* is not set, use the :class`compat32
+   of the message.  If *policy* is not set, use the :class:`compat32
    <email.policy.Compat32>` policy, which maintains backward compatibility with
    the Python 3.2 version of the email package.  For more information see the
    :mod:`~email.policy` documentation.
diff --git a/Doc/library/gettext.rst b/Doc/library/gettext.rst
--- a/Doc/library/gettext.rst
+++ b/Doc/library/gettext.rst
@@ -476,9 +476,9 @@
 
 :program:`xgettext`, :program:`pygettext`, and similar tools generate
 :file:`.po` files that are message catalogs.  They are structured
-:human-readable files that contain every marked string in the source
-:code, along with a placeholder for the translated versions of these
-:strings.
+human-readable files that contain every marked string in the source
+code, along with a placeholder for the translated versions of these
+strings.
 
 Copies of these :file:`.po` files are then handed over to the
 individual human translators who write translations for every
diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst
--- a/Doc/library/unittest.rst
+++ b/Doc/library/unittest.rst
@@ -901,8 +901,8 @@
    | :meth:`assertWarnsRegex(warn, r, fun, *args, **kwds)    | ``fun(*args, **kwds)`` raises *warn* | 3.2        |
    | <TestCase.assertWarnsRegex>`                            | and the message matches regex *r*    |            |
    +---------------------------------------------------------+--------------------------------------+------------+
-   | :meth:`assertLogs(logger, level)`                       | The ``with`` block logs on *logger*  | 3.4        |
-   | <TestCase.assertWarns>`                                 | with minimum *level*                 |            |
+   | :meth:`assertLogs(logger, level)                        | The ``with`` block logs on *logger*  | 3.4        |
+   | <TestCase.assertLogs>`                                  | with minimum *level*                 |            |
    +---------------------------------------------------------+--------------------------------------+------------+
 
    .. method:: assertRaises(exception, callable, *args, **kwds)
diff --git a/Doc/tools/sphinxext/susp-ignored.csv b/Doc/tools/sphinxext/susp-ignored.csv
--- a/Doc/tools/sphinxext/susp-ignored.csv
+++ b/Doc/tools/sphinxext/susp-ignored.csv
@@ -141,15 +141,8 @@
 library/logging.handlers,,:port,host:port
 library/mmap,,:i2,obj[i1:i2]
 library/multiprocessing,,`,# Add more tasks using `put()`
-library/multiprocessing,,`,# A test file for the `multiprocessing` package
-library/multiprocessing,,`,# A test of `multiprocessing.Pool` class
-library/multiprocessing,,`,# `BaseManager`.
-library/multiprocessing,,`,# in the original order then consider using `Pool.map()` or
 library/multiprocessing,,`,">>> l._callmethod('__getitem__', (20,))     # equiv to `l[20]`"
 library/multiprocessing,,`,">>> l._callmethod('__getslice__', (2, 7))   # equiv to `l[2:7]`"
-library/multiprocessing,,`,# Not sure if we should synchronize access to `socket.accept()` method by
-library/multiprocessing,,`,# object.  (We import `multiprocessing.reduction` to enable this pickling.)
-library/multiprocessing,,`,# `Pool.imap()` (which will save on the amount of code needed anyway).
 library/multiprocessing,,:queue,">>> QueueManager.register('get_queue', callable=lambda:queue)"
 library/multiprocessing,,`,# register the Foo class; make `f()` and `g()` accessible via proxy
 library/multiprocessing,,`,# register the Foo class; make `g()` and `_h()` accessible via proxy
@@ -158,6 +151,10 @@
 library/nntplib,,:lines,:lines
 library/optparse,,:len,"del parser.rargs[:len(value)]"
 library/os.path,,:foo,c:foo
+library/pathlib,,:bar,">>> PureWindowsPath('c:/Windows', 'd:bar')"
+library/pathlib,,:bar,PureWindowsPath('d:bar')
+library/pathlib,,:Program,>>> PureWindowsPath('c:Program Files/').root
+library/pathlib,,:Program,>>> PureWindowsPath('c:Program Files/').anchor
 library/pdb,,:lineno,filename:lineno
 library/pickle,,:memory,"conn = sqlite3.connect("":memory:"")"
 library/posix,,`,"CFLAGS=""`getconf LFS_CFLAGS`"" OPT=""-g -O2 $CFLAGS"""
@@ -200,7 +197,12 @@
 library/tarfile,,:xz,'w:xz'
 library/time,,:mm,
 library/time,,:ss,
+library/tracemalloc,,:limit,"for index, stat in enumerate(top_stats[:limit], 1):"
 library/turtle,,::,Example::
+library/unittest,1412,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message',"
+library/unittest,1412,:first,"self.assertEqual(cm.output, ['INFO:foo:first message',"
+library/unittest,1412,:foo,'ERROR:foo.bar:second message'])
+library/unittest,1412,:second,'ERROR:foo.bar:second message'])
 library/urllib.request,,:close,Connection:close
 library/urllib.request,,:lang,"xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">\n\n<head>\n"
 library/urllib.request,,:password,"""joe:password at python.org"""
diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst
--- a/Doc/whatsnew/3.4.rst
+++ b/Doc/whatsnew/3.4.rst
@@ -424,7 +424,7 @@
 
 The encoding and decoding functions in :mod:`base64` now accept any
 :term:`bytes-like object` in cases where it previously required a
-:class:`bytes` or :class:`bytearray` instance (:issue`17839`)
+:class:`bytes` or :class:`bytearray` instance (:issue:`17839`).
 
 
 colorsys
diff --git a/Lib/_strptime.py b/Lib/_strptime.py
--- a/Lib/_strptime.py
+++ b/Lib/_strptime.py
@@ -329,7 +329,7 @@
                                     (bad_directive, format)) from None
             # IndexError only occurs when the format string is "%"
             except IndexError:
-                raise ValueError("stray %% in format '%s'" % format)
+                raise ValueError("stray %% in format '%s'" % format) from None
             _regex_cache[format] = format_regex
     found = format_regex.match(data_string)
     if not found:
diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py
--- a/Lib/asyncio/windows_events.py
+++ b/Lib/asyncio/windows_events.py
@@ -327,14 +327,21 @@
             handle, self._iocp, ov.address, ms)
         f = _WaitHandleFuture(wh, loop=self._loop)
 
-        def finish(timed_out, _, ov):
+        def finish(trans, key, ov):
             if not f.cancelled():
                 try:
                     _overlapped.UnregisterWait(wh)
                 except OSError as e:
                     if e.winerror != _overlapped.ERROR_IO_PENDING:
                         raise
-            return not timed_out
+            # Note that this second wait means that we should only use
+            # this with handles types where a successful wait has no
+            # effect.  So events or processes are all right, but locks
+            # or semaphores are not.  Also note if the handle is
+            # signalled and then quickly reset, then we may return
+            # False even though we have not timed out.
+            return (_winapi.WaitForSingleObject(handle, 0) ==
+                    _winapi.WAIT_OBJECT_0)
 
         self._cache[ov.address] = (f, ov, None, finish)
         return f
diff --git a/Lib/decimal.py b/Lib/decimal.py
--- a/Lib/decimal.py
+++ b/Lib/decimal.py
@@ -140,6 +140,7 @@
 
 __version__ = '1.70'    # Highest version of the spec this complies with
                         # See http://speleotrove.com/decimal/
+__libmpdec_version__ = "2.4.0" # compatible libmpdec version
 
 import copy as _copy
 import math as _math
diff --git a/Lib/fileinput.py b/Lib/fileinput.py
--- a/Lib/fileinput.py
+++ b/Lib/fileinput.py
@@ -224,7 +224,7 @@
                              "'r', 'rU', 'U' and 'rb'")
         if 'U' in mode:
             import warnings
-            warnings.warn("Use of 'U' mode is deprecated",
+            warnings.warn("'U' mode is deprecated",
                           DeprecationWarning, 2)
         self._mode = mode
         if openhook:
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
--- a/Lib/test/test_codecs.py
+++ b/Lib/test/test_codecs.py
@@ -602,7 +602,9 @@
         self.addCleanup(support.unlink, support.TESTFN)
         with open(support.TESTFN, 'wb') as fp:
             fp.write(s)
-        with codecs.open(support.TESTFN, 'U', encoding=self.encoding) as reader:
+        with support.check_warnings(('', DeprecationWarning)):
+            reader = codecs.open(support.TESTFN, 'U', encoding=self.encoding)
+        with reader:
             self.assertEqual(reader.read(), s1)
 
 class UTF16LETest(ReadTest, unittest.TestCase):
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -4149,6 +4149,7 @@
         self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
 
         self.assertEqual(C.__version__, P.__version__)
+        self.assertEqual(C.__libmpdec_version__, P.__libmpdec_version__)
 
         x = dir(C)
         y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py
--- a/Lib/test/test_fileinput.py
+++ b/Lib/test/test_fileinput.py
@@ -22,7 +22,7 @@
 from io import StringIO
 from fileinput import FileInput, hook_encoded
 
-from test.support import verbose, TESTFN, run_unittest
+from test.support import verbose, TESTFN, run_unittest, check_warnings
 from test.support import unlink as safe_unlink
 
 
@@ -224,8 +224,10 @@
         try:
             # try opening in universal newline mode
             t1 = writeTmp(1, [b"A\nB\r\nC\rD"], mode="wb")
-            fi = FileInput(files=t1, mode="U")
-            lines = list(fi)
+            with check_warnings(('', DeprecationWarning)):
+                fi = FileInput(files=t1, mode="U")
+            with check_warnings(('', DeprecationWarning)):
+                lines = list(fi)
             self.assertEqual(lines, ["A\n", "B\n", "C\n", "D"])
         finally:
             remove_tempfiles(t1)
diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py
--- a/Lib/test/test_gdb.py
+++ b/Lib/test/test_gdb.py
@@ -170,6 +170,7 @@
             'Do you need "set solib-search-path" or '
             '"set sysroot"?',
             'warning: Source file is more recent than executable.',
+            'Missing separate debuginfo for ',
             )
         for line in errlines:
             if not line.startswith(ignore_patterns):
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -2777,7 +2777,8 @@
         self.assertEqual(f.mode, "wb")
         f.close()
 
-        f = self.open(support.TESTFN, "U")
+        with support.check_warnings(('', DeprecationWarning)):
+            f = self.open(support.TESTFN, "U")
         self.assertEqual(f.name,            support.TESTFN)
         self.assertEqual(f.buffer.name,     support.TESTFN)
         self.assertEqual(f.buffer.raw.name, support.TESTFN)
diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py
--- a/Lib/test/test_strptime.py
+++ b/Lib/test/test_strptime.py
@@ -223,6 +223,10 @@
         with self.assertRaises(ValueError) as e:
             _strptime._strptime_time('', '%D')
         self.assertIs(e.exception.__suppress_context__, True)
+        # additional check for IndexError branch (issue #19545)
+        with self.assertRaises(ValueError) as e:
+            _strptime._strptime_time('19', '%Y %')
+        self.assertIs(e.exception.__suppress_context__, True)
 
     def test_unconverteddata(self):
         # Check ValueError is raised when there is unconverted data
diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -198,6 +198,10 @@
         with self.assertRaises(ValueError) as e:
             time.strptime('', '%D')
         self.assertIs(e.exception.__suppress_context__, True)
+        # additional check for IndexError branch (issue #19545)
+        with self.assertRaises(ValueError) as e:
+            time.strptime('19', '%Y %')
+        self.assertIs(e.exception.__suppress_context__, True)
 
     def test_asctime(self):
         time.asctime(time.gmtime(self.t))
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -14,7 +14,7 @@
 
 from test.support import (TESTFN, findfile, unlink,
                           requires_zlib, requires_bz2, requires_lzma,
-                          captured_stdout)
+                          captured_stdout, check_warnings)
 
 TESTFN2 = TESTFN + "2"
 TESTFNDIR = TESTFN + "d"
@@ -35,6 +35,10 @@
         yield f
         test.assertFalse(f.closed)
 
+def openU(zipfp, fn):
+    with check_warnings(('', DeprecationWarning)):
+        return zipfp.open(fn, 'rU')
+
 class AbstractTestsWithSourceFile:
     @classmethod
     def setUpClass(cls):
@@ -875,6 +879,17 @@
                 data += zipfp.read(info)
             self.assertIn(data, {b"foobar", b"barfoo"})
 
+    def test_universal_deprecation(self):
+        f = io.BytesIO()
+        with zipfile.ZipFile(f, "w") as zipfp:
+            zipfp.writestr('spam.txt', b'ababagalamaga')
+
+        with zipfile.ZipFile(f, "r") as zipfp:
+            for mode in 'U', 'rU':
+                with self.assertWarns(DeprecationWarning):
+                    zipopen = zipfp.open('spam.txt', mode)
+                zipopen.close()
+
     def test_universal_readaheads(self):
         f = io.BytesIO()
 
@@ -884,7 +899,7 @@
 
         data2 = b''
         with zipfile.ZipFile(f, 'r') as zipfp, \
-             zipfp.open(TESTFN, 'rU') as zipopen:
+             openU(zipfp, TESTFN) as zipopen:
             for line in zipopen:
                 data2 += line
 
@@ -1613,7 +1628,7 @@
         # Read the ZIP archive
         with zipfile.ZipFile(f, "r") as zipfp:
             for sep, fn in self.arcfiles.items():
-                with zipfp.open(fn, "rU") as fp:
+                with openU(zipfp, fn) as fp:
                     zipdata = fp.read()
                 self.assertEqual(self.arcdata[sep], zipdata)
 
@@ -1627,7 +1642,7 @@
         # Read the ZIP archive
         with zipfile.ZipFile(f, "r") as zipfp:
             for sep, fn in self.arcfiles.items():
-                with zipfp.open(fn, "rU") as zipopen:
+                with openU(zipfp, fn) as zipopen:
                     data = b''
                     while True:
                         read = zipopen.readline()
@@ -1652,7 +1667,7 @@
         # Read the ZIP archive
         with zipfile.ZipFile(f, "r") as zipfp:
             for sep, fn in self.arcfiles.items():
-                with zipfp.open(fn, "rU") as zipopen:
+                with openU(zipfp, fn) as zipopen:
                     for line in self.line_gen:
                         linedata = zipopen.readline()
                         self.assertEqual(linedata, line + b'\n')
@@ -1667,7 +1682,7 @@
         # Read the ZIP archive
         with zipfile.ZipFile(f, "r") as zipfp:
             for sep, fn in self.arcfiles.items():
-                with zipfp.open(fn, "rU") as fp:
+                with openU(zipfp, fn) as fp:
                     ziplines = fp.readlines()
                 for line, zipline in zip(self.line_gen, ziplines):
                     self.assertEqual(zipline, line + b'\n')
@@ -1682,7 +1697,7 @@
         # Read the ZIP archive
         with zipfile.ZipFile(f, "r") as zipfp:
             for sep, fn in self.arcfiles.items():
-                with zipfp.open(fn, "rU") as fp:
+                with openU(zipfp, fn) as fp:
                     for line, zipline in zip(self.line_gen, fp):
                         self.assertEqual(zipline, line + b'\n')
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -2,6 +2,21 @@
 Python News
 +++++++++++
 
+What's New in Python 3.4.0 Beta 2?
+==================================
+
+Release date: 2014-01-05
+
+Core and Builtins
+-----------------
+
+Library
+-------
+
+- Issue #19545: Avoid chained exceptions while passing stray % to
+  time.strptime().  Initial patch by Claudiu Popa.
+
+
 What's New in Python 3.4.0 Beta 1?
 ==================================
 
@@ -2518,7 +2533,7 @@
 - Issue #14398: Fix size truncation and overflow bugs in the bz2 module.
 
 - Issue #12692: Fix resource leak in urllib.request when talking to an HTTP
-  server that does not include a "Connection: close" header in its responses.
+  server that does not include a ``Connection: close`` header in its responses.
 
 - Issue #12034: Fix bogus caching of result in check_GetFinalPathNameByHandle.
   Patch by Atsuo Ishimoto.
@@ -6091,7 +6106,7 @@
   given as a low fd, it gets overwritten.
 
 - Issue #12576: Fix urlopen behavior on sites which do not send (or obfuscates)
-  Connection:close header.
+  ``Connection: close`` header.
 
 - Issue #12560: Build libpython.so on OpenBSD. Patch by Stefan Sperling.
 
@@ -6686,7 +6701,7 @@
 
 - Issue #11127: Raise a TypeError when trying to pickle a socket object.
 
-- Issue #11563: Connection:close header is sent by requests using URLOpener
+- Issue #11563: ``Connection: close`` header is sent by requests using URLOpener
   class which helps in closing of sockets after connection is over. Patch
   contributions by Jeff McNeil and Nadeem Vawda.
 
@@ -7262,7 +7277,7 @@
 - Issue #11505: improves test coverage of string.py. Patch by Alicia
   Arlen
 
-- Issue #11490: test_subprocess:test_leaking_fds_on_error no longer gives a
+- Issue #11490: test_subprocess.test_leaking_fds_on_error no longer gives a
   false positive if the last directory in the path is inaccessible.
 
 - Issue #11223: Fix test_threadsignals to fail, not hang, when the
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
--- a/Modules/_decimal/_decimal.c
+++ b/Modules/_decimal/_decimal.c
@@ -39,6 +39,11 @@
 #include "memory.h"
 
 
+#if MPD_MAJOR_VERSION != 2
+  #error "libmpdec major version 2 required"
+#endif
+
+
 /*
  * Type sizes with assertions in mpdecimal.h and pyport.h:
  *    sizeof(size_t) == sizeof(Py_ssize_t)
@@ -5730,7 +5735,8 @@
     }
 
     /* Add specification version number */
-    CHECK_INT(PyModule_AddStringConstant(m, "__version__", " 1.70"));
+    CHECK_INT(PyModule_AddStringConstant(m, "__version__", "1.70"));
+    CHECK_INT(PyModule_AddStringConstant(m, "__libmpdec_version__", mpd_version()));
 
 
     return m;
diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c
--- a/Modules/_decimal/libmpdec/mpdecimal.c
+++ b/Modules/_decimal/libmpdec/mpdecimal.c
@@ -97,6 +97,8 @@
                        mpd_ssize_t exp);
 static inline mpd_ssize_t _mpd_real_size(mpd_uint_t *data, mpd_ssize_t size);
 
+static int _mpd_cmp_abs(const mpd_t *a, const mpd_t *b);
+
 static void _mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,
                       const mpd_context_t *ctx, uint32_t *status);
 static inline void _mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,
@@ -111,6 +113,17 @@
 
 
 /******************************************************************************/
+/*                                  Version                                   */
+/******************************************************************************/
+
+const char *
+mpd_version(void)
+{
+    return MPD_VERSION;
+}
+
+
+/******************************************************************************/
 /*                  Performance critical inline functions                     */
 /******************************************************************************/
 
@@ -1345,6 +1358,91 @@
     return MPD_SSIZE_MAX;
 }
 
+#if defined(CONFIG_32) && !defined(LEGACY_COMPILER)
+/*
+ * Quietly get a uint64_t from a decimal. If the operation is impossible,
+ * MPD_Invalid_operation is set.
+ */
+static uint64_t
+_c32_qget_u64(int use_sign, const mpd_t *a, uint32_t *status)
+{
+    MPD_NEW_STATIC(tmp,0,0,20,3);
+    mpd_context_t maxcontext;
+    uint64_t ret;
+
+    tmp_data[0] = 709551615;
+    tmp_data[1] = 446744073;
+    tmp_data[2] = 18;
+
+    if (mpd_isspecial(a)) {
+        *status |= MPD_Invalid_operation;
+        return UINT64_MAX;
+    }
+    if (mpd_iszero(a)) {
+        return 0;
+    }
+    if (use_sign && mpd_isnegative(a)) {
+        *status |= MPD_Invalid_operation;
+        return UINT64_MAX;
+    }
+    if (!_mpd_isint(a)) {
+        *status |= MPD_Invalid_operation;
+        return UINT64_MAX;
+    }
+
+    if (_mpd_cmp_abs(a, &tmp) > 0) {
+        *status |= MPD_Invalid_operation;
+        return UINT64_MAX;
+    }
+
+    mpd_maxcontext(&maxcontext);
+    mpd_qrescale(&tmp, a, 0, &maxcontext, &maxcontext.status);
+    maxcontext.status &= ~MPD_Rounded;
+    if (maxcontext.status != 0) {
+        *status |= (maxcontext.status|MPD_Invalid_operation); /* GCOV_NOT_REACHED */
+        return UINT64_MAX; /* GCOV_NOT_REACHED */
+    }
+
+    ret = 0;
+    switch (tmp.len) {
+    case 3:
+        ret += (uint64_t)tmp_data[2] * 1000000000000000000ULL;
+    case 2:
+        ret += (uint64_t)tmp_data[1] * 1000000000ULL;
+    case 1:
+        ret += tmp_data[0];
+        break;
+    default:
+        abort(); /* GCOV_NOT_REACHED */
+    }
+
+    return ret;
+}
+
+static int64_t
+_c32_qget_i64(const mpd_t *a, uint32_t *status)
+{
+    uint64_t u;
+    int isneg;
+
+    u = _c32_qget_u64(0, a, status);
+    if (*status&MPD_Invalid_operation) {
+        return INT64_MAX;
+    }
+
+    isneg = mpd_isnegative(a);
+    if (u <= INT64_MAX) {
+        return isneg ? -((int64_t)u) : (int64_t)u;
+    }
+    else if (isneg && u+(INT64_MIN+INT64_MAX) == INT64_MAX) {
+        return INT64_MIN;
+    }
+
+    *status |= MPD_Invalid_operation;
+    return INT64_MAX;
+}
+#endif /* CONFIG_32 && !LEGACY_COMPILER */
+
 #ifdef CONFIG_64
 /* quietly get a uint64_t from a decimal */
 uint64_t
@@ -1359,7 +1457,57 @@
 {
     return mpd_qget_ssize(a, status);
 }
+
+/* quietly get a uint32_t from a decimal */
+uint32_t
+mpd_qget_u32(const mpd_t *a, uint32_t *status)
+{
+    uint64_t x = mpd_qget_uint(a, status);
+
+    if (*status&MPD_Invalid_operation) {
+        return UINT32_MAX;
+    }
+    if (x > UINT32_MAX) {
+        *status |= MPD_Invalid_operation;
+        return UINT32_MAX;
+    }
+
+    return (uint32_t)x;
+}
+
+/* quietly get an int32_t from a decimal */
+int32_t
+mpd_qget_i32(const mpd_t *a, uint32_t *status)
+{
+    int64_t x = mpd_qget_ssize(a, status);
+
+    if (*status&MPD_Invalid_operation) {
+        return INT32_MAX;
+    }
+    if (x < INT32_MIN || x > INT32_MAX) {
+        *status |= MPD_Invalid_operation;
+        return INT32_MAX;
+    }
+
+    return (int32_t)x;
+}
 #else
+#ifndef LEGACY_COMPILER
+/* quietly get a uint64_t from a decimal */
+uint64_t
+mpd_qget_u64(const mpd_t *a, uint32_t *status)
+{
+    return _c32_qget_u64(1, a, status);
+}
+
+/* quietly get an int64_t from a decimal */
+int64_t
+mpd_qget_i64(const mpd_t *a, uint32_t *status)
+{
+    return _c32_qget_i64(a, status);
+}
+#endif
+
 /* quietly get a uint32_t from a decimal */
 uint32_t
 mpd_qget_u32(const mpd_t *a, uint32_t *status)
@@ -3386,6 +3534,34 @@
 {
     mpd_qadd_uint(result, a, b, ctx, status);
 }
+#elif !defined(LEGACY_COMPILER)
+/* Add decimal and int64_t. */
+void
+mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+    mpd_context_t maxcontext;
+    MPD_NEW_STATIC(bb,0,0,0,0);
+
+    mpd_maxcontext(&maxcontext);
+    mpd_qset_i64(&bb, b, &maxcontext, status);
+    mpd_qadd(result, a, &bb, ctx, status);
+    mpd_del(&bb);
+}
+
+/* Add decimal and uint64_t. */
+void
+mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+    mpd_context_t maxcontext;
+    MPD_NEW_STATIC(bb,0,0,0,0);
+
+    mpd_maxcontext(&maxcontext);
+    mpd_qset_u64(&bb, b, &maxcontext, status);
+    mpd_qadd(result, a, &bb, ctx, status);
+    mpd_del(&bb);
+}
 #endif
 
 /* Subtract int32_t from decimal. */
@@ -3420,6 +3596,34 @@
 {
     mpd_qsub_uint(result, a, b, ctx, status);
 }
+#elif !defined(LEGACY_COMPILER)
+/* Subtract int64_t from decimal. */
+void
+mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+    mpd_context_t maxcontext;
+    MPD_NEW_STATIC(bb,0,0,0,0);
+
+    mpd_maxcontext(&maxcontext);
+    mpd_qset_i64(&bb, b, &maxcontext, status);
+    mpd_qsub(result, a, &bb, ctx, status);
+    mpd_del(&bb);
+}
+
+/* Subtract uint64_t from decimal. */
+void
+mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+    mpd_context_t maxcontext;
+    MPD_NEW_STATIC(bb,0,0,0,0);
+
+    mpd_maxcontext(&maxcontext);
+    mpd_qset_u64(&bb, b, &maxcontext, status);
+    mpd_qsub(result, a, &bb, ctx, status);
+    mpd_del(&bb);
+}
 #endif
 
 
@@ -3871,6 +4075,34 @@
 {
     mpd_qdiv_uint(result, a, b, ctx, status);
 }
+#elif !defined(LEGACY_COMPILER)
+/* Divide decimal by int64_t. */
+void
+mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+    mpd_context_t maxcontext;
+    MPD_NEW_STATIC(bb,0,0,0,0);
+
+    mpd_maxcontext(&maxcontext);
+    mpd_qset_i64(&bb, b, &maxcontext, status);
+    mpd_qdiv(result, a, &bb, ctx, status);
+    mpd_del(&bb);
+}
+
+/* Divide decimal by uint64_t. */
+void
+mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+    mpd_context_t maxcontext;
+    MPD_NEW_STATIC(bb,0,0,0,0);
+
+    mpd_maxcontext(&maxcontext);
+    mpd_qset_u64(&bb, b, &maxcontext, status);
+    mpd_qdiv(result, a, &bb, ctx, status);
+    mpd_del(&bb);
+}
 #endif
 
 /* Pad the result with trailing zeros if it has fewer digits than prec. */
@@ -5664,6 +5896,34 @@
 {
     mpd_qmul_uint(result, a, b, ctx, status);
 }
+#elif !defined(LEGACY_COMPILER)
+/* Multiply decimal and int64_t. */
+void
+mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+    mpd_context_t maxcontext;
+    MPD_NEW_STATIC(bb,0,0,0,0);
+
+    mpd_maxcontext(&maxcontext);
+    mpd_qset_i64(&bb, b, &maxcontext, status);
+    mpd_qmul(result, a, &bb, ctx, status);
+    mpd_del(&bb);
+}
+
+/* Multiply decimal and uint64_t. */
+void
+mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+    mpd_context_t maxcontext;
+    MPD_NEW_STATIC(bb,0,0,0,0);
+
+    mpd_maxcontext(&maxcontext);
+    mpd_qset_u64(&bb, b, &maxcontext, status);
+    mpd_qmul(result, a, &bb, ctx, status);
+    mpd_del(&bb);
+}
 #endif
 
 /* Like the minus operator. */
diff --git a/Modules/_decimal/libmpdec/mpdecimal.h b/Modules/_decimal/libmpdec/mpdecimal.h
--- a/Modules/_decimal/libmpdec/mpdecimal.h
+++ b/Modules/_decimal/libmpdec/mpdecimal.h
@@ -32,7 +32,6 @@
 
 #ifdef __cplusplus
 extern "C" {
-#define __STDC_LIMIT_MACROS
 #endif
 
 
@@ -56,12 +55,18 @@
   #define MPD_HIDE_SYMBOLS_END
   #define EXTINLINE extern inline
 #else
-  #ifdef HAVE_STDINT_H
-    #include <stdint.h>
-  #endif
   #ifdef HAVE_INTTYPES_H
     #include <inttypes.h>
   #endif
+  #ifdef HAVE_STDINT_H
+    #if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS)
+      #define __STDC_LIMIT_MACROS
+      #include <stdint.h>
+      #undef __STDC_LIMIT_MACROS
+    #else
+      #include <stdint.h>
+    #endif
+  #endif
   #ifndef __GNUC_STDC_INLINE__
     #define __GNUC_STDC_INLINE__ 1
   #endif
@@ -100,6 +105,19 @@
 
 
 /******************************************************************************/
+/*                                  Version                                   */
+/******************************************************************************/
+
+#define MPD_MAJOR_VERSION 2
+#define MPD_MINOR_VERSION 4
+#define MPD_MICRO_VERSION 0
+
+#define MPD_VERSION "2.4.0"
+
+const char *mpd_version(void);
+
+
+/******************************************************************************/
 /*                              Configuration                                 */
 /******************************************************************************/
 
@@ -241,7 +259,7 @@
 extern const char *mpd_clamp_string[MPD_CLAMP_GUARD];
 
 
-typedef struct {
+typedef struct mpd_context_t {
     mpd_ssize_t prec;   /* precision */
     mpd_ssize_t emax;   /* max positive exp */
     mpd_ssize_t emin;   /* min negative exp */
@@ -353,7 +371,7 @@
 #define MPD_DATAFLAGS (MPD_STATIC_DATA|MPD_SHARED_DATA|MPD_CONST_DATA)
 
 /* mpd_t */
-typedef struct {
+typedef struct mpd_t {
     uint8_t flags;
     mpd_ssize_t exp;
     mpd_ssize_t digits;
@@ -371,7 +389,7 @@
 /******************************************************************************/
 
 /* format specification */
-typedef struct {
+typedef struct mpd_spec_t {
     mpd_ssize_t min_width; /* minimum field width */
     mpd_ssize_t prec;      /* fraction digits or significant digits */
     char type;             /* conversion specifier */
@@ -437,6 +455,12 @@
 mpd_uint_t mpd_qget_uint(const mpd_t *dec, uint32_t *status);
 mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
 
+int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
+uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
+#ifndef LEGACY_COMPILER
+int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
+uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
+#endif
 
 /* quiet functions */
 int mpd_qcheck_nan(mpd_t *nanresult, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
@@ -528,6 +552,17 @@
 void mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
 
+#ifndef LEGACY_COMPILER
+void mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
+#endif
+
 
 size_t mpd_sizeinbase(const mpd_t *a, uint32_t base);
 void mpd_qimport_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen,
@@ -571,6 +606,12 @@
 mpd_ssize_t mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx);
 mpd_uint_t mpd_get_uint(const mpd_t *a, mpd_context_t *ctx);
 mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
+int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
+uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
+#ifndef LEGACY_COMPILER
+int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
+uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
+#endif
 void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
 void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
 void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
@@ -641,6 +682,17 @@
 void mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
 void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
 
+#ifndef LEGACY_COMPILER
+void mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+#endif
+
 
 /******************************************************************************/
 /*                          Configuration specific                            */
@@ -649,36 +701,8 @@
 #ifdef CONFIG_64
 void mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
-int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
-uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
-
-void mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
-void mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
-void mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
-void mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
-void mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
-void mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
-void mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
-void mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
-
 void mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
 void mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
-int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
-uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
-
-void mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
-void mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
-void mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
-void mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
-void mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
-void mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
-void mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
-void mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
-#else
-int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
-uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
-int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
-uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
 #endif
 
 
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -567,8 +567,9 @@
     PyObject* attrib = NULL;
     if (!PyArg_ParseTuple(args, "O!O|O!:SubElement",
                           &Element_Type, &parent, &tag,
-                          &PyDict_Type, &attrib))
+                          &PyDict_Type, &attrib)) {
         return NULL;
+    }
 
     if (attrib) {
         /* attrib passed as positional arg */
@@ -652,7 +653,6 @@
 }
 
 /* -------------------------------------------------------------------- */
-/* methods (in alphabetical order) */
 
 static PyObject*
 element_append(ElementObject* self, PyObject* args)
@@ -696,8 +696,7 @@
         return NULL;
 
     element = (ElementObject*) create_new_element(
-        self->tag, (self->extra) ? self->extra->attrib : Py_None
-        );
+        self->tag, (self->extra) ? self->extra->attrib : Py_None);
     if (!element)
         return NULL;
 
@@ -710,7 +709,6 @@
     Py_INCREF(JOIN_OBJ(element->tail));
 
     if (self->extra) {
-
         if (element_resize(element, self->extra->length) < 0) {
             Py_DECREF(element);
             return NULL;
@@ -722,7 +720,6 @@
         }
 
         element->extra->length = self->extra->length;
-
     }
 
     return (PyObject*) element;
@@ -779,7 +776,6 @@
     element->tail = JOIN_SET(tail, JOIN_GET(self->tail));
 
     if (self->extra) {
-
         if (element_resize(element, self->extra->length) < 0)
             goto error;
 
@@ -793,7 +789,6 @@
         }
 
         element->extra->length = self->extra->length;
-
     }
 
     /* add object to memo dictionary (so deepcopy won't visit it again) */
@@ -1141,8 +1136,8 @@
 
     for (i = 0; i < self->extra->length; i++) {
         ElementObject* item = (ElementObject*) self->extra->children[i];
-        if (Element_CheckExact(item) && (PyObject_RichCompareBool(item->tag, tag, Py_EQ) == 1)) {
-
+        if (Element_CheckExact(item) &&
+            (PyObject_RichCompareBool(item->tag, tag, Py_EQ) == 1)) {
             PyObject* text = element_get_text(item);
             if (text == Py_None)
                 return PyUnicode_New(0, 0);
@@ -1207,12 +1202,12 @@
     elementtreestate *st = ET_STATE_GLOBAL;
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:iterfind", kwlist,
-                                     &tag, &namespaces))
+                                     &tag, &namespaces)) {
         return NULL;
+    }
 
     return _PyObject_CallMethodId(
-        st->elementpath_obj, &PyId_iterfind, "OOO", self, tag, namespaces
-        );
+        st->elementpath_obj, &PyId_iterfind, "OOO", self, tag, namespaces);
 }
 
 static PyObject*
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -1,6 +1,30 @@
 #include "Python.h"
 #include "structmember.h"
 
+/*[clinic]
+module _pickle
+class _pickle.Pickler
+class _pickle.PicklerMemoProxy
+class _pickle.Unpickler
+class _pickle.UnpicklerMemoProxy
+[clinic]*/
+/*[clinic checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
+
+/*[python]
+class PicklerObject_converter(self_converter):
+    type = "PicklerObject *"
+
+class PicklerMemoProxyObject_converter(self_converter):
+    type = "PicklerMemoProxyObject *"
+
+class UnpicklerObject_converter(self_converter):
+    type = "UnpicklerObject *"
+
+class UnpicklerMemoProxyObject_converter(self_converter):
+    type = "UnpicklerMemoProxyObject *"
+[python]*/
+/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
+
 PyDoc_STRVAR(pickle_module_doc,
 "Optimized C implementation for the Python pickle module.");
 
@@ -866,34 +890,29 @@
 }
 
 static int
-_Pickler_SetProtocol(PicklerObject *self, PyObject *proto_obj,
-                     PyObject *fix_imports_obj)
-{
-    long proto = 0;
-    int fix_imports;
-
-    if (proto_obj == NULL || proto_obj == Py_None)
+_Pickler_SetProtocol(PicklerObject *self, PyObject *protocol, int fix_imports)
+{
+    long proto;
+
+    if (protocol == NULL || protocol == Py_None) {
         proto = DEFAULT_PROTOCOL;
+    }
     else {
-        proto = PyLong_AsLong(proto_obj);
-        if (proto == -1 && PyErr_Occurred())
+        proto = PyLong_AsLong(protocol);
+        if (proto < 0) {
+            if (proto == -1 && PyErr_Occurred())
+                return -1;
+            proto = HIGHEST_PROTOCOL;
+        }
+        else if (proto > HIGHEST_PROTOCOL) {
+            PyErr_Format(PyExc_ValueError, "pickle protocol must be <= %d",
+                         HIGHEST_PROTOCOL);
             return -1;
-    }
-    if (proto < 0)
-        proto = HIGHEST_PROTOCOL;
-    if (proto > HIGHEST_PROTOCOL) {
-        PyErr_Format(PyExc_ValueError, "pickle protocol must be <= %d",
-                     HIGHEST_PROTOCOL);
-        return -1;
-    }
-    fix_imports = PyObject_IsTrue(fix_imports_obj);
-    if (fix_imports == -1)
-        return -1;
-
-    self->proto = proto;
+        }
+    }
+    self->proto = (int)proto;
     self->bin = proto > 0;
     self->fix_imports = fix_imports && proto < 3;
-
     return 0;
 }
 
@@ -3708,16 +3727,35 @@
     return 0;
 }
 
-PyDoc_STRVAR(Pickler_clear_memo_doc,
-"clear_memo() -> None. Clears the pickler's \"memo\"."
+/*[clinic]
+
+_pickle.Pickler.clear_memo
+
+  self: PicklerObject
+
+Clears the pickler's "memo".
+
+The memo is the data structure that remembers which objects the
+pickler has already seen, so that shared or recursive objects are
+pickled by reference and not by value.  This method is useful when
+re-using picklers.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_Pickler_clear_memo__doc__,
+"clear_memo()\n"
+"Clears the pickler\'s \"memo\".\n"
 "\n"
 "The memo is the data structure that remembers which objects the\n"
 "pickler has already seen, so that shared or recursive objects are\n"
 "pickled by reference and not by value.  This method is useful when\n"
 "re-using picklers.");
 
+#define _PICKLE_PICKLER_CLEAR_MEMO_METHODDEF    \
+    {"clear_memo", (PyCFunction)_pickle_Pickler_clear_memo, METH_NOARGS, _pickle_Pickler_clear_memo__doc__},
+
 static PyObject *
-Pickler_clear_memo(PicklerObject *self)
+_pickle_Pickler_clear_memo(PicklerObject *self)
+/*[clinic checksum: 9c32be7e7a17ff82a81aae409d0d4f469033a5b2]*/
 {
     if (self->memo)
         PyMemoTable_Clear(self->memo);
@@ -3725,14 +3763,28 @@
     Py_RETURN_NONE;
 }
 
-PyDoc_STRVAR(Pickler_dump_doc,
-"dump(obj) -> None. Write a pickled representation of obj to the open file.");
+/*[clinic]
+
+_pickle.Pickler.dump
+
+  self: PicklerObject
+  obj: object
+  /
+
+Write a pickled representation of the given object to the open file.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_Pickler_dump__doc__,
+"dump(obj)\n"
+"Write a pickled representation of the given object to the open file.");
+
+#define _PICKLE_PICKLER_DUMP_METHODDEF    \
+    {"dump", (PyCFunction)_pickle_Pickler_dump, METH_O, _pickle_Pickler_dump__doc__},
 
 static PyObject *
-Pickler_dump(PicklerObject *self, PyObject *args)
-{
-    PyObject *obj;
-
+_pickle_Pickler_dump(PicklerObject *self, PyObject *obj)
+/*[clinic checksum: b72a69ec98737fabf66dae7c5a3210178bdbd3e6]*/
+{
     /* Check whether the Pickler was initialized correctly (issue3664).
        Developers often forget to call __init__() in their subclasses, which
        would trigger a segfault without this check. */
@@ -3743,9 +3795,6 @@
         return NULL;
     }
 
-    if (!PyArg_ParseTuple(args, "O:dump", &obj))
-        return NULL;
-
     if (_Pickler_ClearBuffer(self) < 0)
         return NULL;
 
@@ -3759,10 +3808,8 @@
 }
 
 static struct PyMethodDef Pickler_methods[] = {
-    {"dump", (PyCFunction)Pickler_dump, METH_VARARGS,
-     Pickler_dump_doc},
-    {"clear_memo", (PyCFunction)Pickler_clear_memo, METH_NOARGS,
-     Pickler_clear_memo_doc},
+    _PICKLE_PICKLER_DUMP_METHODDEF
+    _PICKLE_PICKLER_CLEAR_MEMO_METHODDEF
     {NULL, NULL}                /* sentinel */
 };
 
@@ -3813,9 +3860,39 @@
 }
 
 
-PyDoc_STRVAR(Pickler_doc,
-"Pickler(file, protocol=None)"
-"\n"
+/*[clinic]
+
+_pickle.Pickler.__init__
+
+  self: PicklerObject
+  file: object
+  protocol: object = NULL
+  fix_imports: bool = True
+
+This takes a binary file for writing a pickle data stream.
+
+The optional protocol argument tells the pickler to use the
+given protocol; supported protocols are 0, 1, 2, 3 and 4.  The
+default protocol is 3; a backward-incompatible protocol designed for
+Python 3.
+
+Specifying a negative protocol version selects the highest
+protocol version supported.  The higher the protocol used, the
+more recent the version of Python needed to read the pickle
+produced.
+
+The file argument must have a write() method that accepts a single
+bytes argument. It can thus be a file object opened for binary
+writing, a io.BytesIO instance, or any other custom object that
+meets this interface.
+
+If fix_imports is True and protocol is less than 3, pickle will try to
+map the new Python 3 names to the old module names used in Python 2,
+so that the pickle data stream is readable with Python 2.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_Pickler___init____doc__,
+"__init__(file, protocol=None, fix_imports=True)\n"
 "This takes a binary file for writing a pickle data stream.\n"
 "\n"
 "The optional protocol argument tells the pickler to use the\n"
@@ -3835,37 +3912,55 @@
 "\n"
 "If fix_imports is True and protocol is less than 3, pickle will try to\n"
 "map the new Python 3 names to the old module names used in Python 2,\n"
-"so that the pickle data stream is readable with Python 2.\n");
-
-static int
-Pickler_init(PicklerObject *self, PyObject *args, PyObject *kwds)
-{
-    static char *kwlist[] = {"file", "protocol", "fix_imports", 0};
+"so that the pickle data stream is readable with Python 2.");
+
+#define _PICKLE_PICKLER___INIT___METHODDEF    \
+    {"__init__", (PyCFunction)_pickle_Pickler___init__, METH_VARARGS|METH_KEYWORDS, _pickle_Pickler___init____doc__},
+
+static PyObject *
+_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *protocol, int fix_imports);
+
+static PyObject *
+_pickle_Pickler___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"file", "protocol", "fix_imports", NULL};
     PyObject *file;
-    PyObject *proto_obj = NULL;
-    PyObject *fix_imports = Py_True;
+    PyObject *protocol = NULL;
+    int fix_imports = 1;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+        "O|Op:__init__", _keywords,
+        &file, &protocol, &fix_imports))
+        goto exit;
+    return_value = _pickle_Pickler___init___impl((PicklerObject *)self, file, protocol, fix_imports);
+
+exit:
+    return return_value;
+}
+
+static PyObject *
+_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *protocol, int fix_imports)
+/*[clinic checksum: c99ff417bd703a74affc4b708167e56e135e8969]*/
+{
     _Py_IDENTIFIER(persistent_id);
     _Py_IDENTIFIER(dispatch_table);
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO:Pickler",
-                                     kwlist, &file, &proto_obj, &fix_imports))
-        return -1;
-
     /* In case of multiple __init__() calls, clear previous content. */
     if (self->write != NULL)
         (void)Pickler_clear(self);
 
-    if (_Pickler_SetProtocol(self, proto_obj, fix_imports) < 0)
-        return -1;
+    if (_Pickler_SetProtocol(self, protocol, fix_imports) < 0)
+        return NULL;
 
     if (_Pickler_SetOutputStream(self, file) < 0)
-        return -1;
+        return NULL;
 
     /* memo and output_buffer may have already been created in _Pickler_New */
     if (self->memo == NULL) {
         self->memo = PyMemoTable_New();
         if (self->memo == NULL)
-            return -1;
+            return NULL;
     }
     self->output_len = 0;
     if (self->output_buffer == NULL) {
@@ -3873,7 +3968,7 @@
         self->output_buffer = PyBytes_FromStringAndSize(NULL,
                                                         self->max_output_len);
         if (self->output_buffer == NULL)
-            return -1;
+            return NULL;
     }
 
     self->arg = NULL;
@@ -3885,14 +3980,24 @@
         self->pers_func = _PyObject_GetAttrId((PyObject *)self,
                                               &PyId_persistent_id);
         if (self->pers_func == NULL)
-            return -1;
+            return NULL;
     }
     self->dispatch_table = NULL;
     if (_PyObject_HasAttrId((PyObject *)self, &PyId_dispatch_table)) {
         self->dispatch_table = _PyObject_GetAttrId((PyObject *)self,
                                                    &PyId_dispatch_table);
         if (self->dispatch_table == NULL)
-            return -1;
+            return NULL;
+    }
+    return Py_None;
+}
+
+/* XXX Slight hack to slot a Clinic generated signature in tp_init. */
+static int
+Pickler_init(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    if (_pickle_Pickler___init__(self, args, kwargs) == NULL) {
+        return -1;
     }
     return 0;
 }
@@ -3912,22 +4017,48 @@
     PicklerObject *pickler; /* Pickler whose memo table we're proxying. */
 } PicklerMemoProxyObject;
 
-PyDoc_STRVAR(pmp_clear_doc,
-"memo.clear() -> None.  Remove all items from memo.");
+/*[clinic]
+_pickle.PicklerMemoProxy.clear
+
+  self: PicklerMemoProxyObject
+
+Remove all items from memo.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_PicklerMemoProxy_clear__doc__,
+"clear()\n"
+"Remove all items from memo.");
+
+#define _PICKLE_PICKLERMEMOPROXY_CLEAR_METHODDEF    \
+    {"clear", (PyCFunction)_pickle_PicklerMemoProxy_clear, METH_NOARGS, _pickle_PicklerMemoProxy_clear__doc__},
 
 static PyObject *
-pmp_clear(PicklerMemoProxyObject *self)
+_pickle_PicklerMemoProxy_clear(PicklerMemoProxyObject *self)
+/*[clinic checksum: 507f13938721992e175a3e58b5ad02620045a1cc]*/
 {
     if (self->pickler->memo)
         PyMemoTable_Clear(self->pickler->memo);
     Py_RETURN_NONE;
 }
 
-PyDoc_STRVAR(pmp_copy_doc,
-"memo.copy() -> new_memo.  Copy the memo to a new object.");
+/*[clinic]
+_pickle.PicklerMemoProxy.copy
+
+  self: PicklerMemoProxyObject
+
+Copy the memo to a new object.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_PicklerMemoProxy_copy__doc__,
+"copy()\n"
+"Copy the memo to a new object.");
+
+#define _PICKLE_PICKLERMEMOPROXY_COPY_METHODDEF    \
+    {"copy", (PyCFunction)_pickle_PicklerMemoProxy_copy, METH_NOARGS, _pickle_PicklerMemoProxy_copy__doc__},
 
 static PyObject *
-pmp_copy(PicklerMemoProxyObject *self)
+_pickle_PicklerMemoProxy_copy(PicklerMemoProxyObject *self)
+/*[clinic checksum: 73a5117ab354290ebdbe07bd0bf7232d0936a69d]*/
 {
     Py_ssize_t i;
     PyMemoTable *memo;
@@ -3964,14 +4095,27 @@
     return NULL;
 }
 
-PyDoc_STRVAR(pmp_reduce_doc,
-"memo.__reduce__(). Pickling support.");
+/*[clinic]
+_pickle.PicklerMemoProxy.__reduce__
+
+  self: PicklerMemoProxyObject
+
+Implement pickle support.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_PicklerMemoProxy___reduce____doc__,
+"__reduce__()\n"
+"Implement pickle support.");
+
+#define _PICKLE_PICKLERMEMOPROXY___REDUCE___METHODDEF    \
+    {"__reduce__", (PyCFunction)_pickle_PicklerMemoProxy___reduce__, METH_NOARGS, _pickle_PicklerMemoProxy___reduce____doc__},
 
 static PyObject *
-pmp_reduce(PicklerMemoProxyObject *self, PyObject *args)
+_pickle_PicklerMemoProxy___reduce__(PicklerMemoProxyObject *self)
+/*[clinic checksum: 40f0bf7a9b161e77130674f0481bda0a0184dcce]*/
 {
     PyObject *reduce_value, *dict_args;
-    PyObject *contents = pmp_copy(self);
+    PyObject *contents = _pickle_PicklerMemoProxy_copy(self);
     if (contents == NULL)
         return NULL;
 
@@ -3994,9 +4138,9 @@
 }
 
 static PyMethodDef picklerproxy_methods[] = {
-    {"clear",      (PyCFunction)pmp_clear,  METH_NOARGS,  pmp_clear_doc},
-    {"copy",       (PyCFunction)pmp_copy,   METH_NOARGS,  pmp_copy_doc},
-    {"__reduce__", (PyCFunction)pmp_reduce, METH_VARARGS, pmp_reduce_doc},
+    _PICKLE_PICKLERMEMOPROXY_CLEAR_METHODDEF
+    _PICKLE_PICKLERMEMOPROXY_COPY_METHODDEF
+    _PICKLE_PICKLERMEMOPROXY___REDUCE___METHODDEF
     {NULL, NULL} /* sentinel */
 };
 
@@ -4208,7 +4352,7 @@
     0,                                  /*tp_setattro*/
     0,                                  /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
-    Pickler_doc,                        /*tp_doc*/
+    _pickle_Pickler___init____doc__,    /*tp_doc*/
     (traverseproc)Pickler_traverse,     /*tp_traverse*/
     (inquiry)Pickler_clear,             /*tp_clear*/
     0,                                  /*tp_richcompare*/
@@ -4223,7 +4367,7 @@
     0,                                  /*tp_descr_get*/
     0,                                  /*tp_descr_set*/
     0,                                  /*tp_dictoffset*/
-    (initproc)Pickler_init,             /*tp_init*/
+    Pickler_init,                       /*tp_init*/
     PyType_GenericAlloc,                /*tp_alloc*/
     PyType_GenericNew,                  /*tp_new*/
     PyObject_GC_Del,                    /*tp_free*/
@@ -5938,57 +6082,111 @@
     return value;
 }
 
-PyDoc_STRVAR(Unpickler_load_doc,
-"load() -> object. Load a pickle."
+/*[clinic]
+
+_pickle.Unpickler.load
+
+Load a pickle.
+
+Read a pickled object representation from the open file object given in
+the constructor, and return the reconstituted object hierarchy specified
+therein.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_Unpickler_load__doc__,
+"load()\n"
+"Load a pickle.\n"
 "\n"
 "Read a pickled object representation from the open file object given in\n"
 "the constructor, and return the reconstituted object hierarchy specified\n"
-"therein.\n");
+"therein.");
+
+#define _PICKLE_UNPICKLER_LOAD_METHODDEF    \
+    {"load", (PyCFunction)_pickle_Unpickler_load, METH_NOARGS, _pickle_Unpickler_load__doc__},
 
 static PyObject *
-Unpickler_load(UnpicklerObject *self)
-{
+_pickle_Unpickler_load(PyObject *self)
+/*[clinic checksum: 9a30ba4e4d9221d4dcd705e1471ab11b2c9e3ac6]*/
+{
+    UnpicklerObject *unpickler = (UnpicklerObject*)self;
     /* Check whether the Unpickler was initialized correctly. This prevents
        segfaulting if a subclass overridden __init__ with a function that does
        not call Unpickler.__init__(). Here, we simply ensure that self->read
        is not NULL. */
-    if (self->read == NULL) {
+    if (unpickler->read == NULL) {
         PyErr_Format(UnpicklingError,
                      "Unpickler.__init__() was not called by %s.__init__()",
-                     Py_TYPE(self)->tp_name);
+                     Py_TYPE(unpickler)->tp_name);
         return NULL;
     }
 
-    return load(self);
+    return load(unpickler);
 }
 
 /* The name of find_class() is misleading. In newer pickle protocols, this
    function is used for loading any global (i.e., functions), not just
    classes. The name is kept only for backward compatibility. */
 
-PyDoc_STRVAR(Unpickler_find_class_doc,
-"find_class(module_name, global_name) -> object.\n"
+/*[clinic]
+
+_pickle.Unpickler.find_class
+
+  self: UnpicklerObject
+  module_name: object
+  global_name: object
+  /
+
+Return an object from a specified module.
+
+If necessary, the module will be imported. Subclasses may override this
+method (e.g. to restrict unpickling of arbitrary classes and functions).
+
+This method is called whenever a class or a function object is
+needed.  Both arguments passed are str objects.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_Unpickler_find_class__doc__,
+"find_class(module_name, global_name)\n"
+"Return an object from a specified module.\n"
 "\n"
-"Return an object from a specified module, importing the module if\n"
-"necessary.  Subclasses may override this method (e.g. to restrict\n"
-"unpickling of arbitrary classes and functions).\n"
+"If necessary, the module will be imported. Subclasses may override this\n"
+"method (e.g. to restrict unpickling of arbitrary classes and functions).\n"
 "\n"
 "This method is called whenever a class or a function object is\n"
-"needed.  Both arguments passed are str objects.\n");
+"needed.  Both arguments passed are str objects.");
+
+#define _PICKLE_UNPICKLER_FIND_CLASS_METHODDEF    \
+    {"find_class", (PyCFunction)_pickle_Unpickler_find_class, METH_VARARGS, _pickle_Unpickler_find_class__doc__},
 
 static PyObject *
-Unpickler_find_class(UnpicklerObject *self, PyObject *args)
+_pickle_Unpickler_find_class_impl(UnpicklerObject *self, PyObject *module_name, PyObject *global_name);
+
+static PyObject *
+_pickle_Unpickler_find_class(PyObject *self, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    PyObject *module_name;
+    PyObject *global_name;
+
+    if (!PyArg_ParseTuple(args,
+        "OO:find_class",
+        &module_name, &global_name))
+        goto exit;
+    return_value = _pickle_Unpickler_find_class_impl((UnpicklerObject *)self, module_name, global_name);
+
+exit:
+    return return_value;
+}
+
+static PyObject *
+_pickle_Unpickler_find_class_impl(UnpicklerObject *self, PyObject *module_name, PyObject *global_name)
+/*[clinic checksum: b7d05d4dd8adc698e5780c1ac2be0f5062d33915]*/
 {
     PyObject *global;
     PyObject *modules_dict;
     PyObject *module;
-    PyObject *module_name, *global_name;
     _Py_IDENTIFIER(modules);
 
-    if (!PyArg_UnpackTuple(args, "find_class", 2, 2,
-                           &module_name, &global_name))
-        return NULL;
-
     /* Try to map the old names used in Python 2.x to the new ones used in
        Python 3.x.  We do this only with old pickle protocols and when the
        user has not disabled the feature. */
@@ -6065,10 +6263,8 @@
 }
 
 static struct PyMethodDef Unpickler_methods[] = {
-    {"load", (PyCFunction)Unpickler_load, METH_NOARGS,
-     Unpickler_load_doc},
-    {"find_class", (PyCFunction)Unpickler_find_class, METH_VARARGS,
-     Unpickler_find_class_doc},
+    _PICKLE_UNPICKLER_LOAD_METHODDEF
+    _PICKLE_UNPICKLER_FIND_CLASS_METHODDEF
     {NULL, NULL}                /* sentinel */
 };
 
@@ -6135,9 +6331,41 @@
     return 0;
 }
 
-PyDoc_STRVAR(Unpickler_doc,
-"Unpickler(file, *, encoding='ASCII', errors='strict')"
-"\n"
+/*[clinic]
+
+_pickle.Unpickler.__init__
+
+  self: UnpicklerObject
+  file: object
+  *
+  fix_imports: bool = True
+  encoding: str = 'ASCII'
+  errors: str = 'strict'
+
+This takes a binary file for reading a pickle data stream.
+
+The protocol version of the pickle is detected automatically, so no
+proto argument is needed.
+
+The file-like object must have two methods, a read() method
+that takes an integer argument, and a readline() method that
+requires no arguments.  Both methods should return bytes.
+Thus file-like object can be a binary file object opened for
+reading, a BytesIO object, or any other custom object that
+meets this interface.
+
+Optional keyword arguments are *fix_imports*, *encoding* and *errors*,
+which are used to control compatiblity support for pickle stream
+generated by Python 2.x.  If *fix_imports* is True, pickle will try to
+map the old Python 2.x names to the new names used in Python 3.x.  The
+*encoding* and *errors* tell pickle how to decode 8-bit string
+instances pickled by Python 2.x; these default to 'ASCII' and
+'strict', respectively.
+
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_Unpickler___init____doc__,
+"__init__(file, *, fix_imports=True, encoding=\'ASCII\', errors=\'strict\')\n"
 "This takes a binary file for reading a pickle data stream.\n"
 "\n"
 "The protocol version of the pickle is detected automatically, so no\n"
@@ -6155,57 +6383,60 @@
 "generated by Python 2.x.  If *fix_imports* is True, pickle will try to\n"
 "map the old Python 2.x names to the new names used in Python 3.x.  The\n"
 "*encoding* and *errors* tell pickle how to decode 8-bit string\n"
-"instances pickled by Python 2.x; these default to 'ASCII' and\n"
-"'strict', respectively.\n");
-
-static int
-Unpickler_init(UnpicklerObject *self, PyObject *args, PyObject *kwds)
-{
-    static char *kwlist[] = {"file", "fix_imports", "encoding", "errors", 0};
+"instances pickled by Python 2.x; these default to \'ASCII\' and\n"
+"\'strict\', respectively.");
+
+#define _PICKLE_UNPICKLER___INIT___METHODDEF    \
+    {"__init__", (PyCFunction)_pickle_Unpickler___init__, METH_VARARGS|METH_KEYWORDS, _pickle_Unpickler___init____doc__},
+
+static PyObject *
+_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_imports, const char *encoding, const char *errors);
+
+static PyObject *
+_pickle_Unpickler___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"file", "fix_imports", "encoding", "errors", NULL};
     PyObject *file;
-    PyObject *fix_imports = Py_True;
-    char *encoding = NULL;
-    char *errors = NULL;
+    int fix_imports = 1;
+    const char *encoding = "ASCII";
+    const char *errors = "strict";
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+        "O|$pss:__init__", _keywords,
+        &file, &fix_imports, &encoding, &errors))
+        goto exit;
+    return_value = _pickle_Unpickler___init___impl((UnpicklerObject *)self, file, fix_imports, encoding, errors);
+
+exit:
+    return return_value;
+}
+
+static PyObject *
+_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_imports, const char *encoding, const char *errors)
+/*[clinic checksum: bed0d8bbe1c647960ccc6f997b33bf33935fa56f]*/
+{
     _Py_IDENTIFIER(persistent_load);
 
-    /* XXX: That is an horrible error message. But, I don't know how to do
-       better... */
-    if (Py_SIZE(args) != 1) {
-        PyErr_Format(PyExc_TypeError,
-                     "%s takes exactly one positional argument (%zd given)",
-                     Py_TYPE(self)->tp_name, Py_SIZE(args));
-        return -1;
-    }
-
-    /* Arguments parsing needs to be done in the __init__() method to allow
-       subclasses to define their own __init__() method, which may (or may
-       not) support Unpickler arguments. However, this means we need to be
-       extra careful in the other Unpickler methods, since a subclass could
-       forget to call Unpickler.__init__() thus breaking our internal
-       invariants. */
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oss:Unpickler", kwlist,
-                                     &file, &fix_imports, &encoding, &errors))
-        return -1;
-
     /* In case of multiple __init__() calls, clear previous content. */
     if (self->read != NULL)
         (void)Unpickler_clear(self);
 
     if (_Unpickler_SetInputStream(self, file) < 0)
-        return -1;
+        return NULL;
 
     if (_Unpickler_SetInputEncoding(self, encoding, errors) < 0)
-        return -1;
-
-    self->fix_imports = PyObject_IsTrue(fix_imports);
+        return NULL;
+
+    self->fix_imports = fix_imports;
     if (self->fix_imports == -1)
-        return -1;
+        return NULL;
 
     if (_PyObject_HasAttrId((PyObject *)self, &PyId_persistent_load)) {
         self->pers_func = _PyObject_GetAttrId((PyObject *)self,
                                               &PyId_persistent_load);
         if (self->pers_func == NULL)
-            return -1;
+            return NULL;
     }
     else {
         self->pers_func = NULL;
@@ -6213,16 +6444,26 @@
 
     self->stack = (Pdata *)Pdata_New();
     if (self->stack == NULL)
-        return -1;
+        return NULL;
 
     self->memo_size = 32;
     self->memo = _Unpickler_NewMemo(self->memo_size);
     if (self->memo == NULL)
-        return -1;
+        return NULL;
 
     self->arg = NULL;
     self->proto = 0;
 
+    return Py_None;
+}
+
+/* XXX Slight hack to slot a Clinic generated signature in tp_init. */
+static int
+Unpickler_init(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    if (_pickle_Unpickler___init__(self, args, kwargs) == NULL) {
+        return -1;
+    }
     return 0;
 }
 
@@ -6244,11 +6485,24 @@
     UnpicklerObject *unpickler;
 } UnpicklerMemoProxyObject;
 
-PyDoc_STRVAR(ump_clear_doc,
-"memo.clear() -> None.  Remove all items from memo.");
+/*[clinic]
+_pickle.UnpicklerMemoProxy.clear
+
+  self: UnpicklerMemoProxyObject
+
+Remove all items from memo.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_UnpicklerMemoProxy_clear__doc__,
+"clear()\n"
+"Remove all items from memo.");
+
+#define _PICKLE_UNPICKLERMEMOPROXY_CLEAR_METHODDEF    \
+    {"clear", (PyCFunction)_pickle_UnpicklerMemoProxy_clear, METH_NOARGS, _pickle_UnpicklerMemoProxy_clear__doc__},
 
 static PyObject *
-ump_clear(UnpicklerMemoProxyObject *self)
+_pickle_UnpicklerMemoProxy_clear(UnpicklerMemoProxyObject *self)
+/*[clinic checksum: 46fecf4e33c0c873124f845edf6cc3a2e9864bd5]*/
 {
     _Unpickler_MemoCleanup(self->unpickler);
     self->unpickler->memo = _Unpickler_NewMemo(self->unpickler->memo_size);
@@ -6257,11 +6511,24 @@
     Py_RETURN_NONE;
 }
 
-PyDoc_STRVAR(ump_copy_doc,
-"memo.copy() -> new_memo.  Copy the memo to a new object.");
+/*[clinic]
+_pickle.UnpicklerMemoProxy.copy
+
+  self: UnpicklerMemoProxyObject
+
+Copy the memo to a new object.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_UnpicklerMemoProxy_copy__doc__,
+"copy()\n"
+"Copy the memo to a new object.");
+
+#define _PICKLE_UNPICKLERMEMOPROXY_COPY_METHODDEF    \
+    {"copy", (PyCFunction)_pickle_UnpicklerMemoProxy_copy, METH_NOARGS, _pickle_UnpicklerMemoProxy_copy__doc__},
 
 static PyObject *
-ump_copy(UnpicklerMemoProxyObject *self)
+_pickle_UnpicklerMemoProxy_copy(UnpicklerMemoProxyObject *self)
+/*[clinic checksum: f8856c4e8a33540886dfbb245f286af3008fa0ad]*/
 {
     Py_ssize_t i;
     PyObject *new_memo = PyDict_New();
@@ -6291,15 +6558,28 @@
     return NULL;
 }
 
-PyDoc_STRVAR(ump_reduce_doc,
-"memo.__reduce__(). Pickling support.");
+/*[clinic]
+_pickle.UnpicklerMemoProxy.__reduce__
+
+  self: UnpicklerMemoProxyObject
+
+Implement pickling support.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_UnpicklerMemoProxy___reduce____doc__,
+"__reduce__()\n"
+"Implement pickling support.");
+
+#define _PICKLE_UNPICKLERMEMOPROXY___REDUCE___METHODDEF    \
+    {"__reduce__", (PyCFunction)_pickle_UnpicklerMemoProxy___reduce__, METH_NOARGS, _pickle_UnpicklerMemoProxy___reduce____doc__},
 
 static PyObject *
-ump_reduce(UnpicklerMemoProxyObject *self, PyObject *args)
+_pickle_UnpicklerMemoProxy___reduce__(UnpicklerMemoProxyObject *self)
+/*[clinic checksum: ab5516a77659144e1191c7dd70a0c6c7455660bc]*/
 {
     PyObject *reduce_value;
     PyObject *constructor_args;
-    PyObject *contents = ump_copy(self);
+    PyObject *contents = _pickle_UnpicklerMemoProxy_copy(self);
     if (contents == NULL)
         return NULL;
 
@@ -6322,9 +6602,9 @@
 }
 
 static PyMethodDef unpicklerproxy_methods[] = {
-    {"clear",       (PyCFunction)ump_clear,  METH_NOARGS,  ump_clear_doc},
-    {"copy",        (PyCFunction)ump_copy,   METH_NOARGS,  ump_copy_doc},
-    {"__reduce__",  (PyCFunction)ump_reduce, METH_VARARGS, ump_reduce_doc},
+    _PICKLE_UNPICKLERMEMOPROXY_CLEAR_METHODDEF
+    _PICKLE_UNPICKLERMEMOPROXY_COPY_METHODDEF
+    _PICKLE_UNPICKLERMEMOPROXY___REDUCE___METHODDEF
     {NULL, NULL}    /* sentinel */
 };
 
@@ -6548,7 +6828,7 @@
     0,                                  /*tp_setattro*/
     0,                                  /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
-    Unpickler_doc,                      /*tp_doc*/
+    _pickle_Unpickler___init____doc__,  /*tp_doc*/
     (traverseproc)Unpickler_traverse,   /*tp_traverse*/
     (inquiry)Unpickler_clear,           /*tp_clear*/
     0,                                  /*tp_richcompare*/
@@ -6563,21 +6843,53 @@
     0,                                  /*tp_descr_get*/
     0,                                  /*tp_descr_set*/
     0,                                  /*tp_dictoffset*/
-    (initproc)Unpickler_init,           /*tp_init*/
+    Unpickler_init,                     /*tp_init*/
     PyType_GenericAlloc,                /*tp_alloc*/
     PyType_GenericNew,                  /*tp_new*/
     PyObject_GC_Del,                    /*tp_free*/
     0,                                  /*tp_is_gc*/
 };
 
-PyDoc_STRVAR(pickle_dump_doc,
-"dump(obj, file, protocol=None, *, fix_imports=True) -> None\n"
+/*[clinic]
+
+_pickle.dump
+
+  obj: object
+  file: object
+  protocol: object = NULL
+  *
+  fix_imports: bool = True
+
+Write a pickled representation of obj to the open file object file.
+
+This is equivalent to ``Pickler(file, protocol).dump(obj)``, but may be more
+efficient.
+
+The optional protocol argument tells the pickler to use the given protocol
+supported protocols are 0, 1, 2, 3.  The default protocol is 3; a
+backward-incompatible protocol designed for Python 3.0.
+
+Specifying a negative protocol version selects the highest protocol version
+supported.  The higher the protocol used, the more recent the version of
+Python needed to read the pickle produced.
+
+The file argument must have a write() method that accepts a single bytes
+argument.  It can thus be a file object opened for binary writing, a
+io.BytesIO instance, or any other custom object that meets this interface.
+
+If fix_imports is True and protocol is less than 3, pickle will try to
+map the new Python 3.x names to the old module names used in Python 2.x,
+so that the pickle data stream is readable with Python 2.x.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_dump__doc__,
+"dump(obj, file, protocol=None, *, fix_imports=True)\n"
+"Write a pickled representation of obj to the open file object file.\n"
 "\n"
-"Write a pickled representation of obj to the open file object file.  This\n"
-"is equivalent to ``Pickler(file, protocol).dump(obj)``, but may be more\n"
+"This is equivalent to ``Pickler(file, protocol).dump(obj)``, but may be more\n"
 "efficient.\n"
 "\n"
-"The optional protocol argument tells the pickler to use the given protocol;\n"
+"The optional protocol argument tells the pickler to use the given protocol\n"
 "supported protocols are 0, 1, 2, 3.  The default protocol is 3; a\n"
 "backward-incompatible protocol designed for Python 3.0.\n"
 "\n"
@@ -6591,35 +6903,44 @@
 "\n"
 "If fix_imports is True and protocol is less than 3, pickle will try to\n"
 "map the new Python 3.x names to the old module names used in Python 2.x,\n"
-"so that the pickle data stream is readable with Python 2.x.\n");
+"so that the pickle data stream is readable with Python 2.x.");
+
+#define _PICKLE_DUMP_METHODDEF    \
+    {"dump", (PyCFunction)_pickle_dump, METH_VARARGS|METH_KEYWORDS, _pickle_dump__doc__},
 
 static PyObject *
-pickle_dump(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    static char *kwlist[] = {"obj", "file", "protocol", "fix_imports", 0};
+_pickle_dump_impl(PyModuleDef *module, PyObject *obj, PyObject *file, PyObject *protocol, int fix_imports);
+
+static PyObject *
+_pickle_dump(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"obj", "file", "protocol", "fix_imports", NULL};
     PyObject *obj;
     PyObject *file;
-    PyObject *proto = NULL;
-    PyObject *fix_imports = Py_True;
-    PicklerObject *pickler;
-
-    /* fix_imports is a keyword-only argument.  */
-    if (Py_SIZE(args) > 3) {
-        PyErr_Format(PyExc_TypeError,
-                     "pickle.dump() takes at most 3 positional "
-                     "argument (%zd given)", Py_SIZE(args));
-        return NULL;
-    }
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO:dump", kwlist,
-                                     &obj, &file, &proto, &fix_imports))
-        return NULL;
-
-    pickler = _Pickler_New();
+    PyObject *protocol = NULL;
+    int fix_imports = 1;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+        "OO|O$p:dump", _keywords,
+        &obj, &file, &protocol, &fix_imports))
+        goto exit;
+    return_value = _pickle_dump_impl(module, obj, file, protocol, fix_imports);
+
+exit:
+    return return_value;
+}
+
+static PyObject *
+_pickle_dump_impl(PyModuleDef *module, PyObject *obj, PyObject *file, PyObject *protocol, int fix_imports)
+/*[clinic checksum: e442721b16052d921b5e3fbd146d0a62e94a459e]*/
+{
+    PicklerObject *pickler = _Pickler_New();
+
     if (pickler == NULL)
         return NULL;
 
-    if (_Pickler_SetProtocol(pickler, proto, fix_imports) < 0)
+    if (_Pickler_SetProtocol(pickler, protocol, fix_imports) < 0)
         goto error;
 
     if (_Pickler_SetOutputStream(pickler, file) < 0)
@@ -6639,11 +6960,33 @@
     return NULL;
 }
 
-PyDoc_STRVAR(pickle_dumps_doc,
-"dumps(obj, protocol=None, *, fix_imports=True) -> bytes\n"
-"\n"
-"Return the pickled representation of the object as a bytes\n"
-"object, instead of writing it to a file.\n"
+/*[clinic]
+
+_pickle.dumps
+
+  obj: object
+  protocol: object = NULL
+  *
+  fix_imports: bool = True
+
+Return the pickled representation of the object as a bytes object.
+
+The optional protocol argument tells the pickler to use the given protocol;
+supported protocols are 0, 1, 2, 3.  The default protocol is 3; a
+backward-incompatible protocol designed for Python 3.0.
+
+Specifying a negative protocol version selects the highest protocol version
+supported.  The higher the protocol used, the more recent the version of
+Python needed to read the pickle produced.
+
+If fix_imports is True and *protocol* is less than 3, pickle will try to
+map the new Python 3.x names to the old module names used in Python 2.x,
+so that the pickle data stream is readable with Python 2.x.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_dumps__doc__,
+"dumps(obj, protocol=None, *, fix_imports=True)\n"
+"Return the pickled representation of the object as a bytes object.\n"
 "\n"
 "The optional protocol argument tells the pickler to use the given protocol;\n"
 "supported protocols are 0, 1, 2, 3.  The default protocol is 3; a\n"
@@ -6655,35 +6998,44 @@
 "\n"
 "If fix_imports is True and *protocol* is less than 3, pickle will try to\n"
 "map the new Python 3.x names to the old module names used in Python 2.x,\n"
-"so that the pickle data stream is readable with Python 2.x.\n");
+"so that the pickle data stream is readable with Python 2.x.");
+
+#define _PICKLE_DUMPS_METHODDEF    \
+    {"dumps", (PyCFunction)_pickle_dumps, METH_VARARGS|METH_KEYWORDS, _pickle_dumps__doc__},
 
 static PyObject *
-pickle_dumps(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    static char *kwlist[] = {"obj", "protocol", "fix_imports", 0};
+_pickle_dumps_impl(PyModuleDef *module, PyObject *obj, PyObject *protocol, int fix_imports);
+
+static PyObject *
+_pickle_dumps(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"obj", "protocol", "fix_imports", NULL};
     PyObject *obj;
-    PyObject *proto = NULL;
+    PyObject *protocol = NULL;
+    int fix_imports = 1;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+        "O|O$p:dumps", _keywords,
+        &obj, &protocol, &fix_imports))
+        goto exit;
+    return_value = _pickle_dumps_impl(module, obj, protocol, fix_imports);
+
+exit:
+    return return_value;
+}
+
+static PyObject *
+_pickle_dumps_impl(PyModuleDef *module, PyObject *obj, PyObject *protocol, int fix_imports)
+/*[clinic checksum: df6262c4c487f537f47aec8a1709318204c1e174]*/
+{
     PyObject *result;
-    PyObject *fix_imports = Py_True;
-    PicklerObject *pickler;
-
-    /* fix_imports is a keyword-only argument.  */
-    if (Py_SIZE(args) > 2) {
-        PyErr_Format(PyExc_TypeError,
-                     "pickle.dumps() takes at most 2 positional "
-                     "argument (%zd given)", Py_SIZE(args));
-        return NULL;
-    }
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO:dumps", kwlist,
-                                     &obj, &proto, &fix_imports))
-        return NULL;
-
-    pickler = _Pickler_New();
+    PicklerObject *pickler = _Pickler_New();
+
     if (pickler == NULL)
         return NULL;
 
-    if (_Pickler_SetProtocol(pickler, proto, fix_imports) < 0)
+    if (_Pickler_SetProtocol(pickler, protocol, fix_imports) < 0)
         goto error;
 
     if (dump(pickler, obj) < 0)
@@ -6698,15 +7050,46 @@
     return NULL;
 }
 
-PyDoc_STRVAR(pickle_load_doc,
-"load(file, *, fix_imports=True, encoding='ASCII', errors='strict') -> object\n"
+/*[clinic]
+
+_pickle.load
+
+  file: object
+  *
+  fix_imports: bool = True
+  encoding: str = 'ASCII'
+  errors: str = 'strict'
+
+Return a reconstituted object from the pickle data stored in a file.
+
+This is equivalent to ``Unpickler(file).load()``, but may be more efficient.
+
+The protocol version of the pickle is detected automatically, so no protocol
+argument is needed.  Bytes past the pickled object's representation are
+ignored.
+
+The argument file must have two methods, a read() method that takes an
+integer argument, and a readline() method that requires no arguments.  Both
+methods should return bytes.  Thus *file* can be a binary file object opened
+for reading, a BytesIO object, or any other custom object that meets this
+interface.
+
+Optional keyword arguments are fix_imports, encoding and errors,
+which are used to control compatiblity support for pickle stream generated
+by Python 2.x.  If fix_imports is True, pickle will try to map the old
+Python 2.x names to the new names used in Python 3.x.  The encoding and
+errors tell pickle how to decode 8-bit string instances pickled by Python
+2.x; these default to 'ASCII' and 'strict', respectively.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_load__doc__,
+"load(file, *, fix_imports=True, encoding=\'ASCII\', errors=\'strict\')\n"
+"Return a reconstituted object from the pickle data stored in a file.\n"
 "\n"
-"Read a pickled object representation from the open file object file and\n"
-"return the reconstituted object hierarchy specified therein.  This is\n"
-"equivalent to ``Unpickler(file).load()``, but may be more efficient.\n"
+"This is equivalent to ``Unpickler(file).load()``, but may be more efficient.\n"
 "\n"
 "The protocol version of the pickle is detected automatically, so no protocol\n"
-"argument is needed.  Bytes past the pickled object's representation are\n"
+"argument is needed.  Bytes past the pickled object\'s representation are\n"
 "ignored.\n"
 "\n"
 "The argument file must have two methods, a read() method that takes an\n"
@@ -6720,32 +7103,41 @@
 "by Python 2.x.  If fix_imports is True, pickle will try to map the old\n"
 "Python 2.x names to the new names used in Python 3.x.  The encoding and\n"
 "errors tell pickle how to decode 8-bit string instances pickled by Python\n"
-"2.x; these default to 'ASCII' and 'strict', respectively.\n");
+"2.x; these default to \'ASCII\' and \'strict\', respectively.");
+
+#define _PICKLE_LOAD_METHODDEF    \
+    {"load", (PyCFunction)_pickle_load, METH_VARARGS|METH_KEYWORDS, _pickle_load__doc__},
 
 static PyObject *
-pickle_load(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    static char *kwlist[] = {"file", "fix_imports", "encoding", "errors", 0};
+_pickle_load_impl(PyModuleDef *module, PyObject *file, int fix_imports, const char *encoding, const char *errors);
+
+static PyObject *
+_pickle_load(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"file", "fix_imports", "encoding", "errors", NULL};
     PyObject *file;
-    PyObject *fix_imports = Py_True;
+    int fix_imports = 1;
+    const char *encoding = "ASCII";
+    const char *errors = "strict";
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+        "O|$pss:load", _keywords,
+        &file, &fix_imports, &encoding, &errors))
+        goto exit;
+    return_value = _pickle_load_impl(module, file, fix_imports, encoding, errors);
+
+exit:
+    return return_value;
+}
+
+static PyObject *
+_pickle_load_impl(PyModuleDef *module, PyObject *file, int fix_imports, const char *encoding, const char *errors)
+/*[clinic checksum: e10796f6765b22ce48dca6940f11b3933853ca35]*/
+{
     PyObject *result;
-    char *encoding = NULL;
-    char *errors = NULL;
-    UnpicklerObject *unpickler;
-
-    /* fix_imports, encoding and errors are a keyword-only argument.  */
-    if (Py_SIZE(args) != 1) {
-        PyErr_Format(PyExc_TypeError,
-                     "pickle.load() takes exactly one positional "
-                     "argument (%zd given)", Py_SIZE(args));
-        return NULL;
-    }
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oss:load", kwlist,
-                                     &file, &fix_imports, &encoding, &errors))
-        return NULL;
-
-    unpickler = _Unpickler_New();
+    UnpicklerObject *unpickler = _Unpickler_New();
+
     if (unpickler == NULL)
         return NULL;
 
@@ -6755,9 +7147,7 @@
     if (_Unpickler_SetInputEncoding(unpickler, encoding, errors) < 0)
         goto error;
 
-    unpickler->fix_imports = PyObject_IsTrue(fix_imports);
-    if (unpickler->fix_imports == -1)
-        goto error;
+    unpickler->fix_imports = fix_imports;
 
     result = load(unpickler);
     Py_DECREF(unpickler);
@@ -6768,14 +7158,36 @@
     return NULL;
 }
 
-PyDoc_STRVAR(pickle_loads_doc,
-"loads(input, *, fix_imports=True, encoding='ASCII', errors='strict') -> object\n"
-"\n"
-"Read a pickled object hierarchy from a bytes object and return the\n"
-"reconstituted object hierarchy specified therein\n"
+/*[clinic]
+
+_pickle.loads
+
+  data: object
+  *
+  fix_imports: bool = True
+  encoding: str = 'ASCII'
+  errors: str = 'strict'
+
+Return a reconstituted object from the given pickle data.
+
+The protocol version of the pickle is detected automatically, so no protocol
+argument is needed.  Bytes past the pickled object's representation are
+ignored.
+
+Optional keyword arguments are fix_imports, encoding and errors, which
+are used to control compatiblity support for pickle stream generated
+by Python 2.x.  If fix_imports is True, pickle will try to map the old
+Python 2.x names to the new names used in Python 3.x.  The encoding and
+errors tell pickle how to decode 8-bit string instances pickled by Python
+2.x; these default to 'ASCII' and 'strict', respectively.
+[clinic]*/
+
+PyDoc_STRVAR(_pickle_loads__doc__,
+"loads(data, *, fix_imports=True, encoding=\'ASCII\', errors=\'strict\')\n"
+"Return a reconstituted object from the given pickle data.\n"
 "\n"
 "The protocol version of the pickle is detected automatically, so no protocol\n"
-"argument is needed.  Bytes past the pickled object's representation are\n"
+"argument is needed.  Bytes past the pickled object\'s representation are\n"
 "ignored.\n"
 "\n"
 "Optional keyword arguments are fix_imports, encoding and errors, which\n"
@@ -6783,44 +7195,51 @@
 "by Python 2.x.  If fix_imports is True, pickle will try to map the old\n"
 "Python 2.x names to the new names used in Python 3.x.  The encoding and\n"
 "errors tell pickle how to decode 8-bit string instances pickled by Python\n"
-"2.x; these default to 'ASCII' and 'strict', respectively.\n");
+"2.x; these default to \'ASCII\' and \'strict\', respectively.");
+
+#define _PICKLE_LOADS_METHODDEF    \
+    {"loads", (PyCFunction)_pickle_loads, METH_VARARGS|METH_KEYWORDS, _pickle_loads__doc__},
 
 static PyObject *
-pickle_loads(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    static char *kwlist[] = {"input", "fix_imports", "encoding", "errors", 0};
-    PyObject *input;
-    PyObject *fix_imports = Py_True;
+_pickle_loads_impl(PyModuleDef *module, PyObject *data, int fix_imports, const char *encoding, const char *errors);
+
+static PyObject *
+_pickle_loads(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"data", "fix_imports", "encoding", "errors", NULL};
+    PyObject *data;
+    int fix_imports = 1;
+    const char *encoding = "ASCII";
+    const char *errors = "strict";
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+        "O|$pss:loads", _keywords,
+        &data, &fix_imports, &encoding, &errors))
+        goto exit;
+    return_value = _pickle_loads_impl(module, data, fix_imports, encoding, errors);
+
+exit:
+    return return_value;
+}
+
+static PyObject *
+_pickle_loads_impl(PyModuleDef *module, PyObject *data, int fix_imports, const char *encoding, const char *errors)
+/*[clinic checksum: 29ee725efcbf51a3533c19cb8261a8e267b7080a]*/
+{
     PyObject *result;
-    char *encoding = NULL;
-    char *errors = NULL;
-    UnpicklerObject *unpickler;
-
-    /* fix_imports, encoding and errors are a keyword-only argument.  */
-    if (Py_SIZE(args) != 1) {
-        PyErr_Format(PyExc_TypeError,
-                     "pickle.loads() takes exactly one positional "
-                     "argument (%zd given)", Py_SIZE(args));
-        return NULL;
-    }
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oss:loads", kwlist,
-                                     &input, &fix_imports, &encoding, &errors))
-        return NULL;
-
-    unpickler = _Unpickler_New();
+    UnpicklerObject *unpickler = _Unpickler_New();
+
     if (unpickler == NULL)
         return NULL;
 
-    if (_Unpickler_SetStringInput(unpickler, input) < 0)
+    if (_Unpickler_SetStringInput(unpickler, data) < 0)
         goto error;
 
     if (_Unpickler_SetInputEncoding(unpickler, encoding, errors) < 0)
         goto error;
 
-    unpickler->fix_imports = PyObject_IsTrue(fix_imports);
-    if (unpickler->fix_imports == -1)
-        goto error;
+    unpickler->fix_imports = fix_imports;
 
     result = load(unpickler);
     Py_DECREF(unpickler);
@@ -6833,14 +7252,10 @@
 
 
 static struct PyMethodDef pickle_methods[] = {
-    {"dump",  (PyCFunction)pickle_dump,  METH_VARARGS|METH_KEYWORDS,
-     pickle_dump_doc},
-    {"dumps", (PyCFunction)pickle_dumps, METH_VARARGS|METH_KEYWORDS,
-     pickle_dumps_doc},
-    {"load",  (PyCFunction)pickle_load,  METH_VARARGS|METH_KEYWORDS,
-     pickle_load_doc},
-    {"loads", (PyCFunction)pickle_loads, METH_VARARGS|METH_KEYWORDS,
-     pickle_loads_doc},
+    _PICKLE_DUMP_METHODDEF
+    _PICKLE_DUMPS_METHODDEF
+    _PICKLE_LOAD_METHODDEF
+    _PICKLE_LOADS_METHODDEF
     {NULL, NULL} /* sentinel */
 };
 
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -385,6 +385,8 @@
 #endif
 #endif
 
+#define DWORD_MAX 4294967295U
+
 
 #ifdef MS_WINDOWS
 static int
@@ -897,7 +899,7 @@
 
     length = PyBytes_GET_SIZE(bytes);
 #ifdef MS_WINDOWS
-    if (length > MAX_PATH) {
+    if (length > MAX_PATH-1) {
         FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
         Py_DECREF(bytes);
         return 0;
@@ -1376,18 +1378,18 @@
 static BOOL __stdcall
 win32_chdir(LPCSTR path)
 {
-    char new_path[MAX_PATH+1];
+    char new_path[MAX_PATH];
     int result;
     char env[4] = "=x:";
 
     if(!SetCurrentDirectoryA(path))
         return FALSE;
-    result = GetCurrentDirectoryA(MAX_PATH+1, new_path);
+    result = GetCurrentDirectoryA(Py_ARRAY_LENGTH(new_path), new_path);
     if (!result)
         return FALSE;
     /* In the ANSI API, there should not be any paths longer
-       than MAX_PATH. */
-    assert(result <= MAX_PATH+1);
+       than MAX_PATH-1 (not including the final null character). */
+    assert(result < Py_ARRAY_LENGTH(new_path));
     if (strncmp(new_path, "\\\\", 2) == 0 ||
         strncmp(new_path, "//", 2) == 0)
         /* UNC path, nothing to do. */
@@ -1401,16 +1403,16 @@
 static BOOL __stdcall
 win32_wchdir(LPCWSTR path)
 {
-    wchar_t _new_path[MAX_PATH+1], *new_path = _new_path;
+    wchar_t _new_path[MAX_PATH], *new_path = _new_path;
     int result;
     wchar_t env[4] = L"=x:";
 
     if(!SetCurrentDirectoryW(path))
         return FALSE;
-    result = GetCurrentDirectoryW(MAX_PATH+1, new_path);
+    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(new_path), new_path);
     if (!result)
         return FALSE;
-    if (result > MAX_PATH+1) {
+    if (result > Py_ARRAY_LENGTH(new_path)) {
         new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
         if (!new_path) {
             SetLastError(ERROR_OUTOFMEMORY);
@@ -3396,11 +3398,11 @@
         PyObject *resobj;
         DWORD len;
         Py_BEGIN_ALLOW_THREADS
-        len = GetCurrentDirectoryW(sizeof wbuf/ sizeof wbuf[0], wbuf);
+        len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
         /* If the buffer is large enough, len does not include the
            terminating \0. If the buffer is too small, len includes
            the space needed for the terminator. */
-        if (len >= sizeof wbuf/ sizeof wbuf[0]) {
+        if (len >= Py_ARRAY_LENGTH(wbuf)) {
             wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
             if (wbuf2)
                 len = GetCurrentDirectoryW(len, wbuf2);
@@ -3581,10 +3583,10 @@
     HANDLE hFindFile = INVALID_HANDLE_VALUE;
     BOOL result;
     WIN32_FIND_DATA FileData;
-    char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
+    char namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
     char *bufptr = namebuf;
     /* only claim to have space for MAX_PATH */
-    Py_ssize_t len = sizeof(namebuf)-5;
+    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
     PyObject *po = NULL;
     wchar_t *wnamebuf = NULL;
 
@@ -3873,14 +3875,14 @@
 posix__getfullpathname(PyObject *self, PyObject *args)
 {
     const char *path;
-    char outbuf[MAX_PATH*2];
+    char outbuf[MAX_PATH];
     char *temp;
     PyObject *po;
 
     if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po))
     {
         wchar_t *wpath;
-        wchar_t woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
+        wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
         wchar_t *wtemp;
         DWORD result;
         PyObject *v;
@@ -4039,24 +4041,31 @@
 {
     PyObject *po, *result;
     wchar_t *path, *mountpath=NULL;
-    size_t bufsize;
+    size_t buflen;
     BOOL ret;
 
     if (!PyArg_ParseTuple(args, "U|:_getvolumepathname", &po))
         return NULL;
-    path = PyUnicode_AsUnicode(po);
+    path = PyUnicode_AsUnicodeAndSize(po, &buflen);
     if (path == NULL)
         return NULL;
+    buflen += 1;
 
     /* Volume path should be shorter than entire path */
-    bufsize = max(MAX_PATH, wcslen(path) * 2 * sizeof(wchar_t)+1);
-    mountpath = (wchar_t *)PyMem_Malloc(bufsize);
+    buflen = Py_MAX(buflen, MAX_PATH);
+
+    if (buflen > DWORD_MAX) {
+        PyErr_SetString(PyExc_OverflowError, "path too long");
+        return NULL;
+    }
+
+    mountpath = (wchar_t *)PyMem_Malloc(buflen * sizeof(wchar_t));
     if (mountpath == NULL)
         return PyErr_NoMemory();
 
     Py_BEGIN_ALLOW_THREADS
     ret = GetVolumePathNameW(path, mountpath,
-                             Py_SAFE_DOWNCAST(bufsize, size_t, DWORD));
+                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
     Py_END_ALLOW_THREADS
 
     if (!ret) {
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1956,7 +1956,7 @@
         undef_macros = []
         if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"):
             include_dirs = []
-            libraries = ['mpdec']
+            libraries = [':libmpdec.so.2']
             sources = ['_decimal/_decimal.c']
             depends = ['_decimal/docstrings.h']
         else:

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list