Mercurial > vim
comparison src/if_py_both.h @ 5608:ec02e1474bc2 v7.4.151
updated for version 7.4.151
Problem: Python: slices with steps are not supported.
Solution: Support slices in Python vim.List. (ZyX)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Tue, 14 Jan 2014 16:36:51 +0100 |
parents | 2ca470c6096e |
children | 2ace11abcfb5 |
comparison
equal
deleted
inserted
replaced
5607:98a642716acc | 5608:ec02e1474bc2 |
---|---|
34 static const char *vim_special_path = "_vim_path_"; | 34 static const char *vim_special_path = "_vim_path_"; |
35 | 35 |
36 #define PyErr_SET_STRING(exc, str) PyErr_SetString(exc, _(str)) | 36 #define PyErr_SET_STRING(exc, str) PyErr_SetString(exc, _(str)) |
37 #define PyErr_SetVim(str) PyErr_SetString(VimError, str) | 37 #define PyErr_SetVim(str) PyErr_SetString(VimError, str) |
38 #define PyErr_SET_VIM(str) PyErr_SET_STRING(VimError, str) | 38 #define PyErr_SET_VIM(str) PyErr_SET_STRING(VimError, str) |
39 #define PyErr_FORMAT(exc, str, tail) PyErr_Format(exc, _(str), tail) | 39 #define PyErr_FORMAT(exc, str, arg) PyErr_Format(exc, _(str), arg) |
40 #define PyErr_VIM_FORMAT(str, tail) PyErr_FORMAT(VimError, str, tail) | 40 #define PyErr_FORMAT2(exc, str, arg1, arg2) PyErr_Format(exc, _(str), arg1,arg2) |
41 #define PyErr_VIM_FORMAT(str, arg) PyErr_FORMAT(VimError, str, arg) | |
41 | 42 |
42 #define Py_TYPE_NAME(obj) (obj->ob_type->tp_name == NULL \ | 43 #define Py_TYPE_NAME(obj) (obj->ob_type->tp_name == NULL \ |
43 ? "(NULL)" \ | 44 ? "(NULL)" \ |
44 : obj->ob_type->tp_name) | 45 : obj->ob_type->tp_name) |
45 | 46 |
2106 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""}, | 2107 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""}, |
2107 { NULL, NULL, 0, NULL} | 2108 { NULL, NULL, 0, NULL} |
2108 }; | 2109 }; |
2109 | 2110 |
2110 static PyTypeObject ListType; | 2111 static PyTypeObject ListType; |
2111 static PySequenceMethods ListAsSeq; | |
2112 static PyMappingMethods ListAsMapping; | |
2113 | 2112 |
2114 typedef struct | 2113 typedef struct |
2115 { | 2114 { |
2116 PyObject_HEAD | 2115 PyObject_HEAD |
2117 list_T *list; | 2116 list_T *list; |
2251 { | 2250 { |
2252 return ((PyInt) (self->list->lv_len)); | 2251 return ((PyInt) (self->list->lv_len)); |
2253 } | 2252 } |
2254 | 2253 |
2255 static PyObject * | 2254 static PyObject * |
2256 ListItem(ListObject *self, Py_ssize_t index) | 2255 ListIndex(ListObject *self, Py_ssize_t index) |
2257 { | 2256 { |
2258 listitem_T *li; | 2257 listitem_T *li; |
2259 | 2258 |
2260 if (index >= ListLength(self)) | 2259 if (index >= ListLength(self)) |
2261 { | 2260 { |
2271 return NULL; | 2270 return NULL; |
2272 } | 2271 } |
2273 return ConvertToPyObject(&li->li_tv); | 2272 return ConvertToPyObject(&li->li_tv); |
2274 } | 2273 } |
2275 | 2274 |
2276 #define PROC_RANGE \ | 2275 static PyObject * |
2277 if (last < 0) {\ | 2276 ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t step, |
2278 if (last < -size) \ | 2277 Py_ssize_t slicelen) |
2279 last = 0; \ | |
2280 else \ | |
2281 last += size; \ | |
2282 } \ | |
2283 if (first < 0) \ | |
2284 first = 0; \ | |
2285 if (first > size) \ | |
2286 first = size; \ | |
2287 if (last > size) \ | |
2288 last = size; | |
2289 | |
2290 static PyObject * | |
2291 ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last) | |
2292 { | 2278 { |
2293 PyInt i; | 2279 PyInt i; |
2294 PyInt size = ListLength(self); | |
2295 PyInt n; | |
2296 PyObject *list; | 2280 PyObject *list; |
2297 int reversed = 0; | 2281 |
2298 | 2282 if (step == 0) |
2299 PROC_RANGE | 2283 { |
2300 if (first >= last) | 2284 PyErr_SET_STRING(PyExc_ValueError, N_("slice step cannot be zero")); |
2301 first = last; | 2285 return NULL; |
2302 | 2286 } |
2303 n = last-first; | 2287 |
2304 list = PyList_New(n); | 2288 list = PyList_New(slicelen); |
2305 if (list == NULL) | 2289 if (list == NULL) |
2306 return NULL; | 2290 return NULL; |
2307 | 2291 |
2308 for (i = 0; i < n; ++i) | 2292 for (i = 0; i < slicelen; ++i) |
2309 { | 2293 { |
2310 PyObject *item = ListItem(self, first + i); | 2294 PyObject *item; |
2295 | |
2296 item = ListIndex(self, first + i*step); | |
2311 if (item == NULL) | 2297 if (item == NULL) |
2312 { | 2298 { |
2313 Py_DECREF(list); | 2299 Py_DECREF(list); |
2314 return NULL; | 2300 return NULL; |
2315 } | 2301 } |
2316 | 2302 |
2317 PyList_SET_ITEM(list, ((reversed)?(n-i-1):(i)), item); | 2303 PyList_SET_ITEM(list, i, item); |
2318 } | 2304 } |
2319 | 2305 |
2320 return list; | 2306 return list; |
2321 } | 2307 } |
2322 | 2308 |
2323 typedef struct | 2309 static PyObject * |
2324 { | 2310 ListItem(ListObject *self, PyObject* idx) |
2325 listwatch_T lw; | 2311 { |
2326 list_T *list; | 2312 #if PY_MAJOR_VERSION < 3 |
2327 } listiterinfo_T; | 2313 if (PyInt_Check(idx)) |
2314 { | |
2315 long _idx = PyInt_AsLong(idx); | |
2316 return ListIndex(self, _idx); | |
2317 } | |
2318 else | |
2319 #endif | |
2320 if (PyLong_Check(idx)) | |
2321 { | |
2322 long _idx = PyLong_AsLong(idx); | |
2323 return ListIndex(self, _idx); | |
2324 } | |
2325 else if (PySlice_Check(idx)) | |
2326 { | |
2327 Py_ssize_t start, stop, step, slicelen; | |
2328 | |
2329 if (PySlice_GetIndicesEx(idx, ListLength(self), | |
2330 &start, &stop, &step, &slicelen) < 0) | |
2331 return NULL; | |
2332 return ListSlice(self, start, step, slicelen); | |
2333 } | |
2334 else | |
2335 { | |
2336 RAISE_INVALID_INDEX_TYPE(idx); | |
2337 return NULL; | |
2338 } | |
2339 } | |
2328 | 2340 |
2329 static void | 2341 static void |
2330 ListIterDestruct(listiterinfo_T *lii) | 2342 list_restore(Py_ssize_t numadded, Py_ssize_t numreplaced, Py_ssize_t slicelen, |
2331 { | 2343 list_T *l, listitem_T **lis, listitem_T *lastaddedli) |
2332 list_rem_watch(lii->list, &lii->lw); | 2344 { |
2333 PyMem_Free(lii); | 2345 while (numreplaced--) |
2334 } | 2346 { |
2335 | 2347 list_insert(l, lis[numreplaced], lis[slicelen + numreplaced]); |
2336 static PyObject * | 2348 listitem_remove(l, lis[slicelen + numreplaced]); |
2337 ListIterNext(listiterinfo_T **lii) | 2349 } |
2338 { | 2350 while (numadded--) |
2339 PyObject *ret; | 2351 { |
2340 | 2352 listitem_T *next; |
2341 if (!((*lii)->lw.lw_item)) | 2353 |
2342 return NULL; | 2354 next = lastaddedli->li_prev; |
2343 | 2355 listitem_remove(l, lastaddedli); |
2344 if (!(ret = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv)))) | 2356 lastaddedli = next; |
2345 return NULL; | 2357 } |
2346 | 2358 } |
2347 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next; | 2359 |
2348 | 2360 static int |
2349 return ret; | 2361 ListAssSlice(ListObject *self, Py_ssize_t first, |
2350 } | 2362 Py_ssize_t step, Py_ssize_t slicelen, PyObject *obj) |
2351 | 2363 { |
2352 static PyObject * | 2364 PyObject *iterator; |
2353 ListIter(ListObject *self) | 2365 PyObject *item; |
2354 { | 2366 listitem_T *li; |
2355 listiterinfo_T *lii; | 2367 listitem_T *lastaddedli = NULL; |
2368 listitem_T *next; | |
2369 typval_T v; | |
2356 list_T *l = self->list; | 2370 list_T *l = self->list; |
2357 | 2371 PyInt i; |
2358 if (!(lii = PyMem_New(listiterinfo_T, 1))) | 2372 PyInt j; |
2359 { | 2373 PyInt numreplaced = 0; |
2360 PyErr_NoMemory(); | 2374 PyInt numadded = 0; |
2361 return NULL; | 2375 PyInt size; |
2362 } | 2376 listitem_T **lis; |
2363 | 2377 |
2364 list_add_watch(l, &lii->lw); | 2378 size = ListLength(self); |
2365 lii->lw.lw_item = l->lv_first; | 2379 |
2366 lii->list = l; | 2380 if (l->lv_lock) |
2367 | 2381 { |
2368 return IterNew(lii, | 2382 RAISE_LOCKED_LIST; |
2369 (destructorfun) ListIterDestruct, (nextfun) ListIterNext, | 2383 return -1; |
2370 NULL, NULL); | 2384 } |
2385 | |
2386 if (step == 0) | |
2387 { | |
2388 PyErr_SET_STRING(PyExc_ValueError, N_("slice step cannot be zero")); | |
2389 return -1; | |
2390 } | |
2391 | |
2392 if (step != 1 && slicelen == 0) | |
2393 { | |
2394 /* Nothing to do. Only error out if obj has some items. */ | |
2395 int ret = 0; | |
2396 | |
2397 if (obj == NULL) | |
2398 return 0; | |
2399 | |
2400 if (!(iterator = PyObject_GetIter(obj))) | |
2401 return -1; | |
2402 | |
2403 if ((item = PyIter_Next(iterator))) | |
2404 { | |
2405 PyErr_FORMAT(PyExc_ValueError, | |
2406 N_("attempt to assign sequence of size greater then %d " | |
2407 "to extended slice"), 0); | |
2408 Py_DECREF(item); | |
2409 ret = -1; | |
2410 } | |
2411 Py_DECREF(iterator); | |
2412 return ret; | |
2413 } | |
2414 | |
2415 if (obj != NULL) | |
2416 /* XXX May allocate zero bytes. */ | |
2417 if (!(lis = PyMem_New(listitem_T *, slicelen * 2))) | |
2418 { | |
2419 PyErr_NoMemory(); | |
2420 return -1; | |
2421 } | |
2422 | |
2423 if (first == size) | |
2424 li = NULL; | |
2425 else | |
2426 { | |
2427 li = list_find(l, (long) first); | |
2428 if (li == NULL) | |
2429 { | |
2430 PyErr_VIM_FORMAT(N_("internal error: no vim list item %d"), | |
2431 (int)first); | |
2432 if (obj != NULL) | |
2433 PyMem_Free(lis); | |
2434 return -1; | |
2435 } | |
2436 i = slicelen; | |
2437 while (i-- && li != NULL) | |
2438 { | |
2439 j = step; | |
2440 next = li; | |
2441 if (step > 0) | |
2442 while (next != NULL && ((next = next->li_next) != NULL) && --j); | |
2443 else | |
2444 while (next != NULL && ((next = next->li_prev) != NULL) && ++j); | |
2445 | |
2446 if (obj == NULL) | |
2447 listitem_remove(l, li); | |
2448 else | |
2449 lis[slicelen - i - 1] = li; | |
2450 | |
2451 li = next; | |
2452 } | |
2453 if (li == NULL && i != -1) | |
2454 { | |
2455 PyErr_SET_VIM(N_("internal error: not enough list items")); | |
2456 if (obj != NULL) | |
2457 PyMem_Free(lis); | |
2458 return -1; | |
2459 } | |
2460 } | |
2461 | |
2462 if (obj == NULL) | |
2463 return 0; | |
2464 | |
2465 if (!(iterator = PyObject_GetIter(obj))) | |
2466 { | |
2467 PyMem_Free(lis); | |
2468 return -1; | |
2469 } | |
2470 | |
2471 i = 0; | |
2472 while ((item = PyIter_Next(iterator))) | |
2473 { | |
2474 if (ConvertFromPyObject(item, &v) == -1) | |
2475 { | |
2476 Py_DECREF(iterator); | |
2477 Py_DECREF(item); | |
2478 PyMem_Free(lis); | |
2479 return -1; | |
2480 } | |
2481 Py_DECREF(item); | |
2482 if (list_insert_tv(l, &v, numreplaced < slicelen | |
2483 ? lis[numreplaced] | |
2484 : li) == FAIL) | |
2485 { | |
2486 clear_tv(&v); | |
2487 PyErr_SET_VIM(N_("internal error: failed to add item to list")); | |
2488 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli); | |
2489 PyMem_Free(lis); | |
2490 return -1; | |
2491 } | |
2492 if (numreplaced < slicelen) | |
2493 { | |
2494 lis[slicelen + numreplaced] = lis[numreplaced]->li_prev; | |
2495 list_remove(l, lis[numreplaced], lis[numreplaced]); | |
2496 numreplaced++; | |
2497 } | |
2498 else | |
2499 { | |
2500 if (li) | |
2501 lastaddedli = li->li_prev; | |
2502 else | |
2503 lastaddedli = l->lv_last; | |
2504 numadded++; | |
2505 } | |
2506 clear_tv(&v); | |
2507 if (step != 1 && i >= slicelen) | |
2508 { | |
2509 Py_DECREF(iterator); | |
2510 PyErr_FORMAT(PyExc_ValueError, | |
2511 N_("attempt to assign sequence of size greater then %d " | |
2512 "to extended slice"), slicelen); | |
2513 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli); | |
2514 PyMem_Free(lis); | |
2515 return -1; | |
2516 } | |
2517 ++i; | |
2518 } | |
2519 Py_DECREF(iterator); | |
2520 | |
2521 if (step != 1 && i != slicelen) | |
2522 { | |
2523 PyErr_FORMAT2(PyExc_ValueError, | |
2524 N_("attempt to assign sequence of size %d to extended slice " | |
2525 "of size %d"), i, slicelen); | |
2526 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli); | |
2527 PyMem_Free(lis); | |
2528 return -1; | |
2529 } | |
2530 | |
2531 if (PyErr_Occurred()) | |
2532 { | |
2533 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli); | |
2534 PyMem_Free(lis); | |
2535 return -1; | |
2536 } | |
2537 | |
2538 for (i = 0; i < numreplaced; i++) | |
2539 listitem_free(lis[i]); | |
2540 if (step == 1) | |
2541 for (i = numreplaced; i < slicelen; i++) | |
2542 listitem_remove(l, lis[i]); | |
2543 | |
2544 PyMem_Free(lis); | |
2545 | |
2546 return 0; | |
2371 } | 2547 } |
2372 | 2548 |
2373 static int | 2549 static int |
2374 ListAssItem(ListObject *self, Py_ssize_t index, PyObject *obj) | 2550 ListAssIndex(ListObject *self, Py_ssize_t index, PyObject *obj) |
2375 { | 2551 { |
2376 typval_T tv; | 2552 typval_T tv; |
2377 list_T *l = self->list; | 2553 list_T *l = self->list; |
2378 listitem_T *li; | 2554 listitem_T *li; |
2379 Py_ssize_t length = ListLength(self); | 2555 Py_ssize_t length = ListLength(self); |
2418 clear_tv(&tv); | 2594 clear_tv(&tv); |
2419 } | 2595 } |
2420 return 0; | 2596 return 0; |
2421 } | 2597 } |
2422 | 2598 |
2423 static int | 2599 static Py_ssize_t |
2424 ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj) | 2600 ListAssItem(ListObject *self, PyObject *idx, PyObject *obj) |
2425 { | 2601 { |
2426 PyInt size = ListLength(self); | 2602 #if PY_MAJOR_VERSION < 3 |
2427 PyObject *iterator; | 2603 if (PyInt_Check(idx)) |
2428 PyObject *item; | 2604 { |
2429 listitem_T *li; | 2605 long _idx = PyInt_AsLong(idx); |
2430 listitem_T *next; | 2606 return ListAssIndex(self, _idx, obj); |
2431 typval_T v; | 2607 } |
2432 list_T *l = self->list; | |
2433 PyInt i; | |
2434 | |
2435 if (l->lv_lock) | |
2436 { | |
2437 RAISE_LOCKED_LIST; | |
2438 return -1; | |
2439 } | |
2440 | |
2441 PROC_RANGE | |
2442 | |
2443 if (first == size) | |
2444 li = NULL; | |
2445 else | 2608 else |
2446 { | 2609 #endif |
2447 li = list_find(l, (long) first); | 2610 if (PyLong_Check(idx)) |
2448 if (li == NULL) | 2611 { |
2449 { | 2612 long _idx = PyLong_AsLong(idx); |
2450 PyErr_VIM_FORMAT(N_("internal error: no vim list item %d"), | 2613 return ListAssIndex(self, _idx, obj); |
2451 (int)first); | 2614 } |
2452 return -1; | 2615 else if (PySlice_Check(idx)) |
2453 } | 2616 { |
2454 if (last > first) | 2617 Py_ssize_t start, stop, step, slicelen; |
2455 { | 2618 |
2456 i = last - first; | 2619 if (PySlice_GetIndicesEx(idx, ListLength(self), |
2457 while (i-- && li != NULL) | 2620 &start, &stop, &step, &slicelen) < 0) |
2458 { | 2621 return -1; |
2459 next = li->li_next; | 2622 return ListAssSlice(self, start, step, slicelen, |
2460 listitem_remove(l, li); | 2623 obj); |
2461 li = next; | 2624 } |
2462 } | 2625 else |
2463 } | 2626 { |
2464 } | 2627 RAISE_INVALID_INDEX_TYPE(idx); |
2465 | 2628 return -1; |
2466 if (obj == NULL) | 2629 } |
2467 return 0; | |
2468 | |
2469 if (!(iterator = PyObject_GetIter(obj))) | |
2470 return -1; | |
2471 | |
2472 while ((item = PyIter_Next(iterator))) | |
2473 { | |
2474 if (ConvertFromPyObject(item, &v) == -1) | |
2475 { | |
2476 Py_DECREF(iterator); | |
2477 Py_DECREF(item); | |
2478 return -1; | |
2479 } | |
2480 Py_DECREF(item); | |
2481 if (list_insert_tv(l, &v, li) == FAIL) | |
2482 { | |
2483 clear_tv(&v); | |
2484 PyErr_SET_VIM(N_("internal error: failed to add item to list")); | |
2485 return -1; | |
2486 } | |
2487 clear_tv(&v); | |
2488 } | |
2489 Py_DECREF(iterator); | |
2490 | |
2491 if (PyErr_Occurred()) | |
2492 return -1; | |
2493 | |
2494 return 0; | |
2495 } | 2630 } |
2496 | 2631 |
2497 static PyObject * | 2632 static PyObject * |
2498 ListConcatInPlace(ListObject *self, PyObject *obj) | 2633 ListConcatInPlace(ListObject *self, PyObject *obj) |
2499 { | 2634 { |
2516 } | 2651 } |
2517 Py_DECREF(lookup_dict); | 2652 Py_DECREF(lookup_dict); |
2518 | 2653 |
2519 Py_INCREF(self); | 2654 Py_INCREF(self); |
2520 return (PyObject *)(self); | 2655 return (PyObject *)(self); |
2656 } | |
2657 | |
2658 typedef struct | |
2659 { | |
2660 listwatch_T lw; | |
2661 list_T *list; | |
2662 } listiterinfo_T; | |
2663 | |
2664 static void | |
2665 ListIterDestruct(listiterinfo_T *lii) | |
2666 { | |
2667 list_rem_watch(lii->list, &lii->lw); | |
2668 PyMem_Free(lii); | |
2669 } | |
2670 | |
2671 static PyObject * | |
2672 ListIterNext(listiterinfo_T **lii) | |
2673 { | |
2674 PyObject *ret; | |
2675 | |
2676 if (!((*lii)->lw.lw_item)) | |
2677 return NULL; | |
2678 | |
2679 if (!(ret = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv)))) | |
2680 return NULL; | |
2681 | |
2682 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next; | |
2683 | |
2684 return ret; | |
2685 } | |
2686 | |
2687 static PyObject * | |
2688 ListIter(ListObject *self) | |
2689 { | |
2690 listiterinfo_T *lii; | |
2691 list_T *l = self->list; | |
2692 | |
2693 if (!(lii = PyMem_New(listiterinfo_T, 1))) | |
2694 { | |
2695 PyErr_NoMemory(); | |
2696 return NULL; | |
2697 } | |
2698 | |
2699 list_add_watch(l, &lii->lw); | |
2700 lii->lw.lw_item = l->lv_first; | |
2701 lii->list = l; | |
2702 | |
2703 return IterNew(lii, | |
2704 (destructorfun) ListIterDestruct, (nextfun) ListIterNext, | |
2705 NULL, NULL); | |
2521 } | 2706 } |
2522 | 2707 |
2523 static char *ListAttrs[] = { | 2708 static char *ListAttrs[] = { |
2524 "locked", | 2709 "locked", |
2525 NULL | 2710 NULL |
2564 { | 2749 { |
2565 PyErr_FORMAT(PyExc_AttributeError, N_("cannot set attribute %s"), name); | 2750 PyErr_FORMAT(PyExc_AttributeError, N_("cannot set attribute %s"), name); |
2566 return -1; | 2751 return -1; |
2567 } | 2752 } |
2568 } | 2753 } |
2754 | |
2755 static PySequenceMethods ListAsSeq = { | |
2756 (lenfunc) ListLength, /* sq_length, len(x) */ | |
2757 (binaryfunc) 0, /* RangeConcat, sq_concat, x+y */ | |
2758 0, /* RangeRepeat, sq_repeat, x*n */ | |
2759 (PyIntArgFunc) ListIndex, /* sq_item, x[i] */ | |
2760 0, /* was_sq_slice, x[i:j] */ | |
2761 (PyIntObjArgProc) ListAssIndex, /* sq_as_item, x[i]=v */ | |
2762 0, /* was_sq_ass_slice, x[i:j]=v */ | |
2763 0, /* sq_contains */ | |
2764 (binaryfunc) ListConcatInPlace,/* sq_inplace_concat */ | |
2765 0, /* sq_inplace_repeat */ | |
2766 }; | |
2767 | |
2768 static PyMappingMethods ListAsMapping = { | |
2769 /* mp_length */ (lenfunc) ListLength, | |
2770 /* mp_subscript */ (binaryfunc) ListItem, | |
2771 /* mp_ass_subscript */ (objobjargproc) ListAssItem, | |
2772 }; | |
2569 | 2773 |
2570 static struct PyMethodDef ListMethods[] = { | 2774 static struct PyMethodDef ListMethods[] = { |
2571 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""}, | 2775 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""}, |
2572 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""}, | 2776 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""}, |
2573 { NULL, NULL, 0, NULL} | 2777 { NULL, NULL, 0, NULL} |