mirror of
https://github.com/python/cpython.git
synced 2024-11-28 12:31:14 +08:00
73e5a5b65d
Merged revisions 46490-46494,46496,46498,46500,46506,46521,46538,46558,46563-46567,46570-46571,46583,46593,46595-46598,46604,46606,46609-46753 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r46610 | martin.v.loewis | 2006-06-03 09:42:26 +0200 (Sat, 03 Jun 2006) | 2 lines Updated version (win32-icons2.zip) from #1490384. ........ r46612 | andrew.kuchling | 2006-06-03 20:09:41 +0200 (Sat, 03 Jun 2006) | 1 line [Bug #1472084] Fix description of do_tag ........ r46614 | andrew.kuchling | 2006-06-03 20:33:35 +0200 (Sat, 03 Jun 2006) | 1 line [Bug #1475554] Strengthen text to say 'must' instead of 'should' ........ r46616 | andrew.kuchling | 2006-06-03 20:41:28 +0200 (Sat, 03 Jun 2006) | 1 line [Bug #1441864] Clarify description of 'data' argument ........ r46617 | andrew.kuchling | 2006-06-03 20:43:24 +0200 (Sat, 03 Jun 2006) | 1 line Minor rewording ........ r46619 | andrew.kuchling | 2006-06-03 21:02:35 +0200 (Sat, 03 Jun 2006) | 9 lines [Bug #1497414] _self is a reserved word in the WATCOM 10.6 C compiler. Fix by renaming the variable. In a different module, Neal fixed it by renaming _self to self. There's already a variable named 'self' here, so I used selfptr. (I'm committing this on a Mac without Tk, but it's a simple search-and-replace. <crosses fingers>, so I'll watch the buildbots and see what happens.) ........ r46621 | fredrik.lundh | 2006-06-03 23:56:05 +0200 (Sat, 03 Jun 2006) | 5 lines "_self" is a said to be a reserved word in Watcom C 10.6. I'm not sure that's really standard compliant behaviour, but I guess we have to fix that anyway... ........ r46622 | andrew.kuchling | 2006-06-04 00:44:42 +0200 (Sun, 04 Jun 2006) | 1 line Update readme ........ r46623 | andrew.kuchling | 2006-06-04 00:59:23 +0200 (Sun, 04 Jun 2006) | 1 line Drop 0 parameter ........ r46624 | andrew.kuchling | 2006-06-04 00:59:59 +0200 (Sun, 04 Jun 2006) | 1 line Some code tidying; use curses.wrapper ........ r46625 | andrew.kuchling | 2006-06-04 01:02:15 +0200 (Sun, 04 Jun 2006) | 1 line Use True; value returned from main is unused ........ r46626 | andrew.kuchling | 2006-06-04 01:07:21 +0200 (Sun, 04 Jun 2006) | 1 line Use true division, and the True value ........ r46627 | andrew.kuchling | 2006-06-04 01:09:58 +0200 (Sun, 04 Jun 2006) | 1 line Docstring fix; use True ........ r46628 | andrew.kuchling | 2006-06-04 01:15:56 +0200 (Sun, 04 Jun 2006) | 1 line Put code in a main() function; loosen up the spacing to match current code style ........ r46629 | andrew.kuchling | 2006-06-04 01:39:07 +0200 (Sun, 04 Jun 2006) | 1 line Use functions; modernize code ........ r46630 | andrew.kuchling | 2006-06-04 01:43:22 +0200 (Sun, 04 Jun 2006) | 1 line This demo requires Medusa (not just asyncore); remove it ........ r46631 | andrew.kuchling | 2006-06-04 01:46:36 +0200 (Sun, 04 Jun 2006) | 2 lines Remove xmlrpc demo -- it duplicates the SimpleXMLRPCServer module. ........ r46632 | andrew.kuchling | 2006-06-04 01:47:22 +0200 (Sun, 04 Jun 2006) | 1 line Remove xmlrpc/ directory ........ r46633 | andrew.kuchling | 2006-06-04 01:51:21 +0200 (Sun, 04 Jun 2006) | 1 line Remove dangling reference ........ r46634 | andrew.kuchling | 2006-06-04 01:59:36 +0200 (Sun, 04 Jun 2006) | 1 line Add more whitespace; use a better socket name ........ r46635 | tim.peters | 2006-06-04 03:22:53 +0200 (Sun, 04 Jun 2006) | 2 lines Whitespace normalization. ........ r46637 | tim.peters | 2006-06-04 05:26:02 +0200 (Sun, 04 Jun 2006) | 16 lines In a PYMALLOC_DEBUG build obmalloc adds extra debugging info to each allocated block. This was using 4 bytes for each such piece of info regardless of platform. This didn't really matter before (proof: no bug reports, and the debug-build obmalloc would have assert-failed if it was ever asked for a chunk of memory >= 2**32 bytes), since container indices were plain ints. But after the Py_ssize_t changes, it's at least theoretically possible to allocate a list or string whose guts exceed 2**32 bytes, and the PYMALLOC_DEBUG routines would fail then (having only 4 bytes to record the originally requested size). Now we use sizeof(size_t) bytes for each of a PYMALLOC_DEBUG build's extra debugging fields. This won't make any difference on 32-bit boxes, but will add 16 bytes to each allocation in a debug build on a 64-bit box. ........ r46638 | tim.peters | 2006-06-04 05:38:04 +0200 (Sun, 04 Jun 2006) | 4 lines _PyObject_DebugMalloc(): The return value should add 2*sizeof(size_t) now, not 8. This probably accounts for current disasters on the 64-bit buildbot slaves. ........ r46639 | neal.norwitz | 2006-06-04 08:19:31 +0200 (Sun, 04 Jun 2006) | 1 line SF #1499797, Fix for memory leak in WindowsError_str ........ r46640 | andrew.macintyre | 2006-06-04 14:31:09 +0200 (Sun, 04 Jun 2006) | 2 lines Patch #1454481: Make thread stack size runtime tunable. ........ r46641 | andrew.macintyre | 2006-06-04 14:59:59 +0200 (Sun, 04 Jun 2006) | 2 lines clean up function declarations to conform to PEP-7 style. ........ r46642 | martin.blais | 2006-06-04 15:49:49 +0200 (Sun, 04 Jun 2006) | 15 lines Fixes in struct and socket from merge reviews. - Following Guido's comments, renamed * pack_to -> pack_into * recv_buf -> recv_into * recvfrom_buf -> recvfrom_into - Made fixes to _struct.c according to Neal Norwitz comments on the checkins list. - Converted some ints into the appropriate -- I hope -- ssize_t and size_t. ........ r46643 | ronald.oussoren | 2006-06-04 16:05:28 +0200 (Sun, 04 Jun 2006) | 3 lines "Import" LDFLAGS in Mac/OSX/Makefile.in to ensure pythonw gets build with the right compiler flags. ........ r46644 | ronald.oussoren | 2006-06-04 16:24:59 +0200 (Sun, 04 Jun 2006) | 2 lines Drop Mac wrappers for the WASTE library. ........ r46645 | tim.peters | 2006-06-04 17:49:07 +0200 (Sun, 04 Jun 2006) | 3 lines s_methods[]: Stop compiler warnings by casting s_unpack_from to PyCFunction. ........ r46646 | george.yoshida | 2006-06-04 19:04:12 +0200 (Sun, 04 Jun 2006) | 2 lines Remove a redundant word ........ r46647 | george.yoshida | 2006-06-04 19:17:25 +0200 (Sun, 04 Jun 2006) | 2 lines Markup fix ........ r46648 | martin.v.loewis | 2006-06-04 21:36:28 +0200 (Sun, 04 Jun 2006) | 2 lines Patch #1359618: Speed-up charmap encoder. ........ r46649 | georg.brandl | 2006-06-04 23:46:16 +0200 (Sun, 04 Jun 2006) | 3 lines Repair refleaks in unicodeobject. ........ r46650 | georg.brandl | 2006-06-04 23:56:52 +0200 (Sun, 04 Jun 2006) | 4 lines Patch #1346214: correctly optimize away "if 0"-style stmts (thanks to Neal for review) ........ r46651 | georg.brandl | 2006-06-05 00:15:37 +0200 (Mon, 05 Jun 2006) | 2 lines Bug #1500293: fix memory leaks in _subprocess module. ........ r46654 | tim.peters | 2006-06-05 01:43:53 +0200 (Mon, 05 Jun 2006) | 2 lines Whitespace normalization. ........ r46655 | tim.peters | 2006-06-05 01:52:47 +0200 (Mon, 05 Jun 2006) | 16 lines Revert revisions: 46640 Patch #1454481: Make thread stack size runtime tunable. 46647 Markup fix The first is causing many buildbots to fail test runs, and there are multiple causes with seemingly no immediate prospects for repairing them. See python-dev discussion. Note that a branch can (and should) be created for resolving these problems, like svn copy svn+ssh://svn.python.org/python/trunk -r46640 svn+ssh://svn.python.org/python/branches/NEW_BRANCH followed by merging rev 46647 to the new branch. ........ r46656 | andrew.kuchling | 2006-06-05 02:08:09 +0200 (Mon, 05 Jun 2006) | 1 line Mention second encoding speedup ........ r46657 | gregory.p.smith | 2006-06-05 02:31:01 +0200 (Mon, 05 Jun 2006) | 7 lines bugfix: when log_archive was called with the DB_ARCH_REMOVE flag present in BerkeleyDB >= 4.2 it tried to construct a list out of an uninitialized char **log_list. feature: export the DB_ARCH_REMOVE flag by name in the module on BerkeleyDB >= 4.2. ........ r46658 | gregory.p.smith | 2006-06-05 02:33:35 +0200 (Mon, 05 Jun 2006) | 5 lines fix a bug in the previous commit. don't leak empty list on error return and fix the additional rare (out of memory only) bug that it was supposed to fix of not freeing log_list when the python allocator failed. ........ r46660 | tim.peters | 2006-06-05 02:55:26 +0200 (Mon, 05 Jun 2006) | 9 lines "Flat is better than nested." Move the long-winded, multiply-nested -R support out of runtest() and into some module-level helper functions. This makes runtest() and the -R code easier to follow. That in turn allowed seeing some opportunities for code simplification, and made it obvious that reglog.txt never got closed. ........ r46661 | hyeshik.chang | 2006-06-05 02:59:54 +0200 (Mon, 05 Jun 2006) | 3 lines Fix a potentially invalid memory access of CJKCodecs' shift-jis decoder. (found by Neal Norwitz) ........ r46663 | gregory.p.smith | 2006-06-05 03:39:52 +0200 (Mon, 05 Jun 2006) | 3 lines * support DBEnv.log_stat() method on BerkeleyDB >= 4.0 [patch #1494885] ........ r46664 | tim.peters | 2006-06-05 03:43:03 +0200 (Mon, 05 Jun 2006) | 3 lines Remove doctest.testmod's deprecated (in 2.4) `isprivate` argument. A lot of hair went into supporting that! ........ r46665 | tim.peters | 2006-06-05 03:47:24 +0200 (Mon, 05 Jun 2006) | 2 lines Whitespace normalization. ........ r46666 | tim.peters | 2006-06-05 03:48:21 +0200 (Mon, 05 Jun 2006) | 2 lines Make doctest news more accurate. ........ r46667 | gregory.p.smith | 2006-06-05 03:56:15 +0200 (Mon, 05 Jun 2006) | 3 lines * support DBEnv.lsn_reset() method on BerkeleyDB >= 4.4 [patch #1494902] ........ r46668 | gregory.p.smith | 2006-06-05 04:02:25 +0200 (Mon, 05 Jun 2006) | 3 lines mention the just committed bsddb changes ........ r46671 | gregory.p.smith | 2006-06-05 19:38:04 +0200 (Mon, 05 Jun 2006) | 3 lines * add support for DBSequence objects [patch #1466734] ........ r46672 | gregory.p.smith | 2006-06-05 20:20:07 +0200 (Mon, 05 Jun 2006) | 3 lines forgot to add this file in previous commit ........ r46673 | tim.peters | 2006-06-05 20:36:12 +0200 (Mon, 05 Jun 2006) | 2 lines Whitespace normalization. ........ r46674 | tim.peters | 2006-06-05 20:36:54 +0200 (Mon, 05 Jun 2006) | 2 lines Add missing svn:eol-style property to text files. ........ r46675 | gregory.p.smith | 2006-06-05 20:48:21 +0200 (Mon, 05 Jun 2006) | 4 lines * fix DBCursor.pget() bug with keyword argument names when no data= is supplied [SF pybsddb bug #1477863] ........ r46676 | andrew.kuchling | 2006-06-05 21:05:32 +0200 (Mon, 05 Jun 2006) | 1 line Remove use of Trove name, which isn't very helpful to users ........ r46677 | andrew.kuchling | 2006-06-05 21:08:25 +0200 (Mon, 05 Jun 2006) | 1 line [Bug #1470026] Include link to list of classifiers ........ r46679 | tim.peters | 2006-06-05 22:48:49 +0200 (Mon, 05 Jun 2006) | 10 lines Access _struct attributes directly instead of mucking with getattr. string_reverse(): Simplify. assertRaises(): Raise TestFailed on failure. test_unpack_from(), test_pack_into(), test_pack_into_fn(): never use `assert` to test for an expected result (it doesn't test anything when Python is run with -O). ........ r46680 | tim.peters | 2006-06-05 22:49:27 +0200 (Mon, 05 Jun 2006) | 2 lines Add missing svn:eol-style property to text files. ........ r46681 | gregory.p.smith | 2006-06-06 01:38:06 +0200 (Tue, 06 Jun 2006) | 3 lines add depends = ['md5.h'] to the _md5 module extension for correctness sake. ........ r46682 | brett.cannon | 2006-06-06 01:51:55 +0200 (Tue, 06 Jun 2006) | 4 lines Add 3 more bytes to a buffer to cover constants in string and null byte on top of 10 possible digits for an int. Closes bug #1501223. ........ r46684 | gregory.p.smith | 2006-06-06 01:59:37 +0200 (Tue, 06 Jun 2006) | 5 lines - bsddb: the __len__ method of a DB object has been fixed to return correct results. It could previously incorrectly return 0 in some cases. Fixes SF bug 1493322 (pybsddb bug 1184012). ........ r46686 | tim.peters | 2006-06-06 02:25:07 +0200 (Tue, 06 Jun 2006) | 7 lines _PySys_Init(): It's rarely a good idea to size a buffer to the exact maximum size someone guesses is needed. In this case, if we're really worried about extreme integers, then "cp%d" can actually need 14 bytes (2 for "cp" + 1 for \0 at the end + 11 for -(2**31-1)). So reserve 128 bytes instead -- nothing is actually saved by making a stack-local buffer tiny. ........ r46687 | neal.norwitz | 2006-06-06 09:22:08 +0200 (Tue, 06 Jun 2006) | 1 line Remove unused variable (and stop compiler warning) ........ r46688 | neal.norwitz | 2006-06-06 09:23:01 +0200 (Tue, 06 Jun 2006) | 1 line Fix a bunch of parameter strings ........ r46689 | thomas.heller | 2006-06-06 13:34:33 +0200 (Tue, 06 Jun 2006) | 6 lines Convert CFieldObject tp_members to tp_getset, since there is no structmember typecode for Py_ssize_t fields. This should fix some of the errors on the PPC64 debian machine (64-bit, big endian). Assigning to readonly fields now raises AttributeError instead of TypeError, so the testcase has to be changed as well. ........ r46690 | thomas.heller | 2006-06-06 13:54:32 +0200 (Tue, 06 Jun 2006) | 1 line Damn - the sentinel was missing. And fix another silly mistake. ........ r46691 | martin.blais | 2006-06-06 14:46:55 +0200 (Tue, 06 Jun 2006) | 13 lines Normalized a few cases of whitespace in function declarations. Found them using:: find . -name '*.py' | while read i ; do grep 'def[^(]*( ' $i /dev/null ; done find . -name '*.py' | while read i ; do grep ' ):' $i /dev/null ; done (I was doing this all over my own code anyway, because I'd been using spaces in all defs, so I thought I'd make a run on the Python code as well. If you need to do such fixes in your own code, you can use xx-rename or parenregu.el within emacs.) ........ r46693 | thomas.heller | 2006-06-06 17:34:18 +0200 (Tue, 06 Jun 2006) | 1 line Specify argtypes for all test functions. Maybe that helps on strange ;-) architectures ........ r46694 | tim.peters | 2006-06-06 17:50:17 +0200 (Tue, 06 Jun 2006) | 5 lines BSequence_set_range(): Rev 46688 ("Fix a bunch of parameter strings") changed this function's signature seemingly by mistake, which is causing buildbots to fail test_bsddb3. Restored the pre-46688 signature. ........ r46695 | tim.peters | 2006-06-06 17:52:35 +0200 (Tue, 06 Jun 2006) | 4 lines On python-dev Thomas Heller said these were committed by mistake in rev 46693, so reverting this part of rev 46693. ........ r46696 | andrew.kuchling | 2006-06-06 19:10:41 +0200 (Tue, 06 Jun 2006) | 1 line Fix comment typo ........ r46697 | brett.cannon | 2006-06-06 20:08:16 +0200 (Tue, 06 Jun 2006) | 2 lines Fix coding style guide bug. ........ r46698 | thomas.heller | 2006-06-06 20:50:46 +0200 (Tue, 06 Jun 2006) | 2 lines Add a hack so that foreign functions returning float now do work on 64-bit big endian platforms. ........ r46699 | thomas.heller | 2006-06-06 21:25:13 +0200 (Tue, 06 Jun 2006) | 3 lines Use the same big-endian hack as in _ctypes/callproc.c for callback functions. This fixes the callback function tests that return float. ........ r46700 | ronald.oussoren | 2006-06-06 21:50:24 +0200 (Tue, 06 Jun 2006) | 5 lines * Ensure that "make altinstall" works when the tree was configured with --enable-framework * Also for --enable-framework: allow users to use --prefix to specify the location of the compatibility symlinks (such as /usr/local/bin/python) ........ r46701 | ronald.oussoren | 2006-06-06 21:56:00 +0200 (Tue, 06 Jun 2006) | 3 lines A quick hack to ensure the right key-bindings for IDLE on osx: install patched configuration files during a framework install. ........ r46702 | tim.peters | 2006-06-07 03:04:59 +0200 (Wed, 07 Jun 2006) | 4 lines dash_R_cleanup(): Clear filecmp._cache. This accounts for different results across -R runs (at least on Windows) of test_filecmp. ........ r46705 | tim.peters | 2006-06-07 08:57:51 +0200 (Wed, 07 Jun 2006) | 17 lines SF patch 1501987: Remove randomness from test_exceptions, from ?iga Seilnacht (sorry about the name, but Firefox on my box can't display the first character of the name -- the SF "Unix name" is zseil). This appears to cure the oddball intermittent leaks across runs when running test_exceptions under -R. I'm not sure why, but I'm too sleepy to care ;-) The thrust of the SF patch was to remove randomness in the pickle protocol used. I changed the patch to use range(pickle.HIGHEST_PROTOCOL + 1), to try both pickle and cPickle, and randomly mucked with other test lines to put statements on their own lines. Not a bugfix candidate (this is fiddling new-in-2.5 code). ........ r46706 | andrew.kuchling | 2006-06-07 15:55:33 +0200 (Wed, 07 Jun 2006) | 1 line Add an SQLite introduction, taken from the 'What's New' text ........ r46708 | andrew.kuchling | 2006-06-07 19:02:52 +0200 (Wed, 07 Jun 2006) | 1 line Mention other placeholders ........ r46709 | andrew.kuchling | 2006-06-07 19:03:46 +0200 (Wed, 07 Jun 2006) | 1 line Add an item; also, escape % ........ r46710 | andrew.kuchling | 2006-06-07 19:04:01 +0200 (Wed, 07 Jun 2006) | 1 line Mention other placeholders ........ r46716 | ronald.oussoren | 2006-06-07 20:57:44 +0200 (Wed, 07 Jun 2006) | 2 lines Move Mac/OSX/Tools one level up ........ r46717 | ronald.oussoren | 2006-06-07 20:58:01 +0200 (Wed, 07 Jun 2006) | 2 lines Move Mac/OSX/PythonLauncher one level up ........ r46718 | ronald.oussoren | 2006-06-07 20:58:42 +0200 (Wed, 07 Jun 2006) | 2 lines mv Mac/OSX/BuildScript one level up ........ r46719 | ronald.oussoren | 2006-06-07 21:02:03 +0200 (Wed, 07 Jun 2006) | 2 lines Move Mac/OSX/* one level up ........ r46720 | ronald.oussoren | 2006-06-07 21:06:01 +0200 (Wed, 07 Jun 2006) | 2 lines And the last bit: move IDLE one level up and adjust makefiles ........ r46723 | ronald.oussoren | 2006-06-07 21:38:53 +0200 (Wed, 07 Jun 2006) | 4 lines - Patch the correct version of python in the Info.plists at build time, instead of relying on a maintainer to update them before releases. - Remove the now empty Mac/OSX directory ........ r46727 | ronald.oussoren | 2006-06-07 22:18:44 +0200 (Wed, 07 Jun 2006) | 7 lines * If BuildApplet.py is used as an applet it starts with a version of sys.exutable that isn't usuable on an #!-line. That results in generated applets that don't actually work. Work around this problem by resetting sys.executable. * argvemulator.py didn't work on intel macs. This patch fixes this (bug #1491468) ........ r46728 | tim.peters | 2006-06-07 22:40:06 +0200 (Wed, 07 Jun 2006) | 2 lines Whitespace normalization. ........ r46729 | tim.peters | 2006-06-07 22:40:54 +0200 (Wed, 07 Jun 2006) | 2 lines Add missing svn:eol-style property to text files. ........ r46730 | thomas.heller | 2006-06-07 22:43:06 +0200 (Wed, 07 Jun 2006) | 7 lines Fix for foreign functions returning small structures on 64-bit big endian machines. Should fix the remaininf failure in the PPC64 Debian buildbot. Thanks to Matthias Klose for providing access to a machine to debug and test this. ........ r46731 | brett.cannon | 2006-06-07 23:48:17 +0200 (Wed, 07 Jun 2006) | 2 lines Clarify documentation for bf_getcharbuffer. ........ r46735 | neal.norwitz | 2006-06-08 07:12:45 +0200 (Thu, 08 Jun 2006) | 1 line Fix a refleak in recvfrom_into ........ r46736 | gregory.p.smith | 2006-06-08 07:17:08 +0200 (Thu, 08 Jun 2006) | 9 lines - bsddb: the bsddb.dbtables Modify method now raises the proper error and aborts the db transaction safely when a modifier callback fails. Fixes SF python patch/bug #1408584. Also cleans up the bsddb.dbtables docstrings since thats the only documentation that exists for that unadvertised module. (people really should really just use sqlite3) ........ r46737 | gregory.p.smith | 2006-06-08 07:38:11 +0200 (Thu, 08 Jun 2006) | 4 lines * Turn the deadlock situation described in SF bug #775414 into a DBDeadLockError exception. * add the test case for my previous dbtables commit. ........ r46738 | gregory.p.smith | 2006-06-08 07:39:54 +0200 (Thu, 08 Jun 2006) | 2 lines pasted set_lk_detect line in wrong spot in previous commit. fixed. passes tests this time. ........ r46739 | armin.rigo | 2006-06-08 12:56:24 +0200 (Thu, 08 Jun 2006) | 6 lines (arre, arigo) SF bug #1350060 Give a consistent behavior for comparison and hashing of method objects (both user- and built-in methods). Now compares the 'self' recursively. The hash was already asking for the hash of 'self'. ........ r46740 | andrew.kuchling | 2006-06-08 13:56:44 +0200 (Thu, 08 Jun 2006) | 1 line Typo fix ........ r46741 | georg.brandl | 2006-06-08 14:45:01 +0200 (Thu, 08 Jun 2006) | 2 lines Bug #1502750: Fix getargs "i" format to use LONG_MIN and LONG_MAX for bounds checking. ........ r46743 | georg.brandl | 2006-06-08 14:54:13 +0200 (Thu, 08 Jun 2006) | 2 lines Bug #1502728: Correctly link against librt library on HP-UX. ........ r46745 | georg.brandl | 2006-06-08 14:55:47 +0200 (Thu, 08 Jun 2006) | 3 lines Add news for recent bugfix. ........ r46746 | georg.brandl | 2006-06-08 15:31:07 +0200 (Thu, 08 Jun 2006) | 4 lines Argh. "integer" is a very confusing word ;) Actually, checking for INT_MAX and INT_MIN is correct since the format code explicitly handles a C "int". ........ r46748 | nick.coghlan | 2006-06-08 15:54:49 +0200 (Thu, 08 Jun 2006) | 1 line Add functools.update_wrapper() and functools.wraps() as described in PEP 356 ........ r46751 | georg.brandl | 2006-06-08 16:50:21 +0200 (Thu, 08 Jun 2006) | 4 lines Bug #1502805: don't alias file.__exit__ to file.close since the latter can return something that's true. ........ r46752 | georg.brandl | 2006-06-08 16:50:53 +0200 (Thu, 08 Jun 2006) | 3 lines Convert test_file to unittest. ........
2305 lines
50 KiB
C
2305 lines
50 KiB
C
/* Abstract Object Interface (many thanks to Jim Fulton) */
|
|
|
|
#include "Python.h"
|
|
#include <ctype.h>
|
|
#include "structmember.h" /* we need the offsetof() macro from there */
|
|
#include "longintrepr.h"
|
|
|
|
#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
|
|
Py_TPFLAGS_CHECKTYPES)
|
|
|
|
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
|
|
|
|
|
/* Shorthands to return certain errors */
|
|
|
|
static PyObject *
|
|
type_error(const char *msg)
|
|
{
|
|
PyErr_SetString(PyExc_TypeError, msg);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
null_error(void)
|
|
{
|
|
if (!PyErr_Occurred())
|
|
PyErr_SetString(PyExc_SystemError,
|
|
"null argument to internal routine");
|
|
return NULL;
|
|
}
|
|
|
|
/* Operations on any object */
|
|
|
|
int
|
|
PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
|
|
{
|
|
int r;
|
|
|
|
if (o1 == NULL || o2 == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
r = PyObject_Compare(o1, o2);
|
|
if (PyErr_Occurred())
|
|
return -1;
|
|
*result = r;
|
|
return 0;
|
|
}
|
|
|
|
PyObject *
|
|
PyObject_Type(PyObject *o)
|
|
{
|
|
PyObject *v;
|
|
|
|
if (o == NULL)
|
|
return null_error();
|
|
v = (PyObject *)o->ob_type;
|
|
Py_INCREF(v);
|
|
return v;
|
|
}
|
|
|
|
Py_ssize_t
|
|
PyObject_Size(PyObject *o)
|
|
{
|
|
PySequenceMethods *m;
|
|
|
|
if (o == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
|
|
m = o->ob_type->tp_as_sequence;
|
|
if (m && m->sq_length)
|
|
return m->sq_length(o);
|
|
|
|
return PyMapping_Size(o);
|
|
}
|
|
|
|
#undef PyObject_Length
|
|
Py_ssize_t
|
|
PyObject_Length(PyObject *o)
|
|
{
|
|
return PyObject_Size(o);
|
|
}
|
|
#define PyObject_Length PyObject_Size
|
|
|
|
Py_ssize_t
|
|
_PyObject_LengthHint(PyObject *o)
|
|
{
|
|
Py_ssize_t rv = PyObject_Size(o);
|
|
if (rv != -1)
|
|
return rv;
|
|
if (PyErr_ExceptionMatches(PyExc_TypeError) ||
|
|
PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
|
PyObject *err_type, *err_value, *err_tb, *ro;
|
|
|
|
PyErr_Fetch(&err_type, &err_value, &err_tb);
|
|
ro = PyObject_CallMethod(o, "__length_hint__", NULL);
|
|
if (ro != NULL) {
|
|
rv = PyInt_AsLong(ro);
|
|
Py_DECREF(ro);
|
|
Py_XDECREF(err_type);
|
|
Py_XDECREF(err_value);
|
|
Py_XDECREF(err_tb);
|
|
return rv;
|
|
}
|
|
PyErr_Restore(err_type, err_value, err_tb);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
PyObject *
|
|
PyObject_GetItem(PyObject *o, PyObject *key)
|
|
{
|
|
PyMappingMethods *m;
|
|
|
|
if (o == NULL || key == NULL)
|
|
return null_error();
|
|
|
|
m = o->ob_type->tp_as_mapping;
|
|
if (m && m->mp_subscript)
|
|
return m->mp_subscript(o, key);
|
|
|
|
if (o->ob_type->tp_as_sequence) {
|
|
PyNumberMethods *nb = key->ob_type->tp_as_number;
|
|
if (nb != NULL && HASINDEX(key) && nb->nb_index != NULL) {
|
|
Py_ssize_t key_value = nb->nb_index(key);
|
|
if (key_value == -1 && PyErr_Occurred())
|
|
return NULL;
|
|
return PySequence_GetItem(o, key_value);
|
|
}
|
|
else if (o->ob_type->tp_as_sequence->sq_item)
|
|
return type_error("sequence index must be integer");
|
|
}
|
|
|
|
return type_error("unsubscriptable object");
|
|
}
|
|
|
|
int
|
|
PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value)
|
|
{
|
|
PyMappingMethods *m;
|
|
|
|
if (o == NULL || key == NULL || value == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
m = o->ob_type->tp_as_mapping;
|
|
if (m && m->mp_ass_subscript)
|
|
return m->mp_ass_subscript(o, key, value);
|
|
|
|
if (o->ob_type->tp_as_sequence) {
|
|
PyNumberMethods *nb = key->ob_type->tp_as_number;
|
|
if (nb != NULL && HASINDEX(key) && nb->nb_index != NULL) {
|
|
Py_ssize_t key_value = nb->nb_index(key);
|
|
if (key_value == -1 && PyErr_Occurred())
|
|
return -1;
|
|
return PySequence_SetItem(o, key_value, value);
|
|
}
|
|
else if (o->ob_type->tp_as_sequence->sq_ass_item) {
|
|
type_error("sequence index must be integer");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
type_error("object does not support item assignment");
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
PyObject_DelItem(PyObject *o, PyObject *key)
|
|
{
|
|
PyMappingMethods *m;
|
|
|
|
if (o == NULL || key == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
m = o->ob_type->tp_as_mapping;
|
|
if (m && m->mp_ass_subscript)
|
|
return m->mp_ass_subscript(o, key, (PyObject*)NULL);
|
|
|
|
if (o->ob_type->tp_as_sequence) {
|
|
PyNumberMethods *nb = key->ob_type->tp_as_number;
|
|
if (nb != NULL && HASINDEX(key) && nb->nb_index != NULL) {
|
|
Py_ssize_t key_value = nb->nb_index(key);
|
|
if (key_value == -1 && PyErr_Occurred())
|
|
return -1;
|
|
return PySequence_DelItem(o, key_value);
|
|
}
|
|
else if (o->ob_type->tp_as_sequence->sq_ass_item) {
|
|
type_error("sequence index must be integer");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
type_error("object does not support item deletion");
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
PyObject_DelItemString(PyObject *o, char *key)
|
|
{
|
|
PyObject *okey;
|
|
int ret;
|
|
|
|
if (o == NULL || key == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
okey = PyString_FromString(key);
|
|
if (okey == NULL)
|
|
return -1;
|
|
ret = PyObject_DelItem(o, okey);
|
|
Py_DECREF(okey);
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
PyObject_AsCharBuffer(PyObject *obj,
|
|
const char **buffer,
|
|
Py_ssize_t *buffer_len)
|
|
{
|
|
PyBufferProcs *pb;
|
|
char *pp;
|
|
Py_ssize_t len;
|
|
|
|
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
pb = obj->ob_type->tp_as_buffer;
|
|
if (pb == NULL ||
|
|
pb->bf_getcharbuffer == NULL ||
|
|
pb->bf_getsegcount == NULL) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"expected a character buffer object");
|
|
return -1;
|
|
}
|
|
if ((*pb->bf_getsegcount)(obj,NULL) != 1) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"expected a single-segment buffer object");
|
|
return -1;
|
|
}
|
|
len = (*pb->bf_getcharbuffer)(obj, 0, &pp);
|
|
if (len < 0)
|
|
return -1;
|
|
*buffer = pp;
|
|
*buffer_len = len;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
PyObject_CheckReadBuffer(PyObject *obj)
|
|
{
|
|
PyBufferProcs *pb = obj->ob_type->tp_as_buffer;
|
|
|
|
if (pb == NULL ||
|
|
pb->bf_getreadbuffer == NULL ||
|
|
pb->bf_getsegcount == NULL ||
|
|
(*pb->bf_getsegcount)(obj, NULL) != 1)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
int PyObject_AsReadBuffer(PyObject *obj,
|
|
const void **buffer,
|
|
Py_ssize_t *buffer_len)
|
|
{
|
|
PyBufferProcs *pb;
|
|
void *pp;
|
|
Py_ssize_t len;
|
|
|
|
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
pb = obj->ob_type->tp_as_buffer;
|
|
if (pb == NULL ||
|
|
pb->bf_getreadbuffer == NULL ||
|
|
pb->bf_getsegcount == NULL) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"expected a readable buffer object");
|
|
return -1;
|
|
}
|
|
if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"expected a single-segment buffer object");
|
|
return -1;
|
|
}
|
|
len = (*pb->bf_getreadbuffer)(obj, 0, &pp);
|
|
if (len < 0)
|
|
return -1;
|
|
*buffer = pp;
|
|
*buffer_len = len;
|
|
return 0;
|
|
}
|
|
|
|
int PyObject_AsWriteBuffer(PyObject *obj,
|
|
void **buffer,
|
|
Py_ssize_t *buffer_len)
|
|
{
|
|
PyBufferProcs *pb;
|
|
void*pp;
|
|
Py_ssize_t len;
|
|
|
|
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
pb = obj->ob_type->tp_as_buffer;
|
|
if (pb == NULL ||
|
|
pb->bf_getwritebuffer == NULL ||
|
|
pb->bf_getsegcount == NULL) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"expected a writeable buffer object");
|
|
return -1;
|
|
}
|
|
if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"expected a single-segment buffer object");
|
|
return -1;
|
|
}
|
|
len = (*pb->bf_getwritebuffer)(obj,0,&pp);
|
|
if (len < 0)
|
|
return -1;
|
|
*buffer = pp;
|
|
*buffer_len = len;
|
|
return 0;
|
|
}
|
|
|
|
/* Operations on numbers */
|
|
|
|
int
|
|
PyNumber_Check(PyObject *o)
|
|
{
|
|
return o && o->ob_type->tp_as_number &&
|
|
(o->ob_type->tp_as_number->nb_int ||
|
|
o->ob_type->tp_as_number->nb_float);
|
|
}
|
|
|
|
/* Binary operators */
|
|
|
|
/* New style number protocol support */
|
|
|
|
#define NB_SLOT(x) offsetof(PyNumberMethods, x)
|
|
#define NB_BINOP(nb_methods, slot) \
|
|
(*(binaryfunc*)(& ((char*)nb_methods)[slot]))
|
|
#define NB_TERNOP(nb_methods, slot) \
|
|
(*(ternaryfunc*)(& ((char*)nb_methods)[slot]))
|
|
|
|
/*
|
|
Calling scheme used for binary operations:
|
|
|
|
v w Action
|
|
-------------------------------------------------------------------
|
|
new new w.op(v,w)[*], v.op(v,w), w.op(v,w)
|
|
new old v.op(v,w), coerce(v,w), v.op(v,w)
|
|
old new w.op(v,w), coerce(v,w), v.op(v,w)
|
|
old old coerce(v,w), v.op(v,w)
|
|
|
|
[*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of
|
|
v->ob_type
|
|
|
|
Legend:
|
|
-------
|
|
* new == new style number
|
|
* old == old style number
|
|
* Action indicates the order in which operations are tried until either
|
|
a valid result is produced or an error occurs.
|
|
|
|
*/
|
|
|
|
static PyObject *
|
|
binary_op1(PyObject *v, PyObject *w, const int op_slot)
|
|
{
|
|
PyObject *x;
|
|
binaryfunc slotv = NULL;
|
|
binaryfunc slotw = NULL;
|
|
|
|
if (v->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(v))
|
|
slotv = NB_BINOP(v->ob_type->tp_as_number, op_slot);
|
|
if (w->ob_type != v->ob_type &&
|
|
w->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(w)) {
|
|
slotw = NB_BINOP(w->ob_type->tp_as_number, op_slot);
|
|
if (slotw == slotv)
|
|
slotw = NULL;
|
|
}
|
|
if (slotv) {
|
|
if (slotw && PyType_IsSubtype(w->ob_type, v->ob_type)) {
|
|
x = slotw(v, w);
|
|
if (x != Py_NotImplemented)
|
|
return x;
|
|
Py_DECREF(x); /* can't do it */
|
|
slotw = NULL;
|
|
}
|
|
x = slotv(v, w);
|
|
if (x != Py_NotImplemented)
|
|
return x;
|
|
Py_DECREF(x); /* can't do it */
|
|
}
|
|
if (slotw) {
|
|
x = slotw(v, w);
|
|
if (x != Py_NotImplemented)
|
|
return x;
|
|
Py_DECREF(x); /* can't do it */
|
|
}
|
|
if (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w)) {
|
|
int err = PyNumber_CoerceEx(&v, &w);
|
|
if (err < 0) {
|
|
return NULL;
|
|
}
|
|
if (err == 0) {
|
|
PyNumberMethods *mv = v->ob_type->tp_as_number;
|
|
if (mv) {
|
|
binaryfunc slot;
|
|
slot = NB_BINOP(mv, op_slot);
|
|
if (slot) {
|
|
x = slot(v, w);
|
|
Py_DECREF(v);
|
|
Py_DECREF(w);
|
|
return x;
|
|
}
|
|
}
|
|
/* CoerceEx incremented the reference counts */
|
|
Py_DECREF(v);
|
|
Py_DECREF(w);
|
|
}
|
|
}
|
|
Py_INCREF(Py_NotImplemented);
|
|
return Py_NotImplemented;
|
|
}
|
|
|
|
static PyObject *
|
|
binop_type_error(PyObject *v, PyObject *w, const char *op_name)
|
|
{
|
|
PyErr_Format(PyExc_TypeError,
|
|
"unsupported operand type(s) for %s: '%s' and '%s'",
|
|
op_name,
|
|
v->ob_type->tp_name,
|
|
w->ob_type->tp_name);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)
|
|
{
|
|
PyObject *result = binary_op1(v, w, op_slot);
|
|
if (result == Py_NotImplemented) {
|
|
Py_DECREF(result);
|
|
return binop_type_error(v, w, op_name);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
Calling scheme used for ternary operations:
|
|
|
|
*** In some cases, w.op is called before v.op; see binary_op1. ***
|
|
|
|
v w z Action
|
|
-------------------------------------------------------------------
|
|
new new new v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)
|
|
new old new v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
|
|
old new new w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
|
|
old old new z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
|
|
new new old v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
|
|
new old old v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
|
|
old new old w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
|
|
old old old coerce(v,w,z), v.op(v,w,z)
|
|
|
|
Legend:
|
|
-------
|
|
* new == new style number
|
|
* old == old style number
|
|
* Action indicates the order in which operations are tried until either
|
|
a valid result is produced or an error occurs.
|
|
* coerce(v,w,z) actually does: coerce(v,w), coerce(v,z), coerce(w,z) and
|
|
only if z != Py_None; if z == Py_None, then it is treated as absent
|
|
variable and only coerce(v,w) is tried.
|
|
|
|
*/
|
|
|
|
static PyObject *
|
|
ternary_op(PyObject *v,
|
|
PyObject *w,
|
|
PyObject *z,
|
|
const int op_slot,
|
|
const char *op_name)
|
|
{
|
|
PyNumberMethods *mv, *mw, *mz;
|
|
PyObject *x = NULL;
|
|
ternaryfunc slotv = NULL;
|
|
ternaryfunc slotw = NULL;
|
|
ternaryfunc slotz = NULL;
|
|
|
|
mv = v->ob_type->tp_as_number;
|
|
mw = w->ob_type->tp_as_number;
|
|
if (mv != NULL && NEW_STYLE_NUMBER(v))
|
|
slotv = NB_TERNOP(mv, op_slot);
|
|
if (w->ob_type != v->ob_type &&
|
|
mw != NULL && NEW_STYLE_NUMBER(w)) {
|
|
slotw = NB_TERNOP(mw, op_slot);
|
|
if (slotw == slotv)
|
|
slotw = NULL;
|
|
}
|
|
if (slotv) {
|
|
if (slotw && PyType_IsSubtype(w->ob_type, v->ob_type)) {
|
|
x = slotw(v, w, z);
|
|
if (x != Py_NotImplemented)
|
|
return x;
|
|
Py_DECREF(x); /* can't do it */
|
|
slotw = NULL;
|
|
}
|
|
x = slotv(v, w, z);
|
|
if (x != Py_NotImplemented)
|
|
return x;
|
|
Py_DECREF(x); /* can't do it */
|
|
}
|
|
if (slotw) {
|
|
x = slotw(v, w, z);
|
|
if (x != Py_NotImplemented)
|
|
return x;
|
|
Py_DECREF(x); /* can't do it */
|
|
}
|
|
mz = z->ob_type->tp_as_number;
|
|
if (mz != NULL && NEW_STYLE_NUMBER(z)) {
|
|
slotz = NB_TERNOP(mz, op_slot);
|
|
if (slotz == slotv || slotz == slotw)
|
|
slotz = NULL;
|
|
if (slotz) {
|
|
x = slotz(v, w, z);
|
|
if (x != Py_NotImplemented)
|
|
return x;
|
|
Py_DECREF(x); /* can't do it */
|
|
}
|
|
}
|
|
|
|
if (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w) ||
|
|
(z != Py_None && !NEW_STYLE_NUMBER(z))) {
|
|
/* we have an old style operand, coerce */
|
|
PyObject *v1, *z1, *w2, *z2;
|
|
int c;
|
|
|
|
c = PyNumber_Coerce(&v, &w);
|
|
if (c != 0)
|
|
goto error3;
|
|
|
|
/* Special case: if the third argument is None, it is
|
|
treated as absent argument and not coerced. */
|
|
if (z == Py_None) {
|
|
if (v->ob_type->tp_as_number) {
|
|
slotz = NB_TERNOP(v->ob_type->tp_as_number,
|
|
op_slot);
|
|
if (slotz)
|
|
x = slotz(v, w, z);
|
|
else
|
|
c = -1;
|
|
}
|
|
else
|
|
c = -1;
|
|
goto error2;
|
|
}
|
|
v1 = v;
|
|
z1 = z;
|
|
c = PyNumber_Coerce(&v1, &z1);
|
|
if (c != 0)
|
|
goto error2;
|
|
w2 = w;
|
|
z2 = z1;
|
|
c = PyNumber_Coerce(&w2, &z2);
|
|
if (c != 0)
|
|
goto error1;
|
|
|
|
if (v1->ob_type->tp_as_number != NULL) {
|
|
slotv = NB_TERNOP(v1->ob_type->tp_as_number,
|
|
op_slot);
|
|
if (slotv)
|
|
x = slotv(v1, w2, z2);
|
|
else
|
|
c = -1;
|
|
}
|
|
else
|
|
c = -1;
|
|
|
|
Py_DECREF(w2);
|
|
Py_DECREF(z2);
|
|
error1:
|
|
Py_DECREF(v1);
|
|
Py_DECREF(z1);
|
|
error2:
|
|
Py_DECREF(v);
|
|
Py_DECREF(w);
|
|
error3:
|
|
if (c >= 0)
|
|
return x;
|
|
}
|
|
|
|
if (z == Py_None)
|
|
PyErr_Format(
|
|
PyExc_TypeError,
|
|
"unsupported operand type(s) for ** or pow(): "
|
|
"'%s' and '%s'",
|
|
v->ob_type->tp_name,
|
|
w->ob_type->tp_name);
|
|
else
|
|
PyErr_Format(
|
|
PyExc_TypeError,
|
|
"unsupported operand type(s) for pow(): "
|
|
"'%s', '%s', '%s'",
|
|
v->ob_type->tp_name,
|
|
w->ob_type->tp_name,
|
|
z->ob_type->tp_name);
|
|
return NULL;
|
|
}
|
|
|
|
#define BINARY_FUNC(func, op, op_name) \
|
|
PyObject * \
|
|
func(PyObject *v, PyObject *w) { \
|
|
return binary_op(v, w, NB_SLOT(op), op_name); \
|
|
}
|
|
|
|
BINARY_FUNC(PyNumber_Or, nb_or, "|")
|
|
BINARY_FUNC(PyNumber_Xor, nb_xor, "^")
|
|
BINARY_FUNC(PyNumber_And, nb_and, "&")
|
|
BINARY_FUNC(PyNumber_Lshift, nb_lshift, "<<")
|
|
BINARY_FUNC(PyNumber_Rshift, nb_rshift, ">>")
|
|
BINARY_FUNC(PyNumber_Subtract, nb_subtract, "-")
|
|
BINARY_FUNC(PyNumber_Divmod, nb_divmod, "divmod()")
|
|
|
|
PyObject *
|
|
PyNumber_Add(PyObject *v, PyObject *w)
|
|
{
|
|
PyObject *result = binary_op1(v, w, NB_SLOT(nb_add));
|
|
if (result == Py_NotImplemented) {
|
|
PySequenceMethods *m = v->ob_type->tp_as_sequence;
|
|
Py_DECREF(result);
|
|
if (m && m->sq_concat) {
|
|
return (*m->sq_concat)(v, w);
|
|
}
|
|
result = binop_type_error(v, w, "+");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static PyObject *
|
|
sequence_repeat(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n)
|
|
{
|
|
Py_ssize_t count;
|
|
PyNumberMethods *nb = n->ob_type->tp_as_number;
|
|
if (nb != NULL && HASINDEX(n) && nb->nb_index != NULL) {
|
|
count = nb->nb_index(n);
|
|
if (count == -1 && PyErr_Occurred())
|
|
return NULL;
|
|
}
|
|
else {
|
|
return type_error(
|
|
"can't multiply sequence by non-int");
|
|
}
|
|
return (*repeatfunc)(seq, count);
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_Multiply(PyObject *v, PyObject *w)
|
|
{
|
|
PyObject *result = binary_op1(v, w, NB_SLOT(nb_multiply));
|
|
if (result == Py_NotImplemented) {
|
|
PySequenceMethods *mv = v->ob_type->tp_as_sequence;
|
|
PySequenceMethods *mw = w->ob_type->tp_as_sequence;
|
|
Py_DECREF(result);
|
|
if (mv && mv->sq_repeat) {
|
|
return sequence_repeat(mv->sq_repeat, v, w);
|
|
}
|
|
else if (mw && mw->sq_repeat) {
|
|
return sequence_repeat(mw->sq_repeat, w, v);
|
|
}
|
|
result = binop_type_error(v, w, "*");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_FloorDivide(PyObject *v, PyObject *w)
|
|
{
|
|
/* XXX tp_flags test */
|
|
return binary_op(v, w, NB_SLOT(nb_floor_divide), "//");
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_TrueDivide(PyObject *v, PyObject *w)
|
|
{
|
|
/* XXX tp_flags test */
|
|
return binary_op(v, w, NB_SLOT(nb_true_divide), "/");
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_Remainder(PyObject *v, PyObject *w)
|
|
{
|
|
return binary_op(v, w, NB_SLOT(nb_remainder), "%");
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
|
|
{
|
|
return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()");
|
|
}
|
|
|
|
/* Binary in-place operators */
|
|
|
|
/* The in-place operators are defined to fall back to the 'normal',
|
|
non in-place operations, if the in-place methods are not in place.
|
|
|
|
- If the left hand object has the appropriate struct members, and
|
|
they are filled, call the appropriate function and return the
|
|
result. No coercion is done on the arguments; the left-hand object
|
|
is the one the operation is performed on, and it's up to the
|
|
function to deal with the right-hand object.
|
|
|
|
- Otherwise, in-place modification is not supported. Handle it exactly as
|
|
a non in-place operation of the same kind.
|
|
|
|
*/
|
|
|
|
#define HASINPLACE(t) \
|
|
PyType_HasFeature((t)->ob_type, Py_TPFLAGS_HAVE_INPLACEOPS)
|
|
|
|
static PyObject *
|
|
binary_iop1(PyObject *v, PyObject *w, const int iop_slot, const int op_slot)
|
|
{
|
|
PyNumberMethods *mv = v->ob_type->tp_as_number;
|
|
if (mv != NULL && HASINPLACE(v)) {
|
|
binaryfunc slot = NB_BINOP(mv, iop_slot);
|
|
if (slot) {
|
|
PyObject *x = (slot)(v, w);
|
|
if (x != Py_NotImplemented) {
|
|
return x;
|
|
}
|
|
Py_DECREF(x);
|
|
}
|
|
}
|
|
return binary_op1(v, w, op_slot);
|
|
}
|
|
|
|
static PyObject *
|
|
binary_iop(PyObject *v, PyObject *w, const int iop_slot, const int op_slot,
|
|
const char *op_name)
|
|
{
|
|
PyObject *result = binary_iop1(v, w, iop_slot, op_slot);
|
|
if (result == Py_NotImplemented) {
|
|
Py_DECREF(result);
|
|
return binop_type_error(v, w, op_name);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#define INPLACE_BINOP(func, iop, op, op_name) \
|
|
PyObject * \
|
|
func(PyObject *v, PyObject *w) { \
|
|
return binary_iop(v, w, NB_SLOT(iop), NB_SLOT(op), op_name); \
|
|
}
|
|
|
|
INPLACE_BINOP(PyNumber_InPlaceOr, nb_inplace_or, nb_or, "|=")
|
|
INPLACE_BINOP(PyNumber_InPlaceXor, nb_inplace_xor, nb_xor, "^=")
|
|
INPLACE_BINOP(PyNumber_InPlaceAnd, nb_inplace_and, nb_and, "&=")
|
|
INPLACE_BINOP(PyNumber_InPlaceLshift, nb_inplace_lshift, nb_lshift, "<<=")
|
|
INPLACE_BINOP(PyNumber_InPlaceRshift, nb_inplace_rshift, nb_rshift, ">>=")
|
|
INPLACE_BINOP(PyNumber_InPlaceSubtract, nb_inplace_subtract, nb_subtract, "-=")
|
|
|
|
PyObject *
|
|
PyNumber_InPlaceFloorDivide(PyObject *v, PyObject *w)
|
|
{
|
|
/* XXX tp_flags test */
|
|
return binary_iop(v, w, NB_SLOT(nb_inplace_floor_divide),
|
|
NB_SLOT(nb_floor_divide), "//=");
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_InPlaceTrueDivide(PyObject *v, PyObject *w)
|
|
{
|
|
/* XXX tp_flags test */
|
|
return binary_iop(v, w, NB_SLOT(nb_inplace_true_divide),
|
|
NB_SLOT(nb_true_divide), "/=");
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_InPlaceAdd(PyObject *v, PyObject *w)
|
|
{
|
|
PyObject *result = binary_iop1(v, w, NB_SLOT(nb_inplace_add),
|
|
NB_SLOT(nb_add));
|
|
if (result == Py_NotImplemented) {
|
|
PySequenceMethods *m = v->ob_type->tp_as_sequence;
|
|
Py_DECREF(result);
|
|
if (m != NULL) {
|
|
binaryfunc f = NULL;
|
|
if (HASINPLACE(v))
|
|
f = m->sq_inplace_concat;
|
|
if (f == NULL)
|
|
f = m->sq_concat;
|
|
if (f != NULL)
|
|
return (*f)(v, w);
|
|
}
|
|
result = binop_type_error(v, w, "+=");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_InPlaceMultiply(PyObject *v, PyObject *w)
|
|
{
|
|
PyObject *result = binary_iop1(v, w, NB_SLOT(nb_inplace_multiply),
|
|
NB_SLOT(nb_multiply));
|
|
if (result == Py_NotImplemented) {
|
|
ssizeargfunc f = NULL;
|
|
PySequenceMethods *mv = v->ob_type->tp_as_sequence;
|
|
PySequenceMethods *mw = w->ob_type->tp_as_sequence;
|
|
Py_DECREF(result);
|
|
if (mv != NULL) {
|
|
if (HASINPLACE(v))
|
|
f = mv->sq_inplace_repeat;
|
|
if (f == NULL)
|
|
f = mv->sq_repeat;
|
|
if (f != NULL)
|
|
return sequence_repeat(f, v, w);
|
|
}
|
|
else if (mw != NULL) {
|
|
/* Note that the right hand operand should not be
|
|
* mutated in this case so sq_inplace_repeat is not
|
|
* used. */
|
|
if (mw->sq_repeat)
|
|
return sequence_repeat(mw->sq_repeat, w, v);
|
|
}
|
|
result = binop_type_error(v, w, "*=");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_InPlaceRemainder(PyObject *v, PyObject *w)
|
|
{
|
|
return binary_iop(v, w, NB_SLOT(nb_inplace_remainder),
|
|
NB_SLOT(nb_remainder), "%=");
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z)
|
|
{
|
|
if (HASINPLACE(v) && v->ob_type->tp_as_number &&
|
|
v->ob_type->tp_as_number->nb_inplace_power != NULL) {
|
|
return ternary_op(v, w, z, NB_SLOT(nb_inplace_power), "**=");
|
|
}
|
|
else {
|
|
return ternary_op(v, w, z, NB_SLOT(nb_power), "**=");
|
|
}
|
|
}
|
|
|
|
|
|
/* Unary operators and functions */
|
|
|
|
PyObject *
|
|
PyNumber_Negative(PyObject *o)
|
|
{
|
|
PyNumberMethods *m;
|
|
|
|
if (o == NULL)
|
|
return null_error();
|
|
m = o->ob_type->tp_as_number;
|
|
if (m && m->nb_negative)
|
|
return (*m->nb_negative)(o);
|
|
|
|
return type_error("bad operand type for unary -");
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_Positive(PyObject *o)
|
|
{
|
|
PyNumberMethods *m;
|
|
|
|
if (o == NULL)
|
|
return null_error();
|
|
m = o->ob_type->tp_as_number;
|
|
if (m && m->nb_positive)
|
|
return (*m->nb_positive)(o);
|
|
|
|
return type_error("bad operand type for unary +");
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_Invert(PyObject *o)
|
|
{
|
|
PyNumberMethods *m;
|
|
|
|
if (o == NULL)
|
|
return null_error();
|
|
m = o->ob_type->tp_as_number;
|
|
if (m && m->nb_invert)
|
|
return (*m->nb_invert)(o);
|
|
|
|
return type_error("bad operand type for unary ~");
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_Absolute(PyObject *o)
|
|
{
|
|
PyNumberMethods *m;
|
|
|
|
if (o == NULL)
|
|
return null_error();
|
|
m = o->ob_type->tp_as_number;
|
|
if (m && m->nb_absolute)
|
|
return m->nb_absolute(o);
|
|
|
|
return type_error("bad operand type for abs()");
|
|
}
|
|
|
|
/* Add a check for embedded NULL-bytes in the argument. */
|
|
static PyObject *
|
|
int_from_string(const char *s, Py_ssize_t len)
|
|
{
|
|
char *end;
|
|
PyObject *x;
|
|
|
|
x = PyInt_FromString((char*)s, &end, 10);
|
|
if (x == NULL)
|
|
return NULL;
|
|
if (end != s + len) {
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"null byte in argument for int()");
|
|
Py_DECREF(x);
|
|
return NULL;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
/* Return a Py_ssize_t integer from the object item */
|
|
Py_ssize_t
|
|
PyNumber_Index(PyObject *item)
|
|
{
|
|
Py_ssize_t value = -1;
|
|
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
|
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
|
value = nb->nb_index(item);
|
|
}
|
|
else {
|
|
PyErr_Format(PyExc_TypeError,
|
|
"'%.200s' object cannot be interpreted "
|
|
"as an index", item->ob_type->tp_name);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_Int(PyObject *o)
|
|
{
|
|
PyNumberMethods *m;
|
|
const char *buffer;
|
|
Py_ssize_t buffer_len;
|
|
|
|
if (o == NULL)
|
|
return null_error();
|
|
if (PyInt_CheckExact(o)) {
|
|
Py_INCREF(o);
|
|
return o;
|
|
}
|
|
m = o->ob_type->tp_as_number;
|
|
if (m && m->nb_int) { /* This should include subclasses of int */
|
|
PyObject *res = m->nb_int(o);
|
|
if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
|
|
PyErr_Format(PyExc_TypeError,
|
|
"__int__ returned non-int (type %.200s)",
|
|
res->ob_type->tp_name);
|
|
Py_DECREF(res);
|
|
return NULL;
|
|
}
|
|
return res;
|
|
}
|
|
if (PyInt_Check(o)) { /* A int subclass without nb_int */
|
|
PyIntObject *io = (PyIntObject*)o;
|
|
return PyInt_FromLong(io->ob_ival);
|
|
}
|
|
if (PyString_Check(o))
|
|
return int_from_string(PyString_AS_STRING(o),
|
|
PyString_GET_SIZE(o));
|
|
#ifdef Py_USING_UNICODE
|
|
if (PyUnicode_Check(o))
|
|
return PyInt_FromUnicode(PyUnicode_AS_UNICODE(o),
|
|
PyUnicode_GET_SIZE(o),
|
|
10);
|
|
#endif
|
|
if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
|
|
return int_from_string((char*)buffer, buffer_len);
|
|
|
|
return type_error("int() argument must be a string or a number");
|
|
}
|
|
|
|
/* Add a check for embedded NULL-bytes in the argument. */
|
|
static PyObject *
|
|
long_from_string(const char *s, Py_ssize_t len)
|
|
{
|
|
char *end;
|
|
PyObject *x;
|
|
|
|
x = PyLong_FromString((char*)s, &end, 10);
|
|
if (x == NULL)
|
|
return NULL;
|
|
if (end != s + len) {
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"null byte in argument for long()");
|
|
Py_DECREF(x);
|
|
return NULL;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_Long(PyObject *o)
|
|
{
|
|
PyNumberMethods *m;
|
|
const char *buffer;
|
|
Py_ssize_t buffer_len;
|
|
|
|
if (o == NULL)
|
|
return null_error();
|
|
m = o->ob_type->tp_as_number;
|
|
if (m && m->nb_long) { /* This should include subclasses of long */
|
|
PyObject *res = m->nb_long(o);
|
|
if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
|
|
PyErr_Format(PyExc_TypeError,
|
|
"__long__ returned non-long (type %.200s)",
|
|
res->ob_type->tp_name);
|
|
Py_DECREF(res);
|
|
return NULL;
|
|
}
|
|
return res;
|
|
}
|
|
if (PyLong_Check(o)) /* A long subclass without nb_long */
|
|
return _PyLong_Copy((PyLongObject *)o);
|
|
if (PyString_Check(o))
|
|
/* need to do extra error checking that PyLong_FromString()
|
|
* doesn't do. In particular long('9.5') must raise an
|
|
* exception, not truncate the float.
|
|
*/
|
|
return long_from_string(PyString_AS_STRING(o),
|
|
PyString_GET_SIZE(o));
|
|
#ifdef Py_USING_UNICODE
|
|
if (PyUnicode_Check(o))
|
|
/* The above check is done in PyLong_FromUnicode(). */
|
|
return PyLong_FromUnicode(PyUnicode_AS_UNICODE(o),
|
|
PyUnicode_GET_SIZE(o),
|
|
10);
|
|
#endif
|
|
if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
|
|
return long_from_string(buffer, buffer_len);
|
|
|
|
return type_error("long() argument must be a string or a number");
|
|
}
|
|
|
|
PyObject *
|
|
PyNumber_Float(PyObject *o)
|
|
{
|
|
PyNumberMethods *m;
|
|
|
|
if (o == NULL)
|
|
return null_error();
|
|
m = o->ob_type->tp_as_number;
|
|
if (m && m->nb_float) { /* This should include subclasses of float */
|
|
PyObject *res = m->nb_float(o);
|
|
if (res && !PyFloat_Check(res)) {
|
|
PyErr_Format(PyExc_TypeError,
|
|
"__float__ returned non-float (type %.200s)",
|
|
res->ob_type->tp_name);
|
|
Py_DECREF(res);
|
|
return NULL;
|
|
}
|
|
return res;
|
|
}
|
|
if (PyFloat_Check(o)) { /* A float subclass with nb_float == NULL */
|
|
PyFloatObject *po = (PyFloatObject *)o;
|
|
return PyFloat_FromDouble(po->ob_fval);
|
|
}
|
|
return PyFloat_FromString(o, NULL);
|
|
}
|
|
|
|
/* Operations on sequences */
|
|
|
|
int
|
|
PySequence_Check(PyObject *s)
|
|
{
|
|
if (s && PyInstance_Check(s))
|
|
return PyObject_HasAttrString(s, "__getitem__");
|
|
return s != NULL && s->ob_type->tp_as_sequence &&
|
|
s->ob_type->tp_as_sequence->sq_item != NULL;
|
|
}
|
|
|
|
Py_ssize_t
|
|
PySequence_Size(PyObject *s)
|
|
{
|
|
PySequenceMethods *m;
|
|
|
|
if (s == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
|
|
m = s->ob_type->tp_as_sequence;
|
|
if (m && m->sq_length)
|
|
return m->sq_length(s);
|
|
|
|
type_error("len() of unsized object");
|
|
return -1;
|
|
}
|
|
|
|
#undef PySequence_Length
|
|
Py_ssize_t
|
|
PySequence_Length(PyObject *s)
|
|
{
|
|
return PySequence_Size(s);
|
|
}
|
|
#define PySequence_Length PySequence_Size
|
|
|
|
PyObject *
|
|
PySequence_Concat(PyObject *s, PyObject *o)
|
|
{
|
|
PySequenceMethods *m;
|
|
|
|
if (s == NULL || o == NULL)
|
|
return null_error();
|
|
|
|
m = s->ob_type->tp_as_sequence;
|
|
if (m && m->sq_concat)
|
|
return m->sq_concat(s, o);
|
|
|
|
/* Instances of user classes defining an __add__() method only
|
|
have an nb_add slot, not an sq_concat slot. So we fall back
|
|
to nb_add if both arguments appear to be sequences. */
|
|
if (PySequence_Check(s) && PySequence_Check(o)) {
|
|
PyObject *result = binary_op1(s, o, NB_SLOT(nb_add));
|
|
if (result != Py_NotImplemented)
|
|
return result;
|
|
Py_DECREF(result);
|
|
}
|
|
return type_error("object can't be concatenated");
|
|
}
|
|
|
|
PyObject *
|
|
PySequence_Repeat(PyObject *o, Py_ssize_t count)
|
|
{
|
|
PySequenceMethods *m;
|
|
|
|
if (o == NULL)
|
|
return null_error();
|
|
|
|
m = o->ob_type->tp_as_sequence;
|
|
if (m && m->sq_repeat)
|
|
return m->sq_repeat(o, count);
|
|
|
|
/* Instances of user classes defining a __mul__() method only
|
|
have an nb_multiply slot, not an sq_repeat slot. so we fall back
|
|
to nb_multiply if o appears to be a sequence. */
|
|
if (PySequence_Check(o)) {
|
|
PyObject *n, *result;
|
|
n = PyInt_FromSsize_t(count);
|
|
if (n == NULL)
|
|
return NULL;
|
|
result = binary_op1(o, n, NB_SLOT(nb_multiply));
|
|
Py_DECREF(n);
|
|
if (result != Py_NotImplemented)
|
|
return result;
|
|
Py_DECREF(result);
|
|
}
|
|
return type_error("object can't be repeated");
|
|
}
|
|
|
|
PyObject *
|
|
PySequence_InPlaceConcat(PyObject *s, PyObject *o)
|
|
{
|
|
PySequenceMethods *m;
|
|
|
|
if (s == NULL || o == NULL)
|
|
return null_error();
|
|
|
|
m = s->ob_type->tp_as_sequence;
|
|
if (m && HASINPLACE(s) && m->sq_inplace_concat)
|
|
return m->sq_inplace_concat(s, o);
|
|
if (m && m->sq_concat)
|
|
return m->sq_concat(s, o);
|
|
|
|
if (PySequence_Check(s) && PySequence_Check(o)) {
|
|
PyObject *result = binary_iop1(s, o, NB_SLOT(nb_inplace_add),
|
|
NB_SLOT(nb_add));
|
|
if (result != Py_NotImplemented)
|
|
return result;
|
|
Py_DECREF(result);
|
|
}
|
|
return type_error("object can't be concatenated");
|
|
}
|
|
|
|
PyObject *
|
|
PySequence_InPlaceRepeat(PyObject *o, Py_ssize_t count)
|
|
{
|
|
PySequenceMethods *m;
|
|
|
|
if (o == NULL)
|
|
return null_error();
|
|
|
|
m = o->ob_type->tp_as_sequence;
|
|
if (m && HASINPLACE(o) && m->sq_inplace_repeat)
|
|
return m->sq_inplace_repeat(o, count);
|
|
if (m && m->sq_repeat)
|
|
return m->sq_repeat(o, count);
|
|
|
|
if (PySequence_Check(o)) {
|
|
PyObject *n, *result;
|
|
n = PyInt_FromSsize_t(count);
|
|
if (n == NULL)
|
|
return NULL;
|
|
result = binary_iop1(o, n, NB_SLOT(nb_inplace_multiply),
|
|
NB_SLOT(nb_multiply));
|
|
Py_DECREF(n);
|
|
if (result != Py_NotImplemented)
|
|
return result;
|
|
Py_DECREF(result);
|
|
}
|
|
return type_error("object can't be repeated");
|
|
}
|
|
|
|
PyObject *
|
|
PySequence_GetItem(PyObject *s, Py_ssize_t i)
|
|
{
|
|
PySequenceMethods *m;
|
|
|
|
if (s == NULL)
|
|
return null_error();
|
|
|
|
m = s->ob_type->tp_as_sequence;
|
|
if (m && m->sq_item) {
|
|
if (i < 0) {
|
|
if (m->sq_length) {
|
|
Py_ssize_t l = (*m->sq_length)(s);
|
|
if (l < 0)
|
|
return NULL;
|
|
i += l;
|
|
}
|
|
}
|
|
return m->sq_item(s, i);
|
|
}
|
|
|
|
return type_error("unindexable object");
|
|
}
|
|
|
|
PyObject *
|
|
PySequence_GetSlice(PyObject *s, Py_ssize_t i1, Py_ssize_t i2)
|
|
{
|
|
PySequenceMethods *m;
|
|
PyMappingMethods *mp;
|
|
|
|
if (!s) return null_error();
|
|
|
|
m = s->ob_type->tp_as_sequence;
|
|
if (m && m->sq_slice) {
|
|
if (i1 < 0 || i2 < 0) {
|
|
if (m->sq_length) {
|
|
Py_ssize_t l = (*m->sq_length)(s);
|
|
if (l < 0)
|
|
return NULL;
|
|
if (i1 < 0)
|
|
i1 += l;
|
|
if (i2 < 0)
|
|
i2 += l;
|
|
}
|
|
}
|
|
return m->sq_slice(s, i1, i2);
|
|
} else if ((mp = s->ob_type->tp_as_mapping) && mp->mp_subscript) {
|
|
PyObject *res;
|
|
PyObject *slice = _PySlice_FromIndices(i1, i2);
|
|
if (!slice)
|
|
return NULL;
|
|
res = mp->mp_subscript(s, slice);
|
|
Py_DECREF(slice);
|
|
return res;
|
|
}
|
|
|
|
return type_error("unsliceable object");
|
|
}
|
|
|
|
int
|
|
PySequence_SetItem(PyObject *s, Py_ssize_t i, PyObject *o)
|
|
{
|
|
PySequenceMethods *m;
|
|
|
|
if (s == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
|
|
m = s->ob_type->tp_as_sequence;
|
|
if (m && m->sq_ass_item) {
|
|
if (i < 0) {
|
|
if (m->sq_length) {
|
|
Py_ssize_t l = (*m->sq_length)(s);
|
|
if (l < 0)
|
|
return -1;
|
|
i += l;
|
|
}
|
|
}
|
|
return m->sq_ass_item(s, i, o);
|
|
}
|
|
|
|
type_error("object does not support item assignment");
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
PySequence_DelItem(PyObject *s, Py_ssize_t i)
|
|
{
|
|
PySequenceMethods *m;
|
|
|
|
if (s == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
|
|
m = s->ob_type->tp_as_sequence;
|
|
if (m && m->sq_ass_item) {
|
|
if (i < 0) {
|
|
if (m->sq_length) {
|
|
Py_ssize_t l = (*m->sq_length)(s);
|
|
if (l < 0)
|
|
return -1;
|
|
i += l;
|
|
}
|
|
}
|
|
return m->sq_ass_item(s, i, (PyObject *)NULL);
|
|
}
|
|
|
|
type_error("object doesn't support item deletion");
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
PySequence_SetSlice(PyObject *s, Py_ssize_t i1, Py_ssize_t i2, PyObject *o)
|
|
{
|
|
PySequenceMethods *m;
|
|
PyMappingMethods *mp;
|
|
|
|
if (s == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
|
|
m = s->ob_type->tp_as_sequence;
|
|
if (m && m->sq_ass_slice) {
|
|
if (i1 < 0 || i2 < 0) {
|
|
if (m->sq_length) {
|
|
Py_ssize_t l = (*m->sq_length)(s);
|
|
if (l < 0)
|
|
return -1;
|
|
if (i1 < 0)
|
|
i1 += l;
|
|
if (i2 < 0)
|
|
i2 += l;
|
|
}
|
|
}
|
|
return m->sq_ass_slice(s, i1, i2, o);
|
|
} else if ((mp = s->ob_type->tp_as_mapping) && mp->mp_ass_subscript) {
|
|
int res;
|
|
PyObject *slice = _PySlice_FromIndices(i1, i2);
|
|
if (!slice)
|
|
return -1;
|
|
res = mp->mp_ass_subscript(s, slice, o);
|
|
Py_DECREF(slice);
|
|
return res;
|
|
}
|
|
|
|
type_error("object doesn't support slice assignment");
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
PySequence_DelSlice(PyObject *s, Py_ssize_t i1, Py_ssize_t i2)
|
|
{
|
|
PySequenceMethods *m;
|
|
|
|
if (s == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
|
|
m = s->ob_type->tp_as_sequence;
|
|
if (m && m->sq_ass_slice) {
|
|
if (i1 < 0 || i2 < 0) {
|
|
if (m->sq_length) {
|
|
Py_ssize_t l = (*m->sq_length)(s);
|
|
if (l < 0)
|
|
return -1;
|
|
if (i1 < 0)
|
|
i1 += l;
|
|
if (i2 < 0)
|
|
i2 += l;
|
|
}
|
|
}
|
|
return m->sq_ass_slice(s, i1, i2, (PyObject *)NULL);
|
|
}
|
|
type_error("object doesn't support slice deletion");
|
|
return -1;
|
|
}
|
|
|
|
PyObject *
|
|
PySequence_Tuple(PyObject *v)
|
|
{
|
|
PyObject *it; /* iter(v) */
|
|
Py_ssize_t n; /* guess for result tuple size */
|
|
PyObject *result;
|
|
Py_ssize_t j;
|
|
|
|
if (v == NULL)
|
|
return null_error();
|
|
|
|
/* Special-case the common tuple and list cases, for efficiency. */
|
|
if (PyTuple_CheckExact(v)) {
|
|
/* Note that we can't know whether it's safe to return
|
|
a tuple *subclass* instance as-is, hence the restriction
|
|
to exact tuples here. In contrast, lists always make
|
|
a copy, so there's no need for exactness below. */
|
|
Py_INCREF(v);
|
|
return v;
|
|
}
|
|
if (PyList_Check(v))
|
|
return PyList_AsTuple(v);
|
|
|
|
/* Get iterator. */
|
|
it = PyObject_GetIter(v);
|
|
if (it == NULL)
|
|
return NULL;
|
|
|
|
/* Guess result size and allocate space. */
|
|
n = _PyObject_LengthHint(v);
|
|
if (n < 0) {
|
|
if (!PyErr_ExceptionMatches(PyExc_TypeError) &&
|
|
!PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
|
Py_DECREF(it);
|
|
return NULL;
|
|
}
|
|
PyErr_Clear();
|
|
n = 10; /* arbitrary */
|
|
}
|
|
result = PyTuple_New(n);
|
|
if (result == NULL)
|
|
goto Fail;
|
|
|
|
/* Fill the tuple. */
|
|
for (j = 0; ; ++j) {
|
|
PyObject *item = PyIter_Next(it);
|
|
if (item == NULL) {
|
|
if (PyErr_Occurred())
|
|
goto Fail;
|
|
break;
|
|
}
|
|
if (j >= n) {
|
|
Py_ssize_t oldn = n;
|
|
/* The over-allocation strategy can grow a bit faster
|
|
than for lists because unlike lists the
|
|
over-allocation isn't permanent -- we reclaim
|
|
the excess before the end of this routine.
|
|
So, grow by ten and then add 25%.
|
|
*/
|
|
n += 10;
|
|
n += n >> 2;
|
|
if (n < oldn) {
|
|
/* Check for overflow */
|
|
PyErr_NoMemory();
|
|
Py_DECREF(item);
|
|
goto Fail;
|
|
}
|
|
if (_PyTuple_Resize(&result, n) != 0) {
|
|
Py_DECREF(item);
|
|
goto Fail;
|
|
}
|
|
}
|
|
PyTuple_SET_ITEM(result, j, item);
|
|
}
|
|
|
|
/* Cut tuple back if guess was too large. */
|
|
if (j < n &&
|
|
_PyTuple_Resize(&result, j) != 0)
|
|
goto Fail;
|
|
|
|
Py_DECREF(it);
|
|
return result;
|
|
|
|
Fail:
|
|
Py_XDECREF(result);
|
|
Py_DECREF(it);
|
|
return NULL;
|
|
}
|
|
|
|
PyObject *
|
|
PySequence_List(PyObject *v)
|
|
{
|
|
PyObject *result; /* result list */
|
|
PyObject *rv; /* return value from PyList_Extend */
|
|
|
|
if (v == NULL)
|
|
return null_error();
|
|
|
|
result = PyList_New(0);
|
|
if (result == NULL)
|
|
return NULL;
|
|
|
|
rv = _PyList_Extend((PyListObject *)result, v);
|
|
if (rv == NULL) {
|
|
Py_DECREF(result);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(rv);
|
|
return result;
|
|
}
|
|
|
|
PyObject *
|
|
PySequence_Fast(PyObject *v, const char *m)
|
|
{
|
|
PyObject *it;
|
|
|
|
if (v == NULL)
|
|
return null_error();
|
|
|
|
if (PyList_CheckExact(v) || PyTuple_CheckExact(v)) {
|
|
Py_INCREF(v);
|
|
return v;
|
|
}
|
|
|
|
it = PyObject_GetIter(v);
|
|
if (it == NULL) {
|
|
if (PyErr_ExceptionMatches(PyExc_TypeError))
|
|
return type_error(m);
|
|
return NULL;
|
|
}
|
|
|
|
v = PySequence_List(it);
|
|
Py_DECREF(it);
|
|
|
|
return v;
|
|
}
|
|
|
|
/* Iterate over seq. Result depends on the operation:
|
|
PY_ITERSEARCH_COUNT: -1 if error, else # of times obj appears in seq.
|
|
PY_ITERSEARCH_INDEX: 0-based index of first occurence of obj in seq;
|
|
set ValueError and return -1 if none found; also return -1 on error.
|
|
Py_ITERSEARCH_CONTAINS: return 1 if obj in seq, else 0; -1 on error.
|
|
*/
|
|
Py_ssize_t
|
|
_PySequence_IterSearch(PyObject *seq, PyObject *obj, int operation)
|
|
{
|
|
Py_ssize_t n;
|
|
int wrapped; /* for PY_ITERSEARCH_INDEX, true iff n wrapped around */
|
|
PyObject *it; /* iter(seq) */
|
|
|
|
if (seq == NULL || obj == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
|
|
it = PyObject_GetIter(seq);
|
|
if (it == NULL) {
|
|
type_error("iterable argument required");
|
|
return -1;
|
|
}
|
|
|
|
n = wrapped = 0;
|
|
for (;;) {
|
|
int cmp;
|
|
PyObject *item = PyIter_Next(it);
|
|
if (item == NULL) {
|
|
if (PyErr_Occurred())
|
|
goto Fail;
|
|
break;
|
|
}
|
|
|
|
cmp = PyObject_RichCompareBool(obj, item, Py_EQ);
|
|
Py_DECREF(item);
|
|
if (cmp < 0)
|
|
goto Fail;
|
|
if (cmp > 0) {
|
|
switch (operation) {
|
|
case PY_ITERSEARCH_COUNT:
|
|
++n;
|
|
if (n <= 0) {
|
|
/* XXX(nnorwitz): int means ssize_t */
|
|
PyErr_SetString(PyExc_OverflowError,
|
|
"count exceeds C int size");
|
|
goto Fail;
|
|
}
|
|
break;
|
|
|
|
case PY_ITERSEARCH_INDEX:
|
|
if (wrapped) {
|
|
/* XXX(nnorwitz): int means ssize_t */
|
|
PyErr_SetString(PyExc_OverflowError,
|
|
"index exceeds C int size");
|
|
goto Fail;
|
|
}
|
|
goto Done;
|
|
|
|
case PY_ITERSEARCH_CONTAINS:
|
|
n = 1;
|
|
goto Done;
|
|
|
|
default:
|
|
assert(!"unknown operation");
|
|
}
|
|
}
|
|
|
|
if (operation == PY_ITERSEARCH_INDEX) {
|
|
++n;
|
|
if (n <= 0)
|
|
wrapped = 1;
|
|
}
|
|
}
|
|
|
|
if (operation != PY_ITERSEARCH_INDEX)
|
|
goto Done;
|
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"sequence.index(x): x not in sequence");
|
|
/* fall into failure code */
|
|
Fail:
|
|
n = -1;
|
|
/* fall through */
|
|
Done:
|
|
Py_DECREF(it);
|
|
return n;
|
|
|
|
}
|
|
|
|
/* Return # of times o appears in s. */
|
|
Py_ssize_t
|
|
PySequence_Count(PyObject *s, PyObject *o)
|
|
{
|
|
return _PySequence_IterSearch(s, o, PY_ITERSEARCH_COUNT);
|
|
}
|
|
|
|
/* Return -1 if error; 1 if ob in seq; 0 if ob not in seq.
|
|
* Use sq_contains if possible, else defer to _PySequence_IterSearch().
|
|
*/
|
|
int
|
|
PySequence_Contains(PyObject *seq, PyObject *ob)
|
|
{
|
|
Py_ssize_t result;
|
|
if (PyType_HasFeature(seq->ob_type, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {
|
|
PySequenceMethods *sqm = seq->ob_type->tp_as_sequence;
|
|
if (sqm != NULL && sqm->sq_contains != NULL)
|
|
return (*sqm->sq_contains)(seq, ob);
|
|
}
|
|
result = _PySequence_IterSearch(seq, ob, PY_ITERSEARCH_CONTAINS);
|
|
return Py_SAFE_DOWNCAST(result, Py_ssize_t, int);
|
|
}
|
|
|
|
/* Backwards compatibility */
|
|
#undef PySequence_In
|
|
int
|
|
PySequence_In(PyObject *w, PyObject *v)
|
|
{
|
|
return PySequence_Contains(w, v);
|
|
}
|
|
|
|
Py_ssize_t
|
|
PySequence_Index(PyObject *s, PyObject *o)
|
|
{
|
|
return _PySequence_IterSearch(s, o, PY_ITERSEARCH_INDEX);
|
|
}
|
|
|
|
/* Operations on mappings */
|
|
|
|
int
|
|
PyMapping_Check(PyObject *o)
|
|
{
|
|
if (o && PyInstance_Check(o))
|
|
return PyObject_HasAttrString(o, "__getitem__");
|
|
|
|
return o && o->ob_type->tp_as_mapping &&
|
|
o->ob_type->tp_as_mapping->mp_subscript &&
|
|
!(o->ob_type->tp_as_sequence &&
|
|
o->ob_type->tp_as_sequence->sq_slice);
|
|
}
|
|
|
|
Py_ssize_t
|
|
PyMapping_Size(PyObject *o)
|
|
{
|
|
PyMappingMethods *m;
|
|
|
|
if (o == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
|
|
m = o->ob_type->tp_as_mapping;
|
|
if (m && m->mp_length)
|
|
return m->mp_length(o);
|
|
|
|
type_error("len() of unsized object");
|
|
return -1;
|
|
}
|
|
|
|
#undef PyMapping_Length
|
|
Py_ssize_t
|
|
PyMapping_Length(PyObject *o)
|
|
{
|
|
return PyMapping_Size(o);
|
|
}
|
|
#define PyMapping_Length PyMapping_Size
|
|
|
|
PyObject *
|
|
PyMapping_GetItemString(PyObject *o, char *key)
|
|
{
|
|
PyObject *okey, *r;
|
|
|
|
if (key == NULL)
|
|
return null_error();
|
|
|
|
okey = PyString_FromString(key);
|
|
if (okey == NULL)
|
|
return NULL;
|
|
r = PyObject_GetItem(o, okey);
|
|
Py_DECREF(okey);
|
|
return r;
|
|
}
|
|
|
|
int
|
|
PyMapping_SetItemString(PyObject *o, char *key, PyObject *value)
|
|
{
|
|
PyObject *okey;
|
|
int r;
|
|
|
|
if (key == NULL) {
|
|
null_error();
|
|
return -1;
|
|
}
|
|
|
|
okey = PyString_FromString(key);
|
|
if (okey == NULL)
|
|
return -1;
|
|
r = PyObject_SetItem(o, okey, value);
|
|
Py_DECREF(okey);
|
|
return r;
|
|
}
|
|
|
|
int
|
|
PyMapping_HasKeyString(PyObject *o, char *key)
|
|
{
|
|
PyObject *v;
|
|
|
|
v = PyMapping_GetItemString(o, key);
|
|
if (v) {
|
|
Py_DECREF(v);
|
|
return 1;
|
|
}
|
|
PyErr_Clear();
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
PyMapping_HasKey(PyObject *o, PyObject *key)
|
|
{
|
|
PyObject *v;
|
|
|
|
v = PyObject_GetItem(o, key);
|
|
if (v) {
|
|
Py_DECREF(v);
|
|
return 1;
|
|
}
|
|
PyErr_Clear();
|
|
return 0;
|
|
}
|
|
|
|
/* Operations on callable objects */
|
|
|
|
/* XXX PyCallable_Check() is in object.c */
|
|
|
|
PyObject *
|
|
PyObject_CallObject(PyObject *o, PyObject *a)
|
|
{
|
|
return PyEval_CallObjectWithKeywords(o, a, NULL);
|
|
}
|
|
|
|
PyObject *
|
|
PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
|
|
{
|
|
ternaryfunc call;
|
|
|
|
if ((call = func->ob_type->tp_call) != NULL) {
|
|
PyObject *result = (*call)(func, arg, kw);
|
|
if (result == NULL && !PyErr_Occurred())
|
|
PyErr_SetString(
|
|
PyExc_SystemError,
|
|
"NULL result without error in PyObject_Call");
|
|
return result;
|
|
}
|
|
PyErr_Format(PyExc_TypeError, "'%s' object is not callable",
|
|
func->ob_type->tp_name);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject*
|
|
call_function_tail(PyObject *callable, PyObject *args)
|
|
{
|
|
PyObject *retval;
|
|
|
|
if (args == NULL)
|
|
return NULL;
|
|
|
|
if (!PyTuple_Check(args)) {
|
|
PyObject *a;
|
|
|
|
a = PyTuple_New(1);
|
|
if (a == NULL) {
|
|
Py_DECREF(args);
|
|
return NULL;
|
|
}
|
|
PyTuple_SET_ITEM(a, 0, args);
|
|
args = a;
|
|
}
|
|
retval = PyObject_Call(callable, args, NULL);
|
|
|
|
Py_DECREF(args);
|
|
|
|
return retval;
|
|
}
|
|
|
|
PyObject *
|
|
PyObject_CallFunction(PyObject *callable, char *format, ...)
|
|
{
|
|
va_list va;
|
|
PyObject *args;
|
|
|
|
if (callable == NULL)
|
|
return null_error();
|
|
|
|
if (format && *format) {
|
|
va_start(va, format);
|
|
args = Py_VaBuildValue(format, va);
|
|
va_end(va);
|
|
}
|
|
else
|
|
args = PyTuple_New(0);
|
|
|
|
return call_function_tail(callable, args);
|
|
}
|
|
|
|
PyObject *
|
|
_PyObject_CallFunction_SizeT(PyObject *callable, char *format, ...)
|
|
{
|
|
va_list va;
|
|
PyObject *args;
|
|
|
|
if (callable == NULL)
|
|
return null_error();
|
|
|
|
if (format && *format) {
|
|
va_start(va, format);
|
|
args = _Py_VaBuildValue_SizeT(format, va);
|
|
va_end(va);
|
|
}
|
|
else
|
|
args = PyTuple_New(0);
|
|
|
|
return call_function_tail(callable, args);
|
|
}
|
|
|
|
PyObject *
|
|
PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
|
|
{
|
|
va_list va;
|
|
PyObject *args;
|
|
PyObject *func = NULL;
|
|
PyObject *retval = NULL;
|
|
|
|
if (o == NULL || name == NULL)
|
|
return null_error();
|
|
|
|
func = PyObject_GetAttrString(o, name);
|
|
if (func == NULL) {
|
|
PyErr_SetString(PyExc_AttributeError, name);
|
|
return 0;
|
|
}
|
|
|
|
if (!PyCallable_Check(func)) {
|
|
type_error("call of non-callable attribute");
|
|
goto exit;
|
|
}
|
|
|
|
if (format && *format) {
|
|
va_start(va, format);
|
|
args = Py_VaBuildValue(format, va);
|
|
va_end(va);
|
|
}
|
|
else
|
|
args = PyTuple_New(0);
|
|
|
|
retval = call_function_tail(func, args);
|
|
|
|
exit:
|
|
/* args gets consumed in call_function_tail */
|
|
Py_XDECREF(func);
|
|
|
|
return retval;
|
|
}
|
|
|
|
PyObject *
|
|
_PyObject_CallMethod_SizeT(PyObject *o, char *name, char *format, ...)
|
|
{
|
|
va_list va;
|
|
PyObject *args;
|
|
PyObject *func = NULL;
|
|
PyObject *retval = NULL;
|
|
|
|
if (o == NULL || name == NULL)
|
|
return null_error();
|
|
|
|
func = PyObject_GetAttrString(o, name);
|
|
if (func == NULL) {
|
|
PyErr_SetString(PyExc_AttributeError, name);
|
|
return 0;
|
|
}
|
|
|
|
if (!PyCallable_Check(func)) {
|
|
type_error("call of non-callable attribute");
|
|
goto exit;
|
|
}
|
|
|
|
if (format && *format) {
|
|
va_start(va, format);
|
|
args = _Py_VaBuildValue_SizeT(format, va);
|
|
va_end(va);
|
|
}
|
|
else
|
|
args = PyTuple_New(0);
|
|
|
|
retval = call_function_tail(func, args);
|
|
|
|
exit:
|
|
/* args gets consumed in call_function_tail */
|
|
Py_XDECREF(func);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
static PyObject *
|
|
objargs_mktuple(va_list va)
|
|
{
|
|
int i, n = 0;
|
|
va_list countva;
|
|
PyObject *result, *tmp;
|
|
|
|
#ifdef VA_LIST_IS_ARRAY
|
|
memcpy(countva, va, sizeof(va_list));
|
|
#else
|
|
#ifdef __va_copy
|
|
__va_copy(countva, va);
|
|
#else
|
|
countva = va;
|
|
#endif
|
|
#endif
|
|
|
|
while (((PyObject *)va_arg(countva, PyObject *)) != NULL)
|
|
++n;
|
|
result = PyTuple_New(n);
|
|
if (result != NULL && n > 0) {
|
|
for (i = 0; i < n; ++i) {
|
|
tmp = (PyObject *)va_arg(va, PyObject *);
|
|
PyTuple_SET_ITEM(result, i, tmp);
|
|
Py_INCREF(tmp);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
PyObject *
|
|
PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
|
|
{
|
|
PyObject *args, *tmp;
|
|
va_list vargs;
|
|
|
|
if (callable == NULL || name == NULL)
|
|
return null_error();
|
|
|
|
callable = PyObject_GetAttr(callable, name);
|
|
if (callable == NULL)
|
|
return NULL;
|
|
|
|
/* count the args */
|
|
va_start(vargs, name);
|
|
args = objargs_mktuple(vargs);
|
|
va_end(vargs);
|
|
if (args == NULL) {
|
|
Py_DECREF(callable);
|
|
return NULL;
|
|
}
|
|
tmp = PyObject_Call(callable, args, NULL);
|
|
Py_DECREF(args);
|
|
Py_DECREF(callable);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
PyObject *
|
|
PyObject_CallFunctionObjArgs(PyObject *callable, ...)
|
|
{
|
|
PyObject *args, *tmp;
|
|
va_list vargs;
|
|
|
|
if (callable == NULL)
|
|
return null_error();
|
|
|
|
/* count the args */
|
|
va_start(vargs, callable);
|
|
args = objargs_mktuple(vargs);
|
|
va_end(vargs);
|
|
if (args == NULL)
|
|
return NULL;
|
|
tmp = PyObject_Call(callable, args, NULL);
|
|
Py_DECREF(args);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
|
|
/* isinstance(), issubclass() */
|
|
|
|
/* abstract_get_bases() has logically 4 return states, with a sort of 0th
|
|
* state that will almost never happen.
|
|
*
|
|
* 0. creating the __bases__ static string could get a MemoryError
|
|
* 1. getattr(cls, '__bases__') could raise an AttributeError
|
|
* 2. getattr(cls, '__bases__') could raise some other exception
|
|
* 3. getattr(cls, '__bases__') could return a tuple
|
|
* 4. getattr(cls, '__bases__') could return something other than a tuple
|
|
*
|
|
* Only state #3 is a non-error state and only it returns a non-NULL object
|
|
* (it returns the retrieved tuple).
|
|
*
|
|
* Any raised AttributeErrors are masked by clearing the exception and
|
|
* returning NULL. If an object other than a tuple comes out of __bases__,
|
|
* then again, the return value is NULL. So yes, these two situations
|
|
* produce exactly the same results: NULL is returned and no error is set.
|
|
*
|
|
* If some exception other than AttributeError is raised, then NULL is also
|
|
* returned, but the exception is not cleared. That's because we want the
|
|
* exception to be propagated along.
|
|
*
|
|
* Callers are expected to test for PyErr_Occurred() when the return value
|
|
* is NULL to decide whether a valid exception should be propagated or not.
|
|
* When there's no exception to propagate, it's customary for the caller to
|
|
* set a TypeError.
|
|
*/
|
|
static PyObject *
|
|
abstract_get_bases(PyObject *cls)
|
|
{
|
|
static PyObject *__bases__ = NULL;
|
|
PyObject *bases;
|
|
|
|
if (__bases__ == NULL) {
|
|
__bases__ = PyString_FromString("__bases__");
|
|
if (__bases__ == NULL)
|
|
return NULL;
|
|
}
|
|
bases = PyObject_GetAttr(cls, __bases__);
|
|
if (bases == NULL) {
|
|
if (PyErr_ExceptionMatches(PyExc_AttributeError))
|
|
PyErr_Clear();
|
|
return NULL;
|
|
}
|
|
if (!PyTuple_Check(bases)) {
|
|
Py_DECREF(bases);
|
|
return NULL;
|
|
}
|
|
return bases;
|
|
}
|
|
|
|
|
|
static int
|
|
abstract_issubclass(PyObject *derived, PyObject *cls)
|
|
{
|
|
PyObject *bases;
|
|
Py_ssize_t i, n;
|
|
int r = 0;
|
|
|
|
|
|
if (derived == cls)
|
|
return 1;
|
|
|
|
if (PyTuple_Check(cls)) {
|
|
/* Not a general sequence -- that opens up the road to
|
|
recursion and stack overflow. */
|
|
n = PyTuple_GET_SIZE(cls);
|
|
for (i = 0; i < n; i++) {
|
|
if (derived == PyTuple_GET_ITEM(cls, i))
|
|
return 1;
|
|
}
|
|
}
|
|
bases = abstract_get_bases(derived);
|
|
if (bases == NULL) {
|
|
if (PyErr_Occurred())
|
|
return -1;
|
|
return 0;
|
|
}
|
|
n = PyTuple_GET_SIZE(bases);
|
|
for (i = 0; i < n; i++) {
|
|
r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls);
|
|
if (r != 0)
|
|
break;
|
|
}
|
|
|
|
Py_DECREF(bases);
|
|
|
|
return r;
|
|
}
|
|
|
|
static int
|
|
check_class(PyObject *cls, const char *error)
|
|
{
|
|
PyObject *bases = abstract_get_bases(cls);
|
|
if (bases == NULL) {
|
|
/* Do not mask errors. */
|
|
if (!PyErr_Occurred())
|
|
PyErr_SetString(PyExc_TypeError, error);
|
|
return 0;
|
|
}
|
|
Py_DECREF(bases);
|
|
return -1;
|
|
}
|
|
|
|
static int
|
|
recursive_isinstance(PyObject *inst, PyObject *cls, int recursion_depth)
|
|
{
|
|
PyObject *icls;
|
|
static PyObject *__class__ = NULL;
|
|
int retval = 0;
|
|
|
|
if (__class__ == NULL) {
|
|
__class__ = PyString_FromString("__class__");
|
|
if (__class__ == NULL)
|
|
return -1;
|
|
}
|
|
|
|
if (PyType_Check(cls)) {
|
|
retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);
|
|
if (retval == 0) {
|
|
PyObject *c = PyObject_GetAttr(inst, __class__);
|
|
if (c == NULL) {
|
|
PyErr_Clear();
|
|
}
|
|
else {
|
|
if (c != (PyObject *)(inst->ob_type) &&
|
|
PyType_Check(c))
|
|
retval = PyType_IsSubtype(
|
|
(PyTypeObject *)c,
|
|
(PyTypeObject *)cls);
|
|
Py_DECREF(c);
|
|
}
|
|
}
|
|
}
|
|
else if (PyTuple_Check(cls)) {
|
|
Py_ssize_t i, n;
|
|
|
|
if (!recursion_depth) {
|
|
PyErr_SetString(PyExc_RuntimeError,
|
|
"nest level of tuple too deep");
|
|
return -1;
|
|
}
|
|
|
|
n = PyTuple_GET_SIZE(cls);
|
|
for (i = 0; i < n; i++) {
|
|
retval = recursive_isinstance(
|
|
inst,
|
|
PyTuple_GET_ITEM(cls, i),
|
|
recursion_depth-1);
|
|
if (retval != 0)
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
if (!check_class(cls,
|
|
"isinstance() arg 2 must be a class, type,"
|
|
" or tuple of classes and types"))
|
|
return -1;
|
|
icls = PyObject_GetAttr(inst, __class__);
|
|
if (icls == NULL) {
|
|
PyErr_Clear();
|
|
retval = 0;
|
|
}
|
|
else {
|
|
retval = abstract_issubclass(icls, cls);
|
|
Py_DECREF(icls);
|
|
}
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
int
|
|
PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
|
{
|
|
return recursive_isinstance(inst, cls, Py_GetRecursionLimit());
|
|
}
|
|
|
|
static int
|
|
recursive_issubclass(PyObject *derived, PyObject *cls, int recursion_depth)
|
|
{
|
|
int retval;
|
|
|
|
{
|
|
if (!check_class(derived,
|
|
"issubclass() arg 1 must be a class"))
|
|
return -1;
|
|
|
|
if (PyTuple_Check(cls)) {
|
|
Py_ssize_t i;
|
|
Py_ssize_t n = PyTuple_GET_SIZE(cls);
|
|
|
|
if (!recursion_depth) {
|
|
PyErr_SetString(PyExc_RuntimeError,
|
|
"nest level of tuple too deep");
|
|
return -1;
|
|
}
|
|
for (i = 0; i < n; ++i) {
|
|
retval = recursive_issubclass(
|
|
derived,
|
|
PyTuple_GET_ITEM(cls, i),
|
|
recursion_depth-1);
|
|
if (retval != 0) {
|
|
/* either found it, or got an error */
|
|
return retval;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
else {
|
|
if (!check_class(cls,
|
|
"issubclass() arg 2 must be a class"
|
|
" or tuple of classes"))
|
|
return -1;
|
|
}
|
|
|
|
retval = abstract_issubclass(derived, cls);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
int
|
|
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
|
{
|
|
return recursive_issubclass(derived, cls, Py_GetRecursionLimit());
|
|
}
|
|
|
|
|
|
PyObject *
|
|
PyObject_GetIter(PyObject *o)
|
|
{
|
|
PyTypeObject *t = o->ob_type;
|
|
getiterfunc f = NULL;
|
|
if (PyType_HasFeature(t, Py_TPFLAGS_HAVE_ITER))
|
|
f = t->tp_iter;
|
|
if (f == NULL) {
|
|
if (PySequence_Check(o))
|
|
return PySeqIter_New(o);
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"iteration over non-sequence");
|
|
return NULL;
|
|
}
|
|
else {
|
|
PyObject *res = (*f)(o);
|
|
if (res != NULL && !PyIter_Check(res)) {
|
|
PyErr_Format(PyExc_TypeError,
|
|
"iter() returned non-iterator "
|
|
"of type '%.100s'",
|
|
res->ob_type->tp_name);
|
|
Py_DECREF(res);
|
|
res = NULL;
|
|
}
|
|
return res;
|
|
}
|
|
}
|
|
|
|
/* Return next item.
|
|
* If an error occurs, return NULL. PyErr_Occurred() will be true.
|
|
* If the iteration terminates normally, return NULL and clear the
|
|
* PyExc_StopIteration exception (if it was set). PyErr_Occurred()
|
|
* will be false.
|
|
* Else return the next object. PyErr_Occurred() will be false.
|
|
*/
|
|
PyObject *
|
|
PyIter_Next(PyObject *iter)
|
|
{
|
|
PyObject *result;
|
|
assert(PyIter_Check(iter));
|
|
result = (*iter->ob_type->tp_iternext)(iter);
|
|
if (result == NULL &&
|
|
PyErr_Occurred() &&
|
|
PyErr_ExceptionMatches(PyExc_StopIteration))
|
|
PyErr_Clear();
|
|
return result;
|
|
}
|