Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(908)

Side by Side Diff: Modules/itertoolsmodule.c

Issue 30346: Odd behavior when unpacking `itertools.groupby`
Patch Set: Created 2 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 #define PY_SSIZE_T_CLEAN 2 #define PY_SSIZE_T_CLEAN
3 #include "Python.h" 3 #include "Python.h"
4 #include "structmember.h" 4 #include "structmember.h"
5 5
6 /* Itertools module written and maintained 6 /* Itertools module written and maintained
7 by Raymond D. Hettinger <python@rcn.com> 7 by Raymond D. Hettinger <python@rcn.com>
8 */ 8 */
9 9
10 10
11 /* groupby object ************************************************************/ 11 /* groupby object ************************************************************/
12 12
13 typedef struct { 13 typedef struct {
14 PyObject_HEAD 14 PyObject_HEAD
15 PyObject *it; 15 PyObject *it;
16 PyObject *keyfunc; 16 PyObject *keyfunc;
17 PyObject *tgtkey; 17 PyObject *tgtkey;
18 PyObject *currkey; 18 PyObject *currkey;
19 PyObject *currvalue; 19 PyObject *currvalue;
20 int groupnum;
20 } groupbyobject; 21 } groupbyobject;
21 22
22 static PyTypeObject groupby_type; 23 static PyTypeObject groupby_type;
23 static PyObject *_grouper_create(groupbyobject *, PyObject *); 24 static PyObject *_grouper_create(groupbyobject *, PyObject *);
24 25
25 static PyObject * 26 static PyObject *
26 groupby_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 27 groupby_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
27 { 28 {
28 static char *kwargs[] = {"iterable", "key", NULL}; 29 static char *kwargs[] = {"iterable", "key", NULL};
29 groupbyobject *gbo; 30 groupbyobject *gbo;
30 PyObject *it, *keyfunc = Py_None; 31 PyObject *it, *keyfunc = Py_None;
31 32
32 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:groupby", kwargs, 33 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:groupby", kwargs,
33 &it, &keyfunc)) 34 &it, &keyfunc))
34 return NULL; 35 return NULL;
35 36
36 gbo = (groupbyobject *)type->tp_alloc(type, 0); 37 gbo = (groupbyobject *)type->tp_alloc(type, 0);
37 if (gbo == NULL) 38 if (gbo == NULL)
38 return NULL; 39 return NULL;
39 gbo->tgtkey = NULL; 40 gbo->tgtkey = NULL;
40 gbo->currkey = NULL; 41 gbo->currkey = NULL;
41 gbo->currvalue = NULL; 42 gbo->currvalue = NULL;
42 gbo->keyfunc = keyfunc; 43 gbo->keyfunc = keyfunc;
44 gbo->groupnum = 0;
43 Py_INCREF(keyfunc); 45 Py_INCREF(keyfunc);
44 gbo->it = PyObject_GetIter(it); 46 gbo->it = PyObject_GetIter(it);
45 if (gbo->it == NULL) { 47 if (gbo->it == NULL) {
46 Py_DECREF(gbo); 48 Py_DECREF(gbo);
47 return NULL; 49 return NULL;
48 } 50 }
49 return (PyObject *)gbo; 51 return (PyObject *)gbo;
50 } 52 }
51 53
52 static void 54 static void
(...skipping 27 matching lines...) Expand all
80 /* skip to next iteration group */ 82 /* skip to next iteration group */
81 for (;;) { 83 for (;;) {
82 if (gbo->currkey == NULL) 84 if (gbo->currkey == NULL)
83 /* pass */; 85 /* pass */;
84 else if (gbo->tgtkey == NULL) 86 else if (gbo->tgtkey == NULL)
85 break; 87 break;
86 else { 88 else {
87 int rcmp; 89 int rcmp;
88 90
89 rcmp = PyObject_RichCompareBool(gbo->tgtkey, gbo->currkey, Py_EQ); 91 rcmp = PyObject_RichCompareBool(gbo->tgtkey, gbo->currkey, Py_EQ);
90 if (rcmp == -1) 92 if (rcmp == -1) {
93 gbo->groupnum += 1;
91 return NULL; 94 return NULL;
92 else if (rcmp == 0) 95 } else if (rcmp == 0) {
93 break; 96 break;
97 }
94 } 98 }
95 99
96 newvalue = PyIter_Next(gbo->it); 100 newvalue = PyIter_Next(gbo->it);
97 if (newvalue == NULL) 101 if (newvalue == NULL) {
102 // gbo->currkey = NULL;
103 gbo->groupnum += 1;
98 return NULL; 104 return NULL;
105 }
99 106
100 if (gbo->keyfunc == Py_None) { 107 if (gbo->keyfunc == Py_None) {
101 newkey = newvalue; 108 newkey = newvalue;
102 Py_INCREF(newvalue); 109 Py_INCREF(newvalue);
103 } else { 110 } else {
104 newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, newvalue, NULL); 111 newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, newvalue, NULL);
105 if (newkey == NULL) { 112 if (newkey == NULL) {
106 Py_DECREF(newvalue); 113 Py_DECREF(newvalue);
107 return NULL; 114 return NULL;
108 } 115 }
109 } 116 }
110 117
111 Py_XSETREF(gbo->currkey, newkey); 118 Py_XSETREF(gbo->currkey, newkey);
112 Py_XSETREF(gbo->currvalue, newvalue); 119 Py_XSETREF(gbo->currvalue, newvalue);
113 } 120 }
114 121
115 Py_INCREF(gbo->currkey); 122 Py_INCREF(gbo->currkey);
116 Py_XSETREF(gbo->tgtkey, gbo->currkey); 123 Py_XSETREF(gbo->tgtkey, gbo->currkey);
117 124
125 gbo->groupnum += 1;
118 grouper = _grouper_create(gbo, gbo->tgtkey); 126 grouper = _grouper_create(gbo, gbo->tgtkey);
119 if (grouper == NULL) 127 if (grouper == NULL)
120 return NULL; 128 return NULL;
121 129
122 r = PyTuple_Pack(2, gbo->currkey, grouper); 130 r = PyTuple_Pack(2, gbo->currkey, grouper);
123 Py_DECREF(grouper); 131 Py_DECREF(grouper);
124 return r; 132 return r;
125 } 133 }
126 134
127 static PyObject * 135 static PyObject *
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 PyObject_GC_Del, /* tp_free */ 229 PyObject_GC_Del, /* tp_free */
222 }; 230 };
223 231
224 232
225 /* _grouper object (internal) ************************************************/ 233 /* _grouper object (internal) ************************************************/
226 234
227 typedef struct { 235 typedef struct {
228 PyObject_HEAD 236 PyObject_HEAD
229 PyObject *parent; 237 PyObject *parent;
230 PyObject *tgtkey; 238 PyObject *tgtkey;
239 int groupnum;
231 } _grouperobject; 240 } _grouperobject;
232 241
233 static PyTypeObject _grouper_type; 242 static PyTypeObject _grouper_type;
234 243
235 static PyObject * 244 static PyObject *
236 _grouper_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 245 _grouper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
237 { 246 {
238 PyObject *parent, *tgtkey; 247 PyObject *parent, *tgtkey;
239 248
240 if (!PyArg_ParseTuple(args, "O!O", &groupby_type, &parent, &tgtkey)) 249 if (!PyArg_ParseTuple(args, "O!O", &groupby_type, &parent, &tgtkey))
241 return NULL; 250 return NULL;
242 251
243 return _grouper_create((groupbyobject*) parent, tgtkey); 252 return _grouper_create((groupbyobject*) parent, tgtkey);
244 } 253 }
245 254
246 static PyObject * 255 static PyObject *
247 _grouper_create(groupbyobject *parent, PyObject *tgtkey) 256 _grouper_create(groupbyobject *parent, PyObject *tgtkey)
248 { 257 {
249 _grouperobject *igo; 258 _grouperobject *igo;
250 259
251 igo = PyObject_GC_New(_grouperobject, &_grouper_type); 260 igo = PyObject_GC_New(_grouperobject, &_grouper_type);
252 if (igo == NULL) 261 if (igo == NULL)
253 return NULL; 262 return NULL;
254 igo->parent = (PyObject *)parent; 263 igo->parent = (PyObject *)parent;
264 igo->groupnum = parent->groupnum;
255 Py_INCREF(parent); 265 Py_INCREF(parent);
256 igo->tgtkey = tgtkey; 266 igo->tgtkey = tgtkey;
257 Py_INCREF(tgtkey); 267 Py_INCREF(tgtkey);
258 268
259 PyObject_GC_Track(igo); 269 PyObject_GC_Track(igo);
260 return (PyObject *)igo; 270 return (PyObject *)igo;
261 } 271 }
262 272
263 static void 273 static void
264 _grouper_dealloc(_grouperobject *igo) 274 _grouper_dealloc(_grouperobject *igo)
(...skipping 11 matching lines...) Expand all
276 Py_VISIT(igo->tgtkey); 286 Py_VISIT(igo->tgtkey);
277 return 0; 287 return 0;
278 } 288 }
279 289
280 static PyObject * 290 static PyObject *
281 _grouper_next(_grouperobject *igo) 291 _grouper_next(_grouperobject *igo)
282 { 292 {
283 groupbyobject *gbo = (groupbyobject *)igo->parent; 293 groupbyobject *gbo = (groupbyobject *)igo->parent;
284 PyObject *newvalue, *newkey, *r; 294 PyObject *newvalue, *newkey, *r;
285 int rcmp; 295 int rcmp;
296
297 if (igo->groupnum != gbo->groupnum) {
298 return NULL;
299 }
286 300
287 if (gbo->currvalue == NULL) { 301 if (gbo->currvalue == NULL) {
288 newvalue = PyIter_Next(gbo->it); 302 newvalue = PyIter_Next(gbo->it);
289 if (newvalue == NULL) 303 if (newvalue == NULL)
290 return NULL; 304 return NULL;
291 305
292 if (gbo->keyfunc == Py_None) { 306 if (gbo->keyfunc == Py_None) {
293 newkey = newvalue; 307 newkey = newvalue;
294 Py_INCREF(newvalue); 308 Py_INCREF(newvalue);
295 } else { 309 } else {
(...skipping 4371 matching lines...) Expand 10 before | Expand all | Expand 10 after
4667 if (PyType_Ready(typelist[i]) < 0) 4681 if (PyType_Ready(typelist[i]) < 0)
4668 return NULL; 4682 return NULL;
4669 name = strchr(typelist[i]->tp_name, '.'); 4683 name = strchr(typelist[i]->tp_name, '.');
4670 assert (name != NULL); 4684 assert (name != NULL);
4671 Py_INCREF(typelist[i]); 4685 Py_INCREF(typelist[i]);
4672 PyModule_AddObject(m, name+1, (PyObject *)typelist[i]); 4686 PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);
4673 } 4687 }
4674 4688
4675 return m; 4689 return m;
4676 } 4690 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+