|
7 | 7 | #include <sys/types.h> /* For size_t */
|
8 | 8 | #endif
|
9 | 9 |
|
| 10 | +/*[clinic input] |
| 11 | +class _tuplegetter "_tuplegetterobject *" "&tuplegetter_type" |
| 12 | +[clinic start generated code]*/ |
| 13 | +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ee5ed5baabe35068]*/ |
| 14 | + |
| 15 | +static PyTypeObject tuplegetter_type; |
| 16 | +#include "clinic/_collectionsmodule.c.h" |
| 17 | + |
10 | 18 | /* collections module implementation of a deque() datatype
|
11 | 19 | Written and maintained by Raymond D. Hettinger <python@rcn.com>
|
12 | 20 | */
|
@@ -2328,6 +2336,156 @@ _count_elements(PyObject *self, PyObject *args)
|
2328 | 2336 | Py_RETURN_NONE;
|
2329 | 2337 | }
|
2330 | 2338 |
|
| 2339 | +/* Helper functions for namedtuples */ |
| 2340 | + |
| 2341 | +typedef struct { |
| 2342 | + PyObject_HEAD |
| 2343 | + Py_ssize_t index; |
| 2344 | + PyObject* doc; |
| 2345 | +} _tuplegetterobject; |
| 2346 | + |
| 2347 | +/*[clinic input] |
| 2348 | +@classmethod |
| 2349 | +_tuplegetter.__new__ as tuplegetter_new |
| 2350 | +
|
| 2351 | + index: Py_ssize_t |
| 2352 | + doc: object |
| 2353 | + / |
| 2354 | +[clinic start generated code]*/ |
| 2355 | + |
| 2356 | +static PyObject * |
| 2357 | +tuplegetter_new_impl(PyTypeObject *type, Py_ssize_t index, PyObject *doc) |
| 2358 | +/*[clinic end generated code: output=014be444ad80263f input=87c576a5bdbc0bbb]*/ |
| 2359 | +{ |
| 2360 | + _tuplegetterobject* self; |
| 2361 | + self = (_tuplegetterobject *)type->tp_alloc(type, 0); |
| 2362 | + if (self == NULL) { |
| 2363 | + return NULL; |
| 2364 | + } |
| 2365 | + self->index = index; |
| 2366 | + Py_INCREF(doc); |
| 2367 | + self->doc = doc; |
| 2368 | + return (PyObject *)self; |
| 2369 | +} |
| 2370 | + |
| 2371 | +static PyObject * |
| 2372 | +tuplegetterdescr_get(PyObject *self, PyObject *obj, PyObject *type) |
| 2373 | +{ |
| 2374 | + PyObject *result; |
| 2375 | + if (obj == NULL) { |
| 2376 | + Py_INCREF(self); |
| 2377 | + return self; |
| 2378 | + } |
| 2379 | + if (!PyTuple_Check(obj)) { |
| 2380 | + if (obj == Py_None) { |
| 2381 | + Py_INCREF(self); |
| 2382 | + return self; |
| 2383 | + } |
| 2384 | + PyErr_Format(PyExc_TypeError, |
| 2385 | + "descriptor for index '%d' for tuple subclasses " |
| 2386 | + "doesn't apply to '%s' object", |
| 2387 | + ((_tuplegetterobject*)self)->index, |
| 2388 | + obj->ob_type->tp_name); |
| 2389 | + return NULL; |
| 2390 | + } |
| 2391 | + |
| 2392 | + Py_ssize_t index = ((_tuplegetterobject*)self)->index; |
| 2393 | + |
| 2394 | + if (!valid_index(index, PyTuple_GET_SIZE(obj))) { |
| 2395 | + PyErr_SetString(PyExc_IndexError, "tuple index out of range"); |
| 2396 | + return NULL; |
| 2397 | + } |
| 2398 | + |
| 2399 | + result = PyTuple_GET_ITEM(obj, index); |
| 2400 | + Py_INCREF(result); |
| 2401 | + return result; |
| 2402 | +} |
| 2403 | + |
| 2404 | +static int |
| 2405 | +tuplegetter_set(PyObject *self, PyObject *obj, PyObject *value) |
| 2406 | +{ |
| 2407 | + if (value == NULL) { |
| 2408 | + PyErr_SetString(PyExc_AttributeError, "can't delete attribute"); |
| 2409 | + } else { |
| 2410 | + PyErr_SetString(PyExc_AttributeError, "can't set attribute"); |
| 2411 | + } |
| 2412 | + return -1; |
| 2413 | +} |
| 2414 | + |
| 2415 | +static int |
| 2416 | +tuplegetter_traverse(PyObject *self, visitproc visit, void *arg) |
| 2417 | +{ |
| 2418 | + _tuplegetterobject *tuplegetter = (_tuplegetterobject *)self; |
| 2419 | + Py_VISIT(tuplegetter->doc); |
| 2420 | + return 0; |
| 2421 | +} |
| 2422 | + |
| 2423 | +static int |
| 2424 | +tuplegetter_clear(PyObject *self) |
| 2425 | +{ |
| 2426 | + _tuplegetterobject *tuplegetter = (_tuplegetterobject *)self; |
| 2427 | + Py_CLEAR(tuplegetter->doc); |
| 2428 | + return 0; |
| 2429 | +} |
| 2430 | + |
| 2431 | +static void |
| 2432 | +tuplegetter_dealloc(_tuplegetterobject *self) |
| 2433 | +{ |
| 2434 | + PyObject_GC_UnTrack(self); |
| 2435 | + tuplegetter_clear((PyObject*)self); |
| 2436 | + Py_TYPE(self)->tp_free((PyObject*)self); |
| 2437 | +} |
| 2438 | + |
| 2439 | + |
| 2440 | +static PyMemberDef tuplegetter_members[] = { |
| 2441 | + {"__doc__", T_OBJECT, offsetof(_tuplegetterobject, doc), 0}, |
| 2442 | + {0} |
| 2443 | +}; |
| 2444 | + |
| 2445 | +static PyTypeObject tuplegetter_type = { |
| 2446 | + PyVarObject_HEAD_INIT(NULL, 0) |
| 2447 | + "_collections._tuplegetter", /* tp_name */ |
| 2448 | + sizeof(_tuplegetterobject), /* tp_basicsize */ |
| 2449 | + 0, /* tp_itemsize */ |
| 2450 | + /* methods */ |
| 2451 | + (destructor)tuplegetter_dealloc, /* tp_dealloc */ |
| 2452 | + 0, /* tp_print */ |
| 2453 | + 0, /* tp_getattr */ |
| 2454 | + 0, /* tp_setattr */ |
| 2455 | + 0, /* tp_reserved */ |
| 2456 | + 0, /* tp_repr */ |
| 2457 | + 0, /* tp_as_number */ |
| 2458 | + 0, /* tp_as_sequence */ |
| 2459 | + 0, /* tp_as_mapping */ |
| 2460 | + 0, /* tp_hash */ |
| 2461 | + 0, /* tp_call */ |
| 2462 | + 0, /* tp_str */ |
| 2463 | + 0, /* tp_getattro */ |
| 2464 | + 0, /* tp_setattro */ |
| 2465 | + 0, /* tp_as_buffer */ |
| 2466 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ |
| 2467 | + 0, /* tp_doc */ |
| 2468 | + (traverseproc)tuplegetter_traverse, /* tp_traverse */ |
| 2469 | + (inquiry)tuplegetter_clear, /* tp_clear */ |
| 2470 | + 0, /* tp_richcompare */ |
| 2471 | + 0, /* tp_weaklistoffset */ |
| 2472 | + 0, /* tp_iter */ |
| 2473 | + 0, /* tp_iternext */ |
| 2474 | + 0, /* tp_methods */ |
| 2475 | + tuplegetter_members, /* tp_members */ |
| 2476 | + 0, /* tp_getset */ |
| 2477 | + 0, /* tp_base */ |
| 2478 | + 0, /* tp_dict */ |
| 2479 | + tuplegetterdescr_get, /* tp_descr_get */ |
| 2480 | + tuplegetter_set, /* tp_descr_set */ |
| 2481 | + 0, /* tp_dictoffset */ |
| 2482 | + 0, /* tp_init */ |
| 2483 | + 0, /* tp_alloc */ |
| 2484 | + tuplegetter_new, /* tp_new */ |
| 2485 | + 0, |
| 2486 | +}; |
| 2487 | + |
| 2488 | + |
2331 | 2489 | /* module level code ********************************************************/
|
2332 | 2490 |
|
2333 | 2491 | PyDoc_STRVAR(module_doc,
|
@@ -2386,5 +2544,10 @@ PyInit__collections(void)
|
2386 | 2544 | Py_INCREF(&dequereviter_type);
|
2387 | 2545 | PyModule_AddObject(m, "_deque_reverse_iterator", (PyObject *)&dequereviter_type);
|
2388 | 2546 |
|
| 2547 | + if (PyType_Ready(&tuplegetter_type) < 0) |
| 2548 | + return NULL; |
| 2549 | + Py_INCREF(&tuplegetter_type); |
| 2550 | + PyModule_AddObject(m, "_tuplegetter", (PyObject *)&tuplegetter_type); |
| 2551 | + |
2389 | 2552 | return m;
|
2390 | 2553 | }
|
0 commit comments