summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_decimal/_decimal.c8
-rw-r--r--Modules/_decimal/libmpdec/mpdecimal.c260
-rw-r--r--Modules/_decimal/libmpdec/mpdecimal.h94
-rw-r--r--Modules/_elementtree.c21
-rw-r--r--Modules/_pickle.c929
-rw-r--r--Modules/posixmodule.c47
6 files changed, 1034 insertions, 325 deletions
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) {