diff options
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/_ctypes.c | 4 | ||||
-rw-r--r-- | Modules/_ctypes/_ctypes_test.c | 9 | ||||
-rw-r--r-- | Modules/_ctypes/cfield.c | 14 | ||||
-rw-r--r-- | Modules/_heapqmodule.c | 44 | ||||
-rw-r--r-- | Modules/_struct.c | 6 | ||||
-rw-r--r-- | Modules/datetimemodule.c | 101 | ||||
-rw-r--r-- | Modules/gdbmmodule.c | 8 | ||||
-rw-r--r-- | Modules/itertoolsmodule.c | 296 | ||||
-rw-r--r-- | Modules/timemodule.c | 2 |
9 files changed, 441 insertions, 43 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index e4fa612..d39cf4b 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -203,7 +203,7 @@ static PyTypeObject DictRemover_Type = { 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ + 0, /* tp_new */ 0, /* tp_free */ }; @@ -1242,7 +1242,7 @@ _type_ attribute. */ -static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvtg"; +static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv?g"; static PyObject * c_wchar_p_from_param(PyObject *type, PyObject *value) diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c index 63fb580..ce83df7 100644 --- a/Modules/_ctypes/_ctypes_test.c +++ b/Modules/_ctypes/_ctypes_test.c @@ -12,6 +12,15 @@ /* some functions handy for testing */ +EXPORT(void)testfunc_array(int values[4]) +{ + printf("testfunc_array %d %d %d %d\n", + values[0], + values[1], + values[2], + values[3]); +} + EXPORT(long double)testfunc_Ddd(double a, double b) { long double result = (long double)(a * b); diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index f7c78f3..4e02563 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -716,7 +716,7 @@ vBOOL_get(void *ptr, Py_ssize_t size) #endif static PyObject * -t_set(void *ptr, PyObject *value, Py_ssize_t size) +bool_set(void *ptr, PyObject *value, Py_ssize_t size) { switch (PyObject_IsTrue(value)) { case -1: @@ -731,7 +731,7 @@ t_set(void *ptr, PyObject *value, Py_ssize_t size) } static PyObject * -t_get(void *ptr, Py_ssize_t size) +bool_get(void *ptr, Py_ssize_t size) { return PyBool_FromLong((long)*(BOOL_TYPE *)ptr); } @@ -1665,15 +1665,15 @@ static struct fielddesc formattable[] = { { 'v', vBOOL_set, vBOOL_get, &ffi_type_sshort}, #endif #if SIZEOF__BOOL == 1 - { 't', t_set, t_get, &ffi_type_uchar}, /* Also fallback for no native _Bool support */ + { '?', bool_set, bool_get, &ffi_type_uchar}, /* Also fallback for no native _Bool support */ #elif SIZEOF__BOOL == SIZEOF_SHORT - { 't', t_set, t_get, &ffi_type_ushort}, + { '?', bool_set, bool_get, &ffi_type_ushort}, #elif SIZEOF__BOOL == SIZEOF_INT - { 't', t_set, t_get, &ffi_type_uint, I_set_sw, I_get_sw}, + { '?', bool_set, bool_get, &ffi_type_uint, I_set_sw, I_get_sw}, #elif SIZEOF__BOOL == SIZEOF_LONG - { 't', t_set, t_get, &ffi_type_ulong, L_set_sw, L_get_sw}, + { '?', bool_set, bool_get, &ffi_type_ulong, L_set_sw, L_get_sw}, #elif SIZEOF__BOOL == SIZEOF_LONG_LONG - { 't', t_set, t_get, &ffi_type_ulong, Q_set_sw, Q_get_sw}, + { '?', bool_set, bool_get, &ffi_type_ulong, Q_set_sw, Q_get_sw}, #endif /* SIZEOF__BOOL */ { 'O', O_set, O_get, &ffi_type_pointer}, { 0, NULL, NULL, NULL}, diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c index 2ae1f03..97ccd86 100644 --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -196,6 +196,48 @@ this routine unless written as part of a conditional replacement:\n\n\ item = heapreplace(heap, item)\n"); static PyObject * +heappushpop(PyObject *self, PyObject *args) +{ + PyObject *heap, *item, *returnitem; + int cmp; + + if (!PyArg_UnpackTuple(args, "heappushpop", 2, 2, &heap, &item)) + return NULL; + + if (!PyList_Check(heap)) { + PyErr_SetString(PyExc_TypeError, "heap argument must be a list"); + return NULL; + } + + if (PyList_GET_SIZE(heap) < 1) { + Py_INCREF(item); + return item; + } + + cmp = PyObject_RichCompareBool(item, PyList_GET_ITEM(heap, 0), Py_LE); + if (cmp == -1) + return NULL; + if (cmp == 1) { + Py_INCREF(item); + return item; + } + + returnitem = PyList_GET_ITEM(heap, 0); + Py_INCREF(item); + PyList_SET_ITEM(heap, 0, item); + if (_siftup((PyListObject *)heap, 0) == -1) { + Py_DECREF(returnitem); + return NULL; + } + return returnitem; +} + +PyDoc_STRVAR(heappushpop_doc, +"Push item on the heap, then pop and return the smallest item\n\ +from the heap. The combined action runs more efficiently than\n\ +heappush() followed by a separate call to heappop()."); + +static PyObject * heapify(PyObject *self, PyObject *heap) { Py_ssize_t i, n; @@ -468,6 +510,8 @@ Equivalent to: sorted(iterable)[:n]\n"); static PyMethodDef heapq_methods[] = { {"heappush", (PyCFunction)heappush, METH_VARARGS, heappush_doc}, + {"heappushpop", (PyCFunction)heappushpop, + METH_VARARGS, heappushpop_doc}, {"heappop", (PyCFunction)heappop, METH_O, heappop_doc}, {"heapreplace", (PyCFunction)heapreplace, diff --git a/Modules/_struct.c b/Modules/_struct.c index 28f67e9..13ffee7 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -797,7 +797,7 @@ static formatdef native_table[] = { {'q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong}, {'Q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong}, #endif - {'t', sizeof(BOOL_TYPE), BOOL_ALIGN, nu_bool, np_bool}, + {'?', sizeof(BOOL_TYPE), BOOL_ALIGN, nu_bool, np_bool}, {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float}, {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double}, {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p}, @@ -1034,7 +1034,7 @@ static formatdef bigendian_table[] = { {'L', 4, 0, bu_uint, bp_uint}, {'q', 8, 0, bu_longlong, bp_longlong}, {'Q', 8, 0, bu_ulonglong, bp_ulonglong}, - {'t', 1, 0, bu_bool, bp_bool}, + {'?', 1, 0, bu_bool, bp_bool}, {'f', 4, 0, bu_float, bp_float}, {'d', 8, 0, bu_double, bp_double}, {0} @@ -1253,7 +1253,7 @@ static formatdef lilendian_table[] = { {'L', 4, 0, lu_uint, lp_uint}, {'q', 8, 0, lu_longlong, lp_longlong}, {'Q', 8, 0, lu_ulonglong, lp_ulonglong}, - {'t', 1, 0, bu_bool, bp_bool}, /* Std rep not endian dep, + {'?', 1, 0, bu_bool, bp_bool}, /* Std rep not endian dep, but potentially different from native rep -- reuse bx_bool funcs. */ {'f', 4, 0, lu_float, lp_float}, {'d', 8, 0, lu_double, lp_double}, diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c index 27c404f..798865d 100644 --- a/Modules/datetimemodule.c +++ b/Modules/datetimemodule.c @@ -1170,10 +1170,24 @@ make_Zreplacement(PyObject *object, PyObject *tzinfoarg) return NULL; } +static PyObject * +make_freplacement(PyObject *object) +{ + char freplacement[7]; + if (PyTime_Check(object)) + sprintf(freplacement, "%06d", TIME_GET_MICROSECOND(object)); + else if (PyDateTime_Check(object)) + sprintf(freplacement, "%06d", DATE_GET_MICROSECOND(object)); + else + sprintf(freplacement, "%06d", 0); + + return PyString_FromStringAndSize(freplacement, strlen(freplacement)); +} + /* I sure don't want to reproduce the strftime code from the time module, * so this imports the module and calls it. All the hair is due to - * giving special meanings to the %z and %Z format codes via a preprocessing - * step on the format string. + * giving special meanings to the %z, %Z and %f format codes via a + * preprocessing step on the format string. * tzinfoarg is the argument to pass to the object's tzinfo method, if * needed. */ @@ -1185,6 +1199,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, PyObject *zreplacement = NULL; /* py string, replacement for %z */ PyObject *Zreplacement = NULL; /* py string, replacement for %Z */ + PyObject *freplacement = NULL; /* py string, replacement for %f */ const char *pin;/* pointer to next char in input format */ Py_ssize_t flen;/* length of input format */ @@ -1232,7 +1247,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, } } - /* Scan the input format, looking for %z and %Z escapes, building + /* Scan the input format, looking for %z/%Z/%f escapes, building * a new format. Since computing the replacements for those codes * is expensive, don't unless they're actually used. */ @@ -1295,6 +1310,18 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, &ntoappend); ntoappend = Py_SIZE(Zreplacement); } + else if (ch == 'f') { + /* format microseconds */ + if (freplacement == NULL) { + freplacement = make_freplacement(object); + if (freplacement == NULL) + goto Done; + } + assert(freplacement != NULL); + assert(PyString_Check(freplacement)); + ptoappend = PyString_AS_STRING(freplacement); + ntoappend = PyString_GET_SIZE(freplacement); + } else { /* percent followed by neither z nor Z */ ptoappend = pin - 2; @@ -1341,6 +1368,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, Py_DECREF(time); } Done: + Py_XDECREF(freplacement); Py_XDECREF(zreplacement); Py_XDECREF(Zreplacement); Py_XDECREF(newfmt); @@ -3800,28 +3828,47 @@ datetime_utcfromtimestamp(PyObject *cls, PyObject *args) static PyObject * datetime_strptime(PyObject *cls, PyObject *args) { - PyObject *result = NULL, *obj, *module; + static PyObject *module = NULL; + PyObject *result = NULL, *obj, *st = NULL, *frac = NULL; const Py_UNICODE *string, *format; if (!PyArg_ParseTuple(args, "uu:strptime", &string, &format)) return NULL; - if ((module = PyImport_ImportModuleNoBlock("time")) == NULL) + if (module == NULL && + (module = PyImport_ImportModuleNoBlock("_strptime")) == NULL) return NULL; - obj = PyObject_CallMethod(module, "strptime", "uu", string, format); - Py_DECREF(module); + /* _strptime._strptime returns a two-element tuple. The first + element is a time.struct_time object. The second is the + microseconds (which are not defined for time.struct_time). */ + obj = PyObject_CallMethod(module, "_strptime", "ss", string, format); if (obj != NULL) { - int i, good_timetuple = 1, overflow; - long int ia[6]; - if (PySequence_Check(obj) && PySequence_Size(obj) >= 6) - for (i=0; i < 6; i++) { - PyObject *p = PySequence_GetItem(obj, i); - if (p == NULL) { - Py_DECREF(obj); - return NULL; + int i, good_timetuple = 1; + long int ia[7]; + if (PySequence_Check(obj) && PySequence_Size(obj) == 2) { + st = PySequence_GetItem(obj, 0); + frac = PySequence_GetItem(obj, 1); + if (st == NULL || frac == NULL) + good_timetuple = 0; + /* copy y/m/d/h/m/s values out of the + time.struct_time */ + if (good_timetuple && + PySequence_Check(st) && + PySequence_Size(st) >= 6) { + for (i=0; i < 6; i++) { + PyObject *p = PySequence_GetItem(st, i); + if (p == NULL) { + good_timetuple = 0; + break; + } + if (PyLong_Check(p)) + ia[i] = PyLong_AsLong(p); + else + good_timetuple = 0; + Py_DECREF(p); } - if (PyLong_CheckExact(p)) { +/* if (PyLong_CheckExact(p)) { ia[i] = PyLong_AsLongAndOverflow(p, &overflow); if (overflow) good_timetuple = 0; @@ -3829,17 +3876,29 @@ datetime_strptime(PyObject *cls, PyObject *args) else good_timetuple = 0; Py_DECREF(p); - } +*/ } + else + good_timetuple = 0; + /* follow that up with a little dose of microseconds */ + if (PyLong_Check(frac)) + ia[6] = PyLong_AsLong(frac); + else + good_timetuple = 0; + } else good_timetuple = 0; if (good_timetuple) - result = PyObject_CallFunction(cls, "iiiiii", - ia[0], ia[1], ia[2], ia[3], ia[4], ia[5]); + result = PyObject_CallFunction(cls, "iiiiiii", + ia[0], ia[1], ia[2], + ia[3], ia[4], ia[5], + ia[6]); else PyErr_SetString(PyExc_ValueError, - "unexpected value from time.strptime"); - Py_DECREF(obj); + "unexpected value from _strptime._strptime"); } + Py_XDECREF(obj); + Py_XDECREF(st); + Py_XDECREF(frac); return result; } diff --git a/Modules/gdbmmodule.c b/Modules/gdbmmodule.c index cf197f5..a8abbd3 100644 --- a/Modules/gdbmmodule.c +++ b/Modules/gdbmmodule.c @@ -130,7 +130,7 @@ dbm_subscript(dbmobject *dp, register PyObject *key) PyErr_SetObject(PyExc_KeyError, key); return NULL; } - v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize); + v = PyString_FromStringAndSize(drec.dptr, drec.dsize); free(drec.dptr); return v; } @@ -220,7 +220,7 @@ dbm_keys(register dbmobject *dp, PyObject *unused) key = gdbm_firstkey(dp->di_dbm); while (key.dptr) { - item = PyBytes_FromStringAndSize(key.dptr, key.dsize); + item = PyString_FromStringAndSize(key.dptr, key.dsize); if (item == NULL) { free(key.dptr); Py_DECREF(v); @@ -291,7 +291,7 @@ dbm_firstkey(register dbmobject *dp, PyObject *unused) check_dbmobject_open(dp); key = gdbm_firstkey(dp->di_dbm); if (key.dptr) { - v = PyBytes_FromStringAndSize(key.dptr, key.dsize); + v = PyString_FromStringAndSize(key.dptr, key.dsize); free(key.dptr); return v; } @@ -323,7 +323,7 @@ dbm_nextkey(register dbmobject *dp, PyObject *args) check_dbmobject_open(dp); nextkey = gdbm_nextkey(dp->di_dbm, key); if (nextkey.dptr) { - v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize); + v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize); free(nextkey.dptr); return v; } diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index b52bea8..61128d2 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -198,7 +198,7 @@ _grouper_create(groupbyobject *parent, PyObject *tgtkey) { _grouperobject *igo; - igo = PyObject_New(_grouperobject, &_grouper_type); + igo = PyObject_GC_New(_grouperobject, &_grouper_type); if (igo == NULL) return NULL; igo->parent = (PyObject *)parent; @@ -206,15 +206,25 @@ _grouper_create(groupbyobject *parent, PyObject *tgtkey) igo->tgtkey = tgtkey; Py_INCREF(tgtkey); + PyObject_GC_Track(igo); return (PyObject *)igo; } static void _grouper_dealloc(_grouperobject *igo) { + PyObject_GC_UnTrack(igo); Py_DECREF(igo->parent); Py_DECREF(igo->tgtkey); - PyObject_Del(igo); + PyObject_GC_Del(igo); +} + +static int +_grouper_traverse(_grouperobject *igo, visitproc visit, void *arg) +{ + Py_VISIT(igo->parent); + Py_VISIT(igo->tgtkey); + return 0; } static PyObject * @@ -280,9 +290,9 @@ static PyTypeObject _grouper_type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + (traverseproc)_grouper_traverse,/* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -299,7 +309,7 @@ static PyTypeObject _grouper_type = { 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ - PyObject_Del, /* tp_free */ + PyObject_GC_Del, /* tp_free */ }; @@ -2059,6 +2069,281 @@ static PyTypeObject combinations_type = { }; +/* permutations object ************************************************************ + +def permutations(iterable, r=None): + 'permutations(range(3), 2) --> (0,1) (0,2) (1,0) (1,2) (2,0) (2,1)' + pool = tuple(iterable) + n = len(pool) + r = n if r is None else r + indices = range(n) + cycles = range(n-r+1, n+1)[::-1] + yield tuple(pool[i] for i in indices[:r]) + while n: + for i in reversed(range(r)): + cycles[i] -= 1 + if cycles[i] == 0: + indices[i:] = indices[i+1:] + indices[i:i+1] + cycles[i] = n - i + else: + j = cycles[i] + indices[i], indices[-j] = indices[-j], indices[i] + yield tuple(pool[i] for i in indices[:r]) + break + else: + return +*/ + +typedef struct { + PyObject_HEAD + PyObject *pool; /* input converted to a tuple */ + Py_ssize_t *indices; /* one index per element in the pool */ + Py_ssize_t *cycles; /* one rollover counter per element in the result */ + PyObject *result; /* most recently returned result tuple */ + Py_ssize_t r; /* size of result tuple */ + int stopped; /* set to 1 when the permutations iterator is exhausted */ +} permutationsobject; + +static PyTypeObject permutations_type; + +static PyObject * +permutations_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + permutationsobject *po; + Py_ssize_t n; + Py_ssize_t r; + PyObject *robj = Py_None; + PyObject *pool = NULL; + PyObject *iterable = NULL; + Py_ssize_t *indices = NULL; + Py_ssize_t *cycles = NULL; + Py_ssize_t i; + static char *kwargs[] = {"iterable", "r", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:permutations", kwargs, + &iterable, &robj)) + return NULL; + + pool = PySequence_Tuple(iterable); + if (pool == NULL) + goto error; + n = PyTuple_GET_SIZE(pool); + + r = n; + if (robj != Py_None) { + if (!PyLong_Check(robj)) { + PyErr_SetString(PyExc_TypeError, "Expected int as r"); + return NULL; + } + r = PyLong_AsSsize_t(robj); + if (r == -1 && PyErr_Occurred()) + goto error; + } + if (r < 0) { + PyErr_SetString(PyExc_ValueError, "r must be non-negative"); + goto error; + } + if (r > n) { + PyErr_SetString(PyExc_ValueError, "r cannot be bigger than the iterable"); + goto error; + } + + indices = PyMem_Malloc(n * sizeof(Py_ssize_t)); + cycles = PyMem_Malloc(r * sizeof(Py_ssize_t)); + if (indices == NULL || cycles == NULL) { + PyErr_NoMemory(); + goto error; + } + + for (i=0 ; i<n ; i++) + indices[i] = i; + for (i=0 ; i<r ; i++) + cycles[i] = n - i; + + /* create permutationsobject structure */ + po = (permutationsobject *)type->tp_alloc(type, 0); + if (po == NULL) + goto error; + + po->pool = pool; + po->indices = indices; + po->cycles = cycles; + po->result = NULL; + po->r = r; + po->stopped = 0; + + return (PyObject *)po; + +error: + if (indices != NULL) + PyMem_Free(indices); + if (cycles != NULL) + PyMem_Free(cycles); + Py_XDECREF(pool); + return NULL; +} + +static void +permutations_dealloc(permutationsobject *po) +{ + PyObject_GC_UnTrack(po); + Py_XDECREF(po->pool); + Py_XDECREF(po->result); + PyMem_Free(po->indices); + PyMem_Free(po->cycles); + Py_TYPE(po)->tp_free(po); +} + +static int +permutations_traverse(permutationsobject *po, visitproc visit, void *arg) +{ + Py_VISIT(po->pool); + Py_VISIT(po->result); + return 0; +} + +static PyObject * +permutations_next(permutationsobject *po) +{ + PyObject *elem; + PyObject *oldelem; + PyObject *pool = po->pool; + Py_ssize_t *indices = po->indices; + Py_ssize_t *cycles = po->cycles; + PyObject *result = po->result; + Py_ssize_t n = PyTuple_GET_SIZE(pool); + Py_ssize_t r = po->r; + Py_ssize_t i, j, k, index; + + if (po->stopped) + return NULL; + + if (result == NULL) { + /* On the first pass, initialize result tuple using the indices */ + result = PyTuple_New(r); + if (result == NULL) + goto empty; + po->result = result; + for (i=0; i<r ; i++) { + index = indices[i]; + elem = PyTuple_GET_ITEM(pool, index); + Py_INCREF(elem); + PyTuple_SET_ITEM(result, i, elem); + } + } else { + if (n == 0) + goto empty; + + /* Copy the previous result tuple or re-use it if available */ + if (Py_REFCNT(result) > 1) { + PyObject *old_result = result; + result = PyTuple_New(r); + if (result == NULL) + goto empty; + po->result = result; + for (i=0; i<r ; i++) { + elem = PyTuple_GET_ITEM(old_result, i); + Py_INCREF(elem); + PyTuple_SET_ITEM(result, i, elem); + } + Py_DECREF(old_result); + } + /* Now, we've got the only copy so we can update it in-place */ + assert(r == 0 || Py_REFCNT(result) == 1); + + /* Decrement rightmost cycle, moving leftward upon zero rollover */ + for (i=r-1 ; i>=0 ; i--) { + cycles[i] -= 1; + if (cycles[i] == 0) { + /* rotatation: indices[i:] = indices[i+1:] + indices[i:i+1] */ + index = indices[i]; + for (j=i ; j<n-1 ; j++) + indices[j] = indices[j+1]; + indices[n-1] = index; + cycles[i] = n - i; + } else { + j = cycles[i]; + index = indices[i]; + indices[i] = indices[n-j]; + indices[n-j] = index; + + for (k=i; k<r ; k++) { + /* start with i, the leftmost element that changed */ + /* yield tuple(pool[k] for k in indices[:r]) */ + index = indices[k]; + elem = PyTuple_GET_ITEM(pool, index); + Py_INCREF(elem); + oldelem = PyTuple_GET_ITEM(result, k); + PyTuple_SET_ITEM(result, k, elem); + Py_DECREF(oldelem); + } + break; + } + } + /* If i is negative, then the cycles have all + rolled-over and we're done. */ + if (i < 0) + goto empty; + } + Py_INCREF(result); + return result; + +empty: + po->stopped = 1; + return NULL; +} + +PyDoc_STRVAR(permutations_doc, +"permutations(iterables[, r]) --> permutations object\n\ +\n\ +Return successive r-length permutations of elements in the iterable.\n\n\ +permutations(range(4), 3) --> (0,1,2), (0,1,3), (0,2,3), (1,2,3)"); + +static PyTypeObject permutations_type = { + PyVarObject_HEAD_INIT(NULL, 0) + "itertools.permutations", /* tp_name */ + sizeof(permutationsobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)permutations_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + permutations_doc, /* tp_doc */ + (traverseproc)permutations_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)permutations_next, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + permutations_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + + /* filterfalse object ************************************************************/ typedef struct { @@ -2762,6 +3047,7 @@ inititertools(void) &filterfalse_type, &count_type, &ziplongest_type, + &permutations_type, &product_type, &repeat_type, &groupby_type, diff --git a/Modules/timemodule.c b/Modules/timemodule.c index de8c99c..bd0d063 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -561,7 +561,7 @@ time_strptime(PyObject *self, PyObject *args) if (!strptime_module) return NULL; - strptime_result = PyObject_CallMethod(strptime_module, "strptime", "O", args); + strptime_result = PyObject_CallMethod(strptime_module, "_strptime_time", "O", args); Py_DECREF(strptime_module); return strptime_result; } |