diff options
author | Larry Hastings <larry@hastings.org> | 2013-11-24 22:05:57 (GMT) |
---|---|---|
committer | Larry Hastings <larry@hastings.org> | 2013-11-24 22:05:57 (GMT) |
commit | 99e101013fa36da37e47a5a18b5a62d621b0efb9 (patch) | |
tree | f603004433e242a1eb26573cd9ec54846229d071 | |
parent | d34b620cc3b8b2326b511f98b0ca439ad97b83b8 (diff) | |
parent | 2480c2ed593a164fe3a4821a13d5867a0a7102ed (diff) | |
download | cpython-99e101013fa36da37e47a5a18b5a62d621b0efb9.zip cpython-99e101013fa36da37e47a5a18b5a62d621b0efb9.tar.gz cpython-99e101013fa36da37e47a5a18b5a62d621b0efb9.tar.bz2 |
Merged 3.4.0b1 release head back into trunk.
-rw-r--r-- | Doc/Makefile | 1 | ||||
-rw-r--r-- | Doc/library/email.contentmanager.rst | 4 | ||||
-rw-r--r-- | Doc/library/email.message.rst | 2 | ||||
-rw-r--r-- | Doc/library/gettext.rst | 6 | ||||
-rw-r--r-- | Doc/library/unittest.rst | 4 | ||||
-rw-r--r-- | Doc/tools/sphinxext/susp-ignored.csv | 16 | ||||
-rw-r--r-- | Doc/whatsnew/3.4.rst | 2 | ||||
-rw-r--r-- | Lib/_strptime.py | 2 | ||||
-rw-r--r-- | Lib/asyncio/windows_events.py | 11 | ||||
-rw-r--r-- | Lib/decimal.py | 1 | ||||
-rw-r--r-- | Lib/fileinput.py | 2 | ||||
-rw-r--r-- | Lib/test/test_codecs.py | 4 | ||||
-rw-r--r-- | Lib/test/test_decimal.py | 1 | ||||
-rw-r--r-- | Lib/test/test_fileinput.py | 8 | ||||
-rw-r--r-- | Lib/test/test_gdb.py | 1 | ||||
-rw-r--r-- | Lib/test/test_io.py | 3 | ||||
-rw-r--r-- | Lib/test/test_strptime.py | 4 | ||||
-rw-r--r-- | Lib/test/test_time.py | 4 | ||||
-rw-r--r-- | Lib/test/test_zipfile.py | 29 | ||||
-rw-r--r-- | Misc/NEWS | 23 | ||||
-rw-r--r-- | Modules/_decimal/_decimal.c | 8 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/mpdecimal.c | 260 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/mpdecimal.h | 94 | ||||
-rw-r--r-- | Modules/_elementtree.c | 21 | ||||
-rw-r--r-- | Modules/_pickle.c | 929 | ||||
-rw-r--r-- | Modules/posixmodule.c | 47 | ||||
-rw-r--r-- | setup.py | 2 |
27 files changed, 1127 insertions, 362 deletions
diff --git a/Doc/Makefile b/Doc/Makefile index a774aad..3c7196e 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -186,6 +186,7 @@ serve: 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 index f3ba794..5162da1 100644 --- a/Doc/library/email.contentmanager.rst +++ b/Doc/library/email.contentmanager.rst @@ -96,7 +96,7 @@ this module. 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 @@ this module. 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 index f278a0a..c0f947f 100644 --- a/Doc/library/email.message.rst +++ b/Doc/library/email.message.rst @@ -35,7 +35,7 @@ Here are the methods of the :class:`Message` class: 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 index 18506ff..982780f 100644 --- a/Doc/library/gettext.rst +++ b/Doc/library/gettext.rst @@ -476,9 +476,9 @@ applications.) :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 index c13f9ca..6310624 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -901,8 +901,8 @@ Test cases | :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 index 57b1f1e..67ad01f 100644 --- a/Doc/tools/sphinxext/susp-ignored.csv +++ b/Doc/tools/sphinxext/susp-ignored.csv @@ -141,15 +141,8 @@ library/linecache,,:sys,"sys:x:3:3:sys:/dev:/bin/sh" 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,,:bytes,:bytes 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,'r:xz' 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@python.org""" diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst index 435d582..a47297d 100644 --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -424,7 +424,7 @@ base64 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 index 3884a67..d101c6d 100644 --- a/Lib/_strptime.py +++ b/Lib/_strptime.py @@ -329,7 +329,7 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): (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 index 64fe386..b2ed241 100644 --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -327,14 +327,21 @@ class IocpProactor: 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 index fc95ae9..7bc1c94 100644 --- a/Lib/decimal.py +++ b/Lib/decimal.py @@ -140,6 +140,7 @@ __all__ = [ __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 index 11ba82d..de29518 100644 --- a/Lib/fileinput.py +++ b/Lib/fileinput.py @@ -224,7 +224,7 @@ class FileInput: "'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 index 639ce9f..f682380 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -602,7 +602,9 @@ class UTF16Test(ReadTest, unittest.TestCase): 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 index ac8a7be..6378ef3 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -4149,6 +4149,7 @@ class CheckAttributes(unittest.TestCase): 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 index c5e57d4..db6082c 100644 --- a/Lib/test/test_fileinput.py +++ b/Lib/test/test_fileinput.py @@ -22,7 +22,7 @@ except ImportError: 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 @@ class FileInputTests(unittest.TestCase): 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 index b543889..cc2900f 100644 --- a/Lib/test/test_gdb.py +++ b/Lib/test/test_gdb.py @@ -170,6 +170,7 @@ class DebuggerTests(unittest.TestCase): '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 index c1ea6f2..57f3659 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -2777,7 +2777,8 @@ class MiscIOTest(unittest.TestCase): 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 index 68e6a67..d5bc39d 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -223,6 +223,10 @@ class StrptimeTests(unittest.TestCase): 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 index f3643b6..44bcb94 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -198,6 +198,10 @@ class TimeTestCase(unittest.TestCase): 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 index c15ea9f..49eccbb 100644 --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -14,7 +14,7 @@ from random import randint, random, getrandbits 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 @@ def get_files(test): 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 @@ class OtherTests(unittest.TestCase): 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 @@ class OtherTests(unittest.TestCase): 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 @@ class AbstractUniversalNewlineTests: # 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 @@ class AbstractUniversalNewlineTests: # 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 @@ class AbstractUniversalNewlineTests: # 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 @@ class AbstractUniversalNewlineTests: # 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 @@ class AbstractUniversalNewlineTests: # 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') @@ -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 @@ Library - 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 @@ Library 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 @@ Library - 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 @@ Tests - 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 index 06c2c39..ac20308 100644 --- 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 @@ PyInit__decimal(void) } /* 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 index c63a1a0..287a77ed 100644 --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -97,6 +97,8 @@ static void _settriple(mpd_t *result, uint8_t sign, mpd_uint_t a, 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 @@ static mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n); /******************************************************************************/ +/* Version */ +/******************************************************************************/ + +const char * +mpd_version(void) +{ + return MPD_VERSION; +} + + +/******************************************************************************/ /* Performance critical inline functions */ /******************************************************************************/ @@ -1345,6 +1358,91 @@ mpd_qget_ssize(const mpd_t *a, uint32_t *status) 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 @@ mpd_qget_i64(const mpd_t *a, uint32_t *status) { 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_u64(mpd_t *result, const mpd_t *a, uint64_t b, { 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_u64(mpd_t *result, const mpd_t *a, uint64_t b, { 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_u64(mpd_t *result, const mpd_t *a, uint64_t b, { 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_u64(mpd_t *result, const mpd_t *a, uint64_t b, { 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 index 06f5470..0f31733 100644 --- 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 @@ extern "C" { #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 @@ MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) /******************************************************************************/ +/* 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_round_string[MPD_ROUND_GUARD]; 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 @@ void mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags); #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 @@ typedef unsigned char uchar; /******************************************************************************/ /* 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_ssize_t mpd_qget_ssize(const mpd_t *dec, uint32_t *status); 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_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_ 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 @@ void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx); 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_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx); 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 @@ void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx); #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 index 797e357..46a1f41 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -567,8 +567,9 @@ subelement(PyObject *self, PyObject *args, PyObject *kwds) 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 @@ element_dealloc(ElementObject* self) } /* -------------------------------------------------------------------- */ -/* methods (in alphabetical order) */ static PyObject* element_append(ElementObject* self, PyObject* args) @@ -696,8 +696,7 @@ element_copy(ElementObject* self, PyObject* args) 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 @@ element_copy(ElementObject* self, PyObject* args) 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_copy(ElementObject* self, PyObject* args) } element->extra->length = self->extra->length; - } return (PyObject*) element; @@ -779,7 +776,6 @@ element_deepcopy(ElementObject* self, PyObject* args) 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_deepcopy(ElementObject* self, PyObject* args) } element->extra->length = self->extra->length; - } /* add object to memo dictionary (so deepcopy won't visit it again) */ @@ -1141,8 +1136,8 @@ element_findtext(ElementObject *self, PyObject *args, PyObject *kwds) 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 @@ element_iterfind(ElementObject *self, PyObject *args, PyObject *kwds) 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 index c8ef2ea..28c84f3 100644 --- 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 @@ _Pickler_New(void) } static int -_Pickler_SetProtocol(PicklerObject *self, PyObject *proto_obj, - PyObject *fix_imports_obj) +_Pickler_SetProtocol(PicklerObject *self, PyObject *protocol, int fix_imports) { - long proto = 0; - int fix_imports; + long proto; - if (proto_obj == NULL || proto_obj == Py_None) + 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 @@ dump(PicklerObject *self, PyObject *obj) 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 @@ Pickler_clear_memo(PicklerObject *self) 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) +_pickle_Pickler_dump(PicklerObject *self, PyObject *obj) +/*[clinic checksum: b72a69ec98737fabf66dae7c5a3210178bdbd3e6]*/ { - PyObject *obj; - /* 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 @@ Pickler_dump(PicklerObject *self, PyObject *args) return NULL; } - if (!PyArg_ParseTuple(args, "O:dump", &obj)) - return NULL; - if (_Pickler_ClearBuffer(self) < 0) return NULL; @@ -3759,10 +3808,8 @@ Pickler_dump(PicklerObject *self, PyObject *args) } 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 @@ Pickler_clear(PicklerObject *self) } -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 @@ PyDoc_STRVAR(Pickler_doc, "\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"); +"so that the pickle data stream is readable with Python 2."); -static int -Pickler_init(PicklerObject *self, PyObject *args, PyObject *kwds) +#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) { - static char *kwlist[] = {"file", "protocol", "fix_imports", 0}; + 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 @@ Pickler_init(PicklerObject *self, PyObject *args, PyObject *kwds) 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 @@ Pickler_init(PicklerObject *self, PyObject *args, PyObject *kwds) 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 @@ typedef struct { 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 @@ pmp_copy(PicklerMemoProxyObject *self) 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 @@ pmp_reduce(PicklerMemoProxyObject *self, PyObject *args) } 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 @@ static PyTypeObject Pickler_Type = { 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 @@ static PyTypeObject Pickler_Type = { 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 @@ load(UnpicklerObject *self) 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 * +_pickle_Unpickler_find_class_impl(UnpicklerObject *self, PyObject *module_name, PyObject *global_name); static PyObject * -Unpickler_find_class(UnpicklerObject *self, PyObject *args) +_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 @@ Unpickler_find_class(UnpicklerObject *self, PyObject *args) } 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 @@ Unpickler_clear(UnpicklerObject *self) 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 @@ PyDoc_STRVAR(Unpickler_doc, "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"); +"instances pickled by Python 2.x; these default to \'ASCII\' and\n" +"\'strict\', respectively."); -static int -Unpickler_init(UnpicklerObject *self, PyObject *args, PyObject *kwds) +#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) { - static char *kwlist[] = {"file", "fix_imports", "encoding", "errors", 0}; + 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; - _Py_IDENTIFIER(persistent_load); + int fix_imports = 1; + const char *encoding = "ASCII"; + const char *errors = "strict"; - /* 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; - } + 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); - /* 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; +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); /* 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; + return NULL; - self->fix_imports = PyObject_IsTrue(fix_imports); + 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 @@ Unpickler_init(UnpicklerObject *self, PyObject *args, PyObject *kwds) 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 @@ typedef struct { 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 @@ ump_clear(UnpicklerMemoProxyObject *self) 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 @@ error: 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 @@ ump_reduce(UnpicklerMemoProxyObject *self, PyObject *args) } 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 @@ static PyTypeObject Unpickler_Type = { 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 @@ static PyTypeObject Unpickler_Type = { 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 @@ PyDoc_STRVAR(pickle_dump_doc, "\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_impl(PyModuleDef *module, PyObject *obj, PyObject *file, PyObject *protocol, int fix_imports); static PyObject * -pickle_dump(PyObject *self, PyObject *args, PyObject *kwds) +_pickle_dump(PyModuleDef *module, PyObject *args, PyObject *kwargs) { - static char *kwlist[] = {"obj", "file", "protocol", "fix_imports", 0}; + 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; + PyObject *protocol = NULL; + int fix_imports = 1; - /* 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, kwargs, + "OO|O$p:dump", _keywords, + &obj, &file, &protocol, &fix_imports)) + goto exit; + return_value = _pickle_dump_impl(module, obj, file, protocol, fix_imports); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO:dump", kwlist, - &obj, &file, &proto, &fix_imports)) - return NULL; +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(); - 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 @@ pickle_dump(PyObject *self, PyObject *args, PyObject *kwds) 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 @@ PyDoc_STRVAR(pickle_dumps_doc, "\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_impl(PyModuleDef *module, PyObject *obj, PyObject *protocol, int fix_imports); static PyObject * -pickle_dumps(PyObject *self, PyObject *args, PyObject *kwds) +_pickle_dumps(PyModuleDef *module, PyObject *args, PyObject *kwargs) { - static char *kwlist[] = {"obj", "protocol", "fix_imports", 0}; + PyObject *return_value = NULL; + static char *_keywords[] = {"obj", "protocol", "fix_imports", NULL}; PyObject *obj; - PyObject *proto = NULL; - PyObject *result; - PyObject *fix_imports = Py_True; - PicklerObject *pickler; + PyObject *protocol = NULL; + int fix_imports = 1; - /* 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, kwargs, + "O|O$p:dumps", _keywords, + &obj, &protocol, &fix_imports)) + goto exit; + return_value = _pickle_dumps_impl(module, obj, protocol, fix_imports); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO:dumps", kwlist, - &obj, &proto, &fix_imports)) - return NULL; +exit: + return return_value; +} + +static PyObject * +_pickle_dumps_impl(PyModuleDef *module, PyObject *obj, PyObject *protocol, int fix_imports) +/*[clinic checksum: df6262c4c487f537f47aec8a1709318204c1e174]*/ +{ + PyObject *result; + PicklerObject *pickler = _Pickler_New(); - 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 @@ pickle_dumps(PyObject *self, PyObject *args, PyObject *kwds) 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 @@ PyDoc_STRVAR(pickle_load_doc, "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) +_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) { - static char *kwlist[] = {"file", "fix_imports", "encoding", "errors", 0}; + PyObject *return_value = NULL; + static char *_keywords[] = {"file", "fix_imports", "encoding", "errors", NULL}; PyObject *file; - PyObject *fix_imports = Py_True; - PyObject *result; - char *encoding = NULL; - char *errors = NULL; - UnpicklerObject *unpickler; + int fix_imports = 1; + const char *encoding = "ASCII"; + const char *errors = "strict"; - /* 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, kwargs, + "O|$pss:load", _keywords, + &file, &fix_imports, &encoding, &errors)) + goto exit; + return_value = _pickle_load_impl(module, file, fix_imports, encoding, errors); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oss:load", kwlist, - &file, &fix_imports, &encoding, &errors)) - return NULL; +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; + UnpicklerObject *unpickler = _Unpickler_New(); - unpickler = _Unpickler_New(); if (unpickler == NULL) return NULL; @@ -6755,9 +7147,7 @@ pickle_load(PyObject *self, PyObject *args, PyObject *kwds) 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 @@ pickle_load(PyObject *self, PyObject *args, PyObject *kwds) 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 @@ PyDoc_STRVAR(pickle_loads_doc, "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) +_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) { - static char *kwlist[] = {"input", "fix_imports", "encoding", "errors", 0}; - PyObject *input; - PyObject *fix_imports = Py_True; - PyObject *result; - char *encoding = NULL; - char *errors = NULL; - UnpicklerObject *unpickler; + 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"; - /* 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, kwargs, + "O|$pss:loads", _keywords, + &data, &fix_imports, &encoding, &errors)) + goto exit; + return_value = _pickle_loads_impl(module, data, fix_imports, encoding, errors); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oss:loads", kwlist, - &input, &fix_imports, &encoding, &errors)) - return NULL; +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; + UnpicklerObject *unpickler = _Unpickler_New(); - 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 @@ pickle_loads(PyObject *self, PyObject *args, PyObject *kwds) 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 index d0bd2d9..ae45fc3 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -385,6 +385,8 @@ static int win32_can_symlink = 0; #endif #endif +#define DWORD_MAX 4294967295U + #ifdef MS_WINDOWS static int @@ -897,7 +899,7 @@ path_converter(PyObject *o, void *p) { 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 @@ posix_1str(const char *func_name, PyObject *args, char *format, 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 @@ win32_chdir(LPCSTR path) 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 @@ posix_getcwd(int use_bytes) 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 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) 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 @@ static PyObject * 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 @@ posix__getvolumepathname(PyObject *self, PyObject *args) { 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) { @@ -1956,7 +1956,7 @@ class PyBuildExt(build_ext): 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: |