diff options
26 files changed, 246 insertions, 33 deletions
diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index bc8ab2c..929d41b 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -40,12 +40,12 @@ concatenation of the data fed to it so far using the :meth:`digest` or .. note:: - For better multithreading performance, the Python GIL is released for + For better multithreading performance, the Python :term:`GIL` is released for strings of more than 2047 bytes at object creation or on update. .. note:: - Feeding string objects is to :meth:`update` is not supported, as hashes work + Feeding string objects into :meth:`update` is not supported, as hashes work on bytes, not on characters. .. index:: single: OpenSSL; (use in module hashlib) diff --git a/Lib/_pyio.py b/Lib/_pyio.py index fa77ec1..9cbb364 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -346,8 +346,10 @@ class IOBase(metaclass=abc.ABCMeta): This method has no effect if the file is already closed. """ if not self.__closed: - self.flush() - self.__closed = True + try: + self.flush() + finally: + self.__closed = True def __del__(self): """Destructor. Calls close().""" @@ -1584,8 +1586,10 @@ class TextIOWrapper(TextIOBase): def close(self): if self.buffer is not None and not self.closed: - self.flush() - self.buffer.close() + try: + self.flush() + finally: + self.buffer.close() @property def closed(self): diff --git a/Lib/modulefinder.py b/Lib/modulefinder.py index 683e305..f90a432 100644 --- a/Lib/modulefinder.py +++ b/Lib/modulefinder.py @@ -2,6 +2,7 @@ import dis import imp +import importlib.machinery import marshal import os import sys diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index fe6e939..f88c242 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -701,6 +701,12 @@ class BytesTest(BaseBytesTest): def __bytes__(self): return None self.assertRaises(TypeError, bytes, A()) + class A: + def __bytes__(self): + return b'a' + def __index__(self): + return 42 + self.assertEqual(bytes(A()), b'a') # Test PyBytes_FromFormat() def test_from_format(self): diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 555ad74..6931e0a 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -603,6 +603,7 @@ class IOTest(unittest.TestCase): raise IOError() f.flush = bad_flush self.assertRaises(IOError, f.close) # exception not swallowed + self.assertTrue(f.closed) def test_multi_close(self): f = self.open(support.TESTFN, "wb", buffering=0) @@ -780,6 +781,22 @@ class CommonBufferedTests: raw.flush = bad_flush b = self.tp(raw) self.assertRaises(IOError, b.close) # exception not swallowed + self.assertTrue(b.closed) + + def test_close_error_on_close(self): + raw = self.MockRawIO() + def bad_flush(): + raise IOError('flush') + def bad_close(): + raise IOError('close') + raw.close = bad_close + b = self.tp(raw) + b.flush = bad_flush + with self.assertRaises(IOError) as err: # exception not swallowed + b.close() + self.assertEqual(err.exception.args, ('close',)) + self.assertEqual(err.exception.__context__.args, ('flush',)) + self.assertFalse(b.closed) def test_multi_close(self): raw = self.MockRawIO() @@ -1296,6 +1313,16 @@ class BufferedWriterTest(unittest.TestCase, CommonBufferedTests): with self.assertRaises(TypeError): self.tp(self.MockRawIO(), 8, 12) + def test_write_error_on_close(self): + raw = self.MockRawIO() + def bad_write(b): + raise IOError() + raw.write = bad_write + b = self.tp(raw) + b.write(b'spam') + self.assertRaises(IOError, b.close) # exception not swallowed + self.assertTrue(b.closed) + class CBufferedWriterTest(BufferedWriterTest, SizeofTest): tp = io.BufferedWriter @@ -2465,6 +2492,7 @@ class TextIOWrapperTest(unittest.TestCase): raise IOError() txt.flush = bad_flush self.assertRaises(IOError, txt.close) # exception not swallowed + self.assertTrue(txt.closed) def test_multi_close(self): txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") diff --git a/Lib/test/test_modulefinder.py b/Lib/test/test_modulefinder.py index c5fc320..53ea232 100644 --- a/Lib/test/test_modulefinder.py +++ b/Lib/test/test_modulefinder.py @@ -196,6 +196,18 @@ a/module.py from . import bar """] +relative_import_test_4 = [ + "a.module", + ["a", "a.module"], + [], + [], + """\ +a/__init__.py + def foo(): pass +a/module.py + from . import * +"""] + def open_file(path): dirname = os.path.dirname(path) @@ -273,6 +285,9 @@ class ModuleFinderTest(unittest.TestCase): def test_relative_imports_3(self): self._do_test(relative_import_test_3) + def test_relative_imports_4(self): + self._do_test(relative_import_test_4) + def test_main(): support.run_unittest(ModuleFinderTest) @@ -894,15 +894,13 @@ Dan Parisien William Park Harri Pasanen Gaël Pasgrimaud -Berker Peksag -Bo Peng -Joe Peterson Randy Pausch Samuele Pedroni Justin Peel Marcel van der Peijl Berker Peksag Steven Pemberton +Bo Peng Santiago Peresón George Peristerakis Mathieu Perreault @@ -12,6 +12,12 @@ What's New in Python 3.3.1? Core and Builtins ----------------- +- Issue #16597: In buffered and text IO, call close() on the underlying stream + if invoking flush() fails. + +- Issue #16722: In the bytes() constructor, try to call __bytes__ on the + argument before __index__. + - Issue #16602: When a weakref's target was part of a long deallocation chain, the object could remain reachable through its weakref even though its refcount had dropped to zero. @@ -108,6 +114,8 @@ Core and Builtins Library ------- +- Issue #16752: Add a missing import to modulefinder. Patch by Berker Peksag. + - Issue #16646: ftplib.FTP.makeport() might lose socket error details. (patch by Serhiy Storchaka) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 09320cf..e940ec7 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -817,11 +817,11 @@ static int _call_function_pointer(int flags, space[0] = errno; errno = temp; } - Py_XDECREF(error_object); #ifdef WITH_THREAD if ((flags & FUNCFLAG_PYTHONAPI) == 0) Py_BLOCK_THREADS #endif + Py_XDECREF(error_object); #ifdef MS_WIN32 #ifndef DONT_USE_SEH if (dwExceptionCode) { diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 4fb9998..4dc9087 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -3484,7 +3484,7 @@ PyDec_Round(PyObject *dec, PyObject *args) } } -PyObject *DecimalTuple = NULL; +static PyObject *DecimalTuple = NULL; /* Return the DecimalTuple representation of a PyDecObject. */ static PyObject * PyDec_AsTuple(PyObject *dec, PyObject *dummy UNUSED) diff --git a/Modules/_decimal/libmpdec/basearith.h b/Modules/_decimal/libmpdec/basearith.h index 5004b2c..114cef3 100644 --- a/Modules/_decimal/libmpdec/basearith.h +++ b/Modules/_decimal/libmpdec/basearith.h @@ -35,6 +35,10 @@ #include "typearith.h" +/* Internal header file: all symbols have local scope in the DSO */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + mpd_uint_t _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v, mpd_size_t m, mpd_size_t n); void _mpd_baseaddto(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n); @@ -209,6 +213,9 @@ _mpd_isallnine(const mpd_uint_t *data, mpd_ssize_t len) } +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #endif /* BASEARITH_H */ diff --git a/Modules/_decimal/libmpdec/constants.h b/Modules/_decimal/libmpdec/constants.h index 2d63d7e..13df920 100644 --- a/Modules/_decimal/libmpdec/constants.h +++ b/Modules/_decimal/libmpdec/constants.h @@ -33,6 +33,10 @@ #include "mpdecimal.h" +/* Internal header file: all symbols have local scope in the DSO */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + /* choice of optimized functions */ #if defined(CONFIG_64) /* x64 */ @@ -77,6 +81,9 @@ extern const mpd_uint_t LH_P1P2; extern const mpd_uint_t UH_P1P2; +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #endif /* CONSTANTS_H */ diff --git a/Modules/_decimal/libmpdec/convolute.h b/Modules/_decimal/libmpdec/convolute.h index 2f8d6d8..c35ed46 100644 --- a/Modules/_decimal/libmpdec/convolute.h +++ b/Modules/_decimal/libmpdec/convolute.h @@ -33,11 +33,18 @@ #include "mpdecimal.h" #include <stdio.h> -#define SIX_STEP_THRESHOLD 4096 +/* Internal header file: all symbols have local scope in the DSO */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + +#define SIX_STEP_THRESHOLD 4096 int fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum); int fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum); +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #endif diff --git a/Modules/_decimal/libmpdec/crt.h b/Modules/_decimal/libmpdec/crt.h index 0e03e5d..8909232 100644 --- a/Modules/_decimal/libmpdec/crt.h +++ b/Modules/_decimal/libmpdec/crt.h @@ -34,7 +34,14 @@ #include <stdio.h> +/* Internal header file: all symbols have local scope in the DSO */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + void crt3(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_size_t nmemb); +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #endif diff --git a/Modules/_decimal/libmpdec/difradix2.h b/Modules/_decimal/libmpdec/difradix2.h index 759442a..81aa598 100644 --- a/Modules/_decimal/libmpdec/difradix2.h +++ b/Modules/_decimal/libmpdec/difradix2.h @@ -35,7 +35,14 @@ #include "numbertheory.h" +/* Internal header file: all symbols have local scope in the DSO */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + void fnt_dif2(mpd_uint_t a[], mpd_size_t n, struct fnt_params *tparams); +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #endif diff --git a/Modules/_decimal/libmpdec/fnt.h b/Modules/_decimal/libmpdec/fnt.h index 2d701b6..1f302cc 100644 --- a/Modules/_decimal/libmpdec/fnt.h +++ b/Modules/_decimal/libmpdec/fnt.h @@ -34,9 +34,16 @@ #include <stdio.h> +/* Internal header file: all symbols have local scope in the DSO */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + int std_fnt(mpd_uint_t a[], mpd_size_t n, int modnum); int std_inv_fnt(mpd_uint_t a[], mpd_size_t n, int modnum); +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #endif diff --git a/Modules/_decimal/libmpdec/fourstep.h b/Modules/_decimal/libmpdec/fourstep.h index 61d9d6a..593f27d 100644 --- a/Modules/_decimal/libmpdec/fourstep.h +++ b/Modules/_decimal/libmpdec/fourstep.h @@ -34,8 +34,15 @@ #include <stdio.h> +/* Internal header file: all symbols have local scope in the DSO */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + int four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum); int inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum); +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #endif diff --git a/Modules/_decimal/libmpdec/memory.h b/Modules/_decimal/libmpdec/memory.h index b3a4a56..7e73c13 100644 --- a/Modules/_decimal/libmpdec/memory.h +++ b/Modules/_decimal/libmpdec/memory.h @@ -33,11 +33,18 @@ #include "mpdecimal.h" +/* Internal header file: all symbols have local scope in the DSO */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + int mpd_switch_to_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status); int mpd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status); int mpd_realloc_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status); +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #endif diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c index 05f7628..6633fb6 100644 --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -107,7 +107,7 @@ static inline void _mpd_qpow_uint(mpd_t *result, const mpd_t *base, mpd_uint_t exp, uint8_t resultsign, const mpd_context_t *ctx, uint32_t *status); -mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n); +static mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n); /******************************************************************************/ @@ -2301,7 +2301,7 @@ _mpd_get_rnd(const mpd_uint_t *data, mpd_ssize_t len, int use_msd) * It is the caller's responsibility to ensure that the coefficient is big * enough. The function cannot fail. */ -mpd_uint_t +static mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n) { mpd_uint_t rnd; @@ -5123,7 +5123,7 @@ _karatsuba_rec(mpd_uint_t *c, const mpd_uint_t *a, const mpd_uint_t *b, * to the result or NULL in case of failure (malloc error). * Conditions: ulen >= vlen, ulen >= 4 */ -mpd_uint_t * +static mpd_uint_t * _mpd_kmul(const mpd_uint_t *u, const mpd_uint_t *v, mpd_size_t ulen, mpd_size_t vlen, mpd_size_t *rsize) @@ -5208,7 +5208,7 @@ _mpd_set_control87(unsigned short cw) } #endif -unsigned int +static unsigned int mpd_set_fenv(void) { unsigned int cw; @@ -5228,7 +5228,7 @@ mpd_set_fenv(void) return cw; } -void +static void mpd_restore_fenv(unsigned int cw) { #ifdef _MSC_VER @@ -5246,7 +5246,7 @@ mpd_restore_fenv(unsigned int cw) * Multiply u and v, using the fast number theoretic transform. Returns * a pointer to the result or NULL in case of failure (malloc error). */ -mpd_uint_t * +static mpd_uint_t * _mpd_fntmul(const mpd_uint_t *u, const mpd_uint_t *v, mpd_size_t ulen, mpd_size_t vlen, mpd_size_t *rsize) @@ -5432,7 +5432,7 @@ _karatsuba_rec_fnt(mpd_uint_t *c, const mpd_uint_t *a, const mpd_uint_t *b, * base case. Returns a pointer to the result or NULL in case of failure * (malloc error). Conditions: ulen >= vlen, ulen >= 4. */ -mpd_uint_t * +static mpd_uint_t * _mpd_kmul_fnt(const mpd_uint_t *u, const mpd_uint_t *v, mpd_size_t ulen, mpd_size_t vlen, mpd_size_t *rsize) diff --git a/Modules/_decimal/libmpdec/mpdecimal.h b/Modules/_decimal/libmpdec/mpdecimal.h index d131c71..b7d4ff7 100644 --- a/Modules/_decimal/libmpdec/mpdecimal.h +++ b/Modules/_decimal/libmpdec/mpdecimal.h @@ -51,6 +51,9 @@ extern "C" { #ifndef UNUSED #define UNUSED #endif + #define MPD_PRAGMA(x) + #define MPD_HIDE_SYMBOLS_START + #define MPD_HIDE_SYMBOLS_END #define EXTINLINE extern inline #else #ifdef HAVE_STDINT_H @@ -67,10 +70,25 @@ extern "C" { #else #define UNUSED #endif + #if (defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) && \ + defined(__GNUC__) && __GNUC__ >= 4 && !defined(__INTEL_COMPILER) + #define MPD_PRAGMA(x) _Pragma(x) + #define MPD_HIDE_SYMBOLS_START "GCC visibility push(hidden)" + #define MPD_HIDE_SYMBOLS_END "GCC visibility pop" + #else + #define MPD_PRAGMA(x) + #define MPD_HIDE_SYMBOLS_START + #define MPD_HIDE_SYMBOLS_END + #endif #define EXTINLINE #endif +/* This header file is internal for the purpose of building _decimal.so. + * All symbols should have local scope in the DSO. */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + #if !defined(LEGACY_COMPILER) #if !defined(UINT64_MAX) /* The following #error is just a warning. If the compiler indeed does @@ -789,6 +807,9 @@ int mpd_resize(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx); int mpd_resize_zero(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx); +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #ifdef __cplusplus } /* END extern "C" */ #endif diff --git a/Modules/_decimal/libmpdec/numbertheory.h b/Modules/_decimal/libmpdec/numbertheory.h index f54d11d..1092254 100644 --- a/Modules/_decimal/libmpdec/numbertheory.h +++ b/Modules/_decimal/libmpdec/numbertheory.h @@ -34,6 +34,10 @@ #include "mpdecimal.h" +/* Internal header file: all symbols have local scope in the DSO */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + /* transform parameters */ struct fnt_params { int modnum; @@ -66,6 +70,9 @@ std_setmodulus(int modnum, mpd_uint_t *umod) #endif +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #endif diff --git a/Modules/_decimal/libmpdec/sixstep.h b/Modules/_decimal/libmpdec/sixstep.h index 4d251df..0467007 100644 --- a/Modules/_decimal/libmpdec/sixstep.h +++ b/Modules/_decimal/libmpdec/sixstep.h @@ -34,8 +34,15 @@ #include <stdio.h> +/* Internal header file: all symbols have local scope in the DSO */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + int six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum); int inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum); +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #endif diff --git a/Modules/_decimal/libmpdec/transpose.h b/Modules/_decimal/libmpdec/transpose.h index dd0aec6..7e349ee 100644 --- a/Modules/_decimal/libmpdec/transpose.h +++ b/Modules/_decimal/libmpdec/transpose.h @@ -34,6 +34,10 @@ #include <stdio.h> +/* Internal header file: all symbols have local scope in the DSO */ +MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) + + enum {FORWARD_CYCLE, BACKWARD_CYCLE}; @@ -52,4 +56,7 @@ static inline void pointerswap(mpd_uint_t **a, mpd_uint_t **b) } +MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ + + #endif diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 334734b..b077f34 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -484,7 +484,7 @@ buffered_closed_get(buffered *self, void *context) static PyObject * buffered_close(buffered *self, PyObject *args) { - PyObject *res = NULL; + PyObject *res = NULL, *exc = NULL, *val, *tb; int r; CHECK_INITIALIZED(self) @@ -512,13 +512,29 @@ buffered_close(buffered *self, PyObject *args) res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); if (!ENTER_BUFFERED(self)) return NULL; - if (res == NULL) { - goto end; - } - Py_XDECREF(res); + if (res == NULL) + PyErr_Fetch(&exc, &val, &tb); + else + Py_DECREF(res); res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL); + if (exc != NULL) { + if (res != NULL) { + Py_CLEAR(res); + PyErr_Restore(exc, val, tb); + } + else { + PyObject *val2; + Py_DECREF(exc); + Py_XDECREF(tb); + PyErr_Fetch(&exc, &val2, &tb); + PyErr_NormalizeException(&exc, &val2, &tb); + PyException_SetContext(val2, val); + PyErr_Restore(exc, val2, tb); + } + } + end: LEAVE_BUFFERED(self) return res; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 96434a8..83437d6 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -2554,6 +2554,7 @@ textiowrapper_close(textio *self, PyObject *args) Py_RETURN_NONE; /* stream already closed */ } else { + PyObject *exc = NULL, *val, *tb; if (self->deallocating) { res = _PyObject_CallMethodId(self->buffer, &PyId__dealloc_warn, "O", self); if (res) @@ -2562,13 +2563,28 @@ textiowrapper_close(textio *self, PyObject *args) PyErr_Clear(); } res = _PyObject_CallMethodId((PyObject *)self, &PyId_flush, NULL); - if (res == NULL) { - return NULL; - } + if (res == NULL) + PyErr_Fetch(&exc, &val, &tb); else Py_DECREF(res); - return _PyObject_CallMethodId(self->buffer, &PyId_close, NULL); + res = _PyObject_CallMethodId(self->buffer, &PyId_close, NULL); + if (exc != NULL) { + if (res != NULL) { + Py_CLEAR(res); + PyErr_Restore(exc, val, tb); + } + else { + PyObject *val2; + Py_DECREF(exc); + Py_XDECREF(tb); + PyErr_Fetch(&exc, &val2, &tb); + PyErr_NormalizeException(&exc, &val2, &tb); + PyException_SetContext(val2, val); + PyErr_Restore(exc, val2, tb); + } + } + return res; } } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index bf9259f..52db15d 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2505,8 +2505,10 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds) const char *encoding = NULL; const char *errors = NULL; PyObject *new = NULL; + PyObject *func; Py_ssize_t size; static char *kwlist[] = {"source", "encoding", "errors", 0}; + _Py_IDENTIFIER(__bytes__); if (type != &PyBytes_Type) return str_subtype_new(type, args, kwds); @@ -2536,6 +2538,28 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds) assert(PyBytes_Check(new)); return new; } + + /* We'd like to call PyObject_Bytes here, but we need to check for an + integer argument before deferring to PyBytes_FromObject, something + PyObject_Bytes doesn't do. */ + func = _PyObject_LookupSpecial(x, &PyId___bytes__); + if (func != NULL) { + new = PyObject_CallFunctionObjArgs(func, NULL); + Py_DECREF(func); + if (new == NULL) + return NULL; + if (!PyBytes_Check(new)) { + PyErr_Format(PyExc_TypeError, + "__bytes__ returned non-bytes (type %.200s)", + Py_TYPE(new)->tp_name); + Py_DECREF(new); + return NULL; + } + return new; + } + else if (PyErr_Occurred()) + return NULL; + /* Is it an integer? */ size = PyNumber_AsSsize_t(x, PyExc_OverflowError); if (size == -1 && PyErr_Occurred()) { @@ -2549,12 +2573,10 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } else { new = PyBytes_FromStringAndSize(NULL, size); - if (new == NULL) { + if (new == NULL) return NULL; - } - if (size > 0) { + if (size > 0) memset(((PyBytesObject*)new)->ob_sval, 0, size); - } return new; } @@ -2564,7 +2586,8 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds) "encoding or errors without a string argument"); return NULL; } - return PyObject_Bytes(x); + + return PyBytes_FromObject(x); } PyObject * |