From montanaro@users.sourceforge.net Fri Jun 1 17:25:40 2001 From: montanaro@users.sourceforge.net (Skip Montanaro) Date: Fri, 01 Jun 2001 09:25:40 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib httplib.py,1.34,1.35 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv4026 Modified Files: httplib.py Log Message: more public symbols for __all__ Index: httplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/httplib.py,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -r1.34 -r1.35 *** httplib.py 2001/04/13 14:57:08 1.34 --- httplib.py 2001/06/01 16:25:38 1.35 *************** *** 75,79 **** from StringIO import StringIO ! __all__ = ["HTTP"] HTTP_PORT = 80 --- 75,84 ---- from StringIO import StringIO ! __all__ = ["HTTP", "HTTPResponse", "HTTPConnection", "HTTPSConnection", ! "HTTPException", "NotConnected", "UnknownProtocol", ! "UnknownTransferEncoding", "IllegalKeywordArgument", ! "UnimplementedFileMode", "IncompleteRead", ! "ImproperConnectionState", "CannotSendRequest", "CannotSendHeader", ! "ResponseNotReady", "BadStatusLine", "error"] HTTP_PORT = 80 From tim_one@users.sourceforge.net Sat Jun 2 06:27:21 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Jun 2001 22:27:21 -0700 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.178,1.179 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv8127/python/dist/src/Misc Modified Files: NEWS Log Message: New collision resolution scheme: no polynomials, simpler, faster, less code, less memory. Tests have uncovered no drawbacks. Christian and Vladimir are the other two people who have burned many brain cells on the dict code in recent years, and they like the approach too, so I'm checking it in without further ado. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.178 retrieving revision 1.179 diff -C2 -r1.178 -r1.179 *** NEWS 2001/05/28 22:30:07 1.178 --- NEWS 2001/06/02 05:27:19 1.179 *************** *** 16,20 **** casing of Unicode object return values was dropped (Unicode objects were auto-magically converted to string using the default encoding). ! Both methods will now return whatever the codec in charge of the requested encoding returns as object, e.g. Unicode codecs will --- 16,20 ---- casing of Unicode object return values was dropped (Unicode objects were auto-magically converted to string using the default encoding). ! Both methods will now return whatever the codec in charge of the requested encoding returns as object, e.g. Unicode codecs will *************** *** 117,127 **** values mutated the dicts. Making the code bulletproof slowed it down. ! - Collisions in dicts now use polynomial division instead of multiplication ! to generate the probe sequence, following an idea of Christian Tismer's. ! This allows all bits of the hash code to come into play. It should have ! little or no effect on speed in ordinary cases, but can help dramatically ! in bad cases. For example, looking up every key in a dict d with ! d.keys() = [i << 16 for i in range(20000)] is approximately 500x faster ! now. Library --- 117,125 ---- values mutated the dicts. Making the code bulletproof slowed it down. ! - Collisions in dicts are resolved via a new approach, which can help ! dramatically in bad cases. For example, looking up every key in a dict ! d with d.keys() = [i << 16 for i in range(20000)] is approximately 500x ! faster now. Thanks to Christian Tismer for pointing out the cause and ! the nature of an effective cure (last December! better late than never). Library From tim_one@users.sourceforge.net Sat Jun 2 06:27:21 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Jun 2001 22:27:21 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.96,2.97 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv8127/python/dist/src/Objects Modified Files: dictobject.c Log Message: New collision resolution scheme: no polynomials, simpler, faster, less code, less memory. Tests have uncovered no drawbacks. Christian and Vladimir are the other two people who have burned many brain cells on the dict code in recent years, and they like the approach too, so I'm checking it in without further ado. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.96 retrieving revision 2.97 diff -C2 -r2.96 -r2.97 *** dictobject.c 2001/05/27 07:39:22 2.96 --- dictobject.c 2001/06/02 05:27:19 2.97 *************** *** 4,122 **** #include "Python.h" ! ! /* ! * MINSIZE is the minimum size of a dictionary. This many slots are * allocated directly in the dict object (in the ma_smalltable member). ! * This must be a power of 2, and the first entry in the polys[] vector must ! * match. */ #define MINSIZE 8 ! /* define this out if you don't want conversion statistics on exit */ #undef SHOW_CONVERSION_COUNTS /* ! Table of irreducible polynomials to efficiently cycle through ! GF(2^n)-{0}, 2<=n<=30. A table size is always a power of 2. ! For a table size of 2**i, the polys entry is 2**i + j for some j in 1 thru ! 2**i-1 inclusive. The polys[] entries here happen to add in the smallest j ! values "that work". Work means this: given any integer k in 1 thru 2**i-1 ! inclusive, a poly works if & only if repeating this code: ! print k ! k <<= 1 ! if k >= 2**i: ! k ^= poly ! prints every integer in 1 thru 2**i-1 inclusive exactly once before printing ! k a second time. Theory can be used to find such polys efficiently, but the ! operational defn. of "works" is sufficient to find them in reasonable time ! via brute force program (hint: any poly that has an even number of 1 bits ! cannot work; ditto any poly with low bit 0; exploit those). ! ! Some major subtleties: Most hash schemes depend on having a "good" hash ! function, in the sense of simulating randomness. Python doesn't: some of ! its hash functions are trivial, such as hash(i) == i for ints i (excepting ! i == -1, because -1 is the "error occurred" return value from tp_hash). ! ! This isn't necessarily bad! To the contrary, that our hash tables are powers ! of 2 in size, and that we take the low-order bits as the initial table index, ! means that there are no collisions at all for dicts indexed by a contiguous ! range of ints. This is "better than random" behavior, and that's very ! desirable. ! ! On the other hand, when collisions occur, the tendency to fill contiguous ! slices of the hash table makes a good collision resolution strategy crucial; ! e.g., linear probing is right out. ! ! Reimer Behrends contributed the idea of using a polynomial-based approach, ! using repeated multiplication by x in GF(2**n) where a polynomial is chosen ! such that x is a primitive root. This visits every table location exactly ! once, and the sequence of locations probed is highly non-linear. ! ! The same is also largely true of quadratic probing for power-of-2 tables, of ! the specific ! ! (i + comb(1, 2)) mod size ! (i + comb(2, 2)) mod size ! (i + comb(3, 2)) mod size ! (i + comb(4, 2)) mod size ! ... ! (i + comb(j, 2)) mod size ! ! flavor. The polynomial approach "scrambles" the probe indices better, but ! more importantly allows to get *some* additional bits of the hash code into ! play via computing the initial increment, thus giving a weak form of double ! hashing. Quadratic probing cannot be extended that way (the first probe ! offset must be 1, the second 3, the third 6, etc). ! ! Christian Tismer later contributed the idea of using polynomial division ! instead of multiplication. The problem is that the multiplicative method ! can't get *all* the bits of the hash code into play without expensive ! computations that slow down the initial index and/or initial increment ! computation. For a set of keys like [i << 16 for i in range(20000)], under ! the multiplicative method the initial index and increment were the same for ! all keys, so every key followed exactly the same probe sequence, and so ! this degenerated into a (very slow) linear search. The division method uses ! all the bits of the hash code naturally in the increment, although it *may* ! visit locations more than once until such time as all the high bits of the ! increment have been shifted away. It's also impossible to tell in advance ! whether incr is congruent to 0 modulo poly, so each iteration of the loop has ! to guard against incr becoming 0. These are minor costs, as we usually don't ! get into the probe loop, and when we do we usually get out on its first ! iteration. */ - static long polys[] = { - /* 4 + 3, */ /* first active entry if MINSIZE == 4 */ - 8 + 3, /* first active entry if MINSIZE == 8 */ - 16 + 3, - 32 + 5, - 64 + 3, - 128 + 3, - 256 + 29, - 512 + 17, - 1024 + 9, - 2048 + 5, - 4096 + 83, - 8192 + 27, - 16384 + 43, - 32768 + 3, - 65536 + 45, - 131072 + 9, - 262144 + 39, - 524288 + 39, - 1048576 + 9, - 2097152 + 5, - 4194304 + 3, - 8388608 + 33, - 16777216 + 27, - 33554432 + 9, - 67108864 + 71, - 134217728 + 39, - 268435456 + 9, - 536870912 + 5, - 1073741824 + 83 - /* 2147483648 + 9 -- if we ever boost this to unsigned long */ - }; - /* Object used as dummy key to fill deleted entries */ static PyObject *dummy; /* Initialized by first call to newdictobject() */ --- 4,117 ---- #include "Python.h" ! /* MINSIZE is the minimum size of a dictionary. This many slots are * allocated directly in the dict object (in the ma_smalltable member). ! * It must be a power of 2, and at least 4. 8 allows dicts with no more than ! * 5 active entries to live in ma_smalltable (and so avoid an additional ! * malloc); instrumentation suggested this suffices for the majority of ! * dicts (consisting mostly of usually-small instance dicts and usually-small ! * dicts created to pass keyword arguments). */ #define MINSIZE 8 ! /* Define this out if you don't want conversion statistics on exit. */ #undef SHOW_CONVERSION_COUNTS + /* See large comment block below. This must be >= 1. */ + #define PERTURB_SHIFT 5 + /* ! Major subtleties ahead: Most hash schemes depend on having a "good" hash ! function, in the sense of simulating randomness. Python doesn't: its most ! important hash functions (for strings and ints) are very regular in common ! cases: ! ! >>> map(hash, (0, 1, 2, 3)) ! [0, 1, 2, 3] ! >>> map(hash, ("namea", "nameb", "namec", "named")) ! [-1658398457, -1658398460, -1658398459, -1658398462] ! >>> ! ! This isn't necessarily bad! To the contrary, in a table of size 2**i, taking ! the low-order i bits as the initial table index is extremely fast, and there ! are no collisions at all for dicts indexed by a contiguous range of ints. ! The same is approximately true when keys are "consecutive" strings. So this ! gives better-than-random behavior in common cases, and that's very desirable. ! ! OTOH, when collisions occur, the tendency to fill contiguous slices of the ! hash table makes a good collision resolution strategy crucial. Taking only ! the last i bits of the hash code is also vulnerable: for example, consider ! [i << 16 for i in range(20000)] as a set of keys. Since ints are their own ! hash codes, and this fits in a dict of size 2**15, the last 15 bits of every ! hash code are all 0: they *all* map to the same table index. ! ! But catering to unusual cases should not slow the usual ones, so we just take ! the last i bits anyway. It's up to collision resolution to do the rest. If ! we *usually* find the key we're looking for on the first try (and, it turns ! out, we usually do -- the table load factor is kept under 2/3, so the odds ! are solidly in our favor), then it makes best sense to keep the initial index ! computation dirt cheap. ! ! The first half of collision resolution is to visit table indices via this ! recurrence: ! ! j = ((5*j) + 1) mod 2**i ! ! For any initial j in range(2**i), repeating that 2**i times generates each ! int in range(2**i) exactly once (see any text on random-number generation for ! proof). By itself, this doesn't help much: like linear probing (setting ! j += 1, or j -= 1, on each loop trip), it scans the table entries in a fixed ! order. This would be bad, except that's not the only thing we do, and it's ! actually *good* in the common cases where hash keys are consecutive. In an ! example that's really too small to make this entirely clear, for a table of ! size 2**3 the order of indices is: ! ! 0 -> 1 -> 6 -> 7 -> 4 -> 5 -> 2 -> 3 -> 0 [and here it's repeating] ! ! If two things come in at index 5, the first place we look after is index 2, ! not 6, so if another comes in at index 6 the collision at 5 didn't hurt it. ! Linear probing is deadly in this case because there the fixed probe order ! is the *same* as the order consecutive keys are likely to arrive. But it's ! extremely unlikely hash codes will follow a 5*j+1 recurrence by accident, ! and certain that consecutive hash codes do not. ! ! The other half of the strategy is to get the other bits of the hash code ! into play. This is done by initializing a (unsigned) vrbl "perturb" to the ! full hash code, and changing the recurrence to: ! ! j = (5*j) + 1 + perturb; ! perturb >>= PERTURB_SHIFT; ! use j % 2**i as the next table index; ! ! Now the probe sequence depends (eventually) on every bit in the hash code, ! and the pseudo-scrambling property of recurring on 5*j+1 is more valuable, ! because it quickly magnifies small differences in the bits that didn't affect ! the initial index. Note that because perturb is unsigned, if the recurrence ! is executed often enough perturb eventually becomes and remains 0. At that ! point (very rarely reached) the recurrence is on (just) 5*j+1 again, and ! that's certain to find an empty slot eventually (since it generates every int ! in range(2**i), and we make sure there's always at least one empty slot). ! ! Selecting a good value for PERTURB_SHIFT is a balancing act. You want it ! small so that the high bits of the hash code continue to affect the probe ! sequence across iterations; but you want it large so that in really bad cases ! the high-order hash bits have an effect on early iterations. 5 was "the ! best" in minimizing total collisions across experiments Tim Peters ran (on ! both normal and pathological cases), but 4 and 6 weren't significantly worse. ! ! Historical: Reimer Behrends contributed the idea of using a polynomial-based ! approach, using repeated multiplication by x in GF(2**n) where an irreducible ! polynomial for each table size was chosen such that x was a primitive root. ! Christian Tismer later extended that to use division by x instead, as an ! efficient way to get the high bits of the hash code into play. This scheme ! also gave excellent collision statistics, but was more expensive: two ! if-tests were required inside the loop; computing "the next" index took about ! the same number of operations but without as much potential parallelism ! (e.g., computing 5*j can go on at the same time as computing 1+perturb in the ! above, and then shifting perturb can be done while the table index is being ! masked); and the dictobject struct required a member to hold the table's ! polynomial. In Tim's experiments the current scheme ran faster, produced ! equally good collision statistics, needed less code & used less memory. */ /* Object used as dummy key to fill deleted entries */ static PyObject *dummy; /* Initialized by first call to newdictobject() */ *************** *** 169,173 **** int ma_used; /* # Active */ int ma_size; /* total # slots in ma_table */ - int ma_poly; /* appopriate entry from polys vector */ /* ma_table points to ma_smalltable for small tables, else to * additional malloc'ed memory. ma_table is never NULL! This rule --- 164,167 ---- *************** *** 203,208 **** (mp)->ma_size = MINSIZE; \ (mp)->ma_used = (mp)->ma_fill = 0; \ - (mp)->ma_poly = polys[0]; \ - assert(MINSIZE < (mp)->ma_poly && (mp)->ma_poly < MINSIZE*2); \ } while(0) --- 197,200 ---- *************** *** 236,251 **** Open addressing is preferred over chaining since the link overhead for chaining would be substantial (100% with typical malloc overhead). - However, instead of going through the table at constant steps, we cycle - through the values of GF(2^n). This avoids modulo computations, being - much cheaper on RISC machines, without leading to clustering. - - The initial probe index is computed as hash mod the table size. - Subsequent probe indices use the values of x^i in GF(2^n)-{0} as an offset, - where x is a root. The initial offset is derived from hash, too. All arithmetic on hash should ignore overflow. ! (This version is due to Reimer Behrends, some ideas are also due to ! Jyrki Alakuijala and Vladimir Marangozov.) This function must never return NULL; failures are indicated by returning --- 228,240 ---- Open addressing is preferred over chaining since the link overhead for chaining would be substantial (100% with typical malloc overhead). + The initial probe index is computed as hash mod the table size. Subsequent + probe indices are computed as explained earlier. + All arithmetic on hash should ignore overflow. ! (The details in this version are due to Tim Peters, building on many past ! contributions by Reimer Behrends, Jyrki Alakuijala, Vladimir Marangozov and ! Christian Tismer). This function must never return NULL; failures are indicated by returning *************** *** 253,261 **** reported by this function, and outstanding exceptions are maintained. */ static dictentry * lookdict(dictobject *mp, PyObject *key, register long hash) { register int i; ! register unsigned int incr; register dictentry *freeslot; register unsigned int mask = mp->ma_size-1; --- 242,251 ---- reported by this function, and outstanding exceptions are maintained. */ + static dictentry * lookdict(dictobject *mp, PyObject *key, register long hash) { register int i; ! register unsigned int perturb; register dictentry *freeslot; register unsigned int mask = mp->ma_size-1; *************** *** 266,272 **** register int cmp; PyObject *err_type, *err_value, *err_tb; ! /* We must come up with (i, incr) such that 0 <= i < ma_size ! and 0 < incr < ma_size and both are a function of hash. ! i is the initial table index and incr the initial probe offset. */ i = hash & mask; ep = &ep0[i]; --- 256,260 ---- register int cmp; PyObject *err_type, *err_value, *err_tb; ! i = hash & mask; ep = &ep0[i]; *************** *** 295,308 **** freeslot = NULL; } - /* Derive incr from hash, just to make it more arbitrary. Note that - incr must not be 0, or we will get into an infinite loop.*/ - incr = hash ^ ((unsigned long)hash >> 3); /* In the loop, me_key == dummy is by far (factor of 100s) the least likely outcome, so test for that last. */ ! for (;;) { ! if (!incr) ! incr = 1; /* and incr will never be 0 again */ ! ep = &ep0[(i + incr) & mask]; if (ep->me_key == NULL) { if (restore_error) --- 283,292 ---- freeslot = NULL; } /* In the loop, me_key == dummy is by far (factor of 100s) the least likely outcome, so test for that last. */ ! for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { ! i = (i << 2) + i + perturb + 1; ! ep = &ep0[i & mask]; if (ep->me_key == NULL) { if (restore_error) *************** *** 336,343 **** else if (ep->me_key == dummy && freeslot == NULL) freeslot = ep; - /* Cycle through GF(2**n). */ - if (incr & 1) - incr ^= mp->ma_poly; /* clears the lowest bit */ - incr >>= 1; } } --- 320,323 ---- *************** *** 357,361 **** { register int i; ! register unsigned int incr; register dictentry *freeslot; register unsigned int mask = mp->ma_size-1; --- 337,341 ---- { register int i; ! register unsigned int perturb; register dictentry *freeslot; register unsigned int mask = mp->ma_size-1; *************** *** 371,376 **** return lookdict(mp, key, hash); } - /* We must come up with (i, incr) such that 0 <= i < ma_size - and 0 < incr < ma_size and both are a function of hash */ i = hash & mask; ep = &ep0[i]; --- 351,354 ---- *************** *** 386,399 **** freeslot = NULL; } - /* Derive incr from hash, just to make it more arbitrary. Note that - incr must not be 0, or we will get into an infinite loop.*/ - incr = hash ^ ((unsigned long)hash >> 3); /* In the loop, me_key == dummy is by far (factor of 100s) the least likely outcome, so test for that last. */ ! for (;;) { ! if (!incr) ! incr = 1; /* and incr will never be 0 again */ ! ep = &ep0[(i + incr) & mask]; if (ep->me_key == NULL) return freeslot == NULL ? ep : freeslot; --- 364,373 ---- freeslot = NULL; } /* In the loop, me_key == dummy is by far (factor of 100s) the least likely outcome, so test for that last. */ ! for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { ! i = (i << 2) + i + perturb + 1; ! ep = &ep0[i & mask]; if (ep->me_key == NULL) return freeslot == NULL ? ep : freeslot; *************** *** 405,412 **** if (ep->me_key == dummy && freeslot == NULL) freeslot = ep; - /* Cycle through GF(2**n). */ - if (incr & 1) - incr ^= mp->ma_poly; /* clears the lowest bit */ - incr >>= 1; } } --- 379,382 ---- *************** *** 449,453 **** dictresize(dictobject *mp, int minused) { ! int newsize, newpoly; dictentry *oldtable, *newtable, *ep; int i; --- 419,423 ---- dictresize(dictobject *mp, int minused) { ! int newsize; dictentry *oldtable, *newtable, *ep; int i; *************** *** 457,474 **** assert(minused >= 0); ! /* Find the smallest table size > minused, and its poly[] entry. */ ! newpoly = 0; ! newsize = MINSIZE; ! for (i = 0; i < sizeof(polys)/sizeof(polys[0]); ++i) { ! if (newsize > minused) { ! newpoly = polys[i]; ! break; ! } ! newsize <<= 1; ! if (newsize < 0) /* overflow */ ! break; ! } ! if (newpoly == 0) { ! /* Ran out of polynomials or newsize overflowed. */ PyErr_NoMemory(); return -1; --- 427,436 ---- assert(minused >= 0); ! /* Find the smallest table size > minused. */ ! for (newsize = MINSIZE; ! newsize <= minused && newsize > 0; ! newsize <<= 1) ! ; ! if (newsize <= 0) { PyErr_NoMemory(); return -1; *************** *** 512,516 **** mp->ma_size = newsize; memset(newtable, 0, sizeof(dictentry) * newsize); - mp->ma_poly = newpoly; mp->ma_used = 0; i = mp->ma_fill; --- 474,477 ---- *************** *** 1256,1260 **** /* can't be equal if # of entries differ */ return 0; ! /* Same # of entries -- check all of 'em. Exit early on any diff. */ for (i = 0; i < a->ma_size; i++) { --- 1217,1221 ---- /* can't be equal if # of entries differ */ return 0; ! /* Same # of entries -- check all of 'em. Exit early on any diff. */ for (i = 0; i < a->ma_size; i++) { From tim_one@users.sourceforge.net Sat Jun 2 06:42:31 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Jun 2001 22:42:31 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.97,2.98 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv9951/python/dist/src/Objects Modified Files: dictobject.c Log Message: dict_popitem(): Repaired last-second 2.1 comment, which misidentified the true reason for allocating the tuple before checking the dict size. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.97 retrieving revision 2.98 diff -C2 -r2.97 -r2.98 *** dictobject.c 2001/06/02 05:27:19 2.97 --- dictobject.c 2001/06/02 05:42:29 2.98 *************** *** 1363,1371 **** if (!PyArg_NoArgs(args)) return NULL; ! /* Allocate the result tuple first. Believe it or not, ! * this allocation could trigger a garbage collection which ! * could resize the dict, which would invalidate the pointer ! * (ep) into the dict calculated below. ! * So we have to do this first. */ res = PyTuple_New(2); --- 1363,1374 ---- if (!PyArg_NoArgs(args)) return NULL; ! /* Allocate the result tuple before checking the size. Believe it ! * or not, this allocation could trigger a garbage collection which ! * could empty the dict, so if we checked the size first and that ! * happened, the result would be an infinite loop (searching for an ! * entry that no longer exists). Note that the usual popitem() ! * idiom is "while d: k, v = d.popitem()". so needing to throw the ! * tuple away if the dict *is* empty isn't a significant ! * inefficiency -- possible, but unlikely in practice. */ res = PyTuple_New(2); From nascheme@users.sourceforge.net Sat Jun 2 07:16:04 2001 From: nascheme@users.sourceforge.net (Neil Schemenauer) Date: Fri, 01 Jun 2001 23:16:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Demo/embed Makefile,1.9,1.10 Message-ID: Update of /cvsroot/python/python/dist/src/Demo/embed In directory usw-pr-cvs1:/tmp/cvs-serv14048/Demo/embed Modified Files: Makefile Log Message: Separate CFLAGS and CPPFLAGS. CFLAGS should not contain preprocessor directives, which is the role of CPPFLAGS. Closes SF patch #414991. Index: Makefile =================================================================== RCS file: /cvsroot/python/python/dist/src/Demo/embed/Makefile,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -r1.9 -r1.10 *** Makefile 2001/02/20 20:53:37 1.9 --- Makefile 2001/06/02 06:16:02 1.10 *************** *** 16,20 **** OPT= -g INCLUDES= -I$(srcdir)/Include -I$(blddir) ! CFLAGS= $(OPT) $(INCLUDES) # The Python library --- 16,21 ---- OPT= -g INCLUDES= -I$(srcdir)/Include -I$(blddir) ! CFLAGS= $(OPT) ! CPPFLAGS= $(INCLUDES) # The Python library From nascheme@users.sourceforge.net Sat Jun 2 07:16:04 2001 From: nascheme@users.sourceforge.net (Neil Schemenauer) Date: Fri, 01 Jun 2001 23:16:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Tools/freeze freeze.py,1.38,1.39 makemakefile.py,1.4,1.5 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/freeze In directory usw-pr-cvs1:/tmp/cvs-serv14048/Tools/freeze Modified Files: freeze.py makemakefile.py Log Message: Separate CFLAGS and CPPFLAGS. CFLAGS should not contain preprocessor directives, which is the role of CPPFLAGS. Closes SF patch #414991. Index: freeze.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/freeze/freeze.py,v retrieving revision 1.38 retrieving revision 1.39 diff -C2 -r1.38 -r1.39 *** freeze.py 2001/03/20 20:43:33 1.38 --- freeze.py 2001/06/02 06:16:02 1.39 *************** *** 425,429 **** infp.close() ! cflags = defines + includes + ['$(OPT)'] libs = [os.path.join(binlib, 'libpython$(VERSION).a')] --- 425,430 ---- infp.close() ! cflags = ['$(OPT)'] ! cppflags = defines + includes libs = [os.path.join(binlib, 'libpython$(VERSION).a')] *************** *** 435,438 **** --- 436,440 ---- somevars['CFLAGS'] = string.join(cflags) # override + somevars['CPPFLAGS'] = string.join(cppflags) # override files = ['$(OPT)', '$(LDFLAGS)', base_config_c, base_frozen_c] + \ files + supp_sources + addfiles + libs + \ Index: makemakefile.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/freeze/makemakefile.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -r1.4 -r1.5 *** makemakefile.py 1998/06/12 14:09:34 1.4 --- makemakefile.py 2001/06/02 06:16:02 1.5 *************** *** 20,24 **** dest = base[:-2] + '.o' outfp.write("%s: %s\n" % (dest, file)) ! outfp.write("\t$(CC) $(CFLAGS) -c %s\n" % file) files[i] = dest deps.append(dest) --- 20,24 ---- dest = base[:-2] + '.o' outfp.write("%s: %s\n" % (dest, file)) ! outfp.write("\t$(CC) $(CFLAGS) $(CPPFLAGS) -c %s\n" % file) files[i] = dest deps.append(dest) From nascheme@users.sourceforge.net Sat Jun 2 07:16:04 2001 From: nascheme@users.sourceforge.net (Neil Schemenauer) Date: Fri, 01 Jun 2001 23:16:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Misc Makefile.pre.in,1.20,1.21 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv14048/Misc Modified Files: Makefile.pre.in Log Message: Separate CFLAGS and CPPFLAGS. CFLAGS should not contain preprocessor directives, which is the role of CPPFLAGS. Closes SF patch #414991. Index: Makefile.pre.in =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/Makefile.pre.in,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -r1.20 -r1.21 *** Makefile.pre.in 2001/01/23 01:53:41 1.20 --- Makefile.pre.in 2001/06/02 06:16:02 1.21 *************** *** 96,100 **** # Add more -I and -D options here ! CFLAGS= $(OPT) -I$(INCLUDEPY) -I$(EXECINCLUDEPY) $(DEFS) # These two variables can be set in Setup to merge extensions. --- 96,101 ---- # Add more -I and -D options here ! CFLAGS= $(OPT) ! CPPFLAGS= -I$(INCLUDEPY) -I$(EXECINCLUDEPY) $(DEFS) # These two variables can be set in Setup to merge extensions. *************** *** 229,233 **** # Make config.o from the config.c created by makesetup config.o: config.c ! $(CC) $(CFLAGS) -c config.c # Setup is copied from Setup.in *only* if it doesn't yet exist --- 230,234 ---- # Make config.o from the config.c created by makesetup config.o: config.c ! $(CC) $(CFLAGS) $(CPPFLAGS) -c config.c # Setup is copied from Setup.in *only* if it doesn't yet exist From nascheme@users.sourceforge.net Sat Jun 2 07:16:04 2001 From: nascheme@users.sourceforge.net (Neil Schemenauer) Date: Fri, 01 Jun 2001 23:16:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Demo/pysvr Makefile,1.4,1.5 Message-ID: Update of /cvsroot/python/python/dist/src/Demo/pysvr In directory usw-pr-cvs1:/tmp/cvs-serv14048/Demo/pysvr Modified Files: Makefile Log Message: Separate CFLAGS and CPPFLAGS. CFLAGS should not contain preprocessor directives, which is the role of CPPFLAGS. Closes SF patch #414991. Index: Makefile =================================================================== RCS file: /cvsroot/python/python/dist/src/Demo/pysvr/Makefile,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -r1.4 -r1.5 *** Makefile 2000/11/03 12:58:09 1.4 --- Makefile 2001/06/02 06:16:02 1.5 *************** *** 32,36 **** # Compilation and link flags -- no need to change normally ! CFLAGS=$(PYINCL) $(OPT) LIBS=$(PYLIBS) $(RLLIBS) $(OTHERLIBS) --- 32,37 ---- # Compilation and link flags -- no need to change normally ! CFLAGS=$(OPT) ! CPPFLAGS=$(PYINCL) LIBS=$(PYLIBS) $(RLLIBS) $(OTHERLIBS) From nascheme@users.sourceforge.net Sat Jun 2 07:16:04 2001 From: nascheme@users.sourceforge.net (Neil Schemenauer) Date: Fri, 01 Jun 2001 23:16:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules makesetup,1.35,1.36 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv14048/Modules Modified Files: makesetup Log Message: Separate CFLAGS and CPPFLAGS. CFLAGS should not contain preprocessor directives, which is the role of CPPFLAGS. Closes SF patch #414991. Index: makesetup =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/makesetup,v retrieving revision 1.35 retrieving revision 1.36 diff -C2 -r1.35 -r1.36 *** makesetup 2001/03/02 07:09:54 1.35 --- makesetup 2001/06/02 06:16:02 1.36 *************** *** 217,221 **** esac case $doconfig in ! no) cc="$cc \$(CCSHARED) \$(CFLAGS)";; *) cc="$cc \$(PY_CFLAGS)";; --- 217,221 ---- esac case $doconfig in ! no) cc="$cc \$(CCSHARED) \$(CFLAGS) \$(CPPFLAGS)";; *) cc="$cc \$(PY_CFLAGS)";; From nascheme@users.sourceforge.net Sat Jun 2 07:16:04 2001 From: nascheme@users.sourceforge.net (Neil Schemenauer) Date: Fri, 01 Jun 2001 23:16:04 -0700 Subject: [Python-checkins] CVS: python/dist/src Makefile.pre.in,1.37,1.38 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv14048 Modified Files: Makefile.pre.in Log Message: Separate CFLAGS and CPPFLAGS. CFLAGS should not contain preprocessor directives, which is the role of CPPFLAGS. Closes SF patch #414991. Index: Makefile.pre.in =================================================================== RCS file: /cvsroot/python/python/dist/src/Makefile.pre.in,v retrieving revision 1.37 retrieving revision 1.38 diff -C2 -r1.37 -r1.38 *** Makefile.pre.in 2001/04/20 19:13:01 1.37 --- Makefile.pre.in 2001/06/02 06:16:02 1.38 *************** *** 56,60 **** OPT= @OPT@ DEFS= @DEFS@ ! CFLAGS= $(OPT) -I. -I$(srcdir)/Include $(DEFS) LDFLAGS= @LDFLAGS@ LDLAST= @LDLAST@ --- 56,61 ---- OPT= @OPT@ DEFS= @DEFS@ ! CFLAGS= $(OPT) ! CPPFLAGS= -I. -I$(srcdir)/Include $(DEFS) LDFLAGS= @LDFLAGS@ LDLAST= @LDLAST@ *************** *** 65,69 **** CFLAGSFORSHARED=@CFLAGSFORSHARED@ # C flags used for building the interpreter object files ! PY_CFLAGS= $(CFLAGS) $(CFLAGSFORSHARED) --- 66,70 ---- CFLAGSFORSHARED=@CFLAGSFORSHARED@ # C flags used for building the interpreter object files ! PY_CFLAGS= $(CFLAGS) $(CPPFLAGS) $(CFLAGSFORSHARED) *************** *** 284,288 **** # Build the shared modules sharedmods: $(PYTHON) ! PYTHONPATH= ./$(PYTHON) $(srcdir)/setup.py build # buildno should really depend on something like LIBRARY_SRC --- 285,290 ---- # Build the shared modules sharedmods: $(PYTHON) ! unset PYTHONPATH PYTHONHOME PYTHONSTARTUP; \ ! ./$(PYTHON) $(srcdir)/setup.py build # buildno should really depend on something like LIBRARY_SRC *************** *** 400,407 **** Python/getplatform.o: $(srcdir)/Python/getplatform.c ! $(CC) -c $(CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c Python/importdl.o: $(srcdir)/Python/importdl.c ! $(CC) -c $(CFLAGS) -I$(DLINCLDIR) -o $@ $(srcdir)/Python/importdl.c Objects/object.o: $(srcdir)/Objects/object.c $(srcdir)/Objects/obmalloc.c --- 402,409 ---- Python/getplatform.o: $(srcdir)/Python/getplatform.c ! $(CC) -c $(CFLAGS) $(CPPFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c Python/importdl.o: $(srcdir)/Python/importdl.c ! $(CC) -c $(CFLAGS) $(CPPFLAGS) -I$(DLINCLDIR) -o $@ $(srcdir)/Python/importdl.c Objects/object.o: $(srcdir)/Objects/object.c $(srcdir)/Objects/obmalloc.c From tim_one@users.sourceforge.net Sat Jun 2 09:02:58 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Jun 2001 01:02:58 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_mutants.py,1.3,1.4 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv27849/python/dist/src/Lib/test Modified Files: test_mutants.py Log Message: Coredumpers from Michael Hudson, mutating dicts while printing or converting to string. Critical bugfix candidate -- if you take this seriously . Index: test_mutants.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_mutants.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -r1.3 -r1.4 *** test_mutants.py 2001/05/10 20:18:30 1.3 --- test_mutants.py 2001/06/02 08:02:56 1.4 *************** *** 1,4 **** ! from test_support import verbose import random # From SF bug #422121: Insecurities in dict comparison. --- 1,5 ---- ! from test_support import verbose, TESTFN import random + import os # From SF bug #422121: Insecurities in dict comparison. *************** *** 152,153 **** --- 153,217 ---- # See last comment block for clues about good values for n. test(100) + + ########################################################################## + # Another segfault bug, distilled by Micheal Hundson from a c.l.py post. + + class Child: + def __init__(self, parent): + self.__dict__['parent'] = parent + def __getattr__(self, attr): + self.parent.a = 1 + self.parent.b = 1 + self.parent.c = 1 + self.parent.d = 1 + self.parent.e = 1 + self.parent.f = 1 + self.parent.g = 1 + self.parent.h = 1 + self.parent.i = 1 + return getattr(self.parent, attr) + + class Parent: + def __init__(self): + self.a = Child(self) + + # Hard to say what this will print! May vary from time to time. But + # we're specifically trying to test the tp_print slot here, and this is + # the clearest way to do it. We print the result to a temp file so that + # the expected-output file doesn't need to change. + + f = open(TESTFN, "w") + print >> f, Parent().__dict__ + f.close() + os.unlink(TESTFN) + + ########################################################################## + # And another core-dumper from Michael Hudson. + + dict = {} + + # Force dict to malloc its table. + for i in range(1, 10): + dict[i] = i + + f = open(TESTFN, "w") + + class Machiavelli: + def __repr__(self): + dict.clear() + + # Michael sez: "doesn't crash without this. don't know why." + # Tim sez: "luck of the draw; crashes with or without for me." + print >> f + + return `"machiavelli"` + + def __hash__(self): + return 0 + + dict[Machiavelli()] = Machiavelli() + + print >> f, str(dict) + f.close() + os.unlink(TESTFN) + del f, dict From tim_one@users.sourceforge.net Sat Jun 2 09:02:58 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Jun 2001 01:02:58 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.98,2.99 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv27849/python/dist/src/Objects Modified Files: dictobject.c Log Message: Coredumpers from Michael Hudson, mutating dicts while printing or converting to string. Critical bugfix candidate -- if you take this seriously . Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.98 retrieving revision 2.99 diff -C2 -r2.98 -r2.99 *** dictobject.c 2001/06/02 05:42:29 2.98 --- dictobject.c 2001/06/02 08:02:56 2.99 *************** *** 741,745 **** register int i; register int any; - register dictentry *ep; i = Py_ReprEnter((PyObject*)mp); --- 741,744 ---- *************** *** 753,761 **** fprintf(fp, "{"); any = 0; ! for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) { ! if (ep->me_value != NULL) { if (any++ > 0) fprintf(fp, ", "); if (PyObject_Print((PyObject *)ep->me_key, fp, 0)!=0) { Py_ReprLeave((PyObject*)mp); return -1; --- 752,766 ---- fprintf(fp, "{"); any = 0; ! for (i = 0; i < mp->ma_size; i++) { ! dictentry *ep = mp->ma_table + i; ! PyObject *pvalue = ep->me_value; ! if (pvalue != NULL) { ! /* Prevent PyObject_Repr from deleting value during ! key format */ ! Py_INCREF(pvalue); if (any++ > 0) fprintf(fp, ", "); if (PyObject_Print((PyObject *)ep->me_key, fp, 0)!=0) { + Py_DECREF(pvalue); Py_ReprLeave((PyObject*)mp); return -1; *************** *** 763,769 **** --- 768,776 ---- fprintf(fp, ": "); if (PyObject_Print(ep->me_value, fp, 0) != 0) { + Py_DECREF(pvalue); Py_ReprLeave((PyObject*)mp); return -1; } + Py_DECREF(pvalue); } } *************** *** 780,784 **** register int i; register int any; - register dictentry *ep; i = Py_ReprEnter((PyObject*)mp); --- 787,790 ---- *************** *** 793,803 **** colon = PyString_FromString(": "); any = 0; ! for (i = 0, ep = mp->ma_table; i < mp->ma_size && v; i++, ep++) { ! if (ep->me_value != NULL) { if (any++) PyString_Concat(&v, sepa); PyString_ConcatAndDel(&v, PyObject_Repr(ep->me_key)); PyString_Concat(&v, colon); ! PyString_ConcatAndDel(&v, PyObject_Repr(ep->me_value)); } } --- 799,815 ---- colon = PyString_FromString(": "); any = 0; ! for (i = 0; i < mp->ma_size && v; i++) { ! dictentry *ep = mp->ma_table + i; ! PyObject *pvalue = ep->me_value; ! if (pvalue != NULL) { ! /* Prevent PyObject_Repr from deleting value during ! key format */ ! Py_INCREF(pvalue); if (any++) PyString_Concat(&v, sepa); PyString_ConcatAndDel(&v, PyObject_Repr(ep->me_key)); PyString_Concat(&v, colon); ! PyString_ConcatAndDel(&v, PyObject_Repr(pvalue)); ! Py_DECREF(pvalue); } } From tim_one@users.sourceforge.net Sat Jun 2 09:19:01 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Jun 2001 01:19:01 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_mutants.py,1.4,1.5 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv30168/python/dist/src/Lib/test Modified Files: test_mutants.py Log Message: Fix comment. Index: test_mutants.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_mutants.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -r1.4 -r1.5 *** test_mutants.py 2001/06/02 08:02:56 1.4 --- test_mutants.py 2001/06/02 08:18:58 1.5 *************** *** 155,159 **** ########################################################################## ! # Another segfault bug, distilled by Micheal Hundson from a c.l.py post. class Child: --- 155,159 ---- ########################################################################## ! # Another segfault bug, distilled by Michael Hudson from a c.l.py post. class Child: From tim_one@users.sourceforge.net Sat Jun 2 09:27:42 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Jun 2001 01:27:42 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.99,2.100 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv31412/python/dist/src/Objects Modified Files: dictobject.c Log Message: Finish the dict->string coredump fix. Need sleep. Bugfix candidate. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.99 retrieving revision 2.100 diff -C2 -r2.99 -r2.100 *** dictobject.c 2001/06/02 08:02:56 2.99 --- dictobject.c 2001/06/02 08:27:39 2.100 *************** *** 767,771 **** } fprintf(fp, ": "); ! if (PyObject_Print(ep->me_value, fp, 0) != 0) { Py_DECREF(pvalue); Py_ReprLeave((PyObject*)mp); --- 767,771 ---- } fprintf(fp, ": "); ! if (PyObject_Print(pvalue, fp, 0) != 0) { Py_DECREF(pvalue); Py_ReprLeave((PyObject*)mp); From fdrake@users.sourceforge.net Sun Jun 3 04:12:59 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Sat, 02 Jun 2001 20:12:59 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/api api.tex,1.125,1.126 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/api In directory usw-pr-cvs1:/tmp/cvs-serv21375/api Modified Files: api.tex Log Message: Explained more differences between PyList_SetItem() and PyList_SET_ITEM(). In particular, the affect on existing list content was not sufficiently explained. This closes SF bug #429554. Index: api.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/api.tex,v retrieving revision 1.125 retrieving revision 1.126 diff -C2 -r1.125 -r1.126 *** api.tex 2001/05/29 18:51:41 1.125 --- api.tex 2001/06/03 03:12:57 1.126 *************** *** 3305,3309 **** PyObject *item} Sets the item at index \var{index} in list to \var{item}. ! \strong{Note:} This function ``steals'' a reference to \var{item}. \end{cfuncdesc} --- 3305,3311 ---- PyObject *item} Sets the item at index \var{index} in list to \var{item}. ! \strong{Note:} This function ``steals'' a reference to \var{item} and ! discards a reference to an item already in the list at the affected ! position. \end{cfuncdesc} *************** *** 3311,3315 **** PyObject *o} Macro form of \cfunction{PyList_SetItem()} without error checking. ! \strong{Note:} This function ``steals'' a reference to \var{item}. \end{cfuncdesc} --- 3313,3320 ---- PyObject *o} Macro form of \cfunction{PyList_SetItem()} without error checking. ! \strong{Note:} This function ``steals'' a reference to \var{item}, ! and, unlike \cfunction{PyList_SetItem()}, does \emph{not} discard a ! reference to any item that it being replaced. This is normally only ! used to fill in new lists where there is no previous content.. \end{cfuncdesc} From fdrake@users.sourceforge.net Sun Jun 3 04:16:06 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Sat, 02 Jun 2001 20:16:06 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/api api.tex,1.117.2.3,1.117.2.4 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/api In directory usw-pr-cvs1:/tmp/cvs-serv22227/api Modified Files: Tag: release21-maint api.tex Log Message: Explained more differences between PyList_SetItem() and PyList_SET_ITEM(). In particular, the affect on existing list content was not sufficiently explained. This closes SF bug #429554. Index: api.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/api.tex,v retrieving revision 1.117.2.3 retrieving revision 1.117.2.4 diff -C2 -r1.117.2.3 -r1.117.2.4 *** api.tex 2001/05/29 18:53:11 1.117.2.3 --- api.tex 2001/06/03 03:16:04 1.117.2.4 *************** *** 3246,3250 **** PyObject *item} Sets the item at index \var{index} in list to \var{item}. ! \strong{Note:} This function ``steals'' a reference to \var{item}. \end{cfuncdesc} --- 3246,3252 ---- PyObject *item} Sets the item at index \var{index} in list to \var{item}. ! \strong{Note:} This function ``steals'' a reference to \var{item} and ! discards a reference to an item already in the list at the affected ! position. \end{cfuncdesc} *************** *** 3252,3256 **** PyObject *o} Macro form of \cfunction{PyList_SetItem()} without error checking. ! \strong{Note:} This function ``steals'' a reference to \var{item}. \end{cfuncdesc} --- 3254,3261 ---- PyObject *o} Macro form of \cfunction{PyList_SetItem()} without error checking. ! \strong{Note:} This function ``steals'' a reference to \var{item}, ! and, unlike \cfunction{PyList_SetItem()}, does \emph{not} discard a ! reference to any item that it being replaced. This is normally only ! used to fill in new lists where there is no previous content.. \end{cfuncdesc} From tim_one@users.sourceforge.net Sun Jun 3 05:14:45 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Jun 2001 21:14:45 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.100,2.101 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv3399/python/dist/src/Objects Modified Files: dictobject.c Log Message: lookdict: Reduce obfuscating code duplication with a judicious goto. This code is likely to get even hairier to squash core dumps due to mutating comparisons, and it's hard enough to follow without that. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.100 retrieving revision 2.101 diff -C2 -r2.100 -r2.101 *** dictobject.c 2001/06/02 08:27:39 2.100 --- dictobject.c 2001/06/03 04:14:43 2.101 *************** *** 252,257 **** dictentry *ep0 = mp->ma_table; register dictentry *ep; ! register int restore_error = 0; ! register int checked_error = 0; register int cmp; PyObject *err_type, *err_value, *err_tb; --- 252,257 ---- dictentry *ep0 = mp->ma_table; register dictentry *ep; ! register int restore_error; ! register int checked_error; register int cmp; PyObject *err_type, *err_value, *err_tb; *************** *** 261,264 **** --- 261,266 ---- if (ep->me_key == NULL || ep->me_key == key) return ep; + + restore_error = checked_error = 0; if (ep->me_key == dummy) freeslot = ep; *************** *** 272,282 **** } cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ); ! if (cmp > 0) { ! if (restore_error) ! PyErr_Restore(err_type, err_value, ! err_tb); ! return ep; ! } ! else if (cmp < 0) PyErr_Clear(); } --- 274,280 ---- } cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ); ! if (cmp > 0) ! goto Done; ! if (cmp < 0) PyErr_Clear(); } *************** *** 290,303 **** ep = &ep0[i & mask]; if (ep->me_key == NULL) { ! if (restore_error) ! PyErr_Restore(err_type, err_value, err_tb); ! return freeslot == NULL ? ep : freeslot; ! } ! if (ep->me_key == key) { ! if (restore_error) ! PyErr_Restore(err_type, err_value, err_tb); ! return ep; } ! else if (ep->me_hash == hash && ep->me_key != dummy) { if (!checked_error) { checked_error = 1; --- 288,298 ---- ep = &ep0[i & mask]; if (ep->me_key == NULL) { ! if (freeslot != NULL) ! ep = freeslot; ! break; } ! if (ep->me_key == key) ! break; ! if (ep->me_hash == hash && ep->me_key != dummy) { if (!checked_error) { checked_error = 1; *************** *** 309,319 **** } cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ); ! if (cmp > 0) { ! if (restore_error) ! PyErr_Restore(err_type, err_value, ! err_tb); ! return ep; ! } ! else if (cmp < 0) PyErr_Clear(); } --- 304,310 ---- } cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ); ! if (cmp > 0) ! break; ! if (cmp < 0) PyErr_Clear(); } *************** *** 321,324 **** --- 312,320 ---- freeslot = ep; } + + Done: + if (restore_error) + PyErr_Restore(err_type, err_value, err_tb); + return ep; } From tim_one@users.sourceforge.net Sun Jun 3 05:54:34 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Jun 2001 21:54:34 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_mutants.py,1.5,1.6 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv9638/python/dist/src/Lib/test Modified Files: test_mutants.py Log Message: lookdict: stop more insane core-dump mutating comparison cases. Should be possible to provoke unbounded recursion now, but leaving that to someone else to provoke and repair. Bugfix candidate -- although this is getting harder to backstitch, and the cases it's protecting against are mondo contrived. Index: test_mutants.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_mutants.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -r1.5 -r1.6 *** test_mutants.py 2001/06/02 08:18:58 1.5 --- test_mutants.py 2001/06/03 04:54:32 1.6 *************** *** 216,217 **** --- 216,285 ---- os.unlink(TESTFN) del f, dict + + + ########################################################################## + # And another core-dumper from Michael Hudson. + + dict = {} + + # let's force dict to malloc its table + for i in range(1, 10): + dict[i] = i + + class Machiavelli2: + def __eq__(self, other): + dict.clear() + return 1 + + def __hash__(self): + return 0 + + dict[Machiavelli2()] = Machiavelli2() + + try: + dict[Machiavelli2()] + except KeyError: + pass + + del dict + + ########################################################################## + # And another core-dumper from Michael Hudson. + + dict = {} + + # let's force dict to malloc its table + for i in range(1, 10): + dict[i] = i + + class Machiavelli3: + def __init__(self, id): + self.id = id + + def __eq__(self, other): + if self.id == other.id: + dict.clear() + return 1 + else: + return 0 + + def __repr__(self): + return "%s(%s)"%(self.__class__.__name__, self.id) + + def __hash__(self): + return 0 + + dict[Machiavelli3(1)] = Machiavelli3(0) + dict[Machiavelli3(2)] = Machiavelli3(0) + + f = open(TESTFN, "w") + try: + try: + print >> f, dict[Machiavelli3(2)] + except KeyError: + pass + finally: + f.close() + os.unlink(TESTFN) + + del dict From tim_one@users.sourceforge.net Sun Jun 3 05:54:34 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Jun 2001 21:54:34 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.101,2.102 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv9638/python/dist/src/Objects Modified Files: dictobject.c Log Message: lookdict: stop more insane core-dump mutating comparison cases. Should be possible to provoke unbounded recursion now, but leaving that to someone else to provoke and repair. Bugfix candidate -- although this is getting harder to backstitch, and the cases it's protecting against are mondo contrived. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.101 retrieving revision 2.102 diff -C2 -r2.101 -r2.102 *** dictobject.c 2001/06/03 04:14:43 2.101 --- dictobject.c 2001/06/03 04:54:32 2.102 *************** *** 256,259 **** --- 256,260 ---- register int cmp; PyObject *err_type, *err_value, *err_tb; + PyObject *startkey; i = hash & mask; *************** *** 273,281 **** PyErr_Fetch(&err_type, &err_value, &err_tb); } ! cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ); ! if (cmp > 0) ! goto Done; if (cmp < 0) PyErr_Clear(); } freeslot = NULL; --- 274,294 ---- PyErr_Fetch(&err_type, &err_value, &err_tb); } ! startkey = ep->me_key; ! cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); if (cmp < 0) PyErr_Clear(); + if (ep0 == mp->ma_table && ep->me_key == startkey) { + if (cmp > 0) + goto Done; + } + else { + /* The compare did major nasty stuff to the + * dict: start over. + * XXX A clever adversary could prevent this + * XXX from terminating. + */ + ep = lookdict(mp, key, hash); + goto Done; + } } freeslot = NULL; *************** *** 303,311 **** } } ! cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ); ! if (cmp > 0) ! break; if (cmp < 0) PyErr_Clear(); } else if (ep->me_key == dummy && freeslot == NULL) --- 316,336 ---- } } ! startkey = ep->me_key; ! cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); if (cmp < 0) PyErr_Clear(); + if (ep0 == mp->ma_table && ep->me_key == startkey) { + if (cmp > 0) + break; + } + else { + /* The compare did major nasty stuff to the + * dict: start over. + * XXX A clever adversary could prevent this + * XXX from terminating. + */ + ep = lookdict(mp, key, hash); + break; + } } else if (ep->me_key == dummy && freeslot == NULL) From loewis@users.sourceforge.net Sun Jun 3 15:06:44 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 03 Jun 2001 07:06:44 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/xml/dom minidom.py,1.32,1.33 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/xml/dom In directory usw-pr-cvs1:/tmp/cvs-serv23168 Modified Files: minidom.py Log Message: Fix getElementsByTagNameNS: - actually return a result - Compare with tag.localName in getElementsByTagNameNSHelper Index: minidom.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/xml/dom/minidom.py,v retrieving revision 1.32 retrieving revision 1.33 diff -C2 -r1.32 -r1.33 *** minidom.py 2001/04/05 14:41:30 1.32 --- minidom.py 2001/06/03 14:06:42 1.33 *************** *** 280,284 **** for node in parent.childNodes: if node.nodeType == Node.ELEMENT_NODE: ! if ((localName == "*" or node.tagName == localName) and (nsURI == "*" or node.namespaceURI == nsURI)): rc.append(node) --- 280,284 ---- for node in parent.childNodes: if node.nodeType == Node.ELEMENT_NODE: ! if ((localName == "*" or node.localName == localName) and (nsURI == "*" or node.namespaceURI == nsURI)): rc.append(node) *************** *** 552,556 **** def getElementsByTagNameNS(self, namespaceURI, localName): ! _getElementsByTagNameNSHelper(self, namespaceURI, localName, []) def __repr__(self): --- 552,558 ---- def getElementsByTagNameNS(self, namespaceURI, localName): ! rc = [] ! _getElementsByTagNameNSHelper(self, namespaceURI, localName, rc) ! return rc def __repr__(self): *************** *** 881,885 **** def getElementsByTagNameNS(self, namespaceURI, localName): ! _getElementsByTagNameNSHelper(self, namespaceURI, localName) def getElementsByTagName(self, name): --- 883,889 ---- def getElementsByTagNameNS(self, namespaceURI, localName): ! rc = [] ! _getElementsByTagNameNSHelper(self, namespaceURI, localName, rc) ! return rc def getElementsByTagName(self, name): From loewis@users.sourceforge.net Sun Jun 3 15:27:04 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 03 Jun 2001 07:27:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_minidom.py,1.26,1.27 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv27326 Modified Files: test_minidom.py Log Message: Implement testGetElementsByTagNameNS. Index: test_minidom.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_minidom.py,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -r1.26 -r1.27 *** test_minidom.py 2001/02/21 07:29:48 1.26 --- test_minidom.py 2001/06/03 14:27:02 1.27 *************** *** 240,244 **** def testGetAttributeNode(): pass ! def testGetElementsByTagNameNS(): pass def testGetEmptyNodeListFromElementsByTagNameNS(): pass --- 240,251 ---- def testGetAttributeNode(): pass ! def testGetElementsByTagNameNS(): ! d=""" ! ! """ ! dom = parseString(d) ! elem = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom","myelem") ! confirm(len(elem) == 1) ! dom.unlink() def testGetEmptyNodeListFromElementsByTagNameNS(): pass From loewis@users.sourceforge.net Sun Jun 3 15:27:05 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 03 Jun 2001 07:27:05 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test/output test_minidom,1.12,1.13 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test/output In directory usw-pr-cvs1:/tmp/cvs-serv27326/output Modified Files: test_minidom Log Message: Implement testGetElementsByTagNameNS. Index: test_minidom =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/output/test_minidom,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -r1.12 -r1.13 *** test_minidom 2000/12/31 04:03:27 1.12 --- test_minidom 2001/06/03 14:27:02 1.13 *************** *** 111,114 **** --- 111,115 ---- Test Succeeded testGetElementsByTagName Passed assertion: len(Node.allnodes) == 0 + Passed Test Test Succeeded testGetElementsByTagNameNS Passed assertion: len(Node.allnodes) == 0 From mhammond@users.sourceforge.net Mon Jun 4 03:31:25 2001 From: mhammond@users.sourceforge.net (Mark Hammond) Date: Sun, 03 Jun 2001 19:31:25 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/encodings aliases.py,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/encodings In directory usw-pr-cvs1:/tmp/cvs-serv11108 Modified Files: aliases.py Log Message: Add some useful Windows encodings - patch #423221. Index: aliases.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/encodings/aliases.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -r1.6 -r1.7 *** aliases.py 2001/05/15 15:34:07 1.6 --- aliases.py 2001/06/04 02:31:23 1.7 *************** *** 60,63 **** --- 60,68 ---- 'macturkish': 'mac_turkish', + # Windows + 'windows_1252': 'cp1252', + 'windows_1254': 'cp1254', + 'windows_1255': 'cp1255', + # MBCS 'dbcs': 'mbcs', From fdrake@users.sourceforge.net Mon Jun 4 04:56:27 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Sun, 03 Jun 2001 20:56:27 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test/output test_parser,1.4,NONE Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test/output In directory usw-pr-cvs1:/tmp/cvs-serv25698/output Removed Files: test_parser Log Message: Convert the parser module test to use PyUnit. --- test_parser DELETED --- From fdrake@users.sourceforge.net Mon Jun 4 04:56:27 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Sun, 03 Jun 2001 20:56:27 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_parser.py,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv25698 Modified Files: test_parser.py Log Message: Convert the parser module test to use PyUnit. Index: test_parser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_parser.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -r1.6 -r1.7 *** test_parser.py 2001/01/17 21:51:36 1.6 --- test_parser.py 2001/06/04 03:56:24 1.7 *************** *** 1,9 **** - import os.path import parser ! import pprint ! import sys - from test_support import TestFailed - # # First, we test that we can generate trees from valid source fragments, --- 1,6 ---- import parser ! import test_support ! import unittest # # First, we test that we can generate trees from valid source fragments, *************** *** 12,124 **** # ! def roundtrip(f, s): ! st1 = f(s) ! t = st1.totuple() ! try: ! st2 = parser.sequence2ast(t) ! except parser.ParserError: ! raise TestFailed, s ! ! def roundtrip_fromfile(filename): ! roundtrip(parser.suite, open(filename).read()) ! ! def test_expr(s): ! print "expr:", s ! roundtrip(parser.expr, s) ! ! def test_suite(s): ! print "suite:", s ! roundtrip(parser.suite, s) ! ! ! print "Expressions:" ! ! test_expr("foo(1)") ! test_expr("[1, 2, 3]") ! test_expr("[x**3 for x in range(20)]") ! test_expr("[x**3 for x in range(20) if x % 3]") ! test_expr("foo(*args)") ! test_expr("foo(*args, **kw)") ! test_expr("foo(**kw)") ! test_expr("foo(key=value)") ! test_expr("foo(key=value, *args)") ! test_expr("foo(key=value, *args, **kw)") ! test_expr("foo(key=value, **kw)") ! test_expr("foo(a, b, c, *args)") ! test_expr("foo(a, b, c, *args, **kw)") ! test_expr("foo(a, b, c, **kw)") ! test_expr("foo + bar") ! test_expr("lambda: 0") ! test_expr("lambda x: 0") ! test_expr("lambda *y: 0") ! test_expr("lambda *y, **z: 0") ! test_expr("lambda **z: 0") ! test_expr("lambda x, y: 0") ! test_expr("lambda foo=bar: 0") ! test_expr("lambda foo=bar, spaz=nifty+spit: 0") ! test_expr("lambda foo=bar, **z: 0") ! test_expr("lambda foo=bar, blaz=blat+2, **z: 0") ! test_expr("lambda foo=bar, blaz=blat+2, *y, **z: 0") ! test_expr("lambda x, *y, **z: 0") ! ! print ! print "Statements:" ! test_suite("print") ! test_suite("print 1") ! test_suite("print 1,") ! test_suite("print >>fp") ! test_suite("print >>fp, 1") ! test_suite("print >>fp, 1,") ! ! # expr_stmt ! test_suite("a") ! test_suite("a = b") ! test_suite("a = b = c = d = e") ! test_suite("a += b") ! test_suite("a -= b") ! test_suite("a *= b") ! test_suite("a /= b") ! test_suite("a %= b") ! test_suite("a &= b") ! test_suite("a |= b") ! test_suite("a ^= b") ! test_suite("a <<= b") ! test_suite("a >>= b") ! test_suite("a **= b") ! ! test_suite("def f(): pass") ! test_suite("def f(*args): pass") ! test_suite("def f(*args, **kw): pass") ! test_suite("def f(**kw): pass") ! test_suite("def f(foo=bar): pass") ! test_suite("def f(foo=bar, *args): pass") ! test_suite("def f(foo=bar, *args, **kw): pass") ! test_suite("def f(foo=bar, **kw): pass") ! ! test_suite("def f(a, b): pass") ! test_suite("def f(a, b, *args): pass") ! test_suite("def f(a, b, *args, **kw): pass") ! test_suite("def f(a, b, **kw): pass") ! test_suite("def f(a, b, foo=bar): pass") ! test_suite("def f(a, b, foo=bar, *args): pass") ! test_suite("def f(a, b, foo=bar, *args, **kw): pass") ! test_suite("def f(a, b, foo=bar, **kw): pass") ! ! test_suite("from sys.path import *") ! test_suite("from sys.path import dirname") ! test_suite("from sys.path import dirname as my_dirname") ! test_suite("from sys.path import dirname, basename") ! test_suite("from sys.path import dirname as my_dirname, basename") ! test_suite("from sys.path import dirname, basename as my_basename") ! ! test_suite("import sys") ! test_suite("import sys as system") ! test_suite("import sys, math") ! test_suite("import sys as system, math") ! test_suite("import sys, math as my_math") ! ! #d = os.path.dirname(os.__file__) ! #roundtrip_fromfile(os.path.join(d, "os.py")) ! #roundtrip_fromfile(os.path.join(d, "test", "test_parser.py")) # --- 9,123 ---- # ! class RoundtripLegalSyntaxTestCase(unittest.TestCase): ! def roundtrip(self, f, s): ! st1 = f(s) ! t = st1.totuple() ! try: ! st2 = parser.sequence2ast(t) ! except parser.ParserError: ! self.fail("could not roundtrip %r" % s) ! ! self.assertEquals(t, st2.totuple(), ! "could not re-generate syntax tree") ! ! def check_expr(self, s): ! self.roundtrip(parser.expr, s) ! ! def check_suite(self, s): ! self.roundtrip(parser.suite, s) ! ! def test_expressions(self): ! self.check_expr("foo(1)") ! self.check_expr("[1, 2, 3]") ! self.check_expr("[x**3 for x in range(20)]") ! self.check_expr("[x**3 for x in range(20) if x % 3]") ! self.check_expr("foo(*args)") ! self.check_expr("foo(*args, **kw)") ! self.check_expr("foo(**kw)") ! self.check_expr("foo(key=value)") ! self.check_expr("foo(key=value, *args)") ! self.check_expr("foo(key=value, *args, **kw)") ! self.check_expr("foo(key=value, **kw)") ! self.check_expr("foo(a, b, c, *args)") ! self.check_expr("foo(a, b, c, *args, **kw)") ! self.check_expr("foo(a, b, c, **kw)") ! self.check_expr("foo + bar") ! self.check_expr("lambda: 0") ! self.check_expr("lambda x: 0") ! self.check_expr("lambda *y: 0") ! self.check_expr("lambda *y, **z: 0") ! self.check_expr("lambda **z: 0") ! self.check_expr("lambda x, y: 0") ! self.check_expr("lambda foo=bar: 0") ! self.check_expr("lambda foo=bar, spaz=nifty+spit: 0") ! self.check_expr("lambda foo=bar, **z: 0") ! self.check_expr("lambda foo=bar, blaz=blat+2, **z: 0") ! self.check_expr("lambda foo=bar, blaz=blat+2, *y, **z: 0") ! self.check_expr("lambda x, *y, **z: 0") ! ! def test_print(self): ! self.check_suite("print") ! self.check_suite("print 1") ! self.check_suite("print 1,") ! self.check_suite("print >>fp") ! self.check_suite("print >>fp, 1") ! self.check_suite("print >>fp, 1,") ! ! def test_simple_expression(self): ! # expr_stmt ! self.check_suite("a") ! ! def test_simple_assignments(self): ! self.check_suite("a = b") ! self.check_suite("a = b = c = d = e") ! ! def test_simple_augmented_assignments(self): ! self.check_suite("a += b") ! self.check_suite("a -= b") ! self.check_suite("a *= b") ! self.check_suite("a /= b") ! self.check_suite("a %= b") ! self.check_suite("a &= b") ! self.check_suite("a |= b") ! self.check_suite("a ^= b") ! self.check_suite("a <<= b") ! self.check_suite("a >>= b") ! self.check_suite("a **= b") ! ! def test_function_defs(self): ! self.check_suite("def f(): pass") ! self.check_suite("def f(*args): pass") ! self.check_suite("def f(*args, **kw): pass") ! self.check_suite("def f(**kw): pass") ! self.check_suite("def f(foo=bar): pass") ! self.check_suite("def f(foo=bar, *args): pass") ! self.check_suite("def f(foo=bar, *args, **kw): pass") ! self.check_suite("def f(foo=bar, **kw): pass") ! ! self.check_suite("def f(a, b): pass") ! self.check_suite("def f(a, b, *args): pass") ! self.check_suite("def f(a, b, *args, **kw): pass") ! self.check_suite("def f(a, b, **kw): pass") ! self.check_suite("def f(a, b, foo=bar): pass") ! self.check_suite("def f(a, b, foo=bar, *args): pass") ! self.check_suite("def f(a, b, foo=bar, *args, **kw): pass") ! self.check_suite("def f(a, b, foo=bar, **kw): pass") ! ! def test_import_from_statement(self): ! self.check_suite("from sys.path import *") ! self.check_suite("from sys.path import dirname") ! self.check_suite("from sys.path import dirname as my_dirname") ! self.check_suite("from sys.path import dirname, basename") ! self.check_suite( ! "from sys.path import dirname as my_dirname, basename") ! self.check_suite( ! "from sys.path import dirname, basename as my_basename") ! ! def test_basic_import_statement(self): ! self.check_suite("import sys") ! self.check_suite("import sys as system") ! self.check_suite("import sys, math") ! self.check_suite("import sys as system, math") ! self.check_suite("import sys, math as my_math") # *************** *** 127,222 **** # ! print ! print "Invalid parse trees:" - def check_bad_tree(tree, label): - print - print label - try: - parser.sequence2ast(tree) - except parser.ParserError: - print "caught expected exception for invalid tree" - else: - print "test failed: did not properly detect invalid tree:" - pprint.pprint(tree) - - - # not even remotely valid: - check_bad_tree((1, 2, 3), "") - - # print >>fp, - tree = \ - (257, - (264, - (265, - (266, - (268, - (1, 'print'), - (35, '>>'), - (290, - (291, - (292, - (293, - (295, - (296, - (297, - (298, (299, (300, (301, (302, (303, (1, 'fp')))))))))))))), - (12, ','))), - (4, ''))), - (0, '')) - - check_bad_tree(tree, "print >>fp,") - - # a,,c - tree = \ - (258, - (311, - (290, - (291, - (292, - (293, - (295, - (296, (297, (298, (299, (300, (301, (302, (303, (1, 'a')))))))))))))), - (12, ','), - (12, ','), - (290, - (291, - (292, - (293, - (295, - (296, (297, (298, (299, (300, (301, (302, (303, (1, 'c'))))))))))))))), - (4, ''), - (0, '')) - - check_bad_tree(tree, "a,,c") - - # a $= b - tree = \ - (257, - (264, - (265, - (266, - (267, - (312, - (291, - (292, - (293, - (294, - (296, - (297, - (298, - (299, (300, (301, (302, (303, (304, (1, 'a'))))))))))))))), - (268, (37, '$=')), - (312, - (291, - (292, - (293, - (294, - (296, - (297, - (298, - (299, (300, (301, (302, (303, (304, (1, 'b'))))))))))))))))), - (4, ''))), - (0, '')) ! check_bad_tree(tree, "a $= b") --- 126,226 ---- # ! class IllegalSyntaxTestCase(unittest.TestCase): ! def check_bad_tree(self, tree, label): ! try: ! parser.sequence2ast(tree) ! except parser.ParserError: ! pass ! else: ! self.fail("did not detect invalid tree for %r" % label) ! ! def test_junk(self): ! # not even remotely valid: ! self.check_bad_tree((1, 2, 3), "") ! ! def test_print_chevron_comma(self): ! "Illegal input: print >>fp,""" ! tree = \ ! (257, ! (264, ! (265, ! (266, ! (268, ! (1, 'print'), ! (35, '>>'), ! (290, ! (291, ! (292, ! (293, ! (295, ! (296, ! (297, ! (298, (299, (300, (301, (302, (303, (1, 'fp')))))))))))))), ! (12, ','))), ! (4, ''))), ! (0, '')) ! self.check_bad_tree(tree, "print >>fp,") ! ! def test_a_comma_comma_c(self): ! """Illegal input: a,,c""" ! tree = \ ! (258, ! (311, ! (290, ! (291, ! (292, ! (293, ! (295, ! (296, ! (297, ! (298, (299, (300, (301, (302, (303, (1, 'a')))))))))))))), ! (12, ','), ! (12, ','), ! (290, ! (291, ! (292, ! (293, ! (295, ! (296, ! (297, ! (298, (299, (300, (301, (302, (303, (1, 'c'))))))))))))))), ! (4, ''), ! (0, '')) ! self.check_bad_tree(tree, "a,,c") ! ! def test_illegal_operator(self): ! """Illegal input: a $= b""" ! tree = \ ! (257, ! (264, ! (265, ! (266, ! (267, ! (312, ! (291, ! (292, ! (293, ! (294, ! (296, ! (297, ! (298, ! (299, ! (300, (301, (302, (303, (304, (1, 'a'))))))))))))))), ! (268, (37, '$=')), ! (312, ! (291, ! (292, ! (293, ! (294, ! (296, ! (297, ! (298, ! (299, ! (300, (301, (302, (303, (304, (1, 'b'))))))))))))))))), ! (4, ''))), ! (0, '')) ! self.check_bad_tree(tree, "a $= b") ! test_support.run_unittest(RoundtripLegalSyntaxTestCase) ! test_support.run_unittest(IllegalSyntaxTestCase) From montanaro@users.sourceforge.net Mon Jun 4 16:30:43 2001 From: montanaro@users.sourceforge.net (Skip Montanaro) Date: Mon, 04 Jun 2001 08:30:43 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libos.tex,1.53.4.2,1.53.4.3 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv9402 Modified Files: Tag: release21-maint libos.tex Log Message: is -> if in rename description Index: libos.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libos.tex,v retrieving revision 1.53.4.2 retrieving revision 1.53.4.3 diff -C2 -r1.53.4.2 -r1.53.4.3 *** libos.tex 2001/05/31 20:27:18 1.53.4.2 --- libos.tex 2001/06/04 15:30:41 1.53.4.3 *************** *** 692,696 **** \var{dst} exists and is a file, it will be removed silently if the user has permission. The operation may fail on some \UNIX{} flavors ! is \var{src} and \var{dst} are on different filesystems. If successful, the renaming will be an atomic operation (this is a \POSIX{} requirement). On Windows, if \var{dst} already exists, --- 692,696 ---- \var{dst} exists and is a file, it will be removed silently if the user has permission. The operation may fail on some \UNIX{} flavors ! if \var{src} and \var{dst} are on different filesystems. If successful, the renaming will be an atomic operation (this is a \POSIX{} requirement). On Windows, if \var{dst} already exists, From montanaro@users.sourceforge.net Mon Jun 4 16:31:19 2001 From: montanaro@users.sourceforge.net (Skip Montanaro) Date: Mon, 04 Jun 2001 08:31:19 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libos.tex,1.55,1.56 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv9517 Modified Files: libos.tex Log Message: is -> if in rename description Index: libos.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libos.tex,v retrieving revision 1.55 retrieving revision 1.56 diff -C2 -r1.55 -r1.56 *** libos.tex 2001/05/31 20:27:46 1.55 --- libos.tex 2001/06/04 15:31:17 1.56 *************** *** 692,696 **** \var{dst} exists and is a file, it will be removed silently if the user has permission. The operation may fail on some \UNIX{} flavors ! is \var{src} and \var{dst} are on different filesystems. If successful, the renaming will be an atomic operation (this is a \POSIX{} requirement). On Windows, if \var{dst} already exists, --- 692,696 ---- \var{dst} exists and is a file, it will be removed silently if the user has permission. The operation may fail on some \UNIX{} flavors ! if \var{src} and \var{dst} are on different filesystems. If successful, the renaming will be an atomic operation (this is a \POSIX{} requirement). On Windows, if \var{dst} already exists, From tim_one@users.sourceforge.net Mon Jun 4 19:50:42 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Jun 2001 11:50:42 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0042.txt,1.50,1.51 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv626/python/nondist/peps Modified Files: pep-0042.txt Log Message: Added two math module feature requests. Index: pep-0042.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0042.txt,v retrieving revision 1.50 retrieving revision 1.51 diff -C2 -r1.50 -r1.51 *** pep-0042.txt 2001/03/17 19:52:32 1.50 --- pep-0042.txt 2001/06/04 18:50:40 1.51 *************** *** 7,10 **** --- 7,11 ---- Created: 12-Sep-2000 + Introduction *************** *** 63,66 **** --- 64,68 ---- http://sourceforge.net/bugs/?func=detailbug&bug_id=116405&group_id=5470 + Standard Library *************** *** 218,221 **** --- 220,231 ---- http://sourceforge.net/bugs/?func=detailbug&bug_id=132493&group_id=5470 + + - Fatter math module docs and docstrings. + + http://sf.net/tracker/?func=detail&aid=426539&group_id=5470&atid=105470 + + - New math module radians() and degrees() functions. + + http://sf.net/tracker/?func=detail&aid=426539&group_id=5470&atid=105470 From bwarsaw@users.sourceforge.net Mon Jun 4 19:59:55 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 04 Jun 2001 11:59:55 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_urllib.py,1.2,1.2.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv2658 Modified Files: Tag: release20-maint test_urllib.py Log Message: The SF patch (#129288 - urllib.py - chanign %02x to %02X in quoting) was applied to urllib.py, but the corresponding change to test_urllib.py was not applied. Backport revision 1.6 of this file into the 2.0 maintenance branch. ---------------------------- revision 1.6 date: 2001/01/19 07:00:08; author: tim_one; state: Exp; lines: +8 -3 urllib.py very recently changed to produce uppercase escapes, but no corresponding changes were made to its std test. ---------------------------- Index: test_urllib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_urllib.py,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -C2 -r1.2 -r1.2.2.1 *** test_urllib.py 2000/09/14 16:59:07 1.2 --- test_urllib.py 2001/06/04 18:59:53 1.2.2.1 *************** *** 9,13 **** '\320\321\322\323\324\325\326\330\331\332\333\334\335\336' ! expected = 'abcdefghijklmnopqrstuvwxyz%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f8%f9%fa%fb%fc%fd%fe%ffABCDEFGHIJKLMNOPQRSTUVWXYZ%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d8%d9%da%db%dc%dd%de' test = urllib.quote(chars) --- 9,13 ---- '\320\321\322\323\324\325\326\330\331\332\333\334\335\336' ! expected = 'abcdefghijklmnopqrstuvwxyz%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F8%F9%FA%FB%FC%FD%FE%FFABCDEFGHIJKLMNOPQRSTUVWXYZ%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D8%D9%DA%DB%DC%DD%DE' test = urllib.quote(chars) *************** *** 18,22 **** in1 = "abc/def" out1_1 = "abc/def" ! out1_2 = "abc%2fdef" assert urllib.quote(in1) == out1_1, "urllib.quote problem" --- 18,22 ---- in1 = "abc/def" out1_1 = "abc/def" ! out1_2 = "abc%2Fdef" assert urllib.quote(in1) == out1_1, "urllib.quote problem" *************** *** 24,28 **** in2 = "abc?def" ! out2_1 = "abc%3fdef" out2_2 = "abc?def" --- 24,28 ---- in2 = "abc?def" ! out2_1 = "abc%3Fdef" out2_2 = "abc?def" From bwarsaw@users.sourceforge.net Mon Jun 4 20:35:06 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 04 Jun 2001 12:35:06 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_mailbox.py,1.1,1.1.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv10256 Modified Files: Tag: release20-maint test_mailbox.py Log Message: Backported two fixes from the Py2.1 tree (pre-unittest rewrite): ---------------------------- revision 1.3 date: 2001/04/10 15:01:20; author: gvanrossum; state: Exp; lines: +6 -0 Some other tests, when failing, don't always remove their TESTFN file. Try to do it for them, so our mkdir() operation doesn't fail. ---------------------------- revision 1.2 date: 2001/03/02 05:46:17; author: gvanrossum; state: Exp; lines: +3 -3 When catching errors from os.rmdir(), test for os.error, not IOError! ---------------------------- except I used OSError instead of os.error. Index: test_mailbox.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_mailbox.py,v retrieving revision 1.1 retrieving revision 1.1.2.1 diff -C2 -r1.1 -r1.1.2.1 *** test_mailbox.py 2000/10/23 13:39:13 1.1 --- test_mailbox.py 2001/06/04 19:35:04 1.1.2.1 *************** *** 3,6 **** --- 3,12 ---- import test_support + # cleanup the turds of some of the other tests. :( + try: + os.unlink(test_support.TESTFN) + except OSError: + pass + # create a new maildir mailbox to work with: curdir = os.path.join(test_support.TESTFN, "cur") *************** *** 22,28 **** finally: try: os.rmdir(newdir) ! except IOError: pass try: os.rmdir(curdir) ! except IOError: pass try: os.rmdir(test_support.TESTFN) ! except IOError: pass --- 28,34 ---- finally: try: os.rmdir(newdir) ! except OSError: pass try: os.rmdir(curdir) ! except OSError: pass try: os.rmdir(test_support.TESTFN) ! except OSError: pass From tim_one@users.sourceforge.net Mon Jun 4 22:00:23 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Jun 2001 14:00:23 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.102,2.103 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv29125/python/dist/src/Objects Modified Files: dictobject.c Log Message: Store the mask instead of the size in dictobjects. The mask is more frequently used, and in particular this allows to drop the last remaining obvious time-waster in the crucial lookdict() and lookdict_string() functions. Other changes consist mostly of changing "i < ma_size" to "i <= ma_mask" everywhere. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.102 retrieving revision 2.103 diff -C2 -r2.102 -r2.103 *** dictobject.c 2001/06/03 04:54:32 2.102 --- dictobject.c 2001/06/04 21:00:21 2.103 *************** *** 163,167 **** int ma_fill; /* # Active + # Dummy */ int ma_used; /* # Active */ ! int ma_size; /* total # slots in ma_table */ /* ma_table points to ma_smalltable for small tables, else to * additional malloc'ed memory. ma_table is never NULL! This rule --- 163,173 ---- int ma_fill; /* # Active + # Dummy */ int ma_used; /* # Active */ ! ! /* The table contains ma_mask + 1 slots, and that's a power of 2. ! * We store the mask instead of the size because the mask is more ! * frequently needed. ! */ ! int ma_mask; ! /* ma_table points to ma_smalltable for small tables, else to * additional malloc'ed memory. ma_table is never NULL! This rule *************** *** 195,199 **** memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable)); \ (mp)->ma_table = (mp)->ma_smalltable; \ ! (mp)->ma_size = MINSIZE; \ (mp)->ma_used = (mp)->ma_fill = 0; \ } while(0) --- 201,205 ---- memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable)); \ (mp)->ma_table = (mp)->ma_smalltable; \ ! (mp)->ma_mask = MINSIZE - 1; \ (mp)->ma_used = (mp)->ma_fill = 0; \ } while(0) *************** *** 249,253 **** register unsigned int perturb; register dictentry *freeslot; ! register unsigned int mask = mp->ma_size-1; dictentry *ep0 = mp->ma_table; register dictentry *ep; --- 255,259 ---- register unsigned int perturb; register dictentry *freeslot; ! register unsigned int mask = mp->ma_mask; dictentry *ep0 = mp->ma_table; register dictentry *ep; *************** *** 360,364 **** register unsigned int perturb; register dictentry *freeslot; ! register unsigned int mask = mp->ma_size-1; dictentry *ep0 = mp->ma_table; register dictentry *ep; --- 366,370 ---- register unsigned int perturb; register dictentry *freeslot; ! register unsigned int mask = mp->ma_mask; dictentry *ep0 = mp->ma_table; register dictentry *ep; *************** *** 493,497 **** assert(newtable != oldtable); mp->ma_table = newtable; ! mp->ma_size = newsize; memset(newtable, 0, sizeof(dictentry) * newsize); mp->ma_used = 0; --- 499,503 ---- assert(newtable != oldtable); mp->ma_table = newtable; ! mp->ma_mask = newsize - 1; memset(newtable, 0, sizeof(dictentry) * newsize); mp->ma_used = 0; *************** *** 581,585 **** return -1; } ! assert(mp->ma_fill < mp->ma_size); n_used = mp->ma_used; Py_INCREF(value); --- 587,591 ---- return -1; } ! assert(mp->ma_fill <= mp->ma_mask); /* at least one empty slot */ n_used = mp->ma_used; Py_INCREF(value); *************** *** 592,596 **** * deleted). */ ! if (mp->ma_used > n_used && mp->ma_fill*3 >= mp->ma_size*2) { if (dictresize(mp, mp->ma_used*2) != 0) return -1; --- 598,602 ---- * deleted). */ ! if (mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2) { if (dictresize(mp, mp->ma_used*2) != 0) return -1; *************** *** 653,657 **** mp = (dictobject *)op; #ifdef Py_DEBUG ! n = mp->ma_size; i = 0; #endif --- 659,663 ---- mp = (dictobject *)op; #ifdef Py_DEBUG ! n = mp->ma_mask + 1; i = 0; #endif *************** *** 722,729 **** if (i < 0) return 0; ! while (i < mp->ma_size && mp->ma_table[i].me_value == NULL) i++; *ppos = i+1; ! if (i >= mp->ma_size) return 0; if (pkey) --- 728,735 ---- if (i < 0) return 0; ! while (i <= mp->ma_mask && mp->ma_table[i].me_value == NULL) i++; *ppos = i+1; ! if (i > mp->ma_mask) return 0; if (pkey) *************** *** 773,777 **** fprintf(fp, "{"); any = 0; ! for (i = 0; i < mp->ma_size; i++) { dictentry *ep = mp->ma_table + i; PyObject *pvalue = ep->me_value; --- 779,783 ---- fprintf(fp, "{"); any = 0; ! for (i = 0; i <= mp->ma_mask; i++) { dictentry *ep = mp->ma_table + i; PyObject *pvalue = ep->me_value; *************** *** 820,824 **** colon = PyString_FromString(": "); any = 0; ! for (i = 0; i < mp->ma_size && v; i++) { dictentry *ep = mp->ma_table + i; PyObject *pvalue = ep->me_value; --- 826,830 ---- colon = PyString_FromString(": "); any = 0; ! for (i = 0; i <= mp->ma_mask && v; i++) { dictentry *ep = mp->ma_table + i; PyObject *pvalue = ep->me_value; *************** *** 906,910 **** goto again; } ! for (i = 0, j = 0; i < mp->ma_size; i++) { if (mp->ma_table[i].me_value != NULL) { PyObject *key = mp->ma_table[i].me_key; --- 912,916 ---- goto again; } ! for (i = 0, j = 0; i <= mp->ma_mask; i++) { if (mp->ma_table[i].me_value != NULL) { PyObject *key = mp->ma_table[i].me_key; *************** *** 937,941 **** goto again; } ! for (i = 0, j = 0; i < mp->ma_size; i++) { if (mp->ma_table[i].me_value != NULL) { PyObject *value = mp->ma_table[i].me_value; --- 943,947 ---- goto again; } ! for (i = 0, j = 0; i <= mp->ma_mask; i++) { if (mp->ma_table[i].me_value != NULL) { PyObject *value = mp->ma_table[i].me_value; *************** *** 982,986 **** } /* Nothing we do below makes any function calls. */ ! for (i = 0, j = 0; i < mp->ma_size; i++) { if (mp->ma_table[i].me_value != NULL) { key = mp->ma_table[i].me_key; --- 988,992 ---- } /* Nothing we do below makes any function calls. */ ! for (i = 0, j = 0; i <= mp->ma_mask; i++) { if (mp->ma_table[i].me_value != NULL) { key = mp->ma_table[i].me_key; *************** *** 1011,1019 **** resizing as we insert new items. Expect that there will be no (or few) overlapping keys. */ ! if ((mp->ma_fill + other->ma_used)*3 >= mp->ma_size*2) { if (dictresize(mp, (mp->ma_used + other->ma_used)*3/2) != 0) return NULL; } ! for (i = 0; i < other->ma_size; i++) { entry = &other->ma_table[i]; if (entry->me_value != NULL) { --- 1017,1025 ---- resizing as we insert new items. Expect that there will be no (or few) overlapping keys. */ ! if ((mp->ma_fill + other->ma_used)*3 >= (mp->ma_mask+1)*2) { if (dictresize(mp, (mp->ma_used + other->ma_used)*3/2) != 0) return NULL; } ! for (i = 0; i <= other->ma_mask; i++) { entry = &other->ma_table[i]; if (entry->me_value != NULL) { *************** *** 1056,1060 **** if (dictresize(copy, mp->ma_used*3/2) != 0) return NULL; ! for (i = 0; i < mp->ma_size; i++) { entry = &mp->ma_table[i]; if (entry->me_value != NULL) { --- 1062,1066 ---- if (dictresize(copy, mp->ma_used*3/2) != 0) return NULL; ! for (i = 0; i <= mp->ma_mask; i++) { entry = &mp->ma_table[i]; if (entry->me_value != NULL) { *************** *** 1124,1128 **** int i, cmp; ! for (i = 0; i < a->ma_size; i++) { PyObject *thiskey, *thisaval, *thisbval; if (a->ma_table[i].me_value == NULL) --- 1130,1134 ---- int i, cmp; ! for (i = 0; i <= a->ma_mask; i++) { PyObject *thiskey, *thisaval, *thisbval; if (a->ma_table[i].me_value == NULL) *************** *** 1137,1141 **** } if (cmp > 0 || ! i >= a->ma_size || a->ma_table[i].me_value == NULL) { --- 1143,1147 ---- } if (cmp > 0 || ! i > a->ma_mask || a->ma_table[i].me_value == NULL) { *************** *** 1252,1256 **** /* Same # of entries -- check all of 'em. Exit early on any diff. */ ! for (i = 0; i < a->ma_size; i++) { PyObject *aval = a->ma_table[i].me_value; if (aval != NULL) { --- 1258,1262 ---- /* Same # of entries -- check all of 'em. Exit early on any diff. */ ! for (i = 0; i <= a->ma_mask; i++) { PyObject *aval = a->ma_table[i].me_value; if (aval != NULL) { *************** *** 1428,1436 **** * or the table shrunk -- simply make sure it's in bounds now. */ ! if (i >= mp->ma_size || i < 1) i = 1; /* skip slot 0 */ while ((ep = &mp->ma_table[i])->me_value == NULL) { i++; ! if (i >= mp->ma_size) i = 1; } --- 1434,1442 ---- * or the table shrunk -- simply make sure it's in bounds now. */ ! if (i > mp->ma_mask || i < 1) i = 1; /* skip slot 0 */ while ((ep = &mp->ma_table[i])->me_value == NULL) { i++; ! if (i > mp->ma_mask) i = 1; } From gvanrossum@users.sourceforge.net Mon Jun 4 22:21:13 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 04 Jun 2001 14:21:13 -0700 Subject: [Python-checkins] CVS: python/dist/src/Tools/idle extend.txt,1.3,1.4 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/idle In directory usw-pr-cvs1:/tmp/cvs-serv4092 Modified Files: extend.txt Log Message: Quick update to the extension mechanism (extend.py is gone, long live config.txt). *** This is a bugfix-release candidate (for 2.1.1 and 2.0.1)! *** Index: extend.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/idle/extend.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -r1.3 -r1.4 *** extend.txt 1999/04/20 17:32:52 1.3 --- extend.txt 2001/06/04 21:21:11 1.4 *************** *** 8,12 **** The list of extensions loaded at startup time is configured by editing ! the file extend.py; see below for details. An IDLE extension is defined by a class. Methods of the class define --- 8,12 ---- The list of extensions loaded at startup time is configured by editing ! the file config.txt; see below for details. An IDLE extension is defined by a class. Methods of the class define *************** *** 87,95 **** "...Do what you want here..." ! The final piece of the puzzle is the file "extend.py", which contains a ! simple table used to configure the loading of extensions. This file ! currently contains a single list variable named "standard", which is a ! list of extension names that are to be loaded. (In the future, other ! configuration variables may be added to this module.) Extensions can define key bindings and menu entries that reference --- 87,109 ---- "...Do what you want here..." ! The final piece of the puzzle is the file "config.txt", which is used ! to to configure the loading of extensions. For each extension, ! you must include a section in config.txt (or in any of the other ! configuration files that are consulted at startup: config-unix.txt, ! config-win.txt, or ~/.idle). A section is headed by the module name ! in square brackets, e.g. ! ! [ZoomHeight] ! ! The section may be empty, or it may define configuration options for ! the extension. (See ParenMatch.py for an example.) A special option ! is 'enable': including ! ! enable = 0 ! ! in a section disables that extension. More than one configuration ! file may specify options for the same extension, so a user may disable ! an extension that is loaded by default, or enable an extension that is ! disabled by default. Extensions can define key bindings and menu entries that reference From fdrake@users.sourceforge.net Tue Jun 5 03:17:04 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 04 Jun 2001 19:17:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/ref ref5.tex,1.45,1.46 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory usw-pr-cvs1:/tmp/cvs-serv6705/ref Modified Files: ref5.tex Log Message: Update a "Programmer's note" about lambda forms and scoping to reflect the availability of nested scoping in Python 2.1 and 2.2. Index: ref5.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref5.tex,v retrieving revision 1.45 retrieving revision 1.46 diff -C2 -r1.45 -r1.46 *** ref5.tex 2001/05/09 16:51:49 1.45 --- ref5.tex 2001/06/05 02:17:02 1.46 *************** *** 870,878 **** \indexii{anonmymous}{function} ! \strong{Programmer's note:} a lambda form defined inside a function ! has no access to names defined in the function's namespace. This is ! because Python has only two scopes: local and global. A common ! work-around is to use default argument values to pass selected ! variables into the lambda's namespace, e.g.: \begin{verbatim} --- 870,878 ---- \indexii{anonmymous}{function} ! \strong{Programmer's note:} Prior to Python 2.1, a lambda form defined ! inside a function has no access to names defined in the function's ! namespace. This is because Python had only two scopes: local and ! global. A common work-around was to use default argument values to ! pass selected variables into the lambda's namespace, e.g.: \begin{verbatim} *************** *** 880,883 **** --- 880,897 ---- return lambda x, n=increment: x+n \end{verbatim} + + As of Python 2.1, nested scopes were introduced, and this work-around + has not been necessary. Python 2.1 supports nested scopes in modules + which include the statement \samp{from __future__ import + nested_scopes}, and more recent versions of Python enable nested + scopes by default. This version works starting with Python 2.1: + + \begin{verbatim} + from __future__ import nested_scopes + + def make_incrementor(increment): + return lambda x: x+increment + \end{verbatim} + \section{Expression lists\label{exprlists}} From fdrake@users.sourceforge.net Tue Jun 5 03:24:29 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 04 Jun 2001 19:24:29 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/ref ref5.tex,1.43.2.1,1.43.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory usw-pr-cvs1:/tmp/cvs-serv7965/ref Modified Files: Tag: release21-maint ref5.tex Log Message: Update a "Programmer's note" about lambda forms and scoping to reflect the availability of nested scoping in Python 2.1. Note that this is a slightly different patch than was applied to the trunk of the development for Python 2.2. Index: ref5.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref5.tex,v retrieving revision 1.43.2.1 retrieving revision 1.43.2.2 diff -C2 -r1.43.2.1 -r1.43.2.2 *** ref5.tex 2001/05/09 16:53:19 1.43.2.1 --- ref5.tex 2001/06/05 02:24:26 1.43.2.2 *************** *** 868,876 **** \indexii{anonmymous}{function} ! \strong{Programmer's note:} a lambda form defined inside a function ! has no access to names defined in the function's namespace. This is ! because Python has only two scopes: local and global. A common ! work-around is to use default argument values to pass selected ! variables into the lambda's namespace, e.g.: \begin{verbatim} --- 868,876 ---- \indexii{anonmymous}{function} ! \strong{Programmer's note:} Prior to Python 2.1, a lambda form defined ! inside a function has no access to names defined in the function's ! namespace. This is because Python had only two scopes: local and ! global. A common work-around was to use default argument values to ! pass selected variables into the lambda's namespace, e.g.: \begin{verbatim} *************** *** 878,881 **** --- 878,895 ---- return lambda x, n=increment: x+n \end{verbatim} + + Python 2.1 introduced nested scopes as an optional feature, and this + work-around has not been necessary when the feature is enabled. The + use of nested scopes is enabled by the statement \samp{from __future__ + import nested_scopes}; future versions of Python will enable nested + scopes by default. This version works starting with Python 2.1: + + \begin{verbatim} + from __future__ import nested_scopes + + def make_incrementor(increment): + return lambda x: x+increment + \end{verbatim} + \section{Expression lists\label{exprlists}} From tim_one@users.sourceforge.net Tue Jun 5 05:43:28 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Jun 2001 21:43:28 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules arraymodule.c,2.62,2.63 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv30144/python/dist/src/Modules Modified Files: arraymodule.c Log Message: Make it possible to find the use of tp_as_buffer here with a global search. (Just a change to a comment) Index: arraymodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/arraymodule.c,v retrieving revision 2.62 retrieving revision 2.63 diff -C2 -r2.62 -r2.63 *** arraymodule.c 2001/01/25 22:12:43 2.62 --- arraymodule.c 2001/06/05 04:43:26 2.63 *************** *** 1543,1547 **** 0, /* tp_getattro */ 0, /* tp_setattro */ ! &array_as_buffer, /* tp_as _buffer*/ Py_TPFLAGS_DEFAULT, /* tp_flags */ arraytype_doc, /* tp_doc */ --- 1543,1547 ---- 0, /* tp_getattro */ 0, /* tp_setattro */ ! &array_as_buffer, /* tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /* tp_flags */ arraytype_doc, /* tp_doc */ From loewis@users.sourceforge.net Tue Jun 5 06:17:02 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Mon, 04 Jun 2001 22:17:02 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib mimetypes.py,1.13,1.14 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv1580 Modified Files: mimetypes.py Log Message: Add .pyo as an extension, fixes bug #416462. Also restore alphabetic order. Index: mimetypes.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/mimetypes.py,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -r1.13 -r1.14 *** mimetypes.py 2001/02/09 09:44:47 1.13 --- mimetypes.py 2001/06/05 05:17:00 1.14 *************** *** 198,204 **** '.png': 'image/png', '.ppm': 'image/x-portable-pixmap', '.py': 'text/x-python', '.pyc': 'application/x-python-code', ! '.ps': 'application/postscript', '.qt': 'video/quicktime', '.ras': 'image/x-cmu-raster', --- 198,205 ---- '.png': 'image/png', '.ppm': 'image/x-portable-pixmap', + '.ps': 'application/postscript', '.py': 'text/x-python', '.pyc': 'application/x-python-code', ! '.pyo': 'application/x-python-code', '.qt': 'video/quicktime', '.ras': 'image/x-cmu-raster', From loewis@users.sourceforge.net Tue Jun 5 06:33:21 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Mon, 04 Jun 2001 22:33:21 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib dbhash.py,1.5,1.6 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv3378/Lib Modified Files: dbhash.py Log Message: Fix bug #422702: Make flag argument to open optional, and document it that way. Index: dbhash.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/dbhash.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -r1.5 -r1.6 *** dbhash.py 2001/01/25 13:47:00 1.5 --- dbhash.py 2001/06/05 05:33:19 1.6 *************** *** 13,16 **** error = bsddb.error # Exported for anydbm ! def open(file, flag, mode=0666): return bsddb.hashopen(file, flag, mode) --- 13,16 ---- error = bsddb.error # Exported for anydbm ! def open(file, flag = 'r', mode=0666): return bsddb.hashopen(file, flag, mode) From loewis@users.sourceforge.net Tue Jun 5 06:33:21 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Mon, 04 Jun 2001 22:33:21 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libdbhash.tex,1.3,1.4 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv3378/Doc/lib Modified Files: libdbhash.tex Log Message: Fix bug #422702: Make flag argument to open optional, and document it that way. Index: libdbhash.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libdbhash.tex,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -r1.3 -r1.4 *** libdbhash.tex 1999/04/19 21:19:21 1.3 --- libdbhash.tex 2001/06/05 05:33:19 1.4 *************** *** 22,26 **** \end{excdesc} ! \begin{funcdesc}{open}{path, flag\optional{, mode}} Open a \code{db} database and return the database object. The \var{path} argument is the name of the database file. --- 22,26 ---- \end{excdesc} ! \begin{funcdesc}{open}{path, \optional{, flag\optional{, mode}}} Open a \code{db} database and return the database object. The \var{path} argument is the name of the database file. From loewis@users.sourceforge.net Tue Jun 5 06:58:46 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Mon, 04 Jun 2001 22:58:46 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include rangeobject.h,2.15,2.16 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv6223 Modified Files: rangeobject.h Log Message: Wrap with extern "C". Fixes bug #428419. Also protect against multiple inclusion. Index: rangeobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/rangeobject.h,v retrieving revision 2.15 retrieving revision 2.16 diff -C2 -r2.15 -r2.16 *** rangeobject.h 2000/09/01 23:29:26 2.15 --- rangeobject.h 2001/06/05 05:58:44 2.16 *************** *** 2,5 **** --- 2,11 ---- /* Range object interface */ + #ifndef Py_RANGEOBJECT_H + #define Py_RANGEOBJECT_H + #ifdef __cplusplus + extern "C" { + #endif + /* A range object represents an integer range. This is an immutable object; *************** *** 15,16 **** --- 21,27 ---- extern DL_IMPORT(PyObject *) PyRange_New(long, long, long, int); + + #ifdef __cplusplus + } + #endif + #endif /* !Py_RANGEOBJECT_H */ From gvanrossum@users.sourceforge.net Tue Jun 5 11:33:50 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 03:33:50 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.1.2.8,1.1.2.9 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv19068 Modified Files: Tag: descr-branch test_descr.py Log Message: Somehow a "global log" (or a "from __future__ import nested_scopes" :-) was missing from the pymods() test function. It couldn't have worked. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/Attic/test_descr.py,v retrieving revision 1.1.2.8 retrieving revision 1.1.2.9 diff -C2 -r1.1.2.8 -r1.1.2.9 *** test_descr.py 2001/05/22 20:04:03 1.1.2.8 --- test_descr.py 2001/06/05 10:33:48 1.1.2.9 *************** *** 314,317 **** --- 314,318 ---- def pymods(): if verbose: print "Testing Python subclass of module..." + global log log = [] class MM(MT): From gvanrossum@users.sourceforge.net Tue Jun 5 11:49:26 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 03:49:26 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include object.h,2.79.2.8,2.79.2.9 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv20188/Include Modified Files: Tag: descr-branch object.h Log Message: Redo object creation; touching many files. - Get rid of tp_construct, it had a bogus interface (this moves tp_dictoffset one slot up). - New tp_ slots; the last two are "type methods" (their first argument is a type object, not an instance of that type): - tp_init is what tp_construct wanted to be, without the allocation; - tp_alloc does low-level allocation, initializing the object to its most basic form (up to and including registering it with the GC machinery); - tp_new does high-level object creation: it calls tp_alloc and then tp_init. - New generic functions PyType_GenericAlloc() and PyType_GenericNew() provide default implementations for tp_alloc and tp_new that are usually sufficient. - Used the above things to make standard list, dict and module objects subtypable as before. - Remove tp_construct initializer spacer from funcobject.c. - Add an __init__() override test to test_descr.py. Index: object.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/object.h,v retrieving revision 2.79.2.8 retrieving revision 2.79.2.9 diff -C2 -r2.79.2.8 -r2.79.2.9 *** object.h 2001/05/22 17:21:18 2.79.2.8 --- object.h 2001/06/05 10:49:24 2.79.2.9 *************** *** 205,208 **** --- 205,210 ---- typedef PyObject *(*descrgetfunc) (PyObject *, PyObject *); typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *); + typedef int (*initproc)(PyObject *, PyObject *, PyObject *); + typedef PyObject *(*allocfunc)(struct _typeobject *, PyObject *, PyObject *); typedef struct _typeobject { *************** *** 266,273 **** descrgetfunc tp_descr_get; descrsetfunc tp_descr_set; - ternaryfunc tp_construct; long tp_dictoffset; - #ifdef COUNT_ALLOCS /* these must be last and never explicitly initialized */ --- 268,276 ---- descrgetfunc tp_descr_get; descrsetfunc tp_descr_set; long tp_dictoffset; + initproc tp_init; + allocfunc tp_alloc; + allocfunc tp_new; #ifdef COUNT_ALLOCS /* these must be last and never explicitly initialized */ *************** *** 290,293 **** --- 293,300 ---- extern DL_IMPORT(int) PyType_InitDict(PyTypeObject *); + extern DL_IMPORT(PyObject *) PyType_GenericAlloc(PyTypeObject *, + PyObject *, PyObject *); + extern DL_IMPORT(PyObject *) PyType_GenericNew(PyTypeObject *, + PyObject *, PyObject *); /* Generic operations on objects */ From gvanrossum@users.sourceforge.net Tue Jun 5 11:49:26 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 03:49:26 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.1.2.9,1.1.2.10 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv20188/Lib/test Modified Files: Tag: descr-branch test_descr.py Log Message: Redo object creation; touching many files. - Get rid of tp_construct, it had a bogus interface (this moves tp_dictoffset one slot up). - New tp_ slots; the last two are "type methods" (their first argument is a type object, not an instance of that type): - tp_init is what tp_construct wanted to be, without the allocation; - tp_alloc does low-level allocation, initializing the object to its most basic form (up to and including registering it with the GC machinery); - tp_new does high-level object creation: it calls tp_alloc and then tp_init. - New generic functions PyType_GenericAlloc() and PyType_GenericNew() provide default implementations for tp_alloc and tp_new that are usually sufficient. - Used the above things to make standard list, dict and module objects subtypable as before. - Remove tp_construct initializer spacer from funcobject.c. - Add an __init__() override test to test_descr.py. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/Attic/test_descr.py,v retrieving revision 1.1.2.9 retrieving revision 1.1.2.10 diff -C2 -r1.1.2.9 -r1.1.2.10 *** test_descr.py 2001/06/05 10:33:48 1.1.2.9 --- test_descr.py 2001/06/05 10:49:24 1.1.2.10 *************** *** 317,320 **** --- 317,322 ---- log = [] class MM(MT): + def __init__(self): + MT.__init__(self) def __getattr__(self, name): log.append(("getattr", name)) *************** *** 330,338 **** x = a.foo del a.foo ! verify(log == [('getattr', '__setattr__'), ("setattr", "foo", 12), ("getattr", "foo"), ('getattr', '__delattr__'), ! ("delattr", "foo")]) def all(): --- 332,341 ---- x = a.foo del a.foo ! verify(log == [('getattr', '__init__'), ! ('getattr', '__setattr__'), ("setattr", "foo", 12), ("getattr", "foo"), ('getattr', '__delattr__'), ! ("delattr", "foo")], log) def all(): From gvanrossum@users.sourceforge.net Tue Jun 5 11:49:26 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 03:49:26 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules spam.c,1.1.2.4,1.1.2.5 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv20188/Modules Modified Files: Tag: descr-branch spam.c Log Message: Redo object creation; touching many files. - Get rid of tp_construct, it had a bogus interface (this moves tp_dictoffset one slot up). - New tp_ slots; the last two are "type methods" (their first argument is a type object, not an instance of that type): - tp_init is what tp_construct wanted to be, without the allocation; - tp_alloc does low-level allocation, initializing the object to its most basic form (up to and including registering it with the GC machinery); - tp_new does high-level object creation: it calls tp_alloc and then tp_init. - New generic functions PyType_GenericAlloc() and PyType_GenericNew() provide default implementations for tp_alloc and tp_new that are usually sufficient. - Used the above things to make standard list, dict and module objects subtypable as before. - Remove tp_construct initializer spacer from funcobject.c. - Add an __init__() override test to test_descr.py. Index: spam.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/Attic/spam.c,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -C2 -r1.1.2.4 -r1.1.2.5 *** spam.c 2001/05/14 21:41:41 1.1.2.4 --- spam.c 2001/06/05 10:49:24 1.1.2.5 *************** *** 38,60 **** staticforward PyTypeObject spamlist_type; ! static PyObject * ! spamlist_construct(spamlistobject *arg, PyObject *args, PyObject *kwds) { ! spamlistobject *self; ! ! if (arg != NULL) ! self = arg; ! else { ! self = PyObject_New(spamlistobject, &spamlist_type); ! if (self == NULL) ! return NULL; ! } ! if (PyList_Type.tp_construct((PyObject *)self, args, kwds) == NULL) { ! if (self != arg) ! PyObject_Del(self); ! return NULL; ! } self->state = 0; ! return (PyObject *)self; } --- 38,48 ---- staticforward PyTypeObject spamlist_type; ! static int ! spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds) { ! if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0) ! return -1; self->state = 0; ! return 0; } *************** *** 95,99 **** 0, /* tp_descr_get */ 0, /* tp_descr_set */ ! (ternaryfunc)spamlist_construct, /* tp_construct */ }; --- 83,90 ---- 0, /* tp_descr_get */ 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! (initproc)spamlist_init, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ ! PyType_GenericNew, /* tp_new */ }; *************** *** 141,163 **** staticforward PyTypeObject spamdict_type; ! static PyObject * ! spamdict_construct(spamdictobject *arg, PyObject *args, PyObject *kwds) { ! spamdictobject *self; ! ! if (arg != NULL) ! self = arg; ! else { ! self = PyObject_New(spamdictobject, &spamdict_type); ! if (self == NULL) ! return NULL; ! } ! if (PyDict_Type.tp_construct((PyObject *)self, args, kwds) == NULL) { ! if (self != arg) ! PyObject_Del(self); ! return NULL; ! } self->state = 0; ! return (PyObject *)self; } --- 132,142 ---- staticforward PyTypeObject spamdict_type; ! static int ! spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds) { ! if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0) ! return -1; self->state = 0; ! return 0; } *************** *** 198,202 **** 0, /* tp_descr_get */ 0, /* tp_descr_set */ ! (ternaryfunc)spamdict_construct, /* tp_construct */ }; --- 177,184 ---- 0, /* tp_descr_get */ 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! (initproc)spamdict_init, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ ! PyType_GenericNew, /* tp_new */ }; From gvanrossum@users.sourceforge.net Tue Jun 5 11:49:26 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 03:49:26 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.80.2.6,2.80.2.7 funcobject.c,2.37.4.3,2.37.4.4 listobject.c,2.92.6.4,2.92.6.5 moduleobject.c,2.31.6.2,2.31.6.3 typeobject.c,2.16.8.25,2.16.8.26 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv20188/Objects Modified Files: Tag: descr-branch dictobject.c funcobject.c listobject.c moduleobject.c typeobject.c Log Message: Redo object creation; touching many files. - Get rid of tp_construct, it had a bogus interface (this moves tp_dictoffset one slot up). - New tp_ slots; the last two are "type methods" (their first argument is a type object, not an instance of that type): - tp_init is what tp_construct wanted to be, without the allocation; - tp_alloc does low-level allocation, initializing the object to its most basic form (up to and including registering it with the GC machinery); - tp_new does high-level object creation: it calls tp_alloc and then tp_init. - New generic functions PyType_GenericAlloc() and PyType_GenericNew() provide default implementations for tp_alloc and tp_new that are usually sufficient. - Used the above things to make standard list, dict and module objects subtypable as before. - Remove tp_construct initializer spacer from funcobject.c. - Add an __init__() override test to test_descr.py. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.80.2.6 retrieving revision 2.80.2.7 diff -C2 -r2.80.2.6 -r2.80.2.7 *** dictobject.c 2001/05/22 04:00:17 2.80.2.6 --- dictobject.c 2001/06/05 10:49:24 2.80.2.7 *************** *** 1277,1285 **** staticforward PyObject *dictiter_new(dictobject *); ! static PyObject * ! dict_construct(PyDictObject *self, PyObject *args, PyObject *kw) { - if (self == NULL) - return PyDict_New(); self->ma_size = 0; self->ma_poly = 0; --- 1277,1283 ---- staticforward PyObject *dictiter_new(dictobject *); ! static int ! dict_init(PyDictObject *self, PyObject *args, PyObject *kw) { self->ma_size = 0; self->ma_poly = 0; *************** *** 1291,1295 **** ++created; #endif ! return (PyObject *)self; } --- 1289,1293 ---- ++created; #endif ! return 0; } *************** *** 1330,1334 **** 0, /* tp_descr_get */ 0, /* tp_descr_set */ ! (ternaryfunc)dict_construct, /* tp_construct */ }; --- 1328,1335 ---- 0, /* tp_descr_get */ 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! (initproc)dict_init, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ ! PyType_GenericNew, /* tp_new */ }; Index: funcobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/funcobject.c,v retrieving revision 2.37.4.3 retrieving revision 2.37.4.4 diff -C2 -r2.37.4.3 -r2.37.4.4 *** funcobject.c 2001/05/11 20:45:22 2.37.4.3 --- funcobject.c 2001/06/05 10:49:24 2.37.4.4 *************** *** 377,381 **** func_descr_get, /* tp_descr_get */ 0, /* tp_descr_set */ - 0, /* tp_construct */ offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */ }; --- 377,380 ---- Index: listobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v retrieving revision 2.92.6.4 retrieving revision 2.92.6.5 diff -C2 -r2.92.6.4 -r2.92.6.5 *** listobject.c 2001/05/14 21:35:52 2.92.6.4 --- listobject.c 2001/06/05 10:49:24 2.92.6.5 *************** *** 1243,1246 **** --- 1243,1247 ---- int err; PyObject *compare = NULL; + PyTypeObject *savetype; if (args != NULL) { *************** *** 1248,1256 **** return NULL; } self->ob_type = &immutable_list_type; err = samplesortslice(self->ob_item, self->ob_item + self->ob_size, compare); ! self->ob_type = &PyList_Type; if (err < 0) return NULL; --- 1249,1258 ---- return NULL; } + savetype = self->ob_type; self->ob_type = &immutable_list_type; err = samplesortslice(self->ob_item, self->ob_item + self->ob_size, compare); ! self->ob_type = savetype; if (err < 0) return NULL; *************** *** 1495,1506 **** } ! static PyObject * ! list_construct(PyListObject *self, PyObject *args, PyObject *kw) { - if (self == NULL) - return PyList_New(0); self->ob_size = 0; self->ob_item = NULL; ! return (PyObject *)self; } --- 1497,1506 ---- } ! static int ! list_init(PyListObject *self, PyObject *args, PyObject *kw) { self->ob_size = 0; self->ob_item = NULL; ! return 0; } *************** *** 1586,1590 **** 0, /* tp_descr_get */ 0, /* tp_descr_set */ ! (ternaryfunc)list_construct, /* tp_construct */ }; --- 1586,1593 ---- 0, /* tp_descr_get */ 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! (initproc)list_init, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ ! PyType_GenericNew, /* tp_new */ }; *************** *** 1669,1673 **** 0, /* tp_descr_get */ 0, /* tp_descr_set */ ! (ternaryfunc)list_construct, /* tp_construct */ /* NOTE: This is *not* the standard list_type struct! */ }; --- 1672,1676 ---- 0, /* tp_descr_get */ 0, /* tp_descr_set */ ! 0, /* tp_init */ /* NOTE: This is *not* the standard list_type struct! */ }; Index: moduleobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/moduleobject.c,v retrieving revision 2.31.6.2 retrieving revision 2.31.6.3 diff -C2 -r2.31.6.2 -r2.31.6.3 *** moduleobject.c 2001/05/12 20:40:47 2.31.6.2 --- moduleobject.c 2001/06/05 10:49:24 2.31.6.3 *************** *** 135,147 **** /* Methods */ ! static PyObject * ! module_construct(PyModuleObject *m, PyObject *args, PyObject *kw) { - if (m == NULL) - return PyModule_New("?"); m->md_dict = PyDict_New(); if (m->md_dict == NULL) ! return NULL; ! return (PyObject *)m; } --- 135,145 ---- /* Methods */ ! static int ! module_init(PyModuleObject *m, PyObject *args, PyObject *kw) { m->md_dict = PyDict_New(); if (m->md_dict == NULL) ! return -1; ! return 0; } *************** *** 226,230 **** 0, /* tp_descr_get */ 0, /* tp_descr_set */ - (ternaryfunc)module_construct, /* tp_construct */ offsetof(PyModuleObject, md_dict), /* tp_dictoffset */ }; --- 224,230 ---- 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(PyModuleObject, md_dict), /* tp_dictoffset */ + (initproc)module_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ }; Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.25 retrieving revision 2.16.8.26 diff -C2 -r2.16.8.25 -r2.16.8.26 *** typeobject.c 2001/05/22 19:53:15 2.16.8.25 --- typeobject.c 2001/06/05 10:49:24 2.16.8.26 *************** *** 56,64 **** type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) { ! int size; ! void *mem; ! PyObject *obj, *res; ! ! if (type->tp_construct == NULL) { PyErr_Format(PyExc_TypeError, "cannot construct '%.100s' instances", --- 56,60 ---- type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) { ! if (type->tp_new == NULL) { PyErr_Format(PyExc_TypeError, "cannot construct '%.100s' instances", *************** *** 67,70 **** --- 63,76 ---- } + return type->tp_new(type, args, kwds); + } + + PyObject * + PyType_GenericAlloc(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + int size; + void *mem; + PyObject *obj; + /* Inline PyObject_New() so we can zero the memory */ size = _PyObject_SIZE(type); *************** *** 80,92 **** Py_INCREF(type); PyObject_INIT(obj, type); ! res = (type->tp_construct)(obj, args, kwds); ! if (res == NULL) { ! Py_DECREF(obj); return NULL; } ! if (PyType_IS_GC(type)) ! PyObject_GC_Init(res); ! return res; } --- 86,107 ---- Py_INCREF(type); PyObject_INIT(obj, type); + if (PyType_IS_GC(type)) + PyObject_GC_Init(obj); + return obj; + } ! PyObject * ! PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds) ! { ! PyObject *self; ! ! self = type->tp_alloc(type, args, kwds); ! if (self == NULL) ! return NULL; ! if (type->tp_init(self, args, kwds) < 0) { ! Py_DECREF(self); return NULL; } ! return self; } *************** *** 133,137 **** /* TypeType's constructor is called when a type is subclassed */ static PyObject * ! type_construct(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *name, *bases, *dict, *x, *slots; --- 148,152 ---- /* TypeType's constructor is called when a type is subclassed */ static PyObject * ! type_init(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *name, *bases, *dict, *x, *slots; *************** *** 167,171 **** return NULL; } ! if (base->tp_construct == NULL) { PyErr_SetString(PyExc_TypeError, "base type must have a constructor slot"); --- 182,186 ---- return NULL; } ! if (base->tp_init == NULL) { PyErr_SetString(PyExc_TypeError, "base type must have a constructor slot"); *************** *** 337,342 **** 0, /* tp_descr_get */ 0, /* tp_descr_set */ - (ternaryfunc)type_construct, /* tp_construct */ offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ }; --- 352,359 ---- 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ + (initproc)type_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ }; *************** *** 580,585 **** COPYSLOT(tp_descr_get); COPYSLOT(tp_descr_set); - COPYSLOT(tp_construct); COPYSLOT(tp_dictoffset); } --- 597,604 ---- COPYSLOT(tp_descr_get); COPYSLOT(tp_descr_set); COPYSLOT(tp_dictoffset); + COPYSLOT(tp_init); + COPYSLOT(tp_alloc); + COPYSLOT(tp_new); } *************** *** 1137,1149 **** wrap_init(PyObject *self, PyObject *args, void *wrapped) { ! ternaryfunc func = (ternaryfunc)wrapped; ! PyObject *res; /* XXX What about keyword arguments? */ ! res = (*func)(self, args, NULL); ! if (res == NULL) return NULL; - /* tp_construct doesn't return a new object; it just returns self, - un-INCREF-ed */ Py_INCREF(Py_None); return Py_None; --- 1156,1164 ---- wrap_init(PyObject *self, PyObject *args, void *wrapped) { ! initproc func = (initproc)wrapped; /* XXX What about keyword arguments? */ ! if (func(self, args, NULL) < 0) return NULL; Py_INCREF(Py_None); return Py_None; *************** *** 1243,1247 **** ADD(type->tp_descr_get, tab_descr_get); ADD(type->tp_descr_set, tab_descr_set); ! ADD(type->tp_construct, tab_init); return 0; --- 1258,1262 ---- ADD(type->tp_descr_get, tab_descr_get); ADD(type->tp_descr_set, tab_descr_set); ! ADD(type->tp_init, tab_init); return 0; *************** *** 1514,1519 **** } ! static PyObject * ! slot_tp_construct(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *meth = PyObject_GetAttrString(self, "__init__"); --- 1529,1534 ---- } ! static int ! slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *meth = PyObject_GetAttrString(self, "__init__"); *************** *** 1521,1531 **** if (meth == NULL) ! return NULL; res = PyObject_Call(meth, args, kwds); Py_DECREF(meth); if (res == NULL) ! return NULL; Py_DECREF(res); ! return self; } --- 1536,1546 ---- if (meth == NULL) ! return -1; res = PyObject_Call(meth, args, kwds); Py_DECREF(meth); if (res == NULL) ! return -1; Py_DECREF(res); ! return 0; } *************** *** 1629,1632 **** TPSLOT(get, tp_descr_get); TPSLOT(set, tp_descr_set); ! TPSLOT(init, tp_construct); } --- 1644,1647 ---- TPSLOT(get, tp_descr_get); TPSLOT(set, tp_descr_set); ! TPSLOT(init, tp_init); } From gvanrossum@users.sourceforge.net Tue Jun 5 12:41:25 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 04:41:25 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.26,2.16.8.27 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv30179/Objects Modified Files: Tag: descr-branch typeobject.c Log Message: Modernize type_init() -- it was still the old "constructor" code, returning NULL for errors instead -1. This was unfortunately masked by a cast. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.26 retrieving revision 2.16.8.27 diff -C2 -r2.16.8.26 -r2.16.8.27 *** typeobject.c 2001/06/05 10:49:24 2.16.8.26 --- typeobject.c 2001/06/05 11:41:23 2.16.8.27 *************** *** 147,155 **** /* TypeType's constructor is called when a type is subclassed */ ! static PyObject * ! type_init(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *name, *bases, *dict, *x, *slots; ! PyTypeObject *base; char *dummy = NULL; etype *et; --- 147,155 ---- /* TypeType's constructor is called when a type is subclassed */ ! static int ! type_init(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *name, *bases, *dict, *x, *slots; ! PyTypeObject *type, *base; char *dummy = NULL; etype *et; *************** *** 157,178 **** int i, nslots, slotoffset, allocsize; /* Check arguments */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", &dummy, &name, &bases, &dict)) ! return NULL; if (!PyTuple_Check(bases) || !PyDict_Check(dict)) { PyErr_SetString(PyExc_TypeError, "usage: TypeType(name, bases, dict) "); ! return NULL; } if (PyTuple_GET_SIZE(bases) > 1) { PyErr_SetString(PyExc_TypeError, "can't multiple-inherit from types"); ! return NULL; } if (PyTuple_GET_SIZE(bases) < 1) { PyErr_SetString(PyExc_TypeError, "can't create a new type without a base type"); ! return NULL; } base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); --- 157,181 ---- int i, nslots, slotoffset, allocsize; + assert(PyType_Check(self)); + type = (PyTypeObject *)self; + /* Check arguments */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", &dummy, &name, &bases, &dict)) ! return -1; if (!PyTuple_Check(bases) || !PyDict_Check(dict)) { PyErr_SetString(PyExc_TypeError, "usage: TypeType(name, bases, dict) "); ! return -1; } if (PyTuple_GET_SIZE(bases) > 1) { PyErr_SetString(PyExc_TypeError, "can't multiple-inherit from types"); ! return -1; } if (PyTuple_GET_SIZE(bases) < 1) { PyErr_SetString(PyExc_TypeError, "can't create a new type without a base type"); ! return -1; } base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); *************** *** 180,189 **** PyErr_SetString(PyExc_TypeError, "base type must be a type"); ! return NULL; } if (base->tp_init == NULL) { PyErr_SetString(PyExc_TypeError, "base type must have a constructor slot"); ! return NULL; } --- 183,192 ---- PyErr_SetString(PyExc_TypeError, "base type must be a type"); ! return -1; } if (base->tp_init == NULL) { PyErr_SetString(PyExc_TypeError, "base type must have a constructor slot"); ! return -1; } *************** *** 198,202 **** slots = PySequence_Tuple(slots); if (slots == NULL) ! return NULL; nslots = PyTuple_GET_SIZE(slots); for (i = 0; i < nslots; i++) { --- 201,205 ---- slots = PySequence_Tuple(slots); if (slots == NULL) ! return -1; nslots = PyTuple_GET_SIZE(slots); for (i = 0; i < nslots; i++) { *************** *** 205,209 **** "__slots__ must be a sequence of strings"); Py_DECREF(slots); ! return NULL; } } --- 208,212 ---- "__slots__ must be a sequence of strings"); Py_DECREF(slots); ! return -1; } } *************** *** 214,239 **** nslots = 1; ! /* Allocate memory and construct a type object in it */ allocsize = sizeof(etype) + nslots*sizeof(struct memberlist); ! if (type == NULL) { ! et = PyObject_MALLOC(allocsize); ! if (et == NULL) ! return NULL; ! memset(et, '\0', allocsize); ! type = &et->type; ! PyObject_INIT(type, &PyType_Type); ! } ! else { ! if (type->ob_type->tp_basicsize < allocsize) { ! PyErr_Format( ! PyExc_SystemError, ! "insufficient allocated memory for subtype: " ! "allocated %d, needed %d", ! type->ob_type->tp_basicsize, ! allocsize); ! return NULL; ! } ! et = (etype *)type; } Py_INCREF(name); et->name = name; --- 217,232 ---- nslots = 1; ! /* Check allocation size and initialize the type object */ allocsize = sizeof(etype) + nslots*sizeof(struct memberlist); ! if (type->ob_type->tp_basicsize < allocsize) { ! PyErr_Format( ! PyExc_SystemError, ! "insufficient allocated memory for subtype: " ! "allocated %d, needed %d", ! type->ob_type->tp_basicsize, ! allocsize); ! return -1; } + et = (etype *)type; Py_INCREF(name); et->name = name; *************** *** 251,255 **** if (PyType_InitDict(type) < 0) { Py_DECREF(type); ! return NULL; } --- 244,248 ---- if (PyType_InitDict(type) < 0) { Py_DECREF(type); ! return -1; } *************** *** 293,301 **** if (x == NULL) { Py_DECREF(type); ! return NULL; } Py_DECREF(x); /* throw away None */ override_slots(type, dict); ! return (PyObject *)type; } --- 286,294 ---- if (x == NULL) { Py_DECREF(type); ! return -1; } Py_DECREF(x); /* throw away None */ override_slots(type, dict); ! return 0; } *************** *** 353,357 **** 0, /* tp_descr_set */ offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ ! (initproc)type_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ --- 346,350 ---- 0, /* tp_descr_set */ offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ ! type_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ From gvanrossum@users.sourceforge.net Tue Jun 5 13:45:48 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 05:45:48 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects classobject.c,2.127.2.3,2.127.2.4 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv12535 Modified Files: Tag: descr-branch classobject.c Log Message: Make the class type callable, with a (name, bases, dict) signature. Had to change a few SystemError exceptions to TypeError. Index: classobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/classobject.c,v retrieving revision 2.127.2.3 retrieving revision 2.127.2.4 diff -C2 -r2.127.2.3 -r2.127.2.4 *** classobject.c 2001/05/06 02:31:13 2.127.2.3 --- classobject.c 2001/06/05 12:45:46 2.127.2.4 *************** *** 37,46 **** } if (name == NULL || !PyString_Check(name)) { ! PyErr_SetString(PyExc_SystemError, "PyClass_New: name must be a string"); return NULL; } if (dict == NULL || !PyDict_Check(dict)) { ! PyErr_SetString(PyExc_SystemError, "PyClass_New: dict must be a dictionary"); return NULL; --- 37,46 ---- } if (name == NULL || !PyString_Check(name)) { ! PyErr_SetString(PyExc_TypeError, "PyClass_New: name must be a string"); return NULL; } if (dict == NULL || !PyDict_Check(dict)) { ! PyErr_SetString(PyExc_TypeError, "PyClass_New: dict must be a dictionary"); return NULL; *************** *** 68,72 **** int i; if (!PyTuple_Check(bases)) { ! PyErr_SetString(PyExc_SystemError, "PyClass_New: bases must be a tuple"); return NULL; --- 68,72 ---- int i; if (!PyTuple_Check(bases)) { ! PyErr_SetString(PyExc_TypeError, "PyClass_New: bases must be a tuple"); return NULL; *************** *** 75,79 **** while (--i >= 0) { if (!PyClass_Check(PyTuple_GetItem(bases, i))) { ! PyErr_SetString(PyExc_SystemError, "PyClass_New: base must be a class"); return NULL; --- 75,79 ---- while (--i >= 0) { if (!PyClass_Check(PyTuple_GetItem(bases, i))) { ! PyErr_SetString(PyExc_TypeError, "PyClass_New: base must be a class"); return NULL; *************** *** 107,110 **** --- 107,122 ---- } + static PyObject * + class_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + PyObject *name, *bases, *dict; + static char *kwlist[] = {"name", "bases", "dict", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist, + &name, &bases, &dict)) + return NULL; + return PyClass_New(bases, dict, name); + } + /* Class methods */ *************** *** 405,408 **** --- 417,436 ---- 0, /* tp_doc */ (traverseproc)class_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + class_new, /* tp_new */ }; From gvanrossum@users.sourceforge.net Tue Jun 5 13:48:13 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 05:48:13 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python ceval.c,2.241.2.2,2.241.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv13364 Modified Files: Tag: descr-branch ceval.c Log Message: Greatly simplify build_class. It now always invokes the simplified "Don Beaudry hook": call the type of the first base. If there is no first base, default to PyClass_Type. New feature: if __metaclass__ is set in the dict, it overrides the metaclass choice. Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.241.2.2 retrieving revision 2.241.2.3 diff -C2 -r2.241.2.2 -r2.241.2.3 *** ceval.c 2001/05/06 02:31:13 2.241.2.2 --- ceval.c 2001/06/05 12:48:11 2.241.2.3 *************** *** 3224,3270 **** build_class(PyObject *methods, PyObject *bases, PyObject *name) { ! int i, n; ! if (!PyTuple_Check(bases)) { ! PyErr_SetString(PyExc_SystemError, ! "build_class with non-tuple bases"); ! return NULL; } ! if (!PyDict_Check(methods)) { ! PyErr_SetString(PyExc_SystemError, ! "build_class with non-dictionary"); ! return NULL; ! } ! if (!PyString_Check(name)) { ! PyErr_SetString(PyExc_SystemError, ! "build_class with non-string name"); ! return NULL; ! } ! n = PyTuple_Size(bases); ! for (i = 0; i < n; i++) { ! PyObject *base = PyTuple_GET_ITEM(bases, i); ! if (!PyClass_Check(base)) { ! /* If the base is a type, call its base to clone it. ! This is a weaker form of the Don Beaudry hook ! that used to be here. It should be sufficient ! because types can now be subtyped. */ ! if (PyType_Check(base)) { ! PyObject *basetype = (PyObject *)base->ob_type; ! PyObject *args; ! PyObject *newclass = NULL; ! args = Py_BuildValue( ! "(OOO)", name, bases, methods); ! if (args != NULL) { ! newclass = PyEval_CallObject( ! basetype, args); ! Py_DECREF(args); ! } ! return newclass; ! } ! PyErr_SetString(PyExc_TypeError, ! "base is not a class object"); ! return NULL; ! } ! } ! return PyClass_New(bases, methods, name); } --- 3224,3240 ---- build_class(PyObject *methods, PyObject *bases, PyObject *name) { ! PyObject *metaclass = NULL; ! ! if (PyDict_Check(methods)) ! metaclass = PyDict_GetItemString(methods, "__metaclass__"); ! ! if (metaclass == NULL) { ! if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) ! metaclass = (PyObject *) ! PyTuple_GET_ITEM(bases, 0)->ob_type; ! else ! metaclass = (PyObject *) &PyClass_Type; } ! return PyObject_CallFunction(metaclass, "OOO", name, bases, methods); } From gvanrossum@users.sourceforge.net Tue Jun 5 16:30:41 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 08:30:41 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.27,2.16.8.28 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv798 Modified Files: Tag: descr-branch typeobject.c Log Message: Allow creating subtypes without a base type (specifying an explicit __metaclass__). In this case, the base defaults to "object", whose C name has to be PyBaseObject_Type because PyObject_Type is an existing function. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.27 retrieving revision 2.16.8.28 diff -C2 -r2.16.8.27 -r2.16.8.28 *** typeobject.c 2001/06/05 11:41:23 2.16.8.27 --- typeobject.c 2001/06/05 15:30:39 2.16.8.28 *************** *** 58,62 **** if (type->tp_new == NULL) { PyErr_Format(PyExc_TypeError, ! "cannot construct '%.100s' instances", type->tp_name); return NULL; --- 58,62 ---- if (type->tp_new == NULL) { PyErr_Format(PyExc_TypeError, ! "cannot create '%.100s' instances", type->tp_name); return NULL; *************** *** 99,103 **** if (self == NULL) return NULL; ! if (type->tp_init(self, args, kwds) < 0) { Py_DECREF(self); return NULL; --- 99,103 ---- if (self == NULL) return NULL; ! if (type->tp_init != NULL && type->tp_init(self, args, kwds) < 0) { Py_DECREF(self); return NULL; *************** *** 112,124 **** { int dictoffset = self->ob_type->tp_dictoffset; ! PyTypeObject *base; destructor f; /* This exists so we can DECREF self->ob_type */ ! base = self->ob_type->tp_base; ! while ((f = base->tp_dealloc) == subtype_dealloc) base = base->tp_base; ! if (dictoffset && !base->tp_dictoffset) { PyObject **dictptr = (PyObject **) ((char *)self + dictoffset); PyObject *dict = *dictptr; --- 112,125 ---- { int dictoffset = self->ob_type->tp_dictoffset; ! PyTypeObject *type, *base; destructor f; /* This exists so we can DECREF self->ob_type */ ! type = self->ob_type; ! base = type->tp_base; ! while (base && (f = base->tp_dealloc) == subtype_dealloc) base = base->tp_base; ! if (dictoffset && (base == NULL || !base->tp_dictoffset)) { PyObject **dictptr = (PyObject **) ((char *)self + dictoffset); PyObject *dict = *dictptr; *************** *** 129,134 **** } f(self); ! if (self->ob_type->tp_flags & Py_TPFLAGS_HEAPTYPE) { ! Py_DECREF(self->ob_type); } } --- 130,136 ---- } f(self); ! /* Can't reference self beyond this point */ ! if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { ! Py_DECREF(type); } } *************** *** 146,150 **** } etype; ! /* TypeType's constructor is called when a type is subclassed */ static int type_init(PyObject *self, PyObject *args, PyObject *kwds) --- 148,152 ---- } etype; ! /* TypeType's initializer; called when a type is subclassed */ static int type_init(PyObject *self, PyObject *args, PyObject *kwds) *************** *** 152,156 **** PyObject *name, *bases, *dict, *x, *slots; PyTypeObject *type, *base; ! char *dummy = NULL; etype *et; struct memberlist *mp; --- 154,158 ---- PyObject *name, *bases, *dict, *x, *slots; PyTypeObject *type, *base; ! static char *kwlist[] = {"name", "bases", "dict", 0}; etype *et; struct memberlist *mp; *************** *** 161,165 **** /* Check arguments */ ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", &dummy, &name, &bases, &dict)) return -1; --- 163,167 ---- /* Check arguments */ ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist, &name, &bases, &dict)) return -1; *************** *** 170,192 **** } if (PyTuple_GET_SIZE(bases) > 1) { - PyErr_SetString(PyExc_TypeError, - "can't multiple-inherit from types"); - return -1; - } - if (PyTuple_GET_SIZE(bases) < 1) { - PyErr_SetString(PyExc_TypeError, - "can't create a new type without a base type"); - return -1; - } - base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); - if (!PyType_Check((PyObject *)base)) { PyErr_SetString(PyExc_TypeError, ! "base type must be a type"); return -1; } ! if (base->tp_init == NULL) { ! PyErr_SetString(PyExc_TypeError, ! "base type must have a constructor slot"); ! return -1; } --- 172,193 ---- } if (PyTuple_GET_SIZE(bases) > 1) { PyErr_SetString(PyExc_TypeError, ! "can't multiple-inherit from types (yet)"); return -1; } ! if (PyTuple_GET_SIZE(bases) < 1) ! base = &PyBaseObject_Type; ! else { ! base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); ! if (!PyType_Check((PyObject *)base)) { ! PyErr_SetString(PyExc_TypeError, ! "base type must be a type"); ! return -1; ! } ! if (base->tp_new == NULL) { ! PyErr_SetString(PyExc_TypeError, ! "base type must have a tp_new slot"); ! return -1; ! } } *************** *** 347,350 **** --- 348,402 ---- offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ type_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + }; + + + /* The base type of all types (eventually)... except itself. */ + + static void + object_dealloc(PyObject *self) + { + PyObject_Del(self); + } + + PyTypeObject PyBaseObject_Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ + "object", /* tp_name */ + sizeof(PyObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)object_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyGeneric_GetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "The most base type", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ From gvanrossum@users.sourceforge.net Tue Jun 5 16:35:39 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 08:35:39 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.28,2.16.8.29 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv2102 Modified Files: Tag: descr-branch typeobject.c Log Message: subtype_dealloc() had a check for the case that base ends up NULL. Change this to an assertion, since this is now (again) an error. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.28 retrieving revision 2.16.8.29 diff -C2 -r2.16.8.28 -r2.16.8.29 *** typeobject.c 2001/06/05 15:30:39 2.16.8.28 --- typeobject.c 2001/06/05 15:35:37 2.16.8.29 *************** *** 119,125 **** type = self->ob_type; base = type->tp_base; ! while (base && (f = base->tp_dealloc) == subtype_dealloc) base = base->tp_base; ! if (dictoffset && (base == NULL || !base->tp_dictoffset)) { PyObject **dictptr = (PyObject **) ((char *)self + dictoffset); PyObject *dict = *dictptr; --- 119,127 ---- type = self->ob_type; base = type->tp_base; ! while ((f = base->tp_dealloc) == subtype_dealloc) { base = base->tp_base; ! assert(base); ! } ! if (dictoffset && !base->tp_dictoffset) { PyObject **dictptr = (PyObject **) ((char *)self + dictoffset); PyObject *dict = *dictptr; From bwarsaw@users.sourceforge.net Tue Jun 5 17:39:13 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Tue, 05 Jun 2001 09:39:13 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0006.txt,1.4,1.5 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv15535 Modified Files: pep-0006.txt Log Message: Updated Post-History: (long overdue). Index: pep-0006.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0006.txt,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -r1.4 -r1.5 *** pep-0006.txt 2001/05/08 18:55:57 1.4 --- pep-0006.txt 2001/06/05 16:39:11 1.5 *************** *** 6,10 **** Type: Informational Created: 15-Mar-2001 ! Post-History: 15-Mar-2001 --- 6,10 ---- Type: Informational Created: 15-Mar-2001 ! Post-History: 15-Mar-2001 18-Apr-2001 From bwarsaw@users.sourceforge.net Tue Jun 5 17:42:30 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Tue, 05 Jun 2001 09:42:30 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0236.txt,1.6,1.7 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv16381 Modified Files: pep-0236.txt Log Message: This PEP is finished, so mark it as final. Index: pep-0236.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0236.txt,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -r1.6 -r1.7 *** pep-0236.txt 2001/03/25 05:54:08 1.6 --- pep-0236.txt 2001/06/05 16:42:27 1.7 *************** *** 4,8 **** Author: Tim Peters Python-Version: 2.1 ! Status: Active Type: Standards Track Created: 26-Feb-2001 --- 4,8 ---- Author: Tim Peters Python-Version: 2.1 ! Status: Final Type: Standards Track Created: 26-Feb-2001 *************** *** 355,358 **** --- 355,359 ---- existed in the standard distribution before the 2.1 release, and the double underscores make it a reserved name). + From bwarsaw@users.sourceforge.net Tue Jun 5 17:43:01 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Tue, 05 Jun 2001 09:43:01 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.90,1.91 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv16584 Modified Files: pep-0000.txt Log Message: Mark PEP 236 as final. Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.90 retrieving revision 1.91 diff -C2 -r1.90 -r1.91 *** pep-0000.txt 2001/05/14 13:43:23 1.90 --- pep-0000.txt 2001/06/05 16:42:59 1.91 *************** *** 90,94 **** SF 232 pep-0232.txt Function Attributes Warsaw SF 235 pep-0235.txt Import on Case-Insensitive Platforms Peters ! S 236 pep-0236.txt Back to the __future__ Peters Empty PEPs (or containing only an abstract) --- 90,94 ---- SF 232 pep-0232.txt Function Attributes Warsaw SF 235 pep-0235.txt Import on Case-Insensitive Platforms Peters ! SF 236 pep-0236.txt Back to the __future__ Peters Empty PEPs (or containing only an abstract) *************** *** 157,161 **** S 234 pep-0234.txt Iterators Yee, van Rossum SF 235 pep-0235.txt Import on Case-Insensitive Platforms Peters ! S 236 pep-0236.txt Back to the __future__ Peters S 237 pep-0237.txt Unifying Long Integers and Integers Zadka S 238 pep-0238.txt Non-integer Division Zadka --- 157,161 ---- S 234 pep-0234.txt Iterators Yee, van Rossum SF 235 pep-0235.txt Import on Case-Insensitive Platforms Peters ! SF 236 pep-0236.txt Back to the __future__ Peters S 237 pep-0237.txt Unifying Long Integers and Integers Zadka S 238 pep-0238.txt Non-integer Division Zadka From bwarsaw@users.sourceforge.net Tue Jun 5 17:50:11 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Tue, 05 Jun 2001 09:50:11 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0211.txt,1.5,1.6 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv18171 Modified Files: pep-0211.txt Log Message: Long overdue update from Greg Wilson 22-Apr-2001 Index: pep-0211.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0211.txt,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -r1.5 -r1.6 *** pep-0211.txt 2000/11/27 05:41:46 1.5 --- pep-0211.txt 2001/06/05 16:50:09 1.6 *************** *** 1,6 **** PEP: 211 ! Title: Adding New Linear Algebra Operators to Python Version: $Revision$ ! Author: gvwilson@nevex.com (Greg Wilson) Status: Draft Type: Standards Track --- 1,6 ---- PEP: 211 ! Title: Adding A New Outer Product Operator Version: $Revision$ ! Author: gvwilson@ddj.com (Greg Wilson) Status: Draft Type: Standards Track *************** *** 12,65 **** Introduction ! This PEP describes a conservative proposal to add linear algebra ! operators to Python 2.0. It discusses why such operators are ! desirable, and why a minimalist approach should be adopted at this ! point. This PEP summarizes discussions held in mailing list ! forums, and provides URLs for further information, where ! appropriate. The CVS revision history of this file contains the ! definitive historical record. ! ! ! Summary ! ! Add a single new infix binary operator '@' ("across"), and ! corresponding special methods "__across__()", "__racross__()", and ! "__iacross__()". This operator will perform mathematical matrix ! multiplication on NumPy arrays, and generate cross-products when ! applied to built-in sequence types. No existing operator ! definitions will be changed. Background ! The first high-level programming language, Fortran, was invented ! to do arithmetic. While this is now just a small part of ! computing, there are still many programmers who need to express ! complex mathematical operations in code. ! ! The most influential of Fortran's successors was APL [1]. Its ! author, Kenneth Iverson, designed the language as a notation for ! expressing matrix algebra, and received the 1980 Turing Award for ! his work. ! ! APL's operators supported both familiar algebraic operations, such ! as vector dot product and matrix multiplication, and a wide range ! of structural operations, such as stitching vectors together to ! create arrays. Even by programming's standards, APL is ! exceptionally cryptic: many of its symbols did not exist on ! standard keyboards, and expressions have to be read right to left. ! ! Most subsequent work numerical languages, such as Fortran-90, ! MATLAB, and Mathematica, have tried to provide the power of APL ! without the obscurity. Python's NumPy [2] has most of the ! features that users of such languages expect, but these are ! provided through named functions and methods, rather than ! overloaded operators. This makes NumPy clumsier than most ! alternatives. ! ! The author of this PEP therefore consulted the developers of GNU ! Octave [3], an open source clone of MATLAB. When asked how ! important it was to have infix operators for matrix solution, ! Prof. James Rawlings replied [4]: I DON'T think it's a must have, and I do a lot of matrix --- 12,62 ---- Introduction ! This PEP describes a proposal to define "@" (pronounced "across") ! as a new outer product operator in Python 2.2. When applied to ! sequences (or other iterable objects), this operator will combine ! their iterators, so that: ! ! for (i, j) in S @ T: ! pass ! ! will be equivalent to: ! ! for i in S: ! for j in T: ! pass ! ! Classes will be able to overload this operator using the special ! methods "__across__", "__racross__", and "__iacross__". In ! particular, the new Numeric module (PEP 0209) will overload this ! operator for multi-dimensional arrays to implement matrix ! multiplication. Background ! Number-crunching is now just a small part of computing, but many ! programmers --- including many Python users --- still need to ! express complex mathematical operations in code. Most numerical ! languages, such as APL, Fortran-90, MATLAB, IDL, and Mathematica, ! therefore provide two forms of the common arithmetic operators. ! One form works element-by-element, e.g. multiplies corresponding ! elements of its matrix arguments. The other implements the ! "mathematical" definition of that operation, e.g. performs ! row-column matrix multiplication. ! ! Zhu and Lielens have proposed doubling up Python's operators in ! this way [1]. Their proposal would create six new binary infix ! operators, and six new in-place operators. ! ! The original version of this proposal was much more conservative. ! The author consulted the developers of GNU Octave [2], an open ! source clone of MATLAB. Its developers agreed that providing an ! infix operator for matrix multiplication was important: numerical ! programmers really do care whether they have to write "mmul(A,B)" ! instead of "A op B". ! ! On the other hand, when asked how important it was to have infix ! operators for matrix solution and other operations, Prof. James ! Rawlings replied [3]: I DON'T think it's a must have, and I do a lot of matrix *************** *** 67,323 **** write inv(A)*b instead. I recommend dropping \. ! Rawlings' feedback on other operators was similar. It is worth ! noting in this context that notations such as "/" and "\" for ! matrix solution were invented by programmers, not mathematicians, ! and have not been adopted by the latter. - Based on this discussion, and feedback from classes at the US - national laboratories and elsewhere, we recommend only adding a - matrix multiplication operator to Python at this time. If there - is significant user demand for syntactic support for other - operations, these can be added in a later release. ! Requirements ! The most important requirement is minimal impact on existing ! Python programs and users: the proposal must not break existing ! code (except possibly NumPy). ! The second most important requirement is the ability to handle all ! common cases cleanly and clearly. There are nine such cases: ! |5 6| * 9 = |45 54| MS: matrix-scalar multiplication ! |7 8| |63 72| ! 9 * |5 6| = |45 54| SM: scalar-matrix multiplication ! |7 8| |63 72| ! |2 3| * |4 5| = |8 15| VE: vector elementwise multiplication ! |2 3| * |4| = 23 VD: vector dot product ! |5| ! |2| * |4 5| = | 8 10| VO: vector outer product ! |3| |12 15| ! |1 2| * |5 6| = | 5 12| ME: matrix elementwise multiplication ! |3 4| |7 8| |21 32| ! |1 2| * |5 6| = |19 22| MM: mathematical matrix multiplication ! |3 4| |7 8| |43 50| ! |1 2| * |5 6| = |19 22| VM: vector-matrix multiplication ! |7 8| ! |5 6| * |1| = |17| MV: matrix-vector multiplication ! |7 8| |2| |23| ! Note that 1-dimensional vectors are treated as rows in VM, as ! columns in MV, and as both in VD and VO. Both are special cases ! of 2-dimensional matrices (Nx1 and 1xN respectively). We will ! therefore define the new operator only for 2-dimensional arrays, ! and provide an easy (and efficient) way for users to treat ! 1-dimensional structures as 2-dimensional. ! Third, we must avoid confusion between Python's notation and those ! of MATLAB and Fortran-90. In particular, mathematical matrix ! multiplication (case MM) should not be represented as '.*', since: ! (a) MATLAB uses prefix-'.' forms to mean 'elementwise', and raw ! forms to mean "mathematical"; and ! (b) even if the Python parser can be taught how to handle dotted ! forms, '1.*A' will still be visually ambiguous. - Proposal - The meanings of all existing operators will be unchanged. In - particular, 'A*B' will continue to be interpreted elementwise. - This takes care of the cases MS, SM, VE, and ME, and ensures - minimal impact on existing programs. - - A new operator '@' (pronounced "across") will be added to Python, - along with special methods "__across__()", "__racross__()", and - "__iacross__()", with the usual semantics. (We recommend using - "@", rather than the times-like "><", because of the ease with - which the latter could be mis-typed as inequality "<>".) - - No new operators will be defined to mean "solve a set of linear - equations", or "invert a matrix". - - (Optional) When applied to sequences, the "@" operator will return - a tuple of tuples containing the cross-product of their elements - in left-to-right order: - - >>> [1, 2] @ (3, 4) - ((1, 3), (1, 4), (2, 3), (2, 4)) - - >>> [1, 2] @ (3, 4) @ (5, 6) - ((1, 3, 5), (1, 3, 6), - (1, 4, 5), (1, 4, 6), - (2, 3, 5), (2, 3, 6), - (2, 4, 5), (2, 4, 6)) - - This will require the same kind of special support from the parser - as chained comparisons (such as "a>> for (i, j) in [1, 2] @ [3, 4]: - >>> print i, j - 1 3 - 1 4 - 2 3 - 2 4 - - as a short-hand for the common nested loop idiom: - - >>> for i in [1, 2]: - >>> for j in [3, 4]: - >>> print i, j - - Response to the 'lockstep loop' questionnaire [5] indicated that - newcomers would be comfortable with this (so comfortable, in fact, - that most of them interpreted most multi-loop 'zip' syntaxes [6] - as implementing single-stage nesting). - - Alternatives - - 01. Don't add new operators. - - Python is not primarily a numerical language; it may not be worth - complexifying it for this special case. NumPy's success is proof - that users can and will use functions and methods for linear - algebra. However, support for real matrix multiplication is - frequently requested, as: - - * functional forms are cumbersome for lengthy formulas, and do not - respect the operator precedence rules of conventional mathematics; - and - - * method forms are asymmetric in their operands. - - What's more, the proposed semantics for "@" for built-in sequence - types would simplify expression of a very common idiom (nested - loops). User testing during discussion of 'lockstep loops' - indicated that both new and experienced users would understand - this immediately. - - 02. Introduce prefixed forms of all existing operators, such as - "~*" and "~+", as proposed in PEP 0225 [7]. - - This proposal would duplicate all built-in mathematical operators - with matrix equivalents, as in numerical languages such as - MATLAB. Our objections to this are: - - * Python is not primarily a numerical programming language. While - the (self-selected) participants in the discussions that led to - PEP 0225 may want all of these new operators, the majority of - Python users would be indifferent. The extra complexity they - would introduce into the language therefore does not seem - merited. (See also Rawlings' comments, quoted in the Background - section, about these operators not being essential.) - - * The proposed syntax is difficult to read (i.e. passes the "low - toner" readability test). - - 03. Retain the existing meaning of all operators, but create a - behavioral accessor for arrays, such that: ! A * B ! is elementwise multiplication (ME), but: ! A.m() * B.m() ! is mathematical multiplication (MM). The method "A.m()" would ! return an object that aliased A's memory (for efficiency), but ! which had a different implementation of __mul__(). ! ! This proposal was made by Moshe Zadka, and is also considered by ! PEP 0225 [7]. Its advantage is that it has no effect on the ! existing implementation of Python: changes are localized in the ! Numeric module. The disadvantages are ! ! * The semantics of "A.m() * B", "A + B.m()", and so on would have ! to be defined, and there is no "obvious" choice for them. ! ! * Aliasing objects to trigger different operator behavior feels ! less Pythonic than either calling methods (as in the existing ! Numeric module) or using a different operator. This PEP is ! primarily about look and feel, and about making Python more ! attractive to people who are not already using it. ! ! ! Related Proposals ! ! 0207 : Rich Comparisons ! ! It may become possible to overload comparison operators ! such as '<' so that an expression such as 'A < B' returns ! an array, rather than a scalar value. ! ! 0209 : Adding Multidimensional Arrays ! ! Multidimensional arrays are currently an extension to ! Python, rather than a built-in type. ! ! 0225 : Elementwise/Objectwise Operators ! ! A larger proposal that addresses the same subject, but ! which proposes many more additions to the language. Acknowledgments ! I am grateful to Huaiyu Zhu [8] for initiating this discussion, ! and for some of the ideas and terminology included below. References - - [1] http://www.acm.org/sigapl/whyapl.htm - [2] http://numpy.sourceforge.net - [3] http://bevo.che.wisc.edu/octave/ - [4] http://www.egroups.com/message/python-numeric/4 - [5] http://www.python.org/pipermail/python-dev/2000-July/013139.html - [6] PEP-0201.txt "Lockstep Iteration" - [7] http://www.python.org/pipermail/python-list/2000-August/112529.html - - - Appendix: NumPy - - NumPy will overload "@" to perform mathematical multiplication of - arrays where shapes permit, and to throw an exception otherwise. - Its implementation of "@" will treat built-in sequence types as if - they were column vectors. This takes care of the cases MM and MV. - - An attribute "T" will be added to the NumPy array type, such that - "m.T" is: - - (a) the transpose of "m" for a 2-dimensional array - - (b) the 1xN matrix transpose of "m" if "m" is a 1-dimensional - array; or - - (c) a runtime error for an array with rank >= 3. - - This attribute will alias the memory of the base object. NumPy's - "transpose()" function will be extended to turn built-in sequence - types into row vectors. This takes care of the VM, VD, and VO - cases. We propose an attribute because: - - (a) the resulting notation is similar to the 'superscript T' (at - least, as similar as ASCII allows), and - - (b) it signals that the transposition aliases the original object. ! NumPy will define a value "inv", which will be recognized by the ! exponentiation operator, such that "A ** inv" is the inverse of ! "A". This is similar in spirit to NumPy's existing "newaxis" ! value. --- 64,181 ---- write inv(A)*b instead. I recommend dropping \. ! Based on this discussion, and feedback from students at the US ! national laboratories and elsewhere, we recommended adding only ! one new operator, for matrix multiplication, to Python. + Iterators ! The planned addition of iterators to Python 2.2 opens up a broader ! scope for this proposal. As part of the discussion of PEP 0201 ! "Lockstep Iteration" [4], the author of this proposal conducted an ! informal usability experiment [5]. The results showed that users ! are psychologically receptive to "cross-product" loop syntax. For ! example, most users expected: ! S = [10, 20, 30] ! T = [1, 2, 3] ! for x in S; y in T: ! print x+y, ! to print "11 12 13 21 22 23 31 32 33". We believe that users will ! have the same reaction to: ! for (x, y) in S @ T: ! print x+y ! i.e. that they will naturally interpret this as a tidy way to ! write loop nests. ! This is where iterators come in. Actually constructing the ! cross-product of two (or more) sequences before executing the loop ! would be very expensive. On the other hand, "@" could be defined ! to get its arguments' iterators, and then create an outer iterator ! which returns tuples of the values returned by the inner ! iterators. ! Discussion ! 1. Adding a named function "across" would have less impact on ! Python than a new infix operator. However, this would not make ! Python more appealing to numerical programmers, who really do ! care whether they can write matrix multiplication using an ! operator, or whether they have to write it as a function call. ! 2. "@" would have be chainable in the same way as comparison ! operators, i.e.: ! (1, 2) @ (3, 4) @ (5, 6) ! would have to return (1, 3, 5) ... (2, 4, 6), and *not* ! ((1, 3), 5) ... ((2, 4), 6). This should not require special ! support from the parser, as the outer iterator created by the ! first "@" could easily be taught how to combine itself with ! ordinary iterators. ! 3. There would have to be some way to distinguish restartable ! iterators from ones that couldn't be restarted. For example, ! if S is an input stream (e.g. a file), and L is a list, then "S ! @ L" is straightforward, but "L @ S" is not, since iteration ! through the stream cannot be repeated. This could be treated ! as an error, or by having the outer iterator detect ! non-restartable inner iterators and cache their values. ! 4. Whiteboard testing of this proposal in front of three novice ! Python users (all of them experienced programmers) indicates ! that users will expect: ! "ab" @ "cd" ! to return four strings, not four tuples of pairs of ! characters. Opinion was divided on what: ! ("a", "b") @ "cd" + ought to return... Alternatives ! 1. Do nothing --- keep Python simple. ! This is always the default choice. ! 2. Add a named function instead of an operator. ! Python is not primarily a numerical language; it may not be worth ! complexifying it for this special case. However, support for real ! matrix multiplication *is* frequently requested, and the proposed ! semantics for "@" for built-in sequence types would simplify ! expression of a very common idiom (nested loops). ! ! 3. Introduce prefixed forms of all existing operators, such as ! "~*" and "~+", as proposed in PEP 0225 [1]. ! ! Our objections to this are that there isn't enough demand to ! justify the additional complexity (see Rawlings' comments [3]), ! and that the proposed syntax fails the "low toner" readability ! test. Acknowledgments ! I am grateful to Huaiyu Zhu for initiating this discussion, and to ! James Rawlings and students in various Python courses for their ! discussions of what numerical programmers really care about. References ! [1] http://python.sourceforge.net/peps/pep-0225.html ! [2] http://bevo.che.wisc.edu/octave/ ! [3] http://www.egroups.com/message/python-numeric/4 ! [4] http://python.sourceforge.net/peps/pep-0201.html ! [5] http://mail.python.org/pipermail/python-dev/2000-July/006427.html From bwarsaw@users.sourceforge.net Tue Jun 5 17:51:10 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Tue, 05 Jun 2001 09:51:10 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.91,1.92 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv18335 Modified Files: pep-0000.txt Log Message: PEP 211 update from Greg Wilson, includes a name change, and a change to Greg's email address. Also, I moved the PEP to "Active for 2.2" and un-deferred it. Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.91 retrieving revision 1.92 diff -C2 -r1.91 -r1.92 *** pep-0000.txt 2001/06/05 16:42:59 1.91 --- pep-0000.txt 2001/06/05 16:51:08 1.92 *************** *** 39,42 **** --- 39,43 ---- I 42 pep-0042.txt Small Feature Requests Hylton + S 211 pep-0211.txt Adding A New Outer Product Operator Wilson S 234 pep-0234.txt Iterators Yee, van Rossum S 237 pep-0237.txt Unifying Long Integers and Integers Zadka *************** *** 59,63 **** I 206 pep-0206.txt 2.0 Batteries Included Zadka S 209 pep-0209.txt Adding Multidimensional Arrays Barrett, Oliphant - SD 211 pep-0211.txt Adding New Linear Algebra Operators Wilson SD 212 pep-0212.txt Loop Counter Iteration Schneider-Kamp SD 213 pep-0213.txt Attribute Access Handlers Prescod --- 60,63 ---- *************** *** 132,136 **** S 209 pep-0209.txt Adding Multidimensional Arrays Barrett, Oliphant SD 210 pep-0210.txt Decoupling the Interpreter Loop Ascher ! SD 211 pep-0211.txt Adding New Linear Algebra Operators Wilson SD 212 pep-0212.txt Loop Counter Iteration Schneider-Kamp SD 213 pep-0213.txt Attribute Access Handlers Prescod --- 132,136 ---- S 209 pep-0209.txt Adding Multidimensional Arrays Barrett, Oliphant SD 210 pep-0210.txt Decoupling the Interpreter Loop Ascher ! SD 211 pep-0211.txt Adding A New Outer Product Operator Wilson SD 212 pep-0212.txt Loop Counter Iteration Schneider-Kamp SD 213 pep-0213.txt Attribute Access Handlers Prescod *************** *** 214,218 **** Schneider-Kamp, Peter nowonder@nowonder.de Warsaw, Barry barry@digicool.com ! Wilson, Greg gvwilson@nevex.com Wouters, Thomas thomas@xs4all.net Yee, Ka-Ping ping@lfw.org --- 214,218 ---- Schneider-Kamp, Peter nowonder@nowonder.de Warsaw, Barry barry@digicool.com ! Wilson, Greg gvwilson@ddj.com Wouters, Thomas thomas@xs4all.net Yee, Ka-Ping ping@lfw.org From bwarsaw@users.sourceforge.net Tue Jun 5 17:57:07 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Tue, 05 Jun 2001 09:57:07 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.92,1.93 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv19458 Modified Files: pep-0000.txt Log Message: Move PEP 218 from py-in-the-sky to active-for-2.2 Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.92 retrieving revision 1.93 diff -C2 -r1.92 -r1.93 *** pep-0000.txt 2001/06/05 16:51:08 1.92 --- pep-0000.txt 2001/06/05 16:57:05 1.93 *************** *** 40,43 **** --- 40,44 ---- I 42 pep-0042.txt Small Feature Requests Hylton S 211 pep-0211.txt Adding A New Outer Product Operator Wilson + S 218 pep-0218.txt Adding a Built-In Set Object Type Wilson S 234 pep-0234.txt Iterators Yee, van Rossum S 237 pep-0237.txt Unifying Long Integers and Integers Zadka *************** *** 64,68 **** S 215 pep-0215.txt String Interpolation Yee I 216 pep-0216.txt Docstring Format Zadka - SD 218 pep-0218.txt Adding a Built-In Set Object Type Wilson SD 219 pep-0219.txt Stackless Python McMillan S 222 pep-0222.txt Web Library Enhancements Kuchling --- 65,68 ---- From bwarsaw@users.sourceforge.net Tue Jun 5 18:01:57 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Tue, 05 Jun 2001 10:01:57 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0250.txt,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv20523 Modified Files: pep-0250.txt Log Message: Paul Moore's latest update Index: pep-0250.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0250.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -r1.1 -r1.2 *** pep-0250.txt 2001/04/18 10:28:11 1.1 --- pep-0250.txt 2001/06/05 17:01:55 1.2 *************** *** 7,11 **** Created: 2001-03-30 Python-Version: 2.2 ! Post-History: --- 7,11 ---- Created: 2001-03-30 Python-Version: 2.2 ! Post-History: 30-Mar-2001 *************** *** 70,74 **** else: ! sitedirs == [makepath(prefix, "lib", "site-packages")] Changes would also be required to distutils, in the sysconfig.py --- 70,74 ---- else: ! sitedirs == [prefix, makepath(prefix, "lib", "site-packages")] Changes would also be required to distutils, in the sysconfig.py *************** *** 80,96 **** Notes ! 1. It would be better if this change could be included in Python ! 2.1, as changing something of this nature is better done ! sooner, rather than later, to reduce the backward-compatibility ! burden. This is extremely unlikely to happen at this late stage ! in the release cycle, however. ! ! 2. This change does not preclude packages using the current ! location -- the change only adds a directory to sys.path, it ! does not remove anything. ! ! 3. In the Windows distribution of Python 2.1 (beta 1), the ! Lib\site-packages directory has been removed. It would need to ! be reinstated. --- 80,119 ---- Notes ! - This change does not preclude packages using the current ! location -- the change only adds a directory to sys.path, it ! does not remove anything. ! ! - Both the current location (sys.prefix) and the new directory ! (site-packages) are included in sitedirs, so that .pth files ! will be recognized in either location. ! ! - This proposal adds a single additional site-packages directory ! to sitedirs. On Unix platforms, two directories are added, one ! for version-independent files (Python code) and one for ! version-dependent code (C extensions). This is necessary on ! Unix, as the sitedirs include a common (across Python versions) ! package location, in /usr/local by default. As there is no such ! common location available on Windows, there is also no need for ! having two separate package directories. ! ! - If users want to keep DLLs in a single location on Windows, ! rather than keeping them in the package directory, the DLLs ! subdirectory of the Python install directory is available for ! that purpose. Adding an extra directory solely for DLLs should ! not be necessary. ! ! ! Open Issues ! ! - There have been no comments on this proposal from non-Windows ! users. In the absence of such comments, it is assumed that there ! will be no adverse effects on such platforms caused by the ! proposed change. (The author knows of no reason why there should ! be). ! ! - There could be issues with applications which embed Python. To ! the author's knowledge, there should be no problem as a result ! of this change. Again, there have been no comments (supportive ! or otherwise) from users who embed Python. From bwarsaw@users.sourceforge.net Tue Jun 5 18:11:32 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Tue, 05 Jun 2001 10:11:32 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0255.txt,NONE,1.1 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv22547 Added Files: pep-0255.txt Log Message: Magnus Lie Hetland's first version of this pep. --- NEW FILE: pep-0255.txt --- PEP: 255 Title: Simple Generators Version: $Revision: 1.1 $ Author: nas@python.ca (Neil Schemenauer), tim.one@home.com (Tim Peters), magnus@hetland.org (Magnus Lie Hetland) Discussion-To: python-iterators@lists.sourceforge.net Status: Draft Type: Standards Track Requires: 234 Created: 18-May-2001 Python-Version: 2.2 Post-History: Abstract This PEP introduces the concept of generators to Python, as well as a new statement used in conjunction with them, the "yield" statement. Motivation When a producer function has a hard enough job that it requires maintaining state between values produced, most programming languages offer no pleasant and efficient solution beyond adding a callback function to the producer's argument list, to be called with each value produced. For example, tokenize.py in the standard library takes this approach: the caller must pass a "tokeneater" function to tokenize(), called whenever tokenize() finds the next token. This allows tokenize to be coded in a natural way, but programs calling tokenize are typically convoluted by the need to remember between callbacks which token(s) were seen last. The tokeneater function in tabnanny.py is a good example of that, maintaining a state machine in global variables, to remember across callbacks what it has already seen and what it hopes to see next. This was difficult to get working correctly, and is still difficult for people to understand. Unfortunately, that's typical of this approach. An alternative would have been for tokenize to produce an entire parse of the Python program at once, in a large list. Then tokenize clients could be written in a natural way, using local variables and local control flow (such as loops and nested if statements) to keep track of their state. But this isn't practical: programs can be very large, so no a priori bound can be placed on the memory needed to materialize the whole parse; and some tokenize clients only want to see whether something specific appears early in the program (e.g., a future statement, or, as is done in IDLE, just the first indented statement), and then parsing the whole program first is a severe waste of time. Another alternative would be to make tokenize an iterator[1], delivering the next token whenever its .next() method is invoked. This is pleasant for the caller in the same way a large list of results would be, but without the memory and "what if I want to get out early?" drawbacks. However, this shifts the burden on tokenize to remember *its* state between .next() invocations, and the reader need only glance at tokenize.tokenize_loop() to realize what a horrid chore that would be. Or picture a recursive algorithm for producing the nodes of a general tree structure: to cast that into an iterator framework requires removing the recursion manually and maintaining the state of the traversal by hand. A fourth option is to run the producer and consumer in separate threads. This allows both to maintain their states in natural ways, and so is pleasant for both. Indeed, Demo/threads/Generator.py in the Python source distribution provides a usable synchronized-communication class for doing that in a general way. This doesn't work on platforms without threads, though, and is very slow on platforms that do (compared to what is achievable without threads). A final option is to use the Stackless[2][3] variant implementation of Python instead, which supports lightweight coroutines. This has much the same programmatic benefits as the thread option, but is much more efficient. However, Stackless is a radical and controversial rethinking of the Python core, and it may not be possible for Jython to implement the same semantics. This PEP isn't the place to debate that, so suffice it to say here that generators provide a useful subset of Stackless functionality in a way that fits easily into the current Python implementation. That exhausts the current alternatives. Some other high-level languages provide pleasant solutions, notably iterators in Sather[4], which were inspired by iterators in CLU; and generators in Icon[5], a novel language where every expression "is a generator". There are differences among these, but the basic idea is the same: provide a kind of function that can return an intermediate result ("the next value") to its caller, but maintaining the function's local state so that the function can be resumed again right where it left off. A very simple example: def fib(): a, b = 0, 1 while 1: yield b a, b = b, a+b When fib() is first invoked, it sets a to 0 and b to 1, then yields b back to its caller. The caller sees 1. When fib is resumed, from its point of view the yield statement is really the same as, say, a print statement: fib continues after the yield with all local state intact. a and b then become 1 and 1, and fib loops back to the yield, yielding 1 to its invoker. And so on. From fib's point of view it's just delivering a sequence of results, as if via callback. But from its caller's point of view, the fib invocation is an iterable object that can be resumed at will. As in the thread approach, this allows both sides to be coded in the most natural ways; but unlike the thread approach, this can be done efficiently and on all platforms. Indeed, resuming a generator should be no more expensive than a function call. The same kind of approach applies to many producer/consumer functions. For example, tokenize.py could yield the next token instead of invoking a callback function with it as argument, and tokenize clients could iterate over the tokens in a natural way: a Python generator is a kind of Python iterator[1], but of an especially powerful kind. Specification A new statement, the "yield" statement, is introduced: yield_stmt: "yield" [expression_list] This statement may only be used inside functions. A function which contains a yield statement is a so-called "generator function". A generator function may not contain return statements of the form: "return" expression_list It may, however, contain return statements of the form: "return" When a generator function is called, an iterator[6] is returned. Each time the .next() method of this iterator is called, the code in the body of the generator function is executed until a yield statement or a return statement is encountered, or until the end of the body is reached. If a yield statement is encountered during this execution, the state of the function is frozen, and a value is returned to the object calling .next(). If an empty yield statement was encountered, None is returned; otherwise, the given expression(s) is (are) returned. If an empty return statement is encountered, nothing is returned; however, a StopIteration exception is raised, signalling that the iterator is exhausted. An example of how generators may be used is given below: # A binary tree class class Tree: def __init__(self, label, left=None, right=None): self.label = label self.left = left self.right = right def __repr__(self, level=0, indent=" "): s = level*indent + `self.label` if self.left: s = s + "\n" + self.left.__repr__(level+1, indent) if self.right: s = s + "\n" + self.right.__repr__(level+1, indent) return s def __iter__(self): return inorder(self) # A function that creates a tree from a list def tree(list): if not len(list): return [] i = len(list)/2 return Tree(list[i], tree(list[:i]), tree(list[i+1:])) # A recursive generator that generates the tree leaves in in-order def inorder(t): if t: for x in inorder(t.left): yield x yield t.label for x in inorder(t.right): yield x # Show it off: create a tree t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ") # Print the nodes of the tree in in-order for x in t: print x, print # A non-recursive generator. def inorder(node): stack = [] while node: while node.left: stack.append(node) node = node.left yield node.label while not node.right: try: node = stack.pop() except IndexError: return yield node.label node = node.right # Exercise the non-recursive generator for x in t: print x, print Reference Implementation A preliminary patch against the CVS Python source is available[7]. Footnotes and References [1] PEP 234, http://python.sourceforge.net/peps/pep-0234.html [2] http://www.stackless.com/ [3] PEP 219, http://python.sourceforge.net/peps/pep-0219.html [4] "Iteration Abstraction in Sather" Murer , Omohundro, Stoutamire and Szyperski http://www.icsi.berkeley.edu/~sather/Publications/toplas.html [5] http://www.cs.arizona.edu/icon/ [6] The concept of iterators is described in PEP 234 http://python.sourceforge.net/peps/pep-0234.html [7] http://python.ca/nas/python/generator.diff Copyright This document has been placed in the public domain. Local Variables: mode: indented-text indent-tabs-mode: nil End: From bwarsaw@users.sourceforge.net Tue Jun 5 18:11:52 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Tue, 05 Jun 2001 10:11:52 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.93,1.94 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv22624 Modified Files: pep-0000.txt Log Message: Added pep 255, Simple Generators Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.93 retrieving revision 1.94 diff -C2 -r1.93 -r1.94 *** pep-0000.txt 2001/06/05 16:57:05 1.93 --- pep-0000.txt 2001/06/05 17:11:50 1.94 *************** *** 56,59 **** --- 56,61 ---- S 252 pep-0252.txt Making Types Look More Like Classes van Rossum S 253 pep-0253.txt Subtyping Built-in Types van Rossum + S 254 pep-0254.txt Making Classes Look More Like Types van Rossum + S 255 pep-0255.txt Simple Generators Schemenauer, et al Py-in-the-sky PEPs (not ready; may become active yet) *************** *** 175,178 **** --- 177,182 ---- S 252 pep-0252.txt Making Types Look More Like Classes van Rossum S 253 pep-0253.txt Subtyping Built-in Types van Rossum + S 254 pep-0254.txt Making Classes Look More Like Types van Rossum + S 255 pep-0255.txt Simple Generators Schemenauer, et al From bwarsaw@users.sourceforge.net Tue Jun 5 18:21:21 2001 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Tue, 05 Jun 2001 10:21:21 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep2html.py,1.24,1.25 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv24183 Modified Files: pep2html.py Log Message: fixanchor(): Use a module global RFCURL template for RFC urls. Change this template to point at the nice faqs.org html-ified RFCs. Index: pep2html.py =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep2html.py,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -r1.24 -r1.25 *** pep2html.py 2001/05/01 17:53:52 1.24 --- pep2html.py 2001/06/05 17:21:19 1.25 *************** *** 35,38 **** --- 35,39 ---- PROGRAM = sys.argv[0] + RFCURL = 'http://www.faqs.org/rfcs/rfc%d.html' *************** *** 72,76 **** elif text[:3] == 'RFC': rfcnum = int(match.group('rfcnum'), 10) ! link = 'http://www.rfc-editor.org/rfc/rfc%04d.txt' % rfcnum if link: return "%s" % (link, cgi.escape(text)) --- 73,77 ---- elif text[:3] == 'RFC': rfcnum = int(match.group('rfcnum'), 10) ! link = RFCURL % rfcnum if link: return "%s" % (link, cgi.escape(text)) From gvanrossum@users.sourceforge.net Tue Jun 5 20:31:58 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 12:31:58 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.29,2.16.8.30 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv18671/Objects Modified Files: Tag: descr-branch typeobject.c Log Message: Add type_new(), a slot for tp_new of PyType_Type that chooses the most derived metatype amongst the available metatypes (the explicit __metatype__ variable or the types of the provided bases). This will raise a mysterious type error ("metaclass conflict among bases") if there is no available metatype that derives from all others. Note that there always is at most one uniqe solution (since the "derives from" graph has no cycles). Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.29 retrieving revision 2.16.8.30 diff -C2 -r2.16.8.29 -r2.16.8.30 *** typeobject.c 2001/06/05 15:35:37 2.16.8.29 --- typeobject.c 2001/06/05 19:31:56 2.16.8.30 *************** *** 296,299 **** --- 296,345 ---- } + static int + issubtype(PyTypeObject *a, PyTypeObject *b) + { + while (a != b) { + a = a->tp_base; + if (a == NULL) + return 0; + } + return 1; + } + + #define ISSUBTYPE(a, b) issubtype(a, b) + + static PyObject * + type_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + PyObject *name, *bases, *dict; + static char *kwlist[] = {"name", "bases", "dict", 0}; + + /* Check arguments (again?!?! yes, alas -- we need the bases!) */ + if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist, + &name, &bases, &dict)) + return NULL; + if (PyTuple_Check(bases)) { + PyTypeObject *metatype = type; + int i, n; + n = PyTuple_GET_SIZE(bases); + for (i = 0; i < n; i++) { + PyObject *base_i = PyTuple_GET_ITEM(bases, i); + PyTypeObject *type_i = base_i->ob_type; + if (ISSUBTYPE(metatype, type_i)) + continue; + if (ISSUBTYPE(type_i, metatype)) { + metatype = type_i; + continue; + } + PyErr_SetString(PyExc_TypeError, + "metaclass conflict among bases"); + return NULL; + } + if (metatype->tp_new != type_new) + return metatype->tp_new(type, args, kwds); + } + return PyType_GenericNew(type, args, kwds); + } + static void type_dealloc(PyTypeObject *type) *************** *** 351,355 **** type_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ ! PyType_GenericNew, /* tp_new */ }; --- 397,401 ---- type_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ ! type_new, /* tp_new */ }; From gvanrossum@users.sourceforge.net Wed Jun 6 02:02:23 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 18:02:23 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.30,2.16.8.31 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv29594/Objects Modified Files: Tag: descr-branch typeobject.c Log Message: A VERY preliminary of multiple inheritance. Lots of stuff doesn't work (hey, __bases__ doesn't even reflect the auxiliary base classes!) but it allows me to write and test some simple mix-in classes. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.30 retrieving revision 2.16.8.31 diff -C2 -r2.16.8.30 -r2.16.8.31 *** typeobject.c 2001/06/05 19:31:56 2.16.8.30 --- typeobject.c 2001/06/06 01:02:20 2.16.8.31 *************** *** 139,142 **** --- 139,143 ---- staticforward void override_slots(PyTypeObject *type, PyObject *dict); + staticforward PyTypeObject *solid_base(PyTypeObject *type); typedef struct { *************** *** 150,153 **** --- 151,167 ---- } etype; + static int + issubtype(PyTypeObject *a, PyTypeObject *b) + { + if (b == &PyBaseObject_Type) + return 1; /* Every type is an implicit subtype of this */ + while (a != NULL) { + if (a == b) + return 1; + a = a->tp_base; + } + return 0; + } + /* TypeType's initializer; called when a type is subclassed */ static int *************** *** 159,163 **** etype *et; struct memberlist *mp; ! int i, nslots, slotoffset, allocsize; assert(PyType_Check(self)); --- 173,177 ---- etype *et; struct memberlist *mp; ! int i, n, nslots, slotoffset, allocsize; assert(PyType_Check(self)); *************** *** 172,196 **** "usage: TypeType(name, bases, dict) "); return -1; - } - if (PyTuple_GET_SIZE(bases) > 1) { - PyErr_SetString(PyExc_TypeError, - "can't multiple-inherit from types (yet)"); - return -1; } ! if (PyTuple_GET_SIZE(bases) < 1) ! base = &PyBaseObject_Type; ! else { base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); ! if (!PyType_Check((PyObject *)base)) { ! PyErr_SetString(PyExc_TypeError, ! "base type must be a type"); ! return -1; ! } ! if (base->tp_new == NULL) { ! PyErr_SetString(PyExc_TypeError, ! "base type must have a tp_new slot"); ! return -1; } } /* Check for a __slots__ sequence variable in dict, and count it */ --- 186,226 ---- "usage: TypeType(name, bases, dict) "); return -1; } ! n = PyTuple_GET_SIZE(bases); ! if (n > 0) { ! PyTypeObject *winner, *candidate, *base_i; base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); ! winner = &PyBaseObject_Type; ! for (i = 0; i < n; i++) { ! base_i = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); ! if (!PyType_Check((PyObject *)base_i)) { ! PyErr_SetString( ! PyExc_TypeError, ! "bases must be types"); ! return -1; ! } ! candidate = solid_base(base_i); ! if (issubtype(winner, candidate)) ! ; ! else if (issubtype(candidate, winner)) { ! winner = candidate; ! base = base_i; ! } ! else { ! PyErr_SetString( ! PyExc_TypeError, ! "multiple bases have " ! "instance lay-out conflict"); ! return -1; ! } } } + else + base = &PyBaseObject_Type; + if (base->tp_new == NULL) { + PyErr_SetString(PyExc_TypeError, + "base type must have a tp_new slot"); + return -1; + } /* Check for a __slots__ sequence variable in dict, and count it */ *************** *** 286,289 **** --- 316,333 ---- add_members(type, et->members); + /* XXX This is close, but not quite right! */ + if (n > 1) { + PyTypeObject *t; + for (i = n; --i >= 0; ) { + t = (PyTypeObject *) PyTuple_GET_ITEM(bases, i); + x = PyObject_CallMethod(type->tp_dict, + "update", "O", t->tp_dict); + if (x == NULL) { + Py_DECREF(type); + return -1; + } + } + } + x = PyObject_CallMethod(type->tp_dict, "update", "O", dict); if (x == NULL) { *************** *** 297,311 **** static int ! issubtype(PyTypeObject *a, PyTypeObject *b) { ! while (a != b) { ! a = a->tp_base; ! if (a == NULL) ! return 0; ! } return 1; } ! #define ISSUBTYPE(a, b) issubtype(a, b) static PyObject * --- 341,380 ---- static int ! extra_ivars(PyTypeObject *type, PyTypeObject *base) { ! int t_size = type->tp_basicsize; ! int b_size = base->tp_basicsize; ! ! /* XXX what about tp_itemsize? */ ! assert((type->tp_flags & Py_TPFLAGS_GC) >= ! (base->tp_flags & Py_TPFLAGS_GC)); /* base has GC, type not! */ ! if (type->tp_flags & Py_TPFLAGS_GC) ! t_size -= PyGC_HEAD_SIZE; ! if (base->tp_flags & Py_TPFLAGS_GC) ! b_size -= PyGC_HEAD_SIZE; ! assert(t_size >= b_size); /* type smaller than base! */ ! if (t_size == b_size) ! return 0; ! if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 && ! type->tp_dictoffset == b_size && ! t_size == b_size + sizeof(PyObject *)) ! return 0; /* "Forgive" adding a __dict__ only */ return 1; } ! static PyTypeObject * ! solid_base(PyTypeObject *type) ! { ! PyTypeObject *base; ! ! if (type->tp_base) ! base = solid_base(type->tp_base); ! else ! base = &PyBaseObject_Type; ! if (extra_ivars(type, base)) ! return type; ! else ! return base; ! } static PyObject * *************** *** 326,332 **** PyObject *base_i = PyTuple_GET_ITEM(bases, i); PyTypeObject *type_i = base_i->ob_type; ! if (ISSUBTYPE(metatype, type_i)) continue; ! if (ISSUBTYPE(type_i, metatype)) { metatype = type_i; continue; --- 395,401 ---- PyObject *base_i = PyTuple_GET_ITEM(bases, i); PyTypeObject *type_i = base_i->ob_type; ! if (issubtype(metatype, type_i)) continue; ! if (issubtype(type_i, metatype)) { metatype = type_i; continue; From gvanrossum@users.sourceforge.net Wed Jun 6 02:03:16 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Jun 2001 18:03:16 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.1.2.10,1.1.2.11 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv16053 Modified Files: Tag: descr-branch test_descr.py Log Message: Testing __metaclass__ and multiple inheritance (for mix-ins). Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/Attic/test_descr.py,v retrieving revision 1.1.2.10 retrieving revision 1.1.2.11 diff -C2 -r1.1.2.10 -r1.1.2.11 *** test_descr.py 2001/06/05 10:49:24 1.1.2.10 --- test_descr.py 2001/06/06 01:03:14 1.1.2.11 *************** *** 339,342 **** --- 339,370 ---- ("delattr", "foo")], log) + def baseless(): + if verbose: print "Testing __metaclass__ and mix-ins..." + global C + class C: + __metaclass__ = type(type(0)) + def __init__(self): + self.__state = 0 + def getstate(self): + return self.__state + def setstate(self, state): + self.__state = state + a = C() + verify(a.getstate() == 0) + a.setstate(10) + verify(a.getstate() == 10) + class D(type({}), C): + def __init__(self): + type({}).__init__(self) + C.__init__(self) + d = D() + verify(d.keys() == []) + d["hello"] = "world" + verify(d.items() == [("hello", "world")]) + verify(d["hello"] == "world") + verify(d.getstate() == 0) + d.setstate(10) + verify(d.getstate() == 10) + def all(): lists() *************** *** 349,352 **** --- 377,381 ---- pydicts() pymods() + baseless() all() From loewis@users.sourceforge.net Wed Jun 6 07:24:40 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Tue, 05 Jun 2001 23:24:40 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib glob.py,1.9,1.10 fnmatch.py,1.11,1.12 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv4997 Modified Files: glob.py fnmatch.py Log Message: Patch #409973: Speedup glob.glob, add fnmatch.filter. Index: glob.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/glob.py,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -r1.9 -r1.10 *** glob.py 2001/01/20 23:34:12 1.9 --- glob.py 2001/06/06 06:24:38 1.10 *************** *** 19,23 **** return [] dirname, basename = os.path.split(pathname) ! if has_magic(dirname): list = glob(dirname) else: --- 19,25 ---- return [] dirname, basename = os.path.split(pathname) ! if not dirname: ! return glob1(os.curdir, basename) ! elif has_magic(dirname): list = glob(dirname) else: *************** *** 44,53 **** except os.error: return [] ! result = [] ! for name in names: ! if name[0] != '.' or pattern[0] == '.': ! if fnmatch.fnmatch(name, pattern): ! result.append(name) ! return result --- 46,52 ---- except os.error: return [] ! if pattern[0]!='.': ! names=filter(lambda x: x[0]!='.',names) ! return fnmatch.filter(names,pattern) Index: fnmatch.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/fnmatch.py,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -r1.11 -r1.12 *** fnmatch.py 2001/03/21 18:05:48 1.11 --- fnmatch.py 2001/06/06 06:24:38 1.12 *************** *** 38,41 **** --- 38,61 ---- return fnmatchcase(name, pat) + def filter(names, pat): + """Return the subset of the list NAMES that match PAT""" + import os,posixpath + result=[] + pat=os.path.normcase(pat) + if not _cache.has_key(pat): + res = translate(pat) + _cache[pat] = re.compile(res) + match=_cache[pat].match + if os.path is posixpath: + # normcase on posix is NOP. Optimize it away from the loop. + for name in names: + if match(name): + result.append(name) + else: + for name in names: + if match(os.path.normcase(name)): + result.append(name) + return result + def fnmatchcase(name, pat): """Test whether FILENAME matches PATTERN, including case. From loewis@users.sourceforge.net Wed Jun 6 07:25:42 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Tue, 05 Jun 2001 23:25:42 -0700 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.179,1.180 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv5840 Modified Files: NEWS Log Message: Report on fnmatch.filter. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.179 retrieving revision 1.180 diff -C2 -r1.179 -r1.180 *** NEWS 2001/06/02 05:27:19 1.179 --- NEWS 2001/06/06 06:25:40 1.180 *************** *** 125,128 **** --- 125,130 ---- Library + - A new function fnmatch.filter to filter lists of file names was added. + - calendar.py uses month and day names based on the current locale. From gvanrossum@users.sourceforge.net Wed Jun 6 14:30:57 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 06:30:57 -0700 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.180,1.181 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv3188 Modified Files: NEWS Log Message: Added quopri codec. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.180 retrieving revision 1.181 diff -C2 -r1.180 -r1.181 *** NEWS 2001/06/06 06:25:40 1.180 --- NEWS 2001/06/06 13:30:54 1.181 *************** *** 30,33 **** --- 30,34 ---- uu | string | string | UU codec (e.g. for email) base64 | string | string | base64 codec + quopri | string | string | quoted-printable codec zlib | string | string | zlib compression hex | string | string | 2-byte hex codec From gvanrossum@users.sourceforge.net Wed Jun 6 15:26:14 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 07:26:14 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include object.h,2.79.2.9,2.79.2.10 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv14559 Modified Files: Tag: descr-branch object.h Log Message: - Add the missing decl for PyBaseObject_Type. - Rename PyGeneric_{Get,Set}Attr to PyObject_Generic{Get,Set}Attr (more to follow for this one). Index: object.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/object.h,v retrieving revision 2.79.2.9 retrieving revision 2.79.2.10 diff -C2 -r2.79.2.9 -r2.79.2.10 *** object.h 2001/06/05 10:49:24 2.79.2.9 --- object.h 2001/06/06 14:26:12 2.79.2.10 *************** *** 289,292 **** --- 289,293 ---- extern DL_IMPORT(PyTypeObject) PyType_Type; /* Metatype */ + extern DL_IMPORT(PyTypeObject) PyBaseObject_Type; /* Most base object type */ #define PyType_Check(op) PyObject_TypeCheck(op, &PyType_Type) *************** *** 313,318 **** extern DL_IMPORT(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *); extern DL_IMPORT(int) PyObject_HasAttr(PyObject *, PyObject *); ! extern DL_IMPORT(PyObject *) PyGeneric_GetAttr(PyObject *, PyObject *); ! extern DL_IMPORT(int) PyGeneric_SetAttr(PyObject *, PyObject *, PyObject *); extern DL_IMPORT(long) PyObject_Hash(PyObject *); extern DL_IMPORT(int) PyObject_IsTrue(PyObject *); --- 314,320 ---- extern DL_IMPORT(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *); extern DL_IMPORT(int) PyObject_HasAttr(PyObject *, PyObject *); ! extern DL_IMPORT(PyObject *) PyObject_GenericGetAttr(PyObject *, PyObject *); ! extern DL_IMPORT(int) PyObject_GenericSetAttr(PyObject *, ! PyObject *, PyObject *); extern DL_IMPORT(long) PyObject_Hash(PyObject *); extern DL_IMPORT(int) PyObject_IsTrue(PyObject *); From gvanrossum@users.sourceforge.net Wed Jun 6 15:27:56 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 07:27:56 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules spam.c,1.1.2.5,1.1.2.6 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv14862/Modules Modified Files: Tag: descr-branch spam.c Log Message: Rename PyGeneric_{Get,Set}Attr to PyObject_Genetic{Get,Set}Attr. Index: spam.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/Attic/spam.c,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -C2 -r1.1.2.5 -r1.1.2.6 *** spam.c 2001/06/05 10:49:24 1.1.2.5 --- spam.c 2001/06/06 14:27:54 1.1.2.6 *************** *** 65,69 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 65,69 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ *************** *** 159,163 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 159,163 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ From gvanrossum@users.sourceforge.net Wed Jun 6 15:27:57 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 07:27:57 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects bufferobject.c,2.13.8.1,2.13.8.2 cellobject.c,1.2.4.1,1.2.4.2 complexobject.c,2.35.4.2,2.35.4.3 descrobject.c,1.1.2.8,1.1.2.9 dictobject.c,2.80.2.7,2.80.2.8 fileobject.c,2.112.2.2,2.112.2.3 floatobject.c,2.81.6.2,2.81.6.3 frameobject.c,2.49.4.2,2.49.4.3 funcobject.c,2.37.4.4,2.37.4.5 intobject.c,2.56.6.2,2.56.6.3 iterobject.c,1.3.2.1,1.3.2.2 listobject.c,2.92.6.5,2.92.6.6 longobject.c,1.71.6.1,1.71.6.2 methodobject.c,2.33.8.4,2.33.8.5 moduleobject.c,2.31.6.3,2.31.6.4 object.c,2.124.4.10,2.124.4.11 rangeobject.c,2.24.6.2,2.24.6.3 sliceobject.c,2.7.4.2,2.7.4.3 stringobject.c,2.103.2.3,2.103.2.4 tupleobject.c,2.48.6.1,2.48.6.2 typeobject.c,2.16.8.31,2.16.8.32 unicodeobject.c,2.87.2.2,2.87.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv14862/Objects Modified Files: Tag: descr-branch bufferobject.c cellobject.c complexobject.c descrobject.c dictobject.c fileobject.c floatobject.c frameobject.c funcobject.c intobject.c iterobject.c listobject.c longobject.c methodobject.c moduleobject.c object.c rangeobject.c sliceobject.c stringobject.c tupleobject.c typeobject.c unicodeobject.c Log Message: Rename PyGeneric_{Get,Set}Attr to PyObject_Genetic{Get,Set}Attr. Index: bufferobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/bufferobject.c,v retrieving revision 2.13.8.1 retrieving revision 2.13.8.2 diff -C2 -r2.13.8.1 -r2.13.8.2 *** bufferobject.c 2001/04/30 14:11:39 2.13.8.1 --- bufferobject.c 2001/06/06 14:27:54 2.13.8.2 *************** *** 550,554 **** 0, /* tp_call */ (reprfunc)buffer_str, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ &buffer_as_buffer, /* tp_as_buffer */ --- 550,554 ---- 0, /* tp_call */ (reprfunc)buffer_str, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ &buffer_as_buffer, /* tp_as_buffer */ Index: cellobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/cellobject.c,v retrieving revision 1.2.4.1 retrieving revision 1.2.4.2 diff -C2 -r1.2.4.1 -r1.2.4.2 *** cellobject.c 2001/04/30 14:23:32 1.2.4.1 --- cellobject.c 2001/06/06 14:27:54 1.2.4.2 *************** *** 107,111 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 107,111 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: complexobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/complexobject.c,v retrieving revision 2.35.4.2 retrieving revision 2.35.4.3 diff -C2 -r2.35.4.2 -r2.35.4.3 *** complexobject.c 2001/04/27 18:04:50 2.35.4.2 --- complexobject.c 2001/06/06 14:27:54 2.35.4.3 *************** *** 611,615 **** 0, /* tp_call */ (reprfunc)complex_str, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 611,615 ---- 0, /* tp_call */ (reprfunc)complex_str, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: descrobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/Attic/descrobject.c,v retrieving revision 1.1.2.8 retrieving revision 1.1.2.9 diff -C2 -r1.1.2.8 -r1.1.2.9 *** descrobject.c 2001/05/10 16:37:11 1.1.2.8 --- descrobject.c 2001/06/06 14:27:54 1.1.2.9 *************** *** 378,382 **** (ternaryfunc)descr_call, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 378,382 ---- (ternaryfunc)descr_call, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ *************** *** 634,638 **** 0, /* tp_call */ (reprfunc)proxy_str, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 634,638 ---- 0, /* tp_call */ (reprfunc)proxy_str, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ *************** *** 747,751 **** (ternaryfunc)wrapper_call, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 747,751 ---- (ternaryfunc)wrapper_call, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.80.2.7 retrieving revision 2.80.2.8 diff -C2 -r2.80.2.7 -r2.80.2.8 *** dictobject.c 2001/06/05 10:49:24 2.80.2.7 --- dictobject.c 2001/06/06 14:27:54 2.80.2.8 *************** *** 1310,1314 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 1310,1314 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ *************** *** 1473,1477 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 1473,1477 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: fileobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v retrieving revision 2.112.2.2 retrieving revision 2.112.2.3 diff -C2 -r2.112.2.2 -r2.112.2.3 *** fileobject.c 2001/04/27 18:04:50 2.112.2.2 --- fileobject.c 2001/06/06 14:27:54 2.112.2.3 *************** *** 1317,1321 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 1317,1321 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: floatobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/floatobject.c,v retrieving revision 2.81.6.2 retrieving revision 2.81.6.3 diff -C2 -r2.81.6.2 -r2.81.6.3 *** floatobject.c 2001/04/30 14:08:33 2.81.6.2 --- floatobject.c 2001/06/06 14:27:54 2.81.6.3 *************** *** 680,684 **** 0, /* tp_call */ (reprfunc)float_str, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 680,684 ---- 0, /* tp_call */ (reprfunc)float_str, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: frameobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/frameobject.c,v retrieving revision 2.49.4.2 retrieving revision 2.49.4.3 diff -C2 -r2.49.4.2 -r2.49.4.3 *** frameobject.c 2001/04/27 18:04:51 2.49.4.2 --- frameobject.c 2001/06/06 14:27:54 2.49.4.3 *************** *** 108,113 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ ! PyGeneric_SetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ --- 108,113 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ ! PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ Index: funcobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/funcobject.c,v retrieving revision 2.37.4.4 retrieving revision 2.37.4.5 diff -C2 -r2.37.4.4 -r2.37.4.5 *** funcobject.c 2001/06/05 10:49:24 2.37.4.4 --- funcobject.c 2001/06/06 14:27:54 2.37.4.5 *************** *** 153,157 **** } ! return PyGeneric_GetAttr(op, name); } --- 153,157 ---- } ! return PyObject_GenericGetAttr(op, name); } *************** *** 204,208 **** } ! return PyGeneric_SetAttr(op, name, value); } --- 204,208 ---- } ! return PyObject_GenericSetAttr(op, name, value); } Index: intobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/intobject.c,v retrieving revision 2.56.6.2 retrieving revision 2.56.6.3 diff -C2 -r2.56.6.2 -r2.56.6.3 *** intobject.c 2001/04/30 14:06:20 2.56.6.2 --- intobject.c 2001/06/06 14:27:54 2.56.6.3 *************** *** 806,810 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 806,810 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: iterobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/iterobject.c,v retrieving revision 1.3.2.1 retrieving revision 1.3.2.2 diff -C2 -r1.3.2.1 -r1.3.2.2 *** iterobject.c 2001/04/30 14:25:44 1.3.2.1 --- iterobject.c 2001/06/06 14:27:54 1.3.2.2 *************** *** 108,112 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 108,112 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ *************** *** 212,216 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 212,216 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: listobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v retrieving revision 2.92.6.5 retrieving revision 2.92.6.6 diff -C2 -r2.92.6.5 -r2.92.6.6 *** listobject.c 2001/06/05 10:49:24 2.92.6.5 --- listobject.c 2001/06/06 14:27:54 2.92.6.6 *************** *** 1568,1572 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 1568,1572 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ *************** *** 1654,1658 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 1654,1658 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.71.6.1 retrieving revision 1.71.6.2 diff -C2 -r1.71.6.1 -r1.71.6.2 *** longobject.c 2001/04/30 01:14:56 1.71.6.1 --- longobject.c 2001/06/06 14:27:54 1.71.6.2 *************** *** 1852,1874 **** PyTypeObject PyLong_Type = { PyObject_HEAD_INIT(&PyType_Type) ! 0, ! "long int", ! sizeof(PyLongObject) - sizeof(digit), ! sizeof(digit), ! (destructor)long_dealloc, /*tp_dealloc*/ ! 0, /*tp_print*/ ! 0, /*tp_getattr*/ ! 0, /*tp_setattr*/ ! (cmpfunc)long_compare, /*tp_compare*/ ! (reprfunc)long_repr, /*tp_repr*/ ! &long_as_number, /*tp_as_number*/ ! 0, /*tp_as_sequence*/ ! 0, /*tp_as_mapping*/ ! (hashfunc)long_hash, /*tp_hash*/ ! 0, /*tp_call*/ ! (reprfunc)long_str, /*tp_str*/ ! PyGeneric_GetAttr, /* tp_getattro */ ! 0, /*tp_setattro*/ ! 0, /*tp_as_buffer*/ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /*tp_flags*/ }; --- 1852,1874 ---- PyTypeObject PyLong_Type = { PyObject_HEAD_INIT(&PyType_Type) ! 0, /* ob_size */ ! "long int", /* tp_name */ ! sizeof(PyLongObject) - sizeof(digit), /* tp_basicsize */ ! sizeof(digit), /* tp_itemsize */ ! (destructor)long_dealloc, /* tp_dealloc */ ! 0, /* tp_print */ ! 0, /* tp_getattr */ ! 0, /* tp_setattr */ ! (cmpfunc)long_compare, /* tp_compare */ ! (reprfunc)long_repr, /* tp_repr */ ! &long_as_number, /* tp_as_number */ ! 0, /* tp_as_sequence */ ! 0, /* tp_as_mapping */ ! (hashfunc)long_hash, /* tp_hash */ ! 0, /* tp_call */ ! (reprfunc)long_str, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ ! 0, /* tp_setattro */ ! 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ }; Index: methodobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/methodobject.c,v retrieving revision 2.33.8.4 retrieving revision 2.33.8.5 diff -C2 -r2.33.8.4 -r2.33.8.5 *** methodobject.c 2001/05/05 11:37:29 2.33.8.4 --- methodobject.c 2001/06/06 14:27:54 2.33.8.5 *************** *** 206,210 **** meth_call, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 206,210 ---- meth_call, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: moduleobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/moduleobject.c,v retrieving revision 2.31.6.3 retrieving revision 2.31.6.4 diff -C2 -r2.31.6.3 -r2.31.6.4 *** moduleobject.c 2001/06/05 10:49:24 2.31.6.3 --- moduleobject.c 2001/06/06 14:27:54 2.31.6.4 *************** *** 206,211 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ ! PyGeneric_SetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ --- 206,211 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ ! PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ Index: object.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v retrieving revision 2.124.4.10 retrieving revision 2.124.4.11 diff -C2 -r2.124.4.10 -r2.124.4.11 *** object.c 2001/05/11 20:00:24 2.124.4.10 --- object.c 2001/06/06 14:27:54 2.124.4.11 *************** *** 1077,1081 **** PyObject * ! PyGeneric_GetAttr(PyObject *obj, PyObject *name) { PyTypeObject *tp = obj->ob_type; --- 1077,1081 ---- PyObject * ! PyObject_GenericGetAttr(PyObject *obj, PyObject *name) { PyTypeObject *tp = obj->ob_type; *************** *** 1124,1128 **** int ! PyGeneric_SetAttr(PyObject *obj, PyObject *name, PyObject *value) { PyTypeObject *tp = obj->ob_type; --- 1124,1128 ---- int ! PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value) { PyTypeObject *tp = obj->ob_type; Index: rangeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/rangeobject.c,v retrieving revision 2.24.6.2 retrieving revision 2.24.6.3 diff -C2 -r2.24.6.2 -r2.24.6.3 *** rangeobject.c 2001/04/27 18:04:51 2.24.6.2 --- rangeobject.c 2001/06/06 14:27:54 2.24.6.3 *************** *** 323,327 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 323,327 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: sliceobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/sliceobject.c,v retrieving revision 2.7.4.2 retrieving revision 2.7.4.3 diff -C2 -r2.7.4.2 -r2.7.4.3 *** sliceobject.c 2001/04/27 18:04:51 2.7.4.2 --- sliceobject.c 2001/06/06 14:27:54 2.7.4.3 *************** *** 176,180 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 176,180 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: stringobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v retrieving revision 2.103.2.3 retrieving revision 2.103.2.4 diff -C2 -r2.103.2.3 -r2.103.2.4 *** stringobject.c 2001/05/02 21:24:00 2.103.2.3 --- stringobject.c 2001/06/06 14:27:54 2.103.2.4 *************** *** 2377,2381 **** 0, /* tp_call */ (reprfunc)string_str, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ &string_as_buffer, /* tp_as_buffer */ --- 2377,2381 ---- 0, /* tp_call */ (reprfunc)string_str, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ &string_as_buffer, /* tp_as_buffer */ Index: tupleobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/tupleobject.c,v retrieving revision 2.48.6.1 retrieving revision 2.48.6.2 diff -C2 -r2.48.6.1 -r2.48.6.2 *** tupleobject.c 2001/04/30 14:26:18 2.48.6.1 --- tupleobject.c 2001/06/06 14:27:54 2.48.6.2 *************** *** 473,477 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 473,477 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.31 retrieving revision 2.16.8.32 diff -C2 -r2.16.8.31 -r2.16.8.32 *** typeobject.c 2001/06/06 01:02:20 2.16.8.31 --- typeobject.c 2001/06/06 14:27:54 2.16.8.32 *************** *** 246,250 **** } if (slots == NULL && base->tp_dictoffset == 0 && ! (base->tp_setattro == PyGeneric_SetAttr || base->tp_setattro == NULL)) nslots = 1; --- 246,250 ---- } if (slots == NULL && base->tp_dictoffset == 0 && ! (base->tp_setattro == PyObject_GenericSetAttr || base->tp_setattro == NULL)) nslots = 1; *************** *** 284,292 **** type->tp_dealloc = subtype_dealloc; if (type->tp_getattro == NULL) { ! type->tp_getattro = PyGeneric_GetAttr; type->tp_getattr = NULL; } if (type->tp_setattro == NULL) { ! type->tp_setattro = PyGeneric_SetAttr; type->tp_setattr = NULL; } --- 284,292 ---- type->tp_dealloc = subtype_dealloc; if (type->tp_getattro == NULL) { ! type->tp_getattro = PyObject_GenericGetAttr; type->tp_getattr = NULL; } if (type->tp_setattro == NULL) { ! type->tp_setattro = PyObject_GenericSetAttr; type->tp_setattr = NULL; } *************** *** 445,449 **** (ternaryfunc)type_call, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 445,449 ---- (ternaryfunc)type_call, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ *************** *** 496,500 **** 0, /* tp_call */ 0, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 496,500 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Index: unicodeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/unicodeobject.c,v retrieving revision 2.87.2.2 retrieving revision 2.87.2.3 diff -C2 -r2.87.2.2 -r2.87.2.3 *** unicodeobject.c 2001/04/27 18:04:51 2.87.2.2 --- unicodeobject.c 2001/06/06 14:27:54 2.87.2.3 *************** *** 5239,5243 **** 0, /* tp_call*/ (reprfunc) unicode_str, /* tp_str */ ! PyGeneric_GetAttr, /* tp_getattro */ 0, /* tp_setattro */ &unicode_as_buffer, /* tp_as_buffer */ --- 5239,5243 ---- 0, /* tp_call*/ (reprfunc) unicode_str, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ &unicode_as_buffer, /* tp_as_buffer */ From gvanrossum@users.sourceforge.net Wed Jun 6 15:34:15 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 07:34:15 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects object.c,2.124.4.11,2.124.4.12 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv17474 Modified Files: Tag: descr-branch object.c Log Message: Add _PyObject_GetDictPtr() -- an internal API to get a pointer to where __dict__ is stored in an object. The simplest case is to add tp_dictoffset to the start of the object, but there are comlications: tp_flags may tell us that tp_dictoffset is not defined, or the offset may be negative: indexing from the end of the object, where tp_itemsize may have to be taken into account. Index: object.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v retrieving revision 2.124.4.11 retrieving revision 2.124.4.12 diff -C2 -r2.124.4.11 -r2.124.4.12 *** object.c 2001/06/06 14:27:54 2.124.4.11 --- object.c 2001/06/06 14:34:13 2.124.4.12 *************** *** 1074,1077 **** --- 1074,1111 ---- } + /* Helper to get a pointer to an object's __dict__ slot, if any */ + + PyObject ** + _PyObject_GetDictPtr(PyObject *obj) + { + #define PTRSIZE (sizeof(PyObject *)) + + long dictoffset; + PyTypeObject *tp = obj->ob_type; + + if (!(tp->tp_flags & Py_TPFLAGS_HAVE_CLASS)) + return NULL; + dictoffset = tp->tp_dictoffset; + if (dictoffset == 0) + return NULL; + if (dictoffset < 0) { + dictoffset += tp->tp_basicsize; + assert(dictoffset > 0); /* Sanity check */ + if (tp->tp_itemsize > 0) { + int n = ((PyVarObject *)obj)->ob_size; + if (n > 0) { + dictoffset += tp->tp_itemsize * n; + /* Round up, if necessary */ + if (tp->tp_itemsize % PTRSIZE != 0) { + dictoffset += PTRSIZE - 1; + dictoffset /= PTRSIZE; + dictoffset *= PTRSIZE; + } + } + } + } + return (PyObject **) ((char *)obj + dictoffset); + } + /* Generic GetAttr functions - put these in your tp_[gs]etattro slot */ *************** *** 1082,1086 **** PyObject *descr; descrgetfunc f; ! int dictoffset; if (tp->tp_dict == NULL) { --- 1116,1120 ---- PyObject *descr; descrgetfunc f; ! PyObject **dictptr; if (tp->tp_dict == NULL) { *************** *** 1097,1103 **** } ! dictoffset = tp->tp_dictoffset; ! if (dictoffset != 0) { ! PyObject *dict = * (PyObject **) ((char *)obj + dictoffset); if (dict != NULL) { PyObject *res = PyDict_GetItem(dict, name); --- 1131,1137 ---- } ! dictptr = _PyObject_GetDictPtr(obj); ! if (dictptr != NULL) { ! PyObject *dict = *dictptr; if (dict != NULL) { PyObject *res = PyDict_GetItem(dict, name); *************** *** 1129,1133 **** PyObject *descr; descrsetfunc f; ! int dictoffset; if (tp->tp_dict == NULL) { --- 1163,1167 ---- PyObject *descr; descrsetfunc f; ! PyObject **dictptr; if (tp->tp_dict == NULL) { *************** *** 1143,1149 **** } ! dictoffset = tp->tp_dictoffset; ! if (dictoffset != 0) { ! PyObject **dictptr = (PyObject **) ((char *)obj + dictoffset); PyObject *dict = *dictptr; if (dict == NULL && value != NULL) { --- 1177,1182 ---- } ! dictptr = _PyObject_GetDictPtr(obj); ! if (dictptr != NULL) { PyObject *dict = *dictptr; if (dict == NULL && value != NULL) { From gvanrossum@users.sourceforge.net Wed Jun 6 15:34:59 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 07:34:59 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include object.h,2.79.2.10,2.79.2.11 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv17822 Modified Files: Tag: descr-branch object.h Log Message: Add _PyObject_GetDictPtr() -- an internal API to get a pointer to where __dict__ is stored in an object. The simplest case is to add tp_dictoffset to the start of the object, but there are comlications: tp_flags may tell us that tp_dictoffset is not defined, or the offset may be negative: indexing from the end of the object, where tp_itemsize may have to be taken into account. Index: object.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/object.h,v retrieving revision 2.79.2.10 retrieving revision 2.79.2.11 diff -C2 -r2.79.2.10 -r2.79.2.11 *** object.h 2001/06/06 14:26:12 2.79.2.10 --- object.h 2001/06/06 14:34:57 2.79.2.11 *************** *** 314,317 **** --- 314,318 ---- extern DL_IMPORT(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *); extern DL_IMPORT(int) PyObject_HasAttr(PyObject *, PyObject *); + extern DL_IMPORT(PyObject **) _PyObject_GetDictPtr(PyObject *); extern DL_IMPORT(PyObject *) PyObject_GenericGetAttr(PyObject *, PyObject *); extern DL_IMPORT(int) PyObject_GenericSetAttr(PyObject *, From gvanrossum@users.sourceforge.net Wed Jun 6 15:41:47 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 07:41:47 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include object.h,2.79.2.11,2.79.2.12 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv20162 Modified Files: Tag: descr-branch object.h Log Message: Add three new slots: tp_bases, tp_mro (method resolution), and tp_introduced (introduced methods, as opposed to supported methods, which are in __dict__). Index: object.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/object.h,v retrieving revision 2.79.2.11 retrieving revision 2.79.2.12 diff -C2 -r2.79.2.11 -r2.79.2.12 *** object.h 2001/06/06 14:34:57 2.79.2.11 --- object.h 2001/06/06 14:41:45 2.79.2.12 *************** *** 260,264 **** iternextfunc tp_iternext; ! /* Attribute descriptor stuff */ struct PyMethodDef *tp_methods; struct memberlist *tp_members; --- 260,264 ---- iternextfunc tp_iternext; ! /* Attribute descriptor and subclassing stuff */ struct PyMethodDef *tp_methods; struct memberlist *tp_members; *************** *** 272,275 **** --- 272,278 ---- allocfunc tp_alloc; allocfunc tp_new; + PyObject *tp_bases; + PyObject *tp_mro; /* method resolution order */ + PyObject *tp_introduced; #ifdef COUNT_ALLOCS From gvanrossum@users.sourceforge.net Wed Jun 6 16:40:40 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 08:40:40 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.32,2.16.8.33 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv9395 Modified Files: Tag: descr-branch typeobject.c Log Message: - Correct __bases__ calculation: take multiple bases into account, and make sure every type (except PyBaseObject_Type) is a subtype of PyBaseObject_Type. - New slots for type objects: __basicsize__, __itemsize__, __flags__, __weaklistoffset__, __dictoffset__. - Initialize a type's __dict__ when it's asked for. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.32 retrieving revision 2.16.8.33 diff -C2 -r2.16.8.32 -r2.16.8.33 *** typeobject.c 2001/06/06 14:27:54 2.16.8.32 --- typeobject.c 2001/06/06 15:40:38 2.16.8.33 *************** *** 9,13 **** --- 9,20 ---- struct memberlist type_members[] = { {"__name__", T_STRING, offsetof(PyTypeObject, tp_name), READONLY}, + {"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY}, + {"__itemsize__", T_INT, offsetof(PyTypeObject, tp_itemsize), READONLY}, + {"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY}, {"__doc__", T_STRING, offsetof(PyTypeObject, tp_doc), READONLY}, + {"__weaklistoffset__", T_LONG, + offsetof(PyTypeObject, tp_weaklistoffset), READONLY}, + {"__dictoffset__", T_LONG, + offsetof(PyTypeObject, tp_dictoffset), READONLY}, {0} }; *************** *** 16,23 **** type_bases(PyTypeObject *type, void *context) { ! if (type->tp_base == NULL) ! return PyTuple_New(0); ! else ! return Py_BuildValue("(O)", type->tp_base); } --- 23,41 ---- type_bases(PyTypeObject *type, void *context) { ! PyObject *bases; ! PyTypeObject *base; ! ! bases = type->tp_bases; ! if (bases != NULL) { ! Py_INCREF(bases); ! return bases; ! } ! base = type->tp_base; ! if (base == NULL) { ! if (type == &PyBaseObject_Type) ! return PyTuple_New(0); ! base = &PyBaseObject_Type; ! } ! return Py_BuildValue("(O)", base); } *************** *** 32,37 **** { if (type->tp_dict == NULL) { ! Py_INCREF(Py_None); ! return Py_None; } return PyDictProxy_New(type->tp_dict); --- 50,59 ---- { if (type->tp_dict == NULL) { ! if (PyType_InitDict(type) < 0) ! return NULL; ! if (type->tp_dict == NULL) { ! Py_INCREF(Py_None); ! return Py_None; ! } } return PyDictProxy_New(type->tp_dict); *************** *** 154,157 **** --- 176,183 ---- issubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *bases; + PyTypeObject *base; + int i, n; + if (b == &PyBaseObject_Type) return 1; /* Every type is an implicit subtype of this */ *************** *** 159,163 **** --- 185,203 ---- if (a == b) return 1; + bases = a->tp_bases; a = a->tp_base; + if (bases != NULL && PyTuple_Check(bases)) { + n = PyTuple_GET_SIZE(bases); + for (i = 0; i < n; i++) { + base = (PyTypeObject *) + PyTuple_GET_ITEM(bases, i); + if (base == b) + return 1; + if (base != a) { + if (issubtype(base, b)) + return 1; + } + } + } } return 0; *************** *** 272,278 **** type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE; ! /* Copy slots and dict from the base type */ Py_INCREF(base); type->tp_base = base; if (PyType_InitDict(type) < 0) { Py_DECREF(type); --- 312,325 ---- type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE; ! /* Set tp_base and tp_bases properly */ ! if (PyTuple_GET_SIZE(bases) == 0) ! bases = Py_BuildValue("(O)", &PyBaseObject_Type); ! else ! Py_INCREF(bases); ! type->tp_bases = bases; Py_INCREF(base); type->tp_base = base; + + /* Copy slots and dict from the base type */ if (PyType_InitDict(type) < 0) { Py_DECREF(type); *************** *** 346,350 **** int b_size = base->tp_basicsize; - /* XXX what about tp_itemsize? */ assert((type->tp_flags & Py_TPFLAGS_GC) >= (base->tp_flags & Py_TPFLAGS_GC)); /* base has GC, type not! */ --- 393,396 ---- *************** *** 354,357 **** --- 400,408 ---- b_size -= PyGC_HEAD_SIZE; assert(t_size >= b_size); /* type smaller than base! */ + if (type->tp_itemsize || base->tp_itemsize) { + /* If itemsize is involved, stricter rules */ + return t_size != b_size || + type->tp_itemsize != base->tp_itemsize; + } if (t_size == b_size) return 0; *************** *** 384,387 **** --- 435,446 ---- static char *kwlist[] = {"name", "bases", "dict", 0}; + if (PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 && + (kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) { + /* type(x) -> x.__class__ */ + PyObject *x = PyTuple_GET_ITEM(args, 0); + Py_INCREF(x->ob_type); + return (PyObject *) x->ob_type; + } + /* Check arguments (again?!?! yes, alas -- we need the bases!) */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist, *************** *** 429,436 **** PyTypeObject PyType_Type = { PyObject_HEAD_INIT(&PyType_Type) ! 0, /* Number of items for varobject */ ! "type", /* Name of this type */ ! sizeof(etype) + sizeof(struct memberlist), /* Basic object size */ ! 0, /* Item size for varobject */ (destructor)type_dealloc, /* tp_dealloc */ 0, /* tp_print */ --- 488,495 ---- PyTypeObject PyType_Type = { PyObject_HEAD_INIT(&PyType_Type) ! 0, /* ob_size */ ! "type", /* tp_name */ ! sizeof(etype) + sizeof(struct memberlist), /* tp_basicsize */ ! 0, /* tp_itemsize */ (destructor)type_dealloc, /* tp_dealloc */ 0, /* tp_print */ *************** *** 445,449 **** (ternaryfunc)type_call, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 504,508 ---- (ternaryfunc)type_call, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ *************** *** 496,500 **** 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 555,559 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ From gvanrossum@users.sourceforge.net Wed Jun 6 16:41:04 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 08:41:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib types.py,1.14.10.2,1.14.10.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv9590 Modified Files: Tag: descr-branch types.py Log Message: Added ObjectType, (the most basic type) now that it's accessible. Index: types.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/types.py,v retrieving revision 1.14.10.2 retrieving revision 1.14.10.3 diff -C2 -r1.14.10.2 -r1.14.10.3 *** types.py 2001/05/06 02:31:13 1.14.10.2 --- types.py 2001/06/06 15:41:02 1.14.10.3 *************** *** 8,11 **** --- 8,12 ---- NoneType = type(None) TypeType = type(NoneType) + ObjectType = NoneType.__bases__[0] IntType = type(0) From fdrake@users.sourceforge.net Wed Jun 6 16:59:06 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Wed, 06 Jun 2001 08:59:06 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/templates howto.tex,1.4,1.5 manual.tex,1.2,1.3 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/templates In directory usw-pr-cvs1:/tmp/cvs-serv16121 Modified Files: howto.tex manual.tex Log Message: Add references to the documentation for the Python documentation markup. Suggested by the comments in SF bug #430627. Index: howto.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/templates/howto.tex,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -r1.4 -r1.5 *** howto.tex 1999/03/16 16:10:31 1.4 --- howto.tex 2001/06/06 15:59:04 1.5 *************** *** 1,2 **** --- 1,9 ---- + % Complete documentation on the extended LaTeX markup used for Python + % documentation is available in ``Documenting Python'', which is part + % of the standard documentation for Python. It may be found online + % at: + % + % http://www.python.org/doc/current/doc/doc.html + \documentclass{howto} Index: manual.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/templates/manual.tex,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -r1.2 -r1.3 *** manual.tex 1999/05/17 16:02:38 1.2 --- manual.tex 2001/06/06 15:59:04 1.3 *************** *** 1,2 **** --- 1,9 ---- + % Complete documentation on the extended LaTeX markup used for Python + % documentation is available in ``Documenting Python'', which is part + % of the standard documentation for Python. It may be found online + % at: + % + % http://www.python.org/doc/current/doc/doc.html + \documentclass{manual} From fdrake@users.sourceforge.net Wed Jun 6 17:02:49 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Wed, 06 Jun 2001 09:02:49 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/templates module.tex,1.21,1.22 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/templates In directory usw-pr-cvs1:/tmp/cvs-serv17398 Modified Files: module.tex Log Message: Typo: "descrition" --> "description" Add reference to the documentation for the Python documentation markup. Fixed up a couple of descriptions. This closes SF bug #430627. Index: module.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/templates/module.tex,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -r1.21 -r1.22 *** module.tex 2000/07/06 16:12:47 1.21 --- module.tex 2001/06/06 16:02:47 1.22 *************** *** 1,4 **** --- 1,11 ---- % Template for a library manual section. % PLEASE REMOVE THE COMMENTS AFTER USING THE TEMPLATE + % + % Complete documentation on the extended LaTeX markup used for Python + % documentation is available in ``Documenting Python'', which is part + % of the standard documentation for Python. It may be found online + % at: + % + % http://www.python.org/doc/current/doc/doc.html % ==== 0. ==== *************** *** 14,18 **** \section{\module{spam} --- ! Short descrition, for section title} % Choose one of these to specify the module module name. If there's --- 21,25 ---- \section{\module{spam} --- ! Short description, for section title and table of contents} % Choose one of these to specify the module module name. If there's *************** *** 32,38 **** % is omitted, no availability statement is produced or implied. % ! % \platform{UNIX} ! % These apply to all modules: \moduleauthor{name}{email} % Author of the module code; --- 39,45 ---- % is omitted, no availability statement is produced or implied. % ! % \platform{Unix} ! % These apply to all modules, and may be given more than once: \moduleauthor{name}{email} % Author of the module code; From fdrake@users.sourceforge.net Wed Jun 6 17:09:56 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Wed, 06 Jun 2001 09:09:56 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/templates howto.tex,1.4,1.4.12.1 manual.tex,1.2,1.2.12.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/templates In directory usw-pr-cvs1:/tmp/cvs-serv19574 Modified Files: Tag: release21-maint howto.tex manual.tex Log Message: Add references to the documentation for the Python documentation markup. Suggested by the comments in SF bug #430627. Index: howto.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/templates/howto.tex,v retrieving revision 1.4 retrieving revision 1.4.12.1 diff -C2 -r1.4 -r1.4.12.1 *** howto.tex 1999/03/16 16:10:31 1.4 --- howto.tex 2001/06/06 16:09:54 1.4.12.1 *************** *** 1,2 **** --- 1,9 ---- + % Complete documentation on the extended LaTeX markup used for Python + % documentation is available in ``Documenting Python'', which is part + % of the standard documentation for Python. It may be found online + % at: + % + % http://www.python.org/doc/current/doc/doc.html + \documentclass{howto} Index: manual.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/templates/manual.tex,v retrieving revision 1.2 retrieving revision 1.2.12.1 diff -C2 -r1.2 -r1.2.12.1 *** manual.tex 1999/05/17 16:02:38 1.2 --- manual.tex 2001/06/06 16:09:54 1.2.12.1 *************** *** 1,2 **** --- 1,9 ---- + % Complete documentation on the extended LaTeX markup used for Python + % documentation is available in ``Documenting Python'', which is part + % of the standard documentation for Python. It may be found online + % at: + % + % http://www.python.org/doc/current/doc/doc.html + \documentclass{manual} From fdrake@users.sourceforge.net Wed Jun 6 17:10:40 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Wed, 06 Jun 2001 09:10:40 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/templates module.tex,1.21,1.21.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/templates In directory usw-pr-cvs1:/tmp/cvs-serv19811 Modified Files: Tag: release21-maint module.tex Log Message: Typo: "descrition" --> "description" Add reference to the documentation for the Python documentation markup. Fixed up a couple of descriptions. This closes SF bug #430627. Index: module.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/templates/module.tex,v retrieving revision 1.21 retrieving revision 1.21.6.1 diff -C2 -r1.21 -r1.21.6.1 *** module.tex 2000/07/06 16:12:47 1.21 --- module.tex 2001/06/06 16:10:38 1.21.6.1 *************** *** 1,4 **** --- 1,11 ---- % Template for a library manual section. % PLEASE REMOVE THE COMMENTS AFTER USING THE TEMPLATE + % + % Complete documentation on the extended LaTeX markup used for Python + % documentation is available in ``Documenting Python'', which is part + % of the standard documentation for Python. It may be found online + % at: + % + % http://www.python.org/doc/current/doc/doc.html % ==== 0. ==== *************** *** 14,18 **** \section{\module{spam} --- ! Short descrition, for section title} % Choose one of these to specify the module module name. If there's --- 21,25 ---- \section{\module{spam} --- ! Short description, for section title and table of contents} % Choose one of these to specify the module module name. If there's *************** *** 32,38 **** % is omitted, no availability statement is produced or implied. % ! % \platform{UNIX} ! % These apply to all modules: \moduleauthor{name}{email} % Author of the module code; --- 39,45 ---- % is omitted, no availability statement is produced or implied. % ! % \platform{Unix} ! % These apply to all modules, and may be given more than once: \moduleauthor{name}{email} % Author of the module code; From gvanrossum@users.sourceforge.net Wed Jun 6 18:17:16 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 10:17:16 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.33,2.16.8.34 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv772 Modified Files: Tag: descr-branch typeobject.c Log Message: Improve the docstring and argument checking error messages slightly. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.33 retrieving revision 2.16.8.34 diff -C2 -r2.16.8.33 -r2.16.8.34 *** typeobject.c 2001/06/06 15:40:38 2.16.8.33 --- typeobject.c 2001/06/06 17:17:14 2.16.8.34 *************** *** 219,223 **** /* Check arguments */ ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist, &name, &bases, &dict)) return -1; --- 219,223 ---- /* Check arguments */ ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO:type", kwlist, &name, &bases, &dict)) return -1; *************** *** 444,448 **** /* Check arguments (again?!?! yes, alas -- we need the bases!) */ ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist, &name, &bases, &dict)) return NULL; --- 444,448 ---- /* Check arguments (again?!?! yes, alas -- we need the bases!) */ ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO:type", kwlist, &name, &bases, &dict)) return NULL; *************** *** 486,489 **** --- 486,493 ---- } + static char type_doc[] = + "type(object) -> the object's type\n" + "type(name, bases, dict) -> a new type"; + PyTypeObject PyType_Type = { PyObject_HEAD_INIT(&PyType_Type) *************** *** 508,512 **** 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! "Define the behavior of a particular type of object.", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ --- 512,516 ---- 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! type_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ From gvanrossum@users.sourceforge.net Wed Jun 6 18:34:16 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 10:34:16 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects listobject.c,2.92.6.6,2.92.6.7 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv4094 Modified Files: Tag: descr-branch listobject.c Log Message: Make the list constructor initialize the list from an optional 'sequence' argument. Also add a proper docstring, making this a drop-in replacement for the built-in list() function. Index: listobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v retrieving revision 2.92.6.6 retrieving revision 2.92.6.7 diff -C2 -r2.92.6.6 -r2.92.6.7 *** listobject.c 2001/06/06 14:27:54 2.92.6.6 --- listobject.c 2001/06/06 17:34:14 2.92.6.7 *************** *** 1497,1505 **** } static int list_init(PyListObject *self, PyObject *args, PyObject *kw) { ! self->ob_size = 0; ! self->ob_item = NULL; return 0; } --- 1497,1589 ---- } + /* Adapted from newer code by Tim */ static int + list_fill(PyListObject *result, PyObject *v) + { + PyObject *it; /* iter(v) */ + int n; /* guess for result list size */ + int i; + + n = result->ob_size; + + /* Special-case list(a_list), for speed. */ + if (PyList_Check(v)) { + if (v == (PyObject *)result) + return 0; /* source is destination, we're done */ + return list_ass_slice(result, 0, n, v); + } + + /* Empty previous contents */ + if (n != 0) { + if (list_ass_slice(result, 0, n, (PyObject *)NULL) != 0) + return -1; + } + + /* Get iterator. There may be some low-level efficiency to be gained + * by caching the tp_iternext slot instead of using PyIter_Next() + * later, but premature optimization is the root etc. + */ + it = PyObject_GetIter(v); + if (it == NULL) + return -1; + + /* Guess a result list size. */ + n = -1; /* unknown */ + if (PySequence_Check(v) && + v->ob_type->tp_as_sequence->sq_length) { + n = PySequence_Size(v); + if (n < 0) + PyErr_Clear(); + } + if (n < 0) + n = 8; /* arbitrary */ + NRESIZE(result->ob_item, PyObject*, n); + if (result->ob_item == NULL) + goto error; + result->ob_size = n; + + /* Run iterator to exhaustion. */ + for (i = 0; ; i++) { + PyObject *item = PyIter_Next(it); + if (item == NULL) { + if (PyErr_Occurred()) + goto error; + break; + } + if (i < n) + PyList_SET_ITEM(result, i, item); /* steals ref */ + else { + int status = ins1(result, result->ob_size, item); + Py_DECREF(item); /* append creates a new ref */ + if (status < 0) + goto error; + } + } + + /* Cut back result list if initial guess was too large. */ + if (i < n && result != NULL) { + if (list_ass_slice(result, i, n, (PyObject *)NULL) != 0) + goto error; + } + Py_DECREF(it); + return 0; + + error: + Py_DECREF(it); + return -1; + } + + static int list_init(PyListObject *self, PyObject *args, PyObject *kw) { ! PyObject *arg = NULL; ! static char *kwlist[] = {"sequence", 0}; ! ! if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:list", kwlist, &arg)) ! return -1; ! if (arg != NULL) ! return list_fill(self, arg); ! if (self->ob_size > 0) ! return list_ass_slice(self, 0, self->ob_size, (PyObject*)NULL); return 0; } *************** *** 1550,1553 **** --- 1634,1641 ---- }; + static char list_doc[] = + "list() -> new list\n" + "list(sequence) -> new list initialized from sequence's items"; + PyTypeObject PyList_Type = { PyObject_HEAD_INIT(&PyType_Type) *************** *** 1572,1576 **** 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ ! 0, /* tp_doc */ (traverseproc)list_traverse, /* tp_traverse */ (inquiry)list_clear, /* tp_clear */ --- 1660,1664 ---- 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ ! list_doc, /* tp_doc */ (traverseproc)list_traverse, /* tp_traverse */ (inquiry)list_clear, /* tp_clear */ *************** *** 1658,1662 **** 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ ! 0, /* tp_doc */ (traverseproc)list_traverse, /* tp_traverse */ 0, /* tp_clear */ --- 1746,1750 ---- 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ ! list_doc, /* tp_doc */ (traverseproc)list_traverse, /* tp_traverse */ 0, /* tp_clear */ From gvanrossum@users.sourceforge.net Wed Jun 6 18:43:44 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 10:43:44 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python bltinmodule.c,2.198,2.198.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv5779 Modified Files: Tag: descr-branch bltinmodule.c Log Message: A first step towards an idea that received much enthusiasm on python-dev: instead of having built-in functions list and type, use the built-in types list and type, whose API has been extended to accommodate this usage. Also added object and dictionary (not dict, that's too common a local variable name). (For now, the API for dictionary() is undecided.) Many more will follow in due time(tuple, xrange, str, unicode, int, long, float, complex, slice, maybe iter, maybe open), but first I need to get back to doing multiple inheritance right. Index: bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.198 retrieving revision 2.198.2.1 diff -C2 -r2.198 -r2.198.2.1 *** bltinmodule.c 2001/04/20 19:13:02 2.198 --- bltinmodule.c 2001/06/06 17:43:42 2.198.2.1 *************** *** 1359,1378 **** static PyObject * - builtin_list(PyObject *self, PyObject *args) - { - PyObject *v; - - if (!PyArg_ParseTuple(args, "O:list", &v)) - return NULL; - return PySequence_List(v); - } - - static char list_doc[] = - "list(sequence) -> list\n\ - \n\ - Return a new list whose items are the same as those of the argument sequence."; - - - static PyObject * builtin_slice(PyObject *self, PyObject *args) { --- 1359,1362 ---- *************** *** 1992,2013 **** static PyObject * - builtin_type(PyObject *self, PyObject *args) - { - PyObject *v; - - if (!PyArg_ParseTuple(args, "O:type", &v)) - return NULL; - v = (PyObject *)v->ob_type; - Py_INCREF(v); - return v; - } - - static char type_doc[] = - "type(object) -> type object\n\ - \n\ - Return the type of the object."; - - - static PyObject * builtin_vars(PyObject *self, PyObject *args) { --- 1976,1979 ---- *************** *** 2177,2181 **** {"iter", builtin_iter, 1, iter_doc}, {"len", builtin_len, 1, len_doc}, - {"list", builtin_list, 1, list_doc}, {"locals", builtin_locals, 1, locals_doc}, {"long", builtin_long, 1, long_doc}, --- 2143,2146 ---- *************** *** 2197,2201 **** {"str", builtin_str, 1, str_doc}, {"tuple", builtin_tuple, 1, tuple_doc}, - {"type", builtin_type, 1, type_doc}, {"unicode", builtin_unicode, 1, unicode_doc}, {"unichr", builtin_unichr, 1, unichr_doc}, --- 2162,2165 ---- *************** *** 2227,2230 **** --- 2191,2204 ---- if (PyDict_SetItemString(dict, "NotImplemented", Py_NotImplemented) < 0) + return NULL; + if (PyDict_SetItemString(dict, "dictionary", + (PyObject *) &PyDict_Type) < 0) + return NULL; + if (PyDict_SetItemString(dict, "list", (PyObject *) &PyList_Type) < 0) + return NULL; + if (PyDict_SetItemString(dict, "object", + (PyObject *) &PyBaseObject_Type) < 0) + return NULL; + if (PyDict_SetItemString(dict, "type", (PyObject *) &PyType_Type) < 0) return NULL; debug = PyInt_FromLong(Py_OptimizeFlag == 0); From gvanrossum@users.sourceforge.net Wed Jun 6 18:51:59 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 10:51:59 -0700 Subject: [Python-checkins] CVS: python/dist/src Makefile.pre.in,1.38,1.39 .cvsignore,2.2,2.3 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv7631 Modified Files: Makefile.pre.in .cvsignore Log Message: Acknowledge the existence of the 'platform' file, generated by the Makefile and used by the setup.py script. Ignore it in .cvsignore; remove it in "make clobber". Index: Makefile.pre.in =================================================================== RCS file: /cvsroot/python/python/dist/src/Makefile.pre.in,v retrieving revision 1.38 retrieving revision 1.39 diff -C2 -r1.38 -r1.39 *** Makefile.pre.in 2001/06/02 06:16:02 1.38 --- Makefile.pre.in 2001/06/06 17:51:57 1.39 *************** *** 764,768 **** tags TAGS \ config.cache config.log config.h Modules/config.c ! -rm -rf build # Make things extra clean, before making a distribution: --- 764,768 ---- tags TAGS \ config.cache config.log config.h Modules/config.c ! -rm -rf build platform # Make things extra clean, before making a distribution: Index: .cvsignore =================================================================== RCS file: /cvsroot/python/python/dist/src/.cvsignore,v retrieving revision 2.2 retrieving revision 2.3 diff -C2 -r2.2 -r2.3 *** .cvsignore 2001/05/15 01:53:40 2.2 --- .cvsignore 2001/06/06 17:51:57 2.3 *************** *** 9,10 **** --- 9,11 ---- build Makefile.pre + platform From gvanrossum@users.sourceforge.net Wed Jun 6 18:59:43 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 10:59:43 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects abstract.c,2.60.2.2,2.60.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv9436 Modified Files: Tag: descr-branch abstract.c Log Message: Stamp out duplicate code: PySequence_List(x) should call list(x). Index: abstract.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v retrieving revision 2.60.2.2 retrieving revision 2.60.2.3 diff -C2 -r2.60.2.2 -r2.60.2.3 *** abstract.c 2001/05/05 11:37:29 2.60.2.2 --- abstract.c 2001/06/06 17:59:41 2.60.2.3 *************** *** 1237,1286 **** PySequence_List(PyObject *v) { - PySequenceMethods *m; - if (v == NULL) return null_error(); ! ! if (PyList_Check(v)) ! return PyList_GetSlice(v, 0, PyList_GET_SIZE(v)); ! ! m = v->ob_type->tp_as_sequence; ! if (m && m->sq_item) { ! int i; ! PyObject *l; ! int n = PySequence_Size(v); ! if (n < 0) ! return NULL; ! l = PyList_New(n); ! if (l == NULL) ! return NULL; ! for (i = 0; ; i++) { ! PyObject *item = (*m->sq_item)(v, i); ! if (item == NULL) { ! if (PyErr_ExceptionMatches(PyExc_IndexError)) ! PyErr_Clear(); ! else { ! Py_DECREF(l); ! l = NULL; ! } ! break; ! } ! if (i < n) ! PyList_SET_ITEM(l, i, item); ! else if (PyList_Append(l, item) < 0) { ! Py_DECREF(l); ! l = NULL; ! break; ! } ! } ! if (i < n && l != NULL) { ! if (PyList_SetSlice(l, i, n, (PyObject *)NULL) != 0) { ! Py_DECREF(l); ! l = NULL; ! } ! } ! return l; ! } ! return type_error("list() argument must be a sequence"); } --- 1237,1243 ---- PySequence_List(PyObject *v) { if (v == NULL) return null_error(); ! return PyObject_CallFunction((PyObject *) &PyList_Type, "(O)", v); } From fdrake@users.sourceforge.net Wed Jun 6 19:26:13 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Wed, 06 Jun 2001 11:26:13 -0700 Subject: [Python-checkins] CVS: python/nondist/sftools - New directory Message-ID: Update of /cvsroot/python/python/nondist/sftools In directory usw-pr-cvs1:/tmp/cvs-serv15001/sftools Log Message: Directory /cvsroot/python/python/nondist/sftools added to the repository From fdrake@users.sourceforge.net Wed Jun 6 19:28:02 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Wed, 06 Jun 2001 11:28:02 -0700 Subject: [Python-checkins] CVS: python/nondist/sftools README.txt,NONE,1.1 Message-ID: Update of /cvsroot/python/python/nondist/sftools In directory usw-pr-cvs1:/tmp/cvs-serv15278 Added Files: README.txt Log Message: A description of what can be found in this directory. --- NEW FILE: README.txt --- This directory contains some scripts that Jeremy Hylton wrote for working with the SourceForge bug manager. They do two things: 1. Yank data from a JitterBug database and upload it to SourceForge. This isn't needed for Python anymore, but it may still be useful for someone. 2. Pull data from the SourceForge bug manager and populate a local database with the information. Data is extracted by scraping the SourceForge HTML responses for actual information. The local database can be used to efficiently process ad hoc queries that would be difficult to perform using SourceForge directly, and would have been impossible at the time these scripts were first written. The catch: these scripts were written before SourceForge merged their bug and patch managers to create their general "tracker" facility, and before their framework became as skinnable as it is today. This code will need some measure of revision before it can be used again, but should serve as a nice start for creating an updated form of such tools. From fdrake@users.sourceforge.net Wed Jun 6 19:29:13 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Wed, 06 Jun 2001 11:29:13 -0700 Subject: [Python-checkins] CVS: python/nondist/sftools bug.py,NONE,1.1 buglib.py,NONE,1.1 jitterbuglib.py,NONE,1.1 login.py,NONE,1.1 patchtool.py,NONE,1.1 pest.py,NONE,1.1 sf-schema.txt,NONE,1.1 sfdb.py,NONE,1.1 sflib.py,NONE,1.1 upload.py,NONE,1.1 Message-ID: Update of /cvsroot/python/python/nondist/sftools In directory usw-pr-cvs1:/tmp/cvs-serv15643 Added Files: bug.py buglib.py jitterbuglib.py login.py patchtool.py pest.py sf-schema.txt sfdb.py sflib.py upload.py Log Message: Jeremy's original code to work with the SourceForge bug manager from Python. --- NEW FILE: bug.py --- #! /usr/bin/env python """Update one or more bugs""" import buglib import login import sfdb import getopt import sys # flags: do we use each of the following? LOCAL_DATABASE = 1 SOURCEFORGE = 1 VERBOSE = 0 LOGIN = None PASSWORD = None FIELDS = ("summary", "bug_group_id", "category_id", "resolution_id", "status_id", "assigned_to", "priority", "details") argnames = {} for field in FIELDS: argnames['--' + field] = field def main(bug_ids, updates): """Update one or more bugs using the fields in udpates bug_ids -- list of SF bug_ids updates -- keys are SF field names, values are the strings to put there """ bug_ids = [int(bug) for bug in bug_ids] session = login.Login(LOGIN, PASSWORD) db = sfdb.BugDBInterface() update_ids = translate_updates(db, updates) for bug in bug_ids: b = db.get(bug) for k, v in update_ids.items(): if k == 'assigned_to': b.assign(v) else: b.set(k, v) b.flush() buglib.update_bug(b.get_form_data(), session) if VERBOSE: print bug def translate_updates(db, updates): trans = {} for k, v in updates.items(): if k in ('summary', 'assigned_to', 'details'): trans[k] = v continue table = k[:-3] mapping = getattr(db, table) trans[k] = mapping.lookup(v) if VERBOSE: print trans return trans if __name__ == "__main__": field_args = [field + "=" for field in FIELDS] opts, args = getopt.getopt(sys.argv[1:], 'v', ["verbose", "login=", "password="] \ + field_args) updates = {} for k, v in opts: if k in ('-v', '--verbose'): VERBOSE = 1 elif argnames.has_key(k): updates[argnames[k]] = v elif k == '--login': LOGIN = v elif k == '--password': PASSWORD = v assert len(args) > 0, "Must specify at least one bug id" if LOGIN is None: LOGIN = raw_input("SF username: ") if PASSWORD is None: import getpass PASSWORD = getpass.getpass("SF Password: ") main(args, updates) --- NEW FILE: buglib.py --- """Tools to interact with SF Bug Tracker""" import formatter import getpass import htmllib import httplib import urllib import urlparse try: import cPickle except ImportError: import pickle else: pickle = cPickle import pg import login import sflib import sfdb BUG_SUMMARY_URL = "http://sourceforge.net/bugs/?group_id=5470&set=custom&_assigned_to=0&_status=1&_category=100&_bug_group=100&SUBMIT=Browse" BUG_LOAD_URL = "http://sourceforge.net/bugs/index.php?group_id=5470&func=detailbug&bug_id=%s" BUG_POST_URL = "http://sourceforge.net/bugs/index.php" VERBOSE = 1 class BugParser(htmllib.HTMLParser): __super_init = htmllib.HTMLParser.__init__ VERBOSE = 0 def __init__(self, formatter, verbose=None): self.__super_init(formatter) self.fields = {} self.current_field = None self.current_field_value = None self.summary = None self.bug_id = None if verbose is not None: self.VERBOSE = verbose def start_select(self, attrs): if self.VERBOSE: print "SELECT", attrs for k, v in attrs: if k == 'name': self.current_field = v assert self.current_field is not None def end_select(self): self.current_field = None def start_option(self, attrs): if self.VERBOSE: print "OPTION", attrs assert self.current_field_value is None selected = 0 for k, v in attrs: if k == 'value': value = v if k == 'selected': selected = 1 if selected: self.current_field_value = value self.save_bgn() def end_option(self): if self.current_field_value is not None: label = self.save_end() self.fields[self.current_field] = (label, self.current_field_value) self.current_field_value = None def start_input(self, attrs): summary = 0 bug_id = 0 value = None for k, v in attrs: if k == 'name' and v == 'summary': summary = 1 elif k == 'value': value = v elif k == 'name' and v == 'bug_id': bug_id = 1 if summary: assert self.summary is None assert value is not None self.summary = value if bug_id: assert self.bug_id is None assert value is not None self.bug_id = value def get_bug_urls(): urls = [] p = sflib.SummaryParser(BUG_SUMMARY_URL, ('detailbug',)) p.load(BUG_SUMMARY_URL) for path, query, frag in p.hrefs: url = urlparse.urljoin(BUG_SUMMARY_URL, path) urls.append(url) if VERBOSE: print "%d bugs found" % len(urls) return urls def http_get(url, session): try: f = session.get(url) buf = f.read() f.close() except httplib.HTTPException, err: print "Error occurred loading %s" % url print err print return None return buf def load_bug(url, session): for i in range(3): buf = http_get(url, session) if buf is not None: break time.sleep(10) else: raise RuntimeError, "could not load %s" % url p = BugParser(formatter.NullFormatter()) p.feed(buf) return p.bug_id, p.summary, p.fields # a list of fields in the bug submission form that are currently # ignored and what value should be used for them on submission _ignored_fields = [("canned_response", "100"), ("dependent_on_task[]", "100"), ("dependent_on_bug[]", "100"), ] def update_bug(bug_info, session): """Update SF bug tracker with new bug_info bug_info is a dictionary returned from the local database session is the login session returned by login.Login """ form = {'func': 'postmodbug', 'group_id': '5470', 'submit': 'Submit Changes', } for k, v in bug_info.items(): form[k] = str(v) # fill in blank values for everything else for k, v in _ignored_fields: form[k] = v body = urllib.urlencode(form) headers = {'Content-Type': 'application/x-www-form-urlencoded', } return session.get(BUG_POST_URL, "POST", headers, body) def make_bug_urls(bugs): return [BUG_LOAD_URL % bug for bug in bugs] def main(bugs=None): session = login.Login("jhylton", getpass.getpass()) db = sfdb.BugDBInterface(pg.connect()) if bugs: urls = make_bug_urls(bugs) else: urls = get_bug_urls() for url in urls: if VERBOSE: print url bug_id, summary, fields = load_bug(url, session) if VERBOSE: print bug_id, summary print if db.exists(bug_id): db.update(bug_id, summary, fields) else: db.insert(bug_id, summary, fields) if __name__ == "__main__": import sys if len(sys.argv) > 1: main(sys.argv[1:]) else: main() --- NEW FILE: jitterbuglib.py --- """Library for reading Jitterbug records and submitting them to SF A Jitterbug database has one or more categories of bugs, like incoming, open, resolved, etc. Each category is represented by a directory. Each bug is stored in one or more files in that directory; each bug has a unique id. The files for bug NNN are * NNN: A mail message containing the bug report * NNN.notes: Any notes entered via the Jitterbug Web interface * NNN.audit: A log of changes to the bug record; one per line * NNN.followup.I: one or more followup mail messages; first one is numbered 1 * NNN.reply.I: one or more replies entered throught the Web form; first one is numbered 1 This program loads each bug report for a category into the SF Bug Tracker. """ import cgi import os import re import rfc822 import urllib import urlparse try: from cStringIO import StringIO except ImportError: from StringIO import StringIO import sflib VERBOSE = 0 SF_SUBMIT_URL = "http://sourceforge.net/bugs/index.php" class BugLabels: PROJECT_GROUP_ID = None ASSIGNMENT = "100" CATEGORY = "100" GROUP = "100" PRIORITY = "5" def set_label(label, val): setattr(BugLabels, label, val) class Message: def __init__(self, path): self.path = path f = open(path) self.msg = rfc822.Message(f) self.body = self.msg.fp.read() f.close() def __getattr__(self, attr): return getattr(self.msg, attr) def dump(self): """Return a string with a minimal copy of the message""" headers = [] for field in "From", "Subject", "Date": val = self.msg.getheader(field) if val: headers.append("%s: %s" % (field, val)) return "\n".join(headers) + "\n\n" + self.body class Notes: def __init__(self, buf): self.buf = buf def dump(self): return self.buf class Bug: def __init__(self, dir, bug_id): self.id = bug_id self.dir = dir self.root = os.path.join(dir, bug_id) self._load() def _load(self): self._load_root() self._load_audit() self._load_followups() self._load_replys() self._load_notes() def _load_root(self): f = open(self.root) self.msg = rfc822.Message(f) # The body of a Jitterbug mail message has four more rfc822 # headers. Parse these as another message object, then get # the real body out of the second Message object. g = StringIO(self.msg.fp.read()) self.msg_headers = rfc822.Message(g) self.msg_body = self.msg_headers.fp.read() g.close() f.close() def _load_audit(self): audit_path = self.root + ".audit" if not os.path.exists(audit_path): self.audit = None else: f = open(audit_path) self.audit = f.read() f.close() def _load_notes(self): notes_path = self.root + ".notes" if not os.path.exists(notes_path): self.notes = None else: f = open(notes_path) self.notes = f.read() f.close() def _load_numbered(self, name): rx = re.compile("%s.%s.(\d+)" % (self.id, name)) elts = {} for file in os.listdir(self.dir): mo = rx.match(file) if not mo: continue msg = Message(os.path.join(self.dir, file)) elts[int(mo.group(1))] = msg if elts: l = elts.items() l.sort() l = map(lambda x:x[1], l) else: l = [] return l def _load_followups(self): self.followups = self._load_numbered('followup') def _load_replys(self): self.replys = self._load_numbered('reply') def dump(self, io): template = """Jitterbug-Id: %(jid)s Submitted-By: %(sender)s Date: %(date)s Version: %(version)s OS: %(os)s %(body)s ==================================================================== Audit trail: %(audit)s """ jid = self.id sender = self.msg.getheader('from') date = self.msg.getheader('date') version = self.msg_headers.getheader('version') os = self.msg_headers.getheader('os') body = self.msg_body audit = self.audit io.write(template % vars()) def submit(self, url): buf = self.submit_initial(url) if not (self.followups or self.replys or self.notes): if VERBOSE: print "Done" return # find the SF bug id and post comments for each reply or # followup p = self._load_bug_summary(url, buf) self.submit_followups(url) def submit_initial(self, url): if VERBOSE: print "Submitting bug PR#%s" % self.id data = self.encode_initial_bug_report() f = urllib.urlopen(url, data) resp = f.read() f.close() return resp def submit_followups(self, url): bug_id = self.find_bug_id(url) if bug_id is None: print "Error entering bug PR#%s" % self.id return i = 0 for msg in self.replys + self.followups: i = i + 1 data = self.encode_followup_comment(bug_id, msg) if VERBOSE: print "Submitting followup/reply", i urllib.urlopen(url, data) if self.notes: if VERBOSE: print "Submitting notes" data = self.encode_followup_comment(bug_id, Notes(self.notes)) urllib.urlopen(url, data) def find_bug_id(self, url): try: return self._bsp.get_sf_bug_id(self.id) except KeyError: return None def _load_bug_summary(self, url, buf): """Load a bug summary start with the HTML response in buf""" self._bsp = BugSummaryParser() self._bsp.parse(buf) def encode_initial_bug_report(self): # the form vars definitions are defined by the form used to # submit bugs on SF form_vars = {'func': 'postaddbug', 'group_id': BugLabels.PROJECT_GROUP_ID, 'category': BugLabels.CATEGORY, 'bug_group_id': BugLabels.GROUP, 'priority': BugLabels.PRIORITY, 'assigned_to': BugLabels.ASSIGNMENT, } form_vars['summary'] = "%s (PR#%s)" % \ (self.msg.getheader('subject'), self.id) collector = StringIO() self.dump(collector) collector.seek(0, 0) form_vars['details'] = collector.read().strip() return urllib.urlencode(form_vars) def encode_followup_comment(self, bug_id, msg): form_vars = {'func': 'postaddcomment', 'group_id': BugLabels.PROJECT_GROUP_ID, 'bug_id': bug_id, } form_vars['details'] = msg.dump() return urllib.urlencode(form_vars) class BugSummaryParser: """Parse the bug summary page from sourceforge Specific intent of this class is to extract the SF bug id associated with a newly entered jitterbug record. We identify the Jitterbug record by the (PR#NNN) string in the details line. The Requires that each bug is on its own line in the HTML table. If SF changes its output, all bets are off. """ def __init__(self): self.bugs = {} self.parser = sflib.SummaryParser(SF_SUBMIT_URL, ('detailbug',)) def get_sf_bug_id(self, pr_id): return self.bugs[pr_id] rx_pr = re.compile('\(PR#(\d+)\)') def parse(self, buf): self.parser.parse(buf) self._load_hrefs() def _load_hrefs(self): """Load hrefs from the parser object inecto self.bugs""" for href, query_dict, line in self.parser.get_hrefs(): mo = self.rx_pr.search(line) if not mo: continue pr_id = mo.group(1) bug_id = query_dict['bug_id'] self.bugs[pr_id] = bug_id --- NEW FILE: login.py --- import httplib import re import urllib SF_HOST = "sourceforge.net" FORM_URL = "http://sourceforge.net/account/login.php" test_url = "http://sourceforge.net/bugs/?func=detailbug&group_id=5470&bug_id=112628" class Session: def __init__(self, username, password): self.session_hash = None self._do_login(username, password) if self.session_hash is None: raise ValueError, "invalid username and password" def _do_login(self, username, password): form = {'return_to': '', 'form_loginname': username, 'form_pw': password, 'stay_in_ssl': '1', 'login': 'Login', } query = urllib.urlencode(form) headers = {'Content-Type': 'application/x-www-form-urlencoded', } c = httplib.HTTPConnection(SF_HOST) c.connect() c.request('POST', FORM_URL, query, headers) resp = c.getresponse() cookie = resp.msg.getheader('set-cookie') if cookie is None: raise ValueError, "invalid name/password: %s" % resp.read() self.session_hash = self._get_session_hash(cookie) _rx_sess_hash = re.compile('(session_hash=[a-z0-9]+);') def _get_session_hash(self, cookie): mo = self._rx_sess_hash.search(cookie) if mo: return mo.group(1) raise ValueError, "could not find session_hash in %s" % repr(cookie) def get(self, url, method="GET", headers={}, body=None): c = httplib.HTTPConnection(SF_HOST) c.set_debuglevel(1) c.connect() _headers = {'Cookie': self.session_hash} if headers: _headers.update(headers) if body: c.request(method, url, body, _headers) else: c.request(method, url, headers=_headers) resp = c.getresponse() return resp def Login(username, password): return Session(username, password) --- NEW FILE: patchtool.py --- """Screen scraper for Patch Manager interface The patch form URL is http://www.sourceforge.net/patch/index.php. GET method If I'm lucky, it can be used without authentication. the input fields are: (* means hidden field) *group_id=5470 *custom=set _assigned_to=None _status=None This script produces the following HTML for each entry: 100518 fix bltinmodule.c for 64-bit platforms 2000-Jun-07 03:21 gvanrossum tmick If there are more than 50 patches, the following HTML is produced:   Next 50 --> Future plans: support authentication command-line interface for modifying patches """ import cgi import re import types from urllib import urlencode from urlparse import urljoin from urllib import urlopen import pg from sfdb import PatchDBInterface VERBOSE = 0 DATABASE = None class PatchListParser: """Minimal re-based parsed that grabs relevant URLs from summary""" rx_href = re.compile('HREF="([?/=&_A-Za-z0-9]+)"') def parse_hrefs(self, buf): hrefs = [] offset = 0 while 1: mo = self.rx_href.search(buf, offset) if mo is None: break offset = mo.end(1) hrefs.append(mo.group(1)) return hrefs def get_query_hrefs(self, buf): queries = [] for href in self.parse_hrefs(buf): if href[0] == '?': queries.append(href) return queries class PatchParser: """Minimal re-based parser that pulls key-values from patch page""" rx_entry = re.compile(']*>(.+):
(.+)') def parse(self, buf): entries = {} offset = 0 while 1: mo = self.rx_entry.search(buf, offset) if mo is None: break offset = mo.end(2) k, v = mo.group(1, 2) entries[k] = v return entries def urldecode(query): d = cgi.parse_qs(query) for k, v in d.items(): if len(v) != 1: raise ValueError, "unexpected duplicate entry" d[k] = v[0] return d class PatchManager: url = "http://www.sourceforge.net/patch/index.php" group_id = 5470 list_parser = PatchListParser() patch_parser = PatchParser() # XXX to get the right numeric values for assigned_to and status, # would need to scrape them out of the form... def get_patches(self, assigned_to='0', status='0'): assert type(assigned_to) == types.StringType assert type(status) == types.StringType url = self._get_initial_query(assigned_to, status) patch_list = self._load_patch_summary(url) patches = {} for patch_id, p in patch_list: patches[patch_id] = self._load_patch_detail(p) return patches def _get_initial_query(self, assigned_to, status): dict = {'group_id': self.group_id, 'set': 'custom', 'SUBMIT': 'Browse', '_assigned_to': assigned_to, '_status': status, } query = urlencode(dict) return "%s?%s" % (self.url, query) def _load_patch_summary(self, url): todo = [(url, 0)] patches = [] offset = 0 while todo: url, offset = todo[0] del todo[0] if VERBOSE: print "load %s" % url buf = urlopen(url).read() for href in self.list_parser.get_query_hrefs(buf): d = urldecode(href[1:]) if d['func'] == 'detailpatch': patches.append((int(d['patch_id']), urljoin(self.url, href))) elif d['func'] == 'browse': new_offset = int(d['offset']) if new_offset > offset: todo.append((urljoin(self.url, href), new_offset)) return patches def _load_patch_detail(self, url): if VERBOSE: print "load %s" % url buf = urlopen(url).read() return self.patch_parser.parse(buf) if __name__ == "__main__": import sys import getopt opts, args = getopt.getopt(sys.argv[1:], 'vd:') assert len(args) == 0 for k, v in opts: if k == '-v': VERBOSE = 1 elif k == '-d': DATABASE = v pmgr = PatchManager() if VERBOSE: print "Loading patches" p = pmgr.get_patches() if VERBOSE: print "Retrieved %d patches" % len(p) if VERBOSE: print "Inserting into local database" if DATABASE: db = pg.connect(DATABASE) else: db = pg.connect() pdbi = PatchDBInterface(db) for p_id, attrs in p.items(): pdbi.update(p_id, attrs) if VERBOSE: new = len(p) - pdbi.num_deletes print "Found %d new patches" % new print "Updated %d existing patches" % pdbi.num_deletes --- NEW FILE: pest.py --- #! /usr/bin/env python """Pest people about patches that aren't closed""" import os import pg import smtplib from patchdb import PatchDBInterface SF_MAIL_SERVER = "ns1.varesearch.com" VERBOSE = 1 QUERY = "SELECT * FROM patches_t WHERE assigned_to = %d " \ "AND status = %d" HEADER = " user open accepted\n" \ "---------------+------+-----------" ENTRY = "%-15.15s|%5d | %6d" FROM = "Jeremy Hylton " MSG_TEMPLATE = """From: Jeremy Hylton To: %(user)s Subject: Open and Accepted patches reminder This message is automatically generated using the SF Patch Manager database. The database shows that you have %(count)s patches. Open patches need to be resolved -- either accepted, rejected, or postponed. Accepted patches need to be applied and closed. The sooner this can be done the better. Open patches should be resolved by the end of August in order to meet the 2.0b1 release deadline. The specific patches assigned to you are: """ MSG_ENTRY_TEMPLATE = """Patch #%(patch_id)s: %(summary)s http://sourceforge.net/patch/?func=detailpatch&group_id=5470&patch_id=%(patch_id)s """ def send_pest_mail(user, open, accepted): user = user + "@users.sourceforge.net" n_open = len(open) n_accepted = len(accepted) if n_open: if n_accepted: count = "%d open and %d accepted" % (n_open, n_accepted) else: count = "%d open" % n_open else: if n_accepted: count = "%d accepted" % n_accepted else: raise ValueError, "both open and accepted were empty" msg = MSG_TEMPLATE % locals() status = [] for patch_info in open + accepted: patch_id, summary = patch_info[:2] status.append(MSG_ENTRY_TEMPLATE % locals()) msg = msg + "\n".join(status) s = smtplib.SMTP("smtp.concentric.net") # s.set_debuglevel(1) s.sendmail(FROM, (user,), msg) # s.sendmail(FROM, ("jhylton@users.sourceforge.net",), msg) s.close() def main(): dbname = os.environ['USER'] db = PatchDBInterface(pg.connect(dbname)) st_open = db.status.lookup('Open') st_accepted = db.status.lookup('Accepted') if VERBOSE: print HEADER for user, user_id in db.users.get_dict().items(): if user_id <= 100: # system-defined user ids continue open = db.query(QUERY % (user_id, st_open)).getresult() accepted = db.query(QUERY % (user_id, st_accepted)).getresult() if not (open or accepted): if VERBOSE: print ENTRY % (user, 0, 0) continue if VERBOSE: print ENTRY % (user, len(open), len(accepted)) send_pest_mail(user, open, accepted) if __name__ == "__main__": main() --- NEW FILE: sf-schema.txt --- CREATE TABLE users_t ( user_id int PRIMARY KEY, username text NOT NULL ); CREATE TABLE status_t ( status_id int PRIMARY KEY, name text NOT NULL ); CREATE TABLE patches_t ( patch_id int PRIMARY KEY, summary text, status int REFERENCES status_t, category text, date text, submitted_by int REFERENCES users_t, assigned_to int REFERENCES users_t, summary_url text ); CREATE TABLE category_t ( category_id int PRIMARY KEY, name text NOT NULL ); CREATE TABLE resolution_t ( resolution_id int PRIMARY KEY, name text NOT NULL ); CREATE TABLE bug_group_t ( bug_group_id int PRIMARY KEY, name text NOT NULL ); CREATE TABLE bug_t ( bug_id int PRIMARY KEY, summary text, bug_group_id int REFERENCES bug_group_t, category_id int REFERENCES category_t, resolution_id int REFERENCES resolution_t, status_id int REFERENCES status_t, assigned_to int REFERENCES users_t, priority int ); --- NEW FILE: sfdb.py --- import pg import re def quote(s): return re.sub("'", r"\'", s) class QueryResult: def __init__(self, result): self.__result = result self.__tuple = None def getresult(self): if self.__tuple is None: self.__tuple = self.__result.getresult() return self.__tuple def __len__(self): return len(self.getresult()) def __getattr__(self, attr): return getattr(self.__result, attr) class SQLMapping: """Decode a simple mapping from an SQL table An interface for a simple SQL table of the following sort: CREATE TABLE bug_group_t ( bug_group_id int PRIMARY KEY, name text NOT NULL ); The chief requirements are that the types of the two fields match the example above. Assumes that the keys and values are disjoint, so that a single interface can resolve in either direction. """ def __init__(self, db, table, fields="*"): self.dict1 = {} self.dict2 = {} self.__db = db self.__table = table r = db.query("SELECT %s FROM %s" % (fields, table)).getresult() for key, val in r: assert None not in (key, val) self.dict1[key] = val self.dict2[val] = key def lookup(self, kv): r = self.dict1.get(kv) if r is None: r = self.dict2.get(kv) return r def get_dict(self): """Return dict mapping key to value""" return self.dict2 __insert_q = "INSERT INTO %(table)s VALUES (%(key)s, '%(value)s')" def insert(self, key, value): table = self.__table value = quote(value) query = self.__insert_q % locals() self.__db.query(query) self.dict1[key] = value self.dict2[value] = key class PatchDBInterface: """Interface between the PatchManager and the SQL database Scheme for the patches table is: CREATE TABLE patches_t ( patch_id int PRIMARY KEY, summary text, status int REFERENCES status_t, category text, date text, submitted_by int REFERENCES users_t, assigned_to int REFERENCES users_t, summary_url text ); """ def __init__(self, db=None): db = db or pg.connect() self.db = db self.users = SQLMapping(db, 'users_t') self.status = SQLMapping(db, 'status_t') self.num_deletes = 0 def update(self, patch_id, attrs): # resolve REFERENCES status = self.status.lookup(attrs['Status']) submitted_by = self.users.lookup(attrs['Submitted By']) if submitted_by is None: submitted_by = 0 assigned_to = self.users.lookup(attrs['Assigned To']) if assigned_to is None: assigned_to = 100 # delete old version if necessary if self.has_patch(patch_id): q = "DELETE FROM patches_t WHERE patch_id = %(patch_id)d" self.db.query(q % locals()) self.num_deletes = self.num_deletes + 1 d = locals() del d['attrs'] # just to make debugging prints clearer for k, v in attrs.items(): d[k] = pg._quote(v, 0) q = "INSERT INTO patches_t VALUES (%(patch_id)d," \ " %(Summary)s, %(status)d, %(Category)s, %(Date)s," \ " %(submitted_by)d, %(assigned_to)d)" self.db.query(q % d) def has_patch(self, patch_id): r = self.db.query("SELECT * FROM patches_t" \ " WHERE patch_id = %d" % patch_id).getresult() if r: return 1 else: return 0 def query(self, query): return self.db.query(query) class Bug: """Interface to bug_t row""" def __init__(self, bug_info, db): self.__db = db self.__dict = bug_info self.__clean = 1 # Keep this one around solely for the benefit of the SF Web # interface; the local database ignores it. self.__details = None def get(self, attr): """Get an attribute of the bug This method understands a few different kinds of keys: names of bug_t columns, e.g. summary, status_id, etc. names of bug_t references, e.g. status returns the value referred to by status_id """ if self.__dict.has_key(attr): return self.__dict[attr] ref = attr + "_id" if self.__dict.has_key(ref): return self.__get_ref(attr, ref) if attr == "details": return self.__details raise KeyError, "no attribute: %s" % attr def __get_mapping(self, table): try: mapping = getattr(self.__db, table) except AttributeError: raise KeyError, "no table for attribute: %s" % table return mapping def __get_ref(self, table, id): mapping = self.__get_mapping(table) return mapping.lookup(self.__dict[id]) def set(self, attr, value): if attr == 'details': self.__details = value return if self.__dict.has_key(attr): self.__clean = 0 self.__dict[attr] = value return ref = attr + "_id" if self.__dict.has_key(ref): self.__set_ref(attr, ref, value) return raise KeyError, "no attribute: %s" % attr def __set_ref(self, table, id, value): mapping = self.__get_mapping(table) key = mapping.lookup(value) if key is None: raise ValueError, "invalid attribute for table %s: %s" % \ (table, value) # __dict holds keys to values in the mapping self.__clean = 0 self.__dict[id] = key def assign(self, username): # the set interface does not work well here self.__set_ref("users", "assigned_to", username) _update_ids = ('bug_group_id', 'status_id', 'category_id', 'resolution_id') def get_update_data(self): """Return data in the format expected by db update method""" d = {} for attr in Bug._update_ids: attr_value = attr[:-3] key = self.get(attr_value) if key is not None: d[attr] = key, self.get(attr) d['priority'] = self.get('priority'), self.get('priority') user = self.__get_ref('users', 'assigned_to') if user is not None: d['assigned_to'] = user, self.get('assigned_to') for attr, (k, v) in d.items(): d[attr] = k, str(v) return self.__dict['bug_id'], self.__dict['summary'], d _form_keys = ('bug_id', 'summary', 'category_id', 'priority', 'bug_group_id', 'resolution_id', 'assigned_to', 'status_id') def get_form_data(self): d = {} for name in Bug._form_keys: val = self.get(name) if val is None: val = 100 s = str(val) d[name] = s if self.__details is not None: d['details'] = self.__details return d def flush_sf(self): # XXX not sure what to do here... pass def flush_local(self): args = self.get_update_data() self.__db.update(*args) def flush(self): if not self.__clean: self.flush_sf() self.flush_local() self.__clean = 1 class BugDBInterface: """Interface to bug_t""" def __init__(self, db=None): db = db or pg.connect() self.__db = db self.bug_group = SQLMapping(db, "bug_group_t") self.category = SQLMapping(db, "category_t") self.status = SQLMapping(db, "status_t") self.users = SQLMapping(db, "users_t") self.resolution = SQLMapping(db, "resolution_t") def __query(self, query): print query return QueryResult(self.__db.query(query)) def get(self, bug_id): r = self.__query('select * from bug_t where bug_id = %s' % bug_id) if len(r) == 0: return None assert len(r) == 1 return Bug(r.dictresult()[0], self) def insert(self, bug_id, summary, attrs): """Load bug using the info from the buglig BugParser""" self._do_bug_query(bug_id, summary, attrs, self.__insert_q) def update(self, bug_id, summary, attrs): """Update existing bug using info from buglib BugParser""" self.__query("BEGIN WORK") sql = 'DELETE FROM bug_t WHERE bug_id = %(bug_id)s' % locals() self.__query(sql) self.insert(bug_id, summary, attrs) self.__query("COMMIT WORK") __insert_q = "INSERT INTO bug_t (bug_id, summary, " \ "%(optional_keys)s, priority) VALUES " \ "(%(bug_id)s, '%(summary)s', %(optional_values)s, " \ "%(priority)s)" def _do_bug_query(self, bug_id, summary, attrs, query): summary = quote(summary) priority = int(attrs["priority"][1]) optional_keys, optional_values = self._prep_query_refs(attrs) sql = self.__insert_q % locals() self.__query(sql) def _prep_query_refs(self, attrs): self._new_query() self._lookup_ref(self.bug_group, attrs, "bug_group_id") self._lookup_ref(self.category, attrs, "category_id") self._lookup_ref(self.resolution, attrs, "resolution_id") self._lookup_ref(self.status, attrs, "status_id") self._lookup_ref(self.users, attrs, "assigned_to") # now figure out which of the optional fields have values (yuck) for k, v in self.refs.items(): if v is None: del self.refs[k] optional_keys = ", ".join(self.refs.keys()) optional_values = ", ".join(map(str, self.refs.values())) return optional_keys, optional_values __exists_q = "SELECT * FROM bug_t WHERE bug_id = %(bug_id)s" def exists(self, bug_id): if self.__query(self.__exists_q % locals()): return 1 else: return 0 def _new_query(self): self.refs = {} def _lookup_ref(self, table, attrs, attrname): pair = attrs.get(attrname) if pair is None: self.refs[attrname] = None return None value, key = pair id = table.lookup(value) if id is None: id = int(key) table.insert(id, value) self.refs[attrname] = id return id --- NEW FILE: sflib.py --- """Routines for interacting with SourceForge interfaces""" import cgi import re import urllib import urlparse def urldecode(query): d = cgi.parse_qs(query) for k, v in d.items(): if len(v) != 1: raise ValueError, "unexpected duplicate entry" d[k] = v[0] return d class SummaryParser: rx_href = re.compile('HREF="(\S*\?[A-Za-z0-9=&_]+)"') VERBOSE = 0 def __init__(self, root_url, funcs, verbose=None): if verbose: self.VERBOSE = verbose self.root_url = root_url self.offset = 0 self.hrefs = [] self.funcs = {} self.next = None for func in funcs: self.funcs[func] = 1 def get_hrefs(self): return self.hrefs def load(self, _url, offset=None): url = urlparse.urljoin(self.root_url, _url) if self.VERBOSE: print "loading", url if offset is not None: self.offset = offset f = urllib.urlopen(url) resp = f.read() f.close() self.parse(resp) def parse(self, buf): for line in buf.split("\n"): line_offset = 0 while 1: mo = self.rx_href.search(line, line_offset) if mo: self.handle_href_match(mo, line) line_offset = mo.end(1) else: break if self.VERBOSE: print "found %d hrefs" % len(self.hrefs) if self.next: self.load_next() def handle_href_match(self, mo, line): query = mo.group(1) d = self.parse_query(query) self.handle_query(query, d, line) def handle_query(self, query, dict, line): if self.VERBOSE: print query if not dict.has_key('func'): return if dict['func'] == 'browse' and dict.has_key('offset'): off = int(dict['offset']) if off > self.offset: self.next = query, dict if self.keep_func(dict['func']): self.hrefs.append((query, dict, line)) def keep_func(self, func): if self.funcs.has_key(func): return 1 def parse_query(self, href): i = href.find("?") return urldecode(href[i+1:]) def load_next(self): assert self.next is not None query, dict = self.next self.next = None new_offset = int(dict['offset']) self.load(query, new_offset) --- NEW FILE: upload.py --- #! /usr/bin/env python """Enter Jitterbug reports into the SF Bug Tracker upload.py [OPTIONS] [jitterbug_path] This script reads Jitterbug data from its filesystem representation and uploads each bug report to the SourceForge Bug Tracker. Jitterbug stores each of its bug categories in a separate directory (e.g. open, notabug, etc.). This script reads all of the bug files from a single directory. To upload an entire Jitterbug database, the script must be run once on each directory. The command-line options are used to specify metadata for SF. For each option, you must specify the SF id for the field, which you can find by viewing the source of the standard bug submission form. -P [project_group_id] which project to add bugs to (REQUIRED) -p [1..10] bug priority (default 5) -c [category_id] SF bug category -g [group_id] SF bug group The -v option provides verbose output. The -h option prints this message. """ import sys import os import re import getopt import jitterbuglib VERBOSE = 0 _rx_num = re.compile('\d+$') def find_bugs(dir): """Return a list of the bug ids contained in dir""" bug_ids = [] for file in os.listdir(dir): mo = _rx_num.match(file) if mo: bug_ids.append(file) bug_ids.sort() return bug_ids def main(dir): bug_ids = find_bugs(dir) for bid in bug_ids: bug = jitterbuglib.Bug(dir, bid) if VERBOSE: print "loaded PR#%s" % bid bug.submit(jitterbuglib.SF_SUBMIT_URL) def usage(code, msg=''): print >> sys.stderr, __doc__ if msg: print >> sys.stderr, msg sys.exit(code) if __name__ == "__main__": proj_group_set = 0 try: opts, args = getopt.getopt(sys.argv[1:], 'P:g:vp:hc:') except getopt.error, msg: usage(1, msg) if len(args) > 1: usage(1, 'unexpected arguments: ' + ' '.join(args[1:])) if len(args) == 0: usage(1, 'jitterbug_path missing') for k, v in opts: if k == '-v': VERBOSE = 1 elif k == '-h': usage(0) elif k == '-g': jitterbuglib.set_label("GROUP", v) elif k == '-p': jitterbuglib.set_label("PRIORITY", v) elif k == '-P': jitterbuglib.set_label("PROJECT_GROUP_ID", v) proj_group_set = 1 elif k == '-c': jitterbuglib.set_label("CATEGORY", v) if not proj_group_set: usage(1, '-P option is required') # all's well main(args[0]) From gvanrossum@users.sourceforge.net Wed Jun 6 20:00:35 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 06 Jun 2001 12:00:35 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.34,2.16.8.35 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv21388 Modified Files: Tag: descr-branch typeobject.c Log Message: Bugfix in type_init(): when merging the dicts of multiple base classes, don't call d1.update(d2) when d2 is NULL! Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.34 retrieving revision 2.16.8.35 diff -C2 -r2.16.8.34 -r2.16.8.35 *** typeobject.c 2001/06/06 17:17:14 2.16.8.34 --- typeobject.c 2001/06/06 19:00:33 2.16.8.35 *************** *** 368,371 **** --- 368,373 ---- for (i = n; --i >= 0; ) { t = (PyTypeObject *) PyTuple_GET_ITEM(bases, i); + if (t->tp_dict == NULL) + continue; x = PyObject_CallMethod(type->tp_dict, "update", "O", t->tp_dict); From loewis@users.sourceforge.net Thu Jun 7 06:49:07 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Wed, 06 Jun 2001 22:49:07 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib pstats.py,1.17,1.18 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv21211 Modified Files: pstats.py Log Message: Patch #416220: Fix misplaced paren. Index: pstats.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pstats.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -r1.17 -r1.18 *** pstats.py 2001/05/11 19:21:41 1.17 --- pstats.py 2001/06/07 05:49:05 1.18 *************** *** 614,618 **** return self.prompt = line + "% " ! elif len(self.prompt > 2): line = self.prompt[-2:] else: --- 614,618 ---- return self.prompt = line + "% " ! elif len(self.prompt) > 2: line = self.prompt[-2:] else: From loewis@users.sourceforge.net Thu Jun 7 06:49:07 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Wed, 06 Jun 2001 22:49:07 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/xml/sax xmlreader.py,1.14,1.15 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/xml/sax In directory usw-pr-cvs1:/tmp/cvs-serv21211/xml/sax Modified Files: xmlreader.py Log Message: Patch #416220: Fix misplaced paren. Index: xmlreader.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/xml/sax/xmlreader.py,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -r1.14 -r1.15 *** xmlreader.py 2001/03/14 22:43:47 1.14 --- xmlreader.py 2001/06/07 05:49:05 1.15 *************** *** 3,9 **** import handler ! ! from _exceptions import SAXNotSupportedException, SAXNotRecognizedException ! # ===== XMLREADER ===== --- 3,7 ---- import handler ! from _exceptions import * # ===== XMLREADER ===== From nowonder@users.sourceforge.net Thu Jun 7 06:51:39 2001 From: nowonder@users.sourceforge.net (Peter Schneider-Kamp) Date: Wed, 06 Jun 2001 22:51:39 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules binascii.c,2.28,2.29 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv21401 Modified Files: binascii.c Log Message: This closes bug #430849 (internal error produced by binascii.a2b_base64) Index: binascii.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/binascii.c,v retrieving revision 2.28 retrieving revision 2.29 diff -C2 -r2.28 -r2.29 *** binascii.c 2001/01/09 02:11:57 2.28 --- binascii.c 2001/06/07 05:51:36 2.29 *************** *** 336,339 **** --- 336,343 ---- return NULL; + if ( ascii_len == 0) { + PyErr_SetString(Error, "Cannot decode empty input"); + return NULL; + } bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */ From loewis@users.sourceforge.net Thu Jun 7 06:52:19 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Wed, 06 Jun 2001 22:52:19 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/xml/sax xmlreader.py,1.15,1.16 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/xml/sax In directory usw-pr-cvs1:/tmp/cvs-serv21571 Modified Files: xmlreader.py Log Message: Previous check-in was by mistake, undo it. Index: xmlreader.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/xml/sax/xmlreader.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -r1.15 -r1.16 *** xmlreader.py 2001/06/07 05:49:05 1.15 --- xmlreader.py 2001/06/07 05:52:17 1.16 *************** *** 3,7 **** import handler ! from _exceptions import * # ===== XMLREADER ===== --- 3,9 ---- import handler ! ! from _exceptions import SAXNotSupportedException, SAXNotRecognizedException ! # ===== XMLREADER ===== From gvanrossum@users.sourceforge.net Thu Jun 7 12:28:08 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 07 Jun 2001 04:28:08 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python getargs.c,2.54,2.54.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv4406 Modified Files: Tag: descr-branch getargs.c Log Message: Use PyObject_TypeCheck() for O! rather than a straight comparison. Index: getargs.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/getargs.c,v retrieving revision 2.54 retrieving revision 2.54.6.1 diff -C2 -r2.54 -r2.54.6.1 *** getargs.c 2001/02/12 22:13:26 2.54 --- getargs.c 2001/06/07 11:28:06 2.54.6.1 *************** *** 858,862 **** p = va_arg(*p_va, PyObject **); format++; ! if (arg->ob_type == type) *p = arg; else --- 858,862 ---- p = va_arg(*p_va, PyObject **); format++; ! if (PyObject_TypeCheck(arg, type)) *p = arg; else From gvanrossum@users.sourceforge.net Thu Jun 7 12:38:57 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 07 Jun 2001 04:38:57 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.80.2.8,2.80.2.9 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv5732 Modified Files: Tag: descr-branch dictobject.c Log Message: Make PyDict_SetItem() and PyDict_DelItem() call on their PyObject_ cousins when the type is a derived type from PyDict_Type -- this makes it possible to create a derived dictionary class that implements restrictions on item assignments and pass that as the dict to exec/eval, for example. Don't do this for PyDict_Clear(). It's trickier there: there's no PyObject_Clear(), and calling self.clear() might recurse right into PyDict_Clear(). PyDict_Clear() is only used by the standard library in a few places, and in at least one of those (GC) setting a trap would be inappropriate anyway. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.80.2.8 retrieving revision 2.80.2.9 diff -C2 -r2.80.2.8 -r2.80.2.9 *** dictobject.c 2001/06/06 14:27:54 2.80.2.8 --- dictobject.c 2001/06/07 11:38:55 2.80.2.9 *************** *** 424,428 **** register int n_used; ! if (!PyDict_Check(op)) { PyErr_BadInternalCall(); return -1; --- 424,430 ---- register int n_used; ! if (op->ob_type != &PyDict_Type) { ! if (PyDict_Check(op)) ! return PyObject_SetItem(op, key, value); PyErr_BadInternalCall(); return -1; *************** *** 486,490 **** PyObject *old_value, *old_key; ! if (!PyDict_Check(op)) { PyErr_BadInternalCall(); return -1; --- 488,494 ---- PyObject *old_value, *old_key; ! if (op->ob_type != &PyDict_Type) { ! if (PyDict_Check(op)) ! return PyObject_DelItem(op, key); PyErr_BadInternalCall(); return -1; From gvanrossum@users.sourceforge.net Thu Jun 7 12:50:07 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 07 Jun 2001 04:50:07 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.80.2.9,2.80.2.10 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv7612 Modified Files: Tag: descr-branch dictobject.c Log Message: Ow! Undo the last change. It causes infinite recursion in certain cases and I don't know how to fix that right now. Later, maybe. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.80.2.9 retrieving revision 2.80.2.10 diff -C2 -r2.80.2.9 -r2.80.2.10 *** dictobject.c 2001/06/07 11:38:55 2.80.2.9 --- dictobject.c 2001/06/07 11:50:05 2.80.2.10 *************** *** 424,430 **** register int n_used; ! if (op->ob_type != &PyDict_Type) { ! if (PyDict_Check(op)) ! return PyObject_SetItem(op, key, value); PyErr_BadInternalCall(); return -1; --- 424,428 ---- register int n_used; ! if (!PyDict_Check(op)) { PyErr_BadInternalCall(); return -1; *************** *** 488,494 **** PyObject *old_value, *old_key; ! if (op->ob_type != &PyDict_Type) { ! if (PyDict_Check(op)) ! return PyObject_DelItem(op, key); PyErr_BadInternalCall(); return -1; --- 486,490 ---- PyObject *old_value, *old_key; ! if (!PyDict_Check(op)) { PyErr_BadInternalCall(); return -1; From lemburg@users.sourceforge.net Thu Jun 7 13:26:59 2001 From: lemburg@users.sourceforge.net (M.-A. Lemburg) Date: Thu, 07 Jun 2001 05:26:59 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects unicodeobject.c,2.92,2.93 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv12368 Modified Files: unicodeobject.c Log Message: Fixes [ #430986 ] Buglet in PyUnicode_FromUnicode. Index: unicodeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/unicodeobject.c,v retrieving revision 2.92 retrieving revision 2.93 diff -C2 -r2.92 -r2.93 *** unicodeobject.c 2001/05/29 17:13:15 2.92 --- unicodeobject.c 2001/06/07 12:26:56 2.93 *************** *** 298,304 **** if (!unicode) { unicode = _PyUnicode_New(1); - unicode->str[0] = *u; if (!unicode) return NULL; unicode_latin1[*u] = unicode; } --- 298,304 ---- if (!unicode) { unicode = _PyUnicode_New(1); if (!unicode) return NULL; + unicode->str[0] = *u; unicode_latin1[*u] = unicode; } From gvanrossum@users.sourceforge.net Thu Jun 7 16:45:06 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 07 Jun 2001 08:45:06 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.1.2.11,1.1.2.12 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv30314 Modified Files: Tag: descr-branch test_descr.py Log Message: Change type({}) to dictionary. Rename the baseless() test to metaclass(), and test only that. Add a new test for multiple inheritance. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/Attic/test_descr.py,v retrieving revision 1.1.2.11 retrieving revision 1.1.2.12 diff -C2 -r1.1.2.11 -r1.1.2.12 *** test_descr.py 2001/06/06 01:03:14 1.1.2.11 --- test_descr.py 2001/06/07 15:45:04 1.1.2.12 *************** *** 117,121 **** verify(l == l1) l = [] ! for i in type({}).__iter__(d): l.append(i) verify(l == l1) testunop({1:2,3:4}, 2, "len(a)", "__len__") --- 117,121 ---- verify(l == l1) l = [] ! for i in dictionary.__iter__(d): l.append(i) verify(l == l1) testunop({1:2,3:4}, 2, "len(a)", "__len__") *************** *** 256,270 **** "a[b]=c", "__setitem__") - DT = type({}) - def pydicts(): if verbose: print "Testing Python subclass of dict..." ! verify(issubclass(DT, DT)) ! verify(isinstance({}, DT)) ! d = DT() verify(d == {}) ! verify(d.__class__ is DT) ! verify(isinstance(d, DT)) ! class C(DT): state = -1 def __init__(self, *a, **kw): --- 256,268 ---- "a[b]=c", "__setitem__") def pydicts(): if verbose: print "Testing Python subclass of dict..." ! verify(issubclass(dictionary, dictionary)) ! verify(isinstance({}, dictionary)) ! d = dictionary() verify(d == {}) ! verify(d.__class__ is dictionary) ! verify(isinstance(d, dictionary)) ! class C(dictionary): state = -1 def __init__(self, *a, **kw): *************** *** 278,287 **** def __setitem__(self, key, value): assert isinstance(key, type(0)) ! DT.__setitem__(self, key, value) def setstate(self, state): self.state = state def getstate(self): return self.state ! verify(issubclass(C, DT)) a1 = C(12) verify(a1.state == 12) --- 276,285 ---- def __setitem__(self, key, value): assert isinstance(key, type(0)) ! dictionary.__setitem__(self, key, value) def setstate(self, state): self.state = state def getstate(self): return self.state ! verify(issubclass(C, dictionary)) a1 = C(12) verify(a1.state == 12) *************** *** 309,312 **** --- 307,326 ---- verify(a[i][j] == i*j) + def metaclass(): + if verbose: print "Testing __metaclass__..." + global C + class C: + __metaclass__ = type(type(0)) + def __init__(self): + self.__state = 0 + def getstate(self): + return self.__state + def setstate(self, state): + self.__state = state + a = C() + verify(a.getstate() == 0) + a.setstate(10) + verify(a.getstate() == 10) + import sys MT = type(sys) *************** *** 339,347 **** ("delattr", "foo")], log) ! def baseless(): ! if verbose: print "Testing __metaclass__ and mix-ins..." global C ! class C: ! __metaclass__ = type(type(0)) def __init__(self): self.__state = 0 --- 353,360 ---- ("delattr", "foo")], log) ! def multi(): ! if verbose: print "Testing multiple inheritance..." global C ! class C(object): def __init__(self): self.__state = 0 *************** *** 354,358 **** a.setstate(10) verify(a.getstate() == 10) ! class D(type({}), C): def __init__(self): type({}).__init__(self) --- 367,371 ---- a.setstate(10) verify(a.getstate() == 10) ! class D(dictionary, C): def __init__(self): type({}).__init__(self) *************** *** 376,381 **** spamdicts() pydicts() pymods() ! baseless() all() --- 389,395 ---- spamdicts() pydicts() + metaclass() pymods() ! multi() all() From loewis@users.sourceforge.net Thu Jun 7 18:17:02 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Thu, 07 Jun 2001 10:17:02 -0700 Subject: [Python-checkins] CVS: python/dist/src/Tools/scripts ftpmirror.py,1.13,1.14 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/scripts In directory usw-pr-cvs1:/tmp/cvs-serv16324 Modified Files: ftpmirror.py Log Message: Patch #430754: Makes ftpmirror.py .netrc aware Index: ftpmirror.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/scripts/ftpmirror.py,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -r1.13 -r1.14 *** ftpmirror.py 2001/01/17 08:48:39 1.13 --- ftpmirror.py 2001/06/07 17:17:00 1.14 *************** *** 12,16 **** -n: don't log in -r: remove local files/directories no longer pertinent ! -l username [-p passwd [-a account]]: login info (default anonymous ftp) -s pat: skip files matching pattern hostname: remote host --- 12,16 ---- -n: don't log in -r: remove local files/directories no longer pertinent ! -l username [-p passwd [-a account]]: login info (default .netrc or anonymous) -s pat: skip files matching pattern hostname: remote host *************** *** 25,28 **** --- 25,29 ---- import string import ftplib + import netrc from fnmatch import fnmatch *************** *** 51,54 **** --- 52,63 ---- passwd = '' account = '' + if not args: usage('hostname missing') + host = args[0] + try: + auth = netrc.netrc().authenticators(host) + if auth is not None: + login, account, passwd = auth + except (netrc.NetrcParseError, IOError): + pass for o, a in opts: if o == '-l': login = a *************** *** 62,67 **** if o == '-r': rmok = 1 if o == '-s': skippats.append(a) - if not args: usage('hostname missing') - host = args[0] remotedir = '' localdir = '' --- 71,74 ---- From gvanrossum@users.sourceforge.net Thu Jun 7 19:31:57 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 07 Jun 2001 11:31:57 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects object.c,2.124.4.12,2.124.4.13 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv31479/Objects Modified Files: Tag: descr-branch object.c Log Message: Change the signature of _PyObject_TypeCheck() to take two type objects; change PyObject_TypeCheck() to hide the change from its users. This might generate faster code if the compiler notices that (ob)->ob_type is loaded twice. It also (and this was the real reason to do this now) avoids warnings when op is not a PyObject * but a derived object, e.g. a PyTypeObject *. Index: object.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v retrieving revision 2.124.4.12 retrieving revision 2.124.4.13 diff -C2 -r2.124.4.12 -r2.124.4.13 *** object.c 2001/06/06 14:34:13 2.124.4.12 --- object.c 2001/06/07 18:31:55 2.124.4.13 *************** *** 1327,1334 **** int ! _PyObject_TypeCheck(PyObject *obj, PyTypeObject *type) { - PyTypeObject *tp = obj->ob_type; - do { if (tp == type) --- 1327,1332 ---- int ! _PyObject_TypeCheck(PyTypeObject *tp, PyTypeObject *type) { do { if (tp == type) From gvanrossum@users.sourceforge.net Thu Jun 7 19:31:57 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 07 Jun 2001 11:31:57 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include object.h,2.79.2.12,2.79.2.13 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv31479/Include Modified Files: Tag: descr-branch object.h Log Message: Change the signature of _PyObject_TypeCheck() to take two type objects; change PyObject_TypeCheck() to hide the change from its users. This might generate faster code if the compiler notices that (ob)->ob_type is loaded twice. It also (and this was the real reason to do this now) avoids warnings when op is not a PyObject * but a derived object, e.g. a PyTypeObject *. Index: object.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/object.h,v retrieving revision 2.79.2.12 retrieving revision 2.79.2.13 diff -C2 -r2.79.2.12 -r2.79.2.13 *** object.h 2001/06/06 14:41:45 2.79.2.12 --- object.h 2001/06/07 18:31:55 2.79.2.13 *************** *** 287,293 **** /* Generic type check */ ! extern DL_IMPORT(int) _PyObject_TypeCheck(PyObject *, PyTypeObject *); #define PyObject_TypeCheck(ob, tp) \ ! ((ob)->ob_type == (tp) || _PyObject_TypeCheck(ob, tp)) extern DL_IMPORT(PyTypeObject) PyType_Type; /* Metatype */ --- 287,293 ---- /* Generic type check */ ! extern DL_IMPORT(int) _PyObject_TypeCheck(PyTypeObject *, PyTypeObject *); #define PyObject_TypeCheck(ob, tp) \ ! ((ob)->ob_type == (tp) || _PyObject_TypeCheck((ob)->ob_type, (tp))) extern DL_IMPORT(PyTypeObject) PyType_Type; /* Metatype */ From nowonder@users.sourceforge.net Thu Jun 7 19:56:15 2001 From: nowonder@users.sourceforge.net (Peter Schneider-Kamp) Date: Thu, 07 Jun 2001 11:56:15 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib base64.py,1.11,1.12 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv3615 Modified Files: base64.py Log Message: check in for patch #430846 use faster code for base64.encodestring (courtesy of Mr. Tim Peters) and for base64.decodestring (courtesy of Anthony Baxter) Index: base64.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/base64.py,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -r1.11 -r1.12 *** base64.py 2001/01/20 19:54:20 1.11 --- base64.py 2001/06/07 18:56:13 1.12 *************** *** 34,50 **** def encodestring(s): """Encode a string.""" ! import StringIO ! f = StringIO.StringIO(s) ! g = StringIO.StringIO() ! encode(f, g) ! return g.getvalue() def decodestring(s): """Decode a string.""" ! import StringIO ! f = StringIO.StringIO(s) ! g = StringIO.StringIO() ! decode(f, g) ! return g.getvalue() def test(): --- 34,46 ---- def encodestring(s): """Encode a string.""" ! pieces = [] ! for i in range(0, len(s), MAXBINSIZE): ! chunk = s[i : i + MAXBINSIZE] ! pieces.append(binascii.b2a_base64(chunk)) ! return "".join(pieces) def decodestring(s): """Decode a string.""" ! return binascii.a2b_base64(s) def test(): From loewis@users.sourceforge.net Thu Jun 7 20:01:26 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Thu, 07 Jun 2001 12:01:26 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libfnmatch.tex,1.17,1.18 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv4830 Modified Files: libfnmatch.tex Log Message: Document filter. Index: libfnmatch.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libfnmatch.tex,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -r1.17 -r1.18 *** libfnmatch.tex 2000/10/09 18:12:29 1.17 --- libfnmatch.tex 2001/06/07 19:01:24 1.18 *************** *** 44,47 **** --- 44,52 ---- \end{funcdesc} + \begin{funcdesc}{filter}{names, pattern} + Return the subset of the list of \var{names} that match \var{pattern}. + It is the same as \code{[n for n in names if fnmatch(n, pattern)]}, but + implemented more efficiently. + \end{funcdesc} \begin{seealso} From gvanrossum@users.sourceforge.net Thu Jun 7 20:03:11 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 07 Jun 2001 12:03:11 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib types.py,1.14.10.3,1.14.10.4 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv5199 Modified Files: Tag: descr-branch types.py Log Message: Use type, object, list, dictionary built-ins. Index: types.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/types.py,v retrieving revision 1.14.10.3 retrieving revision 1.14.10.4 diff -C2 -r1.14.10.3 -r1.14.10.4 *** types.py 2001/06/06 15:41:02 1.14.10.3 --- types.py 2001/06/07 19:03:08 1.14.10.4 *************** *** 7,12 **** NoneType = type(None) ! TypeType = type(NoneType) ! ObjectType = NoneType.__bases__[0] IntType = type(0) --- 7,12 ---- NoneType = type(None) ! TypeType = type ! ObjectType = object IntType = type(0) *************** *** 23,28 **** TupleType = type(()) ! ListType = type([]) ! DictType = DictionaryType = type({}) def _f(): pass --- 23,28 ---- TupleType = type(()) ! ListType = list ! DictType = DictionaryType = dictionary def _f(): pass From gvanrossum@users.sourceforge.net Thu Jun 7 20:14:47 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 07 Jun 2001 12:14:47 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.35,2.16.8.36 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv7429 Modified Files: Tag: descr-branch typeobject.c Log Message: Better multiple inheritance, using the method resolution order specification from "Putting Metaclasses to Work" by Forman and Danforth (Addison-Wesley 1999). The functions type_init() and PyType_InitDict() are quite different now. __bases__ and tp_base are now set properly by PyType_InitDict() to make the default base class 'object'; thus the __bases__ descriptor can be simpler. New standard attributes of type objects: - __base__ (singular!), the unique base class on the path to the root that has all the instance variable additions; - __mro__, the method resolution order (a tuple of classes starting with type type itself and ending with 'object'); - __introduced__, a read-only proxy for the dictionary of methods and slots introduced by this class (possibly overriding or extending an inherited method, but not *just* inherited). The former "intrinsic attributes" of objects are now inherited from 'object'. The 'object' type now has a (no-op) constructor, so that every type now has an __init__ method! The helper functions add_methods(), add_wrappers(), add_members() and add_getset() now update tp_introduced instead of tp_dict, and don't overwrite existing keys. There's still a lot to do! E.g. the method resolution order computation doesn't even check for errors. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.35 retrieving revision 2.16.8.36 diff -C2 -r2.16.8.35 -r2.16.8.36 *** typeobject.c 2001/06/06 19:00:33 2.16.8.35 --- typeobject.c 2001/06/07 19:14:45 2.16.8.36 *************** *** 15,44 **** {"__weaklistoffset__", T_LONG, offsetof(PyTypeObject, tp_weaklistoffset), READONLY}, {"__dictoffset__", T_LONG, offsetof(PyTypeObject, tp_dictoffset), READONLY}, {0} }; static PyObject * - type_bases(PyTypeObject *type, void *context) - { - PyObject *bases; - PyTypeObject *base; - - bases = type->tp_bases; - if (bases != NULL) { - Py_INCREF(bases); - return bases; - } - base = type->tp_base; - if (base == NULL) { - if (type == &PyBaseObject_Type) - return PyTuple_New(0); - base = &PyBaseObject_Type; - } - return Py_BuildValue("(O)", base); - } - - static PyObject * type_module(PyTypeObject *type, void *context) { --- 15,27 ---- {"__weaklistoffset__", T_LONG, offsetof(PyTypeObject, tp_weaklistoffset), READONLY}, + {"__base__", T_OBJECT, offsetof(PyTypeObject, tp_base), READONLY}, {"__dictoffset__", T_LONG, offsetof(PyTypeObject, tp_dictoffset), READONLY}, + {"__bases__", T_OBJECT, offsetof(PyTypeObject, tp_bases), READONLY}, + {"__mro__", T_OBJECT, offsetof(PyTypeObject, tp_mro), READONLY}, {0} }; static PyObject * type_module(PyTypeObject *type, void *context) { *************** *** 50,67 **** { if (type->tp_dict == NULL) { ! if (PyType_InitDict(type) < 0) ! return NULL; ! if (type->tp_dict == NULL) { ! Py_INCREF(Py_None); ! return Py_None; ! } } return PyDictProxy_New(type->tp_dict); } struct getsetlist type_getsets[] = { - {"__bases__", (getter)type_bases, NULL, NULL}, {"__module__", (getter)type_module, NULL, NULL}, {"__dict__", (getter)type_dict, NULL, NULL}, {0} }; --- 33,56 ---- { if (type->tp_dict == NULL) { ! Py_INCREF(Py_None); ! return Py_None; } return PyDictProxy_New(type->tp_dict); } + static PyObject * + type_introduced(PyTypeObject *type, void *context) + { + if (type->tp_introduced == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return PyDictProxy_New(type->tp_introduced); + } + struct getsetlist type_getsets[] = { {"__module__", (getter)type_module, NULL, NULL}, {"__dict__", (getter)type_dict, NULL, NULL}, + {"__introduced__", (getter)type_introduced, NULL, NULL}, {0} }; *************** *** 204,217 **** } /* TypeType's initializer; called when a type is subclassed */ static int type_init(PyObject *self, PyObject *args, PyObject *kwds) { ! PyObject *name, *bases, *dict, *x, *slots; PyTypeObject *type, *base; static char *kwlist[] = {"name", "bases", "dict", 0}; etype *et; struct memberlist *mp; ! int i, n, nslots, slotoffset, allocsize; assert(PyType_Check(self)); --- 193,328 ---- } + /* Method resolution order algorithm from "Putting Metaclasses to Work" + by Forman and Danforth (Addison-Wesley 1999). */ + + static int + conservative_merge(PyObject *left, PyObject *right) + { + int left_size; + int right_size; + int i, j, r; + PyObject *temp, *rr; + + /* XXX add error checking */ + + again: + left_size = PyList_GET_SIZE(left); + right_size = PyList_GET_SIZE(right); + for (i = 0; i < left_size; i++) { + for (j = 0; j < right_size; j++) { + if (PyList_GET_ITEM(left, i) == + PyList_GET_ITEM(right, j)) { + /* found a merge point */ + temp = PyList_New(0); + for (r = 0; r < j; r++) { + rr = PyList_GET_ITEM(right, r); + if (!PySequence_Contains(left, rr)) + PyList_Append(temp, rr); + } + PyList_SetSlice(left, i, i, temp); + Py_DECREF(temp); + PyList_SetSlice(right, 0, j+1, NULL); + goto again; + } + } + } + return PyList_SetSlice(left, left_size, left_size, right); + } + + static int + serious_order_disagreements(PyObject *left, PyObject *right) + { + return 0; /* XXX later -- for now, we cheat: "don't do that" */ + } + + static PyObject * + method_resolution_order(PyTypeObject *type) + { + int i, n; + PyObject *bases; + PyObject *result; + + /* XXX add error checking */ + + if (type->tp_mro != NULL) + return PySequence_List(type->tp_mro); + + bases = type->tp_bases; + if (bases == NULL || !PyTuple_Check(bases)) + return NULL; + n = PyTuple_GET_SIZE(bases); + result = Py_BuildValue("[O]", type); + for (i = 0; i < n; i++) { + PyTypeObject *base = (PyTypeObject *) + PyTuple_GET_ITEM(bases, i); + PyObject *parentMRO = method_resolution_order(base); + if (parentMRO == NULL) { + Py_DECREF(result); + return NULL; + } + if (serious_order_disagreements(result, parentMRO)) { + Py_DECREF(result); + return NULL; + } + conservative_merge(result, parentMRO); + Py_DECREF(parentMRO); + } + if (result != NULL && type->tp_mro == NULL) + type->tp_mro = PySequence_Tuple(result); + return result; + } + + /* Calculate the best base amongst multiple base classes. + This is the first one that's on the path to the "solid base". */ + + static PyTypeObject * + best_base(PyObject *bases) + { + int i, n; + PyTypeObject *base, *winner, *candidate, *base_i; + + assert(PyTuple_Check(bases)); + n = PyTuple_GET_SIZE(bases); + assert(n > 0); + base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); + winner = &PyBaseObject_Type; + for (i = 0; i < n; i++) { + base_i = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); + if (!PyType_Check((PyObject *)base_i)) { + PyErr_SetString( + PyExc_TypeError, + "bases must be types"); + return NULL; + } + candidate = solid_base(base_i); + if (issubtype(winner, candidate)) + ; + else if (issubtype(candidate, winner)) { + winner = candidate; + base = base_i; + } + else { + PyErr_SetString( + PyExc_TypeError, + "multiple bases have " + "instance lay-out conflict"); + return NULL; + } + } + assert(base != NULL); + return base; + } + /* TypeType's initializer; called when a type is subclassed */ + static int type_init(PyObject *self, PyObject *args, PyObject *kwds) { ! PyObject *name, *bases, *dict, *slots; PyTypeObject *type, *base; static char *kwlist[] = {"name", "bases", "dict", 0}; etype *et; struct memberlist *mp; ! int i, nbases, nslots, slotoffset, allocsize; assert(PyType_Check(self)); *************** *** 227,267 **** return -1; } ! n = PyTuple_GET_SIZE(bases); ! if (n > 0) { ! PyTypeObject *winner, *candidate, *base_i; ! base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); ! winner = &PyBaseObject_Type; ! for (i = 0; i < n; i++) { ! base_i = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); ! if (!PyType_Check((PyObject *)base_i)) { ! PyErr_SetString( ! PyExc_TypeError, ! "bases must be types"); ! return -1; ! } ! candidate = solid_base(base_i); ! if (issubtype(winner, candidate)) ! ; ! else if (issubtype(candidate, winner)) { ! winner = candidate; ! base = base_i; ! } ! else { ! PyErr_SetString( ! PyExc_TypeError, ! "multiple bases have " ! "instance lay-out conflict"); ! return -1; ! } ! } } else ! base = &PyBaseObject_Type; ! if (base->tp_new == NULL) { PyErr_SetString(PyExc_TypeError, ! "base type must have a tp_new slot"); return -1; } /* Check for a __slots__ sequence variable in dict, and count it */ slots = PyDict_GetItemString(dict, "__slots__"); --- 338,368 ---- return -1; } ! ! /* Adjust empty bases */ ! nbases = PyTuple_GET_SIZE(bases); ! if (nbases == 0) { ! bases = Py_BuildValue("(O)", &PyBaseObject_Type); ! if (bases == NULL) ! return -1; ! nbases = 1; } else ! Py_INCREF(bases); ! ! /* Calculate best base */ ! base = best_base(bases); ! if (base == NULL) ! return -1; ! if (base->tp_init == NULL) { PyErr_SetString(PyExc_TypeError, ! "base type must have a constructor slot"); return -1; } + /* Set tp_base and tp_bases */ + type->tp_bases = bases; + Py_INCREF(base); + type->tp_base = base; + /* Check for a __slots__ sequence variable in dict, and count it */ slots = PyDict_GetItemString(dict, "__slots__"); *************** *** 312,330 **** type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE; - /* Set tp_base and tp_bases properly */ - if (PyTuple_GET_SIZE(bases) == 0) - bases = Py_BuildValue("(O)", &PyBaseObject_Type); - else - Py_INCREF(bases); - type->tp_bases = bases; - Py_INCREF(base); - type->tp_base = base; - - /* Copy slots and dict from the base type */ - if (PyType_InitDict(type) < 0) { - Py_DECREF(type); - return -1; - } - /* Override some slots with specific requirements */ if (type->tp_dealloc) --- 413,416 ---- *************** *** 338,346 **** type->tp_setattr = NULL; } ! /* Add custom slots */ mp = et->members; ! slotoffset = type->tp_basicsize; ! if (type->tp_flags & Py_TPFLAGS_GC) slotoffset -= PyGC_HEAD_SIZE; if (slots != NULL) { --- 424,437 ---- type->tp_setattr = NULL; } + + /* Initialize tp_introduced from passed-in dict */ + type->tp_introduced = dict = PyDict_Copy(dict); + if (dict == NULL) + return -1; ! /* Add descriptors for custom slots from __slots__, or for __dict__ */ mp = et->members; ! slotoffset = base->tp_basicsize; ! if (base->tp_flags & Py_TPFLAGS_GC) slotoffset -= PyGC_HEAD_SIZE; if (slots != NULL) { *************** *** 349,359 **** PyTuple_GET_ITEM(slots, i)); mp->type = T_OBJECT; ! mp->offset = slotoffset + i*sizeof(PyObject *); } - type->tp_basicsize += nslots*sizeof(PyObject *); } else if (nslots) { type->tp_dictoffset = slotoffset; ! type->tp_basicsize += sizeof(PyObject *); mp->name = "__dict__"; mp->type = T_OBJECT; --- 440,450 ---- PyTuple_GET_ITEM(slots, i)); mp->type = T_OBJECT; ! mp->offset = slotoffset; ! slotoffset += i*sizeof(PyObject *); } } else if (nslots) { type->tp_dictoffset = slotoffset; ! slotoffset += sizeof(PyObject *); mp->name = "__dict__"; mp->type = T_OBJECT; *************** *** 361,389 **** mp->readonly = 1; } add_members(type, et->members); ! /* XXX This is close, but not quite right! */ ! if (n > 1) { ! PyTypeObject *t; ! for (i = n; --i >= 0; ) { ! t = (PyTypeObject *) PyTuple_GET_ITEM(bases, i); ! if (t->tp_dict == NULL) ! continue; ! x = PyObject_CallMethod(type->tp_dict, ! "update", "O", t->tp_dict); ! if (x == NULL) { ! Py_DECREF(type); ! return -1; ! } ! } ! } ! ! x = PyObject_CallMethod(type->tp_dict, "update", "O", dict); ! if (x == NULL) { ! Py_DECREF(type); return -1; ! } ! Py_DECREF(x); /* throw away None */ ! override_slots(type, dict); return 0; } --- 452,464 ---- mp->readonly = 1; } + type->tp_basicsize = slotoffset; add_members(type, et->members); ! /* Initialize tp_bases, tp_dict, tp_introduced; inherit slots */ ! if (PyType_InitDict(type) < 0) return -1; ! ! /* Override slots that deserve it */ ! override_slots(type, type->tp_dict); return 0; } *************** *** 485,488 **** --- 560,564 ---- Py_XDECREF(et->name); Py_XDECREF(et->slots); + /* XXX more, e.g. bases, mro, introduced ... */ PyObject_DEL(type); } *************** *** 543,546 **** --- 619,633 ---- } + static struct memberlist object_members[] = { + {"__class__", T_OBJECT, offsetof(PyObject, ob_type), READONLY}, + {0} + }; + + static int + object_init(PyObject *self, PyObject *args, PyObject *kwds) + { + return 0; + } + PyTypeObject PyBaseObject_Type = { PyObject_HEAD_INIT(&PyType_Type) *************** *** 573,577 **** 0, /* tp_iternext */ 0, /* tp_methods */ ! 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ --- 660,664 ---- 0, /* tp_iternext */ 0, /* tp_methods */ ! object_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ *************** *** 580,584 **** 0, /* tp_descr_set */ 0, /* tp_dictoffset */ ! 0, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ --- 667,671 ---- 0, /* tp_descr_set */ 0, /* tp_dictoffset */ ! object_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ *************** *** 588,611 **** /* Initialize the __dict__ in a type object */ - static struct PyMethodDef intrinsic_methods[] = { - {0} - }; - - static struct memberlist intrinsic_members[] = { - {"__class__", T_OBJECT, offsetof(PyObject, ob_type), READONLY}, - {0} - }; - - static struct getsetlist intrinsic_getsets[] = { - {0} - }; - static int add_methods(PyTypeObject *type, PyMethodDef *meth) { ! PyObject *dict = type->tp_dict; for (; meth->ml_name != NULL; meth++) { ! PyObject *descr = PyDescr_NewMethod(type, meth); if (descr == NULL) return -1; --- 675,688 ---- /* Initialize the __dict__ in a type object */ static int add_methods(PyTypeObject *type, PyMethodDef *meth) { ! PyObject *dict = type->tp_introduced; for (; meth->ml_name != NULL; meth++) { ! PyObject *descr; ! if (PyDict_GetItemString(dict, meth->ml_name)) ! continue; ! descr = PyDescr_NewMethod(type, meth); if (descr == NULL) return -1; *************** *** 620,627 **** add_wrappers(PyTypeObject *type, struct wrapperbase *base, void *wrapped) { ! PyObject *dict = type->tp_dict; for (; base->name != NULL; base++) { ! PyObject *descr = PyDescr_NewWrapper(type, base, wrapped); if (descr == NULL) return -1; --- 697,707 ---- add_wrappers(PyTypeObject *type, struct wrapperbase *base, void *wrapped) { ! PyObject *dict = type->tp_introduced; for (; base->name != NULL; base++) { ! PyObject *descr; ! if (PyDict_GetItemString(dict, base->name)) ! continue; ! descr = PyDescr_NewWrapper(type, base, wrapped); if (descr == NULL) return -1; *************** *** 636,643 **** add_members(PyTypeObject *type, struct memberlist *memb) { ! PyObject *dict = type->tp_dict; for (; memb->name != NULL; memb++) { ! PyObject *descr = PyDescr_NewMember(type, memb); if (descr == NULL) return -1; --- 716,726 ---- add_members(PyTypeObject *type, struct memberlist *memb) { ! PyObject *dict = type->tp_introduced; for (; memb->name != NULL; memb++) { ! PyObject *descr; ! if (PyDict_GetItemString(dict, memb->name)) ! continue; ! descr = PyDescr_NewMember(type, memb); if (descr == NULL) return -1; *************** *** 652,659 **** add_getset(PyTypeObject *type, struct getsetlist *gsp) { ! PyObject *dict = type->tp_dict; for (; gsp->name != NULL; gsp++) { ! PyObject *descr = PyDescr_NewGetSet(type, gsp); if (descr == NULL) --- 735,745 ---- add_getset(PyTypeObject *type, struct getsetlist *gsp) { ! PyObject *dict = type->tp_introduced; for (; gsp->name != NULL; gsp++) { ! PyObject *descr; ! if (PyDict_GetItemString(dict, gsp->name)) ! continue; ! descr = PyDescr_NewGetSet(type, gsp); if (descr == NULL) *************** *** 836,866 **** PyType_InitDict(PyTypeObject *type) { ! PyObject *dict; ! PyTypeObject *base = type->tp_base; if (type->tp_dict != NULL) ! return 0; if (base) { if (PyType_InitDict(base) < 0) return -1; - dict = PyDict_Copy(base->tp_dict); } ! else dict = PyDict_New(); ! if (dict == NULL) ! return -1; ! type->tp_dict = dict; ! /* Add intrinsics */ ! if (add_methods(type, intrinsic_methods) < 0) ! return -1; ! if (add_members(type, intrinsic_members) < 0) ! return -1; ! if (add_getset(type, intrinsic_getsets) < 0) ! return -1; if (add_operators(type) < 0) return -1; - - /* Add type-specific descriptors */ if (type->tp_methods != NULL) { if (add_methods(type, type->tp_methods) < 0) --- 922,967 ---- PyType_InitDict(PyTypeObject *type) { ! PyObject *dict, *bases, *x; ! PyTypeObject *base; ! int i, n; if (type->tp_dict != NULL) ! return 0; /* Already initialized */ ! ! /* Initialize tp_base (defaults to BaseObject unless that's us) */ ! base = type->tp_base; ! if (base == NULL && type != &PyBaseObject_Type) ! base = type->tp_base = &PyBaseObject_Type; ! ! /* Initialize tp_bases */ ! bases = type->tp_bases; ! if (bases == NULL) { ! if (base == NULL) ! bases = PyTuple_New(0); ! else ! bases = Py_BuildValue("(O)", base); ! if (bases == NULL) ! return -1; ! type->tp_bases = bases; ! } ! ! /* Initialize the base class */ if (base) { if (PyType_InitDict(base) < 0) return -1; } ! ! /* Initialize tp_introduced */ ! dict = type->tp_introduced; ! if (dict == NULL) { dict = PyDict_New(); ! if (dict == NULL) ! return -1; ! type->tp_introduced = dict; ! } ! /* Add type-specific descriptors to tp_introduced */ if (add_operators(type) < 0) return -1; if (type->tp_methods != NULL) { if (add_methods(type, type->tp_methods) < 0) *************** *** 875,884 **** return -1; } ! /* Inherit base class slots and methods */ if (base) { if (inherit_slots(type, base) < 0) return -1; } return 0; --- 976,1022 ---- return -1; } + + /* Initialize tp_dict from tp_introduced */ + type->tp_dict = PyDict_Copy(dict); + if (type->tp_dict == NULL) + return -1; ! /* Inherit base class slots */ if (base) { if (inherit_slots(type, base) < 0) return -1; } + + /* Calculate method resolution order */ + x = method_resolution_order(type); + if (x == NULL) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_TypeError, + "method resolution order failed"); + return -1; + } + Py_DECREF(x); + + /* Inherit methods, updating from last base backwards */ + bases = type->tp_mro; + assert(bases != NULL); + assert(PyTuple_Check(bases)); + n = PyTuple_GET_SIZE(bases); + for (i = n; --i >= 0; ) { + base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); + assert(PyType_Check(base)); + x = base->tp_introduced; + if (x != NULL) { + x = PyObject_CallMethod(type->tp_dict, "update","O",x); + if (x == NULL) + return -1; + Py_DECREF(x); /* throw away None */ + } + } + + /* Inherit slots from direct base */ + if (type->tp_base != NULL) + if (inherit_slots(type, type->tp_base) < 0) + return -1; return 0; From gvanrossum@users.sourceforge.net Thu Jun 7 20:17:41 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 07 Jun 2001 12:17:41 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.1.2.12,1.1.2.13 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv8217 Modified Files: Tag: descr-branch test_descr.py Log Message: - Reduce the size of the pydict stress test (I got tired of waiting :-). The size is now parameterized through a local variable so it's easy to change. - Add a test for __mro__ to the multi() test. - Add diamond(), a test for proper method resolution order in diamond diagrams. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/Attic/test_descr.py,v retrieving revision 1.1.2.12 retrieving revision 1.1.2.13 diff -C2 -r1.1.2.12 -r1.1.2.13 *** test_descr.py 2001/06/07 15:45:04 1.1.2.12 --- test_descr.py 2001/06/07 19:17:39 1.1.2.13 *************** *** 299,308 **** verify(a[42] == 24) if verbose: print "pydict stress test ..." ! for i in range(100): a[i] = C() ! for j in range(100): a[i][j] = i*j ! for i in range(100): ! for j in range(100): verify(a[i][j] == i*j) --- 299,309 ---- verify(a[42] == 24) if verbose: print "pydict stress test ..." ! N = 50 ! for i in range(N): a[i] = C() ! for j in range(N): a[i][j] = i*j ! for i in range(N): ! for j in range(N): verify(a[i][j] == i*j) *************** *** 379,383 **** --- 380,416 ---- d.setstate(10) verify(d.getstate() == 10) + verify(D.__mro__ == (D, dictionary, C, object)) + def diamond(): + if verbose: print "Testing multiple inheritance special cases..." + class A(object): + def spam(self): return "A" + verify(A().spam() == "A") + class B(A): + def boo(self): return "B" + def spam(self): return "B" + verify(B().spam() == "B") + verify(B().boo() == "B") + class C(A): + def boo(self): return "C" + verify(C().spam() == "A") + verify(C().boo() == "C") + class D(B, C): pass + verify(D().spam() == "B") + verify(D().boo() == "B") + verify(D.__mro__ == (D, B, C, A, object)) + class E(C, B): pass + verify(E().spam() == "B") + verify(E().boo() == "C") + verify(E.__mro__ == (E, C, B, A, object)) + class F(D, E): pass + verify(F().spam() == "B") + verify(F().boo() == "B") + verify(F.__mro__ == (F, D, E, B, C, A, object)) + class G(E, D): pass + verify(G().spam() == "B") + verify(G().boo() == "C") + verify(G.__mro__ == (G, E, D, C, B, A, object)) + def all(): lists() *************** *** 392,395 **** --- 425,429 ---- pymods() multi() + diamond() all() From loewis@users.sourceforge.net Thu Jun 7 20:39:27 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Thu, 07 Jun 2001 12:39:27 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/encodings cp1140.py,NONE,1.1 aliases.py,1.7,1.8 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/encodings In directory usw-pr-cvs1:/tmp/cvs-serv12371 Modified Files: aliases.py Added Files: cp1140.py Log Message: Patch #429957: Add support for cp1140, which is identical to cp037, with the addition of the euro character. Also added a few EDBDIC aliases. --- NEW FILE: cp1140.py --- """ Python Character Mapping Codec for cp1140 Written by Brian Quinlan(brian@sweetapp.com). NO WARRANTY. """ import codecs import copy import cp037 ### Codec APIs class Codec(codecs.Codec): def encode(self,input,errors='strict'): return codecs.charmap_encode(input,errors,encoding_map) def decode(self,input,errors='strict'): return codecs.charmap_decode(input,errors,decoding_map) class StreamWriter(Codec,codecs.StreamWriter): pass class StreamReader(Codec,codecs.StreamReader): pass ### encodings module API def getregentry(): return (Codec().encode,Codec().decode,StreamReader,StreamWriter) ### Decoding Map decoding_map = copy.copy(cp037.decoding_map) decoding_map.update({ 0x009f: 0x20ac # EURO SIGN }) ### Encoding Map encoding_map = codecs.make_encoding_map(decoding_map) Index: aliases.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/encodings/aliases.py,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -r1.7 -r1.8 *** aliases.py 2001/06/04 02:31:23 1.7 --- aliases.py 2001/06/07 19:39:25 1.8 *************** *** 33,36 **** --- 33,41 ---- 'us_ascii': 'ascii', + # EBCDIC + 'ebcdic_cp_us': 'cp037', + 'ibm039': 'cp037', + 'ibm1140': 'cp1140', + # ISO '8859': 'latin_1', From fdrake@users.sourceforge.net Fri Jun 8 05:25:26 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Thu, 07 Jun 2001 21:25:26 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib profile.py,1.27,1.28 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv26018 Modified Files: profile.py Log Message: Performance improvements to the profiler: Ensure that all the default timers are called as functions, not an expensive method wrapper around a variety of different functions. Agressively avoid dictionary lookups. Modify the dispatch scheme (Profile.trace_dispatch_*(), where * is not 'call', 'exception' or 'return') so that the callables dispatched to are simple functions and not bound methods -- this reduces the number of layers of Python call machinery that gets touched. Remove a couple of duplicate imports from the "if __name__ == ..." section. This closes SF patch #430948. Index: profile.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/profile.py,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -r1.27 -r1.28 *** profile.py 2001/03/14 20:01:19 1.27 --- profile.py 2001/06/08 04:25:24 1.28 *************** *** 90,93 **** --- 90,103 ---- + if os.name == "mac": + def _get_time_mac(timer=MacOS.GetTicks): + return timer() / 60.0 + + if hasattr(os, "times"): + def _get_time_times(timer=os.times): + t = timer() + return t[0] + t[1] + + class Profile: """Profiler class. *************** *** 133,142 **** self.cmd = "" - self.dispatch = { \ - 'call' : self.trace_dispatch_call, \ - 'return' : self.trace_dispatch_return, \ - 'exception': self.trace_dispatch_exception, \ - } - if not timer: if os.name == 'mac': --- 143,146 ---- *************** *** 144,156 **** self.timer = MacOS.GetTicks self.dispatcher = self.trace_dispatch_mac ! self.get_time = self.get_time_mac elif hasattr(time, 'clock'): ! self.timer = time.clock self.dispatcher = self.trace_dispatch_i elif hasattr(os, 'times'): self.timer = os.times self.dispatcher = self.trace_dispatch else: ! self.timer = time.time self.dispatcher = self.trace_dispatch_i else: --- 148,161 ---- self.timer = MacOS.GetTicks self.dispatcher = self.trace_dispatch_mac ! self.get_time = _get_time_mac elif hasattr(time, 'clock'): ! self.timer = self.get_time = time.clock self.dispatcher = self.trace_dispatch_i elif hasattr(os, 'times'): self.timer = os.times self.dispatcher = self.trace_dispatch + self.get_time = _get_time_times else: ! self.timer = self.get_time = time.time self.dispatcher = self.trace_dispatch_i else: *************** *** 158,192 **** t = self.timer() # test out timer function try: ! if len(t) == 2: self.dispatcher = self.trace_dispatch else: self.dispatcher = self.trace_dispatch_l ! except TypeError: ! self.dispatcher = self.trace_dispatch_i self.t = self.get_time() self.simulate_call('profiler') - - def get_time(self): # slow simulation of method to acquire time - t = self.timer() - if type(t) == type(()) or type(t) == type([]): - t = reduce(lambda x,y: x+y, t, 0) - return t - - def get_time_mac(self): - return self.timer()/60.0 - # Heavily optimized dispatch routine for os.times() timer def trace_dispatch(self, frame, event, arg): ! t = self.timer() t = t[0] + t[1] - self.t # No Calibration constant # t = t[0] + t[1] - self.t - .00053 # Calibration constant ! if self.dispatch[event](frame,t): ! t = self.timer() self.t = t[0] + t[1] else: ! r = self.timer() self.t = r[0] + r[1] - t # put back unrecorded delta return --- 163,200 ---- t = self.timer() # test out timer function try: ! length = len(t) ! except TypeError: ! self.get_time = timer ! self.dispatcher = self.trace_dispatch_i ! else: ! if length == 2: self.dispatcher = self.trace_dispatch else: self.dispatcher = self.trace_dispatch_l ! # This get_time() implementation needs to be defined ! # here to capture the passed-in timer in the parameter ! # list (for performance). Note that we can't assume ! # the timer() result contains two values in all ! # cases. ! def get_time_timer(timer=timer, ! reduce=reduce, reducer=operator.add): ! return reduce(reducer, timer(), 0) ! self.get_time = get_time_timer self.t = self.get_time() self.simulate_call('profiler') # Heavily optimized dispatch routine for os.times() timer def trace_dispatch(self, frame, event, arg): ! timer = self.timer ! t = timer() t = t[0] + t[1] - self.t # No Calibration constant # t = t[0] + t[1] - self.t - .00053 # Calibration constant ! if self.dispatch[event](self, frame,t): ! t = timer() self.t = t[0] + t[1] else: ! r = timer() self.t = r[0] + r[1] - t # put back unrecorded delta return *************** *** 197,215 **** def trace_dispatch_i(self, frame, event, arg): ! t = self.timer() - self.t # - 1 # Integer calibration constant ! if self.dispatch[event](frame,t): ! self.t = self.timer() else: ! self.t = self.timer() - t # put back unrecorded delta return ! # Dispatch routine for macintosh (timer returns time in ticks of 1/60th second) def trace_dispatch_mac(self, frame, event, arg): ! t = self.timer()/60.0 - self.t # - 1 # Integer calibration constant ! if self.dispatch[event](frame,t): ! self.t = self.timer()/60.0 else: ! self.t = self.timer()/60.0 - t # put back unrecorded delta return --- 205,226 ---- def trace_dispatch_i(self, frame, event, arg): ! timer = self.timer ! t = timer() - self.t # - 1 # Integer calibration constant ! if self.dispatch[event](self, frame,t): ! self.t = timer() else: ! self.t = timer() - t # put back unrecorded delta return ! # Dispatch routine for macintosh (timer returns time in ticks of ! # 1/60th second) def trace_dispatch_mac(self, frame, event, arg): ! timer = self.timer ! t = timer()/60.0 - self.t # - 1 # Integer calibration constant ! if self.dispatch[event](self, frame,t): ! self.t = timer()/60.0 else: ! self.t = timer()/60.0 - t # put back unrecorded delta return *************** *** 218,227 **** def trace_dispatch_l(self, frame, event, arg): ! t = self.get_time() - self.t ! if self.dispatch[event](frame,t): ! self.t = self.get_time() else: ! self.t = self.get_time()-t # put back unrecorded delta return --- 229,239 ---- def trace_dispatch_l(self, frame, event, arg): ! get_time = self.get_time ! t = get_time() - self.t ! if self.dispatch[event](self, frame,t): ! self.t = get_time() else: ! self.t = get_time() - t # put back unrecorded delta return *************** *** 238,246 **** fn = (fcode.co_filename, fcode.co_firstlineno, fcode.co_name) self.cur = (t, 0, 0, fn, frame, self.cur) ! if self.timings.has_key(fn): ! cc, ns, tt, ct, callers = self.timings[fn] ! self.timings[fn] = cc, ns + 1, tt, ct, callers else: ! self.timings[fn] = 0, 0, 0, 0, {} return 1 --- 250,259 ---- fn = (fcode.co_filename, fcode.co_firstlineno, fcode.co_name) self.cur = (t, 0, 0, fn, frame, self.cur) ! timings = self.timings ! if timings.has_key(fn): ! cc, ns, tt, ct, callers = timings[fn] ! timings[fn] = cc, ns + 1, tt, ct, callers else: ! timings[fn] = 0, 0, 0, 0, {} return 1 *************** *** 258,262 **** self.cur = pt, ptt+rt, pct+sft, pfn, pframe, pcur ! cc, ns, tt, ct, callers = self.timings[rfn] if not ns: ct = ct + sft --- 271,276 ---- self.cur = pt, ptt+rt, pct+sft, pfn, pframe, pcur ! timings = self.timings ! cc, ns, tt, ct, callers = timings[rfn] if not ns: ct = ct + sft *************** *** 269,276 **** else: callers[pfn] = 1 ! self.timings[rfn] = cc, ns - 1, tt+rtt, ct, callers return 1 # The next few function play with self.cmd. By carefully preloading # our parallel stack, we can force the profiled result to include --- 283,298 ---- else: callers[pfn] = 1 ! timings[rfn] = cc, ns - 1, tt+rtt, ct, callers return 1 + + dispatch = { + "call": trace_dispatch_call, + "exception": trace_dispatch_exception, + "return": trace_dispatch_return, + } + + # The next few function play with self.cmd. By carefully preloading # our parallel stack, we can force the profiled result to include *************** *** 306,310 **** pframe = None frame = self.fake_frame(code, pframe) ! a = self.dispatch['call'](frame, 0) return --- 328,332 ---- pframe = None frame = self.fake_frame(code, pframe) ! a = self.dispatch['call'](self, frame, 0) return *************** *** 313,323 **** def simulate_cmd_complete(self): ! t = self.get_time() - self.t while self.cur[-1]: # We *can* cause assertion errors here if # dispatch_trace_return checks for a frame match! ! a = self.dispatch['return'](self.cur[-2], t) t = 0 ! self.t = self.get_time() - t --- 335,346 ---- def simulate_cmd_complete(self): ! get_time = self.get_time ! t = get_time() - self.t while self.cur[-1]: # We *can* cause assertion errors here if # dispatch_trace_return checks for a frame match! ! a = self.dispatch['return'](self, self.cur[-2], t) t = 0 ! self.t = get_time() - t *************** *** 366,374 **** # This method is more useful to profile a single function call. ! def runcall(self, func, *args): self.set_cmd(`func`) sys.setprofile(self.dispatcher) try: ! return apply(func, args) finally: sys.setprofile(None) --- 389,397 ---- # This method is more useful to profile a single function call. ! def runcall(self, func, *args, **kw): self.set_cmd(`func`) sys.setprofile(self.dispatcher) try: ! return apply(func, args, kw) finally: sys.setprofile(None) *************** *** 420,438 **** def calibrate(self, m): # Modified by Tim Peters n = m ! s = self.get_time() while n: self.simple() n = n - 1 ! f = self.get_time() my_simple = f - s #print "Simple =", my_simple, n = m ! s = self.get_time() while n: self.instrumented() n = n - 1 ! f = self.get_time() my_inst = f - s # print "Instrumented =", my_inst --- 443,462 ---- def calibrate(self, m): # Modified by Tim Peters + get_time = self.get_time n = m ! s = get_time() while n: self.simple() n = n - 1 ! f = get_time() my_simple = f - s #print "Simple =", my_simple, n = m ! s = get_time() while n: self.instrumented() n = n - 1 ! f = get_time() my_inst = f - s # print "Instrumented =", my_inst *************** *** 504,507 **** --- 528,538 ---- + dispatch = { + "call": trace_dispatch_call, + "exception": trace_dispatch_exception, + "return": trace_dispatch_return, + } + + def snapshot_stats(self): self.stats = {} *************** *** 550,553 **** --- 581,591 ---- + dispatch = { + "call": trace_dispatch_call, + "exception": trace_dispatch_exception, + "return": trace_dispatch_return, + } + + def snapshot_stats(self): self.stats = {} *************** *** 565,570 **** # When invoked as main program, invoke the profiler on a script if __name__ == '__main__': - import sys - import os if not sys.argv[1:]: print "usage: profile.py scriptfile [arg] ..." --- 603,606 ---- From fdrake@users.sourceforge.net Fri Jun 8 05:33:11 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Thu, 07 Jun 2001 21:33:11 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python ceval.c,2.245,2.246 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv27000 Modified Files: ceval.c Log Message: call_trace(): Add an additional parameter -- pointer to a PyObject* that should be used to cache an interned version of the event string passed to the profile/trace function. call_trace() will create interned strings and cache them in using the storage specified by this additional parameter, avoiding a lot of string object creation at runtime when using the profiling or tracing functions. All call sites are modified to pass the additional parameter, and four static PyObject* variables are allocated to cache the interned string objects. This closes SF patch #431257. Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.245 retrieving revision 2.246 diff -C2 -r2.245 -r2.246 *** ceval.c 2001/05/29 16:23:26 2.245 --- ceval.c 2001/06/08 04:33:09 2.246 *************** *** 63,67 **** static void call_exc_trace(PyObject **, PyObject**, PyFrameObject *); static int call_trace(PyObject **, PyObject **, ! PyFrameObject *, char *, PyObject *); static PyObject *loop_subscript(PyObject *, PyObject *); static PyObject *apply_slice(PyObject *, PyObject *, PyObject *); --- 63,67 ---- static void call_exc_trace(PyObject **, PyObject**, PyFrameObject *); static int call_trace(PyObject **, PyObject **, ! PyFrameObject *, char *, PyObject **, PyObject *); static PyObject *loop_subscript(PyObject *, PyObject *); static PyObject *apply_slice(PyObject *, PyObject *, PyObject *); *************** *** 98,101 **** --- 98,110 ---- #endif + /* Cached interned string objects used for calling the profile and + * trace functions. + */ + static PyObject *str_call = NULL; + static PyObject *str_exception = NULL; + static PyObject *str_line = NULL; + static PyObject *str_return = NULL; + + #ifdef WITH_THREAD *************** *** 646,650 **** is detected. */ if (call_trace(&tstate->sys_tracefunc, ! &f->f_trace, f, "call", Py_None/*XXX how to compute arguments now?*/)) { /* Trace function raised an error */ --- 655,659 ---- is detected. */ if (call_trace(&tstate->sys_tracefunc, ! &f->f_trace, f, "call", &str_call, Py_None/*XXX how to compute arguments now?*/)) { /* Trace function raised an error */ *************** *** 657,661 **** itself and isn't called for "line" events */ if (call_trace(&tstate->sys_profilefunc, ! (PyObject**)0, f, "call", Py_None/*XXX*/)) { goto fail; --- 666,670 ---- itself and isn't called for "line" events */ if (call_trace(&tstate->sys_profilefunc, ! (PyObject**)0, f, "call", &str_call, Py_None/*XXX*/)) { goto fail; *************** *** 1953,1957 **** f->f_lasti = INSTR_OFFSET(); err = call_trace(&f->f_trace, &f->f_trace, ! f, "line", Py_None); break; --- 1962,1966 ---- f->f_lasti = INSTR_OFFSET(); err = call_trace(&f->f_trace, &f->f_trace, ! f, "line", &str_line, Py_None); break; *************** *** 2298,2302 **** if (why == WHY_RETURN) { if (call_trace(&f->f_trace, &f->f_trace, f, ! "return", retval)) { Py_XDECREF(retval); retval = NULL; --- 2307,2311 ---- if (why == WHY_RETURN) { if (call_trace(&f->f_trace, &f->f_trace, f, ! "return", &str_return, retval)) { Py_XDECREF(retval); retval = NULL; *************** *** 2308,2312 **** if (tstate->sys_profilefunc && why == WHY_RETURN) { if (call_trace(&tstate->sys_profilefunc, (PyObject**)0, ! f, "return", retval)) { Py_XDECREF(retval); retval = NULL; --- 2317,2321 ---- if (tstate->sys_profilefunc && why == WHY_RETURN) { if (call_trace(&tstate->sys_profilefunc, (PyObject**)0, ! f, "return", &str_return, retval)) { Py_XDECREF(retval); retval = NULL; *************** *** 2576,2580 **** return; } ! err = call_trace(p_trace, p_newtrace, f, "exception", arg); Py_DECREF(arg); if (err == 0) --- 2585,2590 ---- return; } ! err = call_trace(p_trace, p_newtrace, f, ! "exception", &str_exception, arg); Py_DECREF(arg); if (err == 0) *************** *** 2589,2599 **** /* PyObject **p_trace: in/out; may not be NULL; may not point to NULL variable initially ! PyObject **p_newtrace: in/out; may be NULL; may point to NULL variable; ! may be same variable as p_newtrace */ static int call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, ! char *msg, PyObject *arg) { PyThreadState *tstate = f->f_tstate; --- 2599,2614 ---- /* PyObject **p_trace: in/out; may not be NULL; may not point to NULL variable initially ! PyObject **p_newtrace: in/out; may be NULL; may point to NULL variable; ! may be same variable as p_newtrace ! PyObject **p_omsg: in/out; may not be NULL; ! if non-null & *p_omsg == NULL, will be ! initialized with an interned string ! corresponding to msg. ! */ static int call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, ! char *msg, PyObject **p_omsg, PyObject *arg) { PyThreadState *tstate = f->f_tstate; *************** *** 2612,2619 **** args = PyTuple_New(3); if (args == NULL) - goto cleanup; - what = PyString_FromString(msg); - if (what == NULL) goto cleanup; Py_INCREF(f); PyTuple_SET_ITEM(args, 0, (PyObject *)f); --- 2627,2642 ---- args = PyTuple_New(3); if (args == NULL) goto cleanup; + if (*p_omsg != NULL) { + what = *p_omsg; + Py_INCREF(what); + } + else { + what = PyString_InternFromString(msg); + if (what == NULL) + goto cleanup; + *p_omsg = what; + Py_INCREF(what); + } Py_INCREF(f); PyTuple_SET_ITEM(args, 0, (PyObject *)f); From fdrake@users.sourceforge.net Fri Jun 8 06:04:22 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Thu, 07 Jun 2001 22:04:22 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libprofile.tex,1.32,1.33 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv30817/lib Modified Files: libprofile.tex Log Message: In the section on extending the profiler, add some additional discussion about setting up the dispatch table, and update the OldProfile and HotProfile classes to the current implementations, showing the adjusted construction for the dispatch table. Index: libprofile.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libprofile.tex,v retrieving revision 1.32 retrieving revision 1.33 diff -C2 -r1.32 -r1.33 *** libprofile.tex 2001/04/13 14:34:58 1.32 --- libprofile.tex 2001/06/08 05:04:19 1.33 *************** *** 656,667 **** returns a lone integer value will provide the best results in terms of low overhead during profiling. (\function{os.times()} is ! \emph{pretty} bad, 'cause it returns a tuple of floating point values, so all arithmetic is floating point in the profiler!). If you want to substitute a better timer in the cleanest fashion, you should derive a class, and simply put in the replacement dispatch method that better handles your timer call, along with the appropriate calibration ! constant :-). \subsection{OldProfile Class \label{profile-old}} --- 656,695 ---- returns a lone integer value will provide the best results in terms of low overhead during profiling. (\function{os.times()} is ! \emph{pretty} bad, as it returns a tuple of floating point values, so all arithmetic is floating point in the profiler!). If you want to substitute a better timer in the cleanest fashion, you should derive a class, and simply put in the replacement dispatch method that better handles your timer call, along with the appropriate calibration ! constant. + Note that subclasses which override any of the + \method{trace_dispatch_call()}, \method{trace_dispatch_exception()}, + or \method{trace_dispatch_return()} methods also need to specify a + dispatch table as well. The table, named \member{dispatch}, should + have the three keys \code{'call'}, \code{'exception'}, and + \code{'return'}, each giving the function of the corresponding + handler. Note that best performance is achieved by using the + \emph{function} objects for the handlers and not bound methods. This + is preferred since calling a simple function object executes less code + in the runtime than calling either bound or unbound methods. For + example, if the derived profiler overrides only one method, the + \member{dispatch} table can be built like this: + \begin{verbatim} + from profile import Profile + + class MyProfiler(Profile): + def trace_dispath_call(self, frame, t): + # do something interesting here + ... + + dispatch = { + 'call': trace_dispatch_call, + 'exception': Profile.__dict__['trace_dispatch_exception'], + 'return': Profile.__dict__['trace_dispatch_return'], + } + \end{verbatim} + + \subsection{OldProfile Class \label{profile-old}} *************** *** 685,689 **** def trace_dispatch_call(self, frame, t): fn = `frame.f_code` ! self.cur = (t, 0, 0, fn, frame, self.cur) if self.timings.has_key(fn): --- 713,717 ---- def trace_dispatch_call(self, frame, t): fn = `frame.f_code` ! self.cur = (t, 0, 0, fn, frame, self.cur) if self.timings.has_key(fn): *************** *** 711,714 **** --- 739,747 ---- return 1 + dispatch = { + "call": trace_dispatch_call, + "exception": trace_dispatch_exception, + "return": trace_dispatch_return, + } def snapshot_stats(self): *************** *** 716,729 **** for func in self.timings.keys(): tt, ct, callers = self.timings[func] ! nor_func = self.func_normalize(func) ! nor_callers = {} nc = 0 for func_caller in callers.keys(): - nor_callers[self.func_normalize(func_caller)] = \ - callers[func_caller] nc = nc + callers[func_caller] ! self.stats[nor_func] = nc, nc, tt, ct, nor_callers \end{verbatim} \subsection{HotProfile Class \label{profile-HotProfile}} --- 749,760 ---- for func in self.timings.keys(): tt, ct, callers = self.timings[func] ! callers = callers.copy() nc = 0 for func_caller in callers.keys(): nc = nc + callers[func_caller] ! self.stats[func] = nc, nc, tt, ct, callers \end{verbatim} + \subsection{HotProfile Class \label{profile-HotProfile}} *************** *** 764,767 **** --- 795,803 ---- return 1 + dispatch = { + "call": trace_dispatch_call, + "exception": trace_dispatch_exception, + "return": trace_dispatch_return, + } def snapshot_stats(self): *************** *** 769,773 **** for func in self.timings.keys(): nc, tt = self.timings[func] ! nor_func = self.func_normalize(func) ! self.stats[nor_func] = nc, nc, tt, 0, {} \end{verbatim} --- 805,808 ---- for func in self.timings.keys(): nc, tt = self.timings[func] ! self.stats[func] = nc, nc, tt, 0, {} \end{verbatim} From montanaro@users.sourceforge.net Fri Jun 8 15:40:30 2001 From: montanaro@users.sourceforge.net (Skip Montanaro) Date: Fri, 08 Jun 2001 07:40:30 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libdoctest.tex,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv24607 Modified Files: libdoctest.tex Log Message: add warning about situation where code may be executed twice, once when module is __main__ and once when module is imported. Index: libdoctest.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libdoctest.tex,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -r1.6 -r1.7 *** libdoctest.tex 2001/04/05 18:31:27 1.6 --- libdoctest.tex 2001/06/08 14:40:28 1.7 *************** *** 409,412 **** --- 409,422 ---- \end{enumerate} + \item Be careful if you have code that must only execute once. + + If you have module-level code that must only execute once, a more foolproof + definition of \function{_test} is + + \begin{verbatim} + def _test(): + import doctest, sys + doctest.testmod(sys.modules["__main__"]) + \end{verbatim} \subsection{Soapbox} From fdrake@users.sourceforge.net Fri Jun 8 17:25:01 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Fri, 08 Jun 2001 09:25:01 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/tut tut.tex,1.136,1.137 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tut In directory usw-pr-cvs1:/tmp/cvs-serv13703/tut Modified Files: tut.tex Log Message: Text from Tim & Guido discussing floating point arithmetic and what users need to understand about the binary & decimal fp, so that representation weirdness is documented somewhere. This makes it easier to repond to "bug" reports caused by user confusion & ignorance of the issues. This closes SF patch #426208. Index: tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.136 retrieving revision 1.137 diff -C2 -r1.136 -r1.137 *** tut.tex 2001/05/22 06:54:14 1.136 --- tut.tex 2001/06/08 16:24:58 1.137 *************** *** 4086,4088 **** --- 4086,4353 ---- + \chapter{Floating Point Arithmetic: Issues and Limitations + \label{fp-issues}} + + Floating-point numbers are represented in computer hardware as + base 2 (binary) fractions. For example, the decimal fraction + + \begin{verbatim} + 0.125 + \end{verbatim} + + has value 1/10 + 2/100 + 5/1000, and in the same way the binary fraction + + \begin{verbatim} + 0.001 + \end{verbatim} + + has value 0/2 + 0/4 + 1/8. These two fractions have identical values, + the only real difference being that the first is written in base 10 + fractional notation, and the second in base 2. + + Unfortunately, most decimal fractions cannot be represented exactly as + binary fractions. A consequence is that, in general, the decimal + floating-point numbers you enter are only approximated by the binary + floating-point numbers actually stored in the machine. + + The problem is easier to understand at first in base 10. Consider the + fraction 1/3. You can approximate that as a base 10 fraction: + + \begin{verbatim} + 0.3 + \end{verbatim} + + or, better, + + \begin{verbatim} + 0.33 + \end{verbatim} + + or, better, + + \begin{verbatim} + 0.333 + \end{verbatim} + + and so on. No matter how many digits you're willing to write down, the + result will never be exactly 1/3, but will be an increasingly better + approximation to 1/3. + + In the same way, no matter how many base 2 digits you're willing to + use, the decimal value 0.1 cannot be represented exactly as a base 2 + fraction. In base 2, 1/10 is the infinitely repeating fraction + + \begin{verbatim} + 0.0001100110011001100110011001100110011001100110011... + \end{verbatim} + + Stop at any finite number of bits, and you get an approximation. This + is why you see things like: + + \begin{verbatim} + >>> 0.1 + 0.10000000000000001 + \end{verbatim} + + On most machines today, that is what you'll see if you enter 0.1 at + a Python prompt. You may not, though, because the number of bits + used by the hardware to store floating-point values can vary across + machines, and Python only prints a decimal approximation to the true + decimal value of the binary approximation stored by the machine. On + most machines, if Python were to print the true decimal value of + the binary approximation stored for 0.1, it would have to display + + \begin{verbatim} + >>> 0.1 + 0.1000000000000000055511151231257827021181583404541015625 + \end{verbatim} + + instead! The Python prompt (implicitly) uses the builtin + \function{repr()} function to obtain a string version of everything it + displays. For floats, \code{repr(\var{float})} rounds the true + decimal value to 17 significant digits, giving + + \begin{verbatim} + 0.10000000000000001 + \end{verbatim} + + \code{repr(\var{float})} produces 17 significant digits because it + turns out that's enough (on most machines) so that + \code{eval(repr(\var{x})) == \var{x}} exactly for all finite floats + \var{x}, but rounding to 16 digits is not enough to make that true. + + Note that this is in the very nature of binary floating-point: this is + not a bug in Python, it is not a bug in your code either, and you'll + see the same kind of thing in all languages that support your + hardware's floating-point arithmetic. + + Python's builtin \function{str()} function produces only 12 + significant digits, and you may wish to use that instead. It's + unusual for \code{eval(str(\var{x}))} to reproduce \var{x}, but the + output may be more pleasant to look at: + + \begin{verbatim} + >>> print str(0.1) + 0.1 + \end{verbatim} + + It's important to realize that this is, in a real sense, an illusion: + the value in the machine is not exactly 1/10, you're simply rounding + the \emph{display} of the true machine value. + + Other surprises follow from this one. For example, after seeing + + \begin{verbatim} + >>> 0.1 + 0.10000000000000001 + \end{verbatim} + + you may be tempted to use the \function{round()} function to chop it + back to the single digit you expect. But that makes no difference: + + \begin{verbatim} + >>> round(0.1, 1) + 0.10000000000000001 + \end{verbatim} + + The problem is that the binary floating-point value stored for "0.1" + was already the best possible binary approximation to 1/10, so trying + to round it again can't make it better: it was already as good as it + gets. + + Another consequence is that since 0.1 is not exactly 1/10, adding 0.1 + to itself 10 times may not yield exactly 1.0, either: + + \begin{verbatim} + >>> sum = 0.0 + >>> for i in range(10): + ... sum += 0.1 + ... + >>> sum + 0.99999999999999989 + \end{verbatim} + + Binary floating-point arithmetic holds many surprises like this. The + problem with "0.1" is explained in precise detail below, in the + "Representation Error" section. See + \citetitle[http://www.lahey.com/float.htm]{The Perils of Floating + Point} for a more complete account of other common surprises. + + As that says near the end, ``there are no easy answers.'' Still, + don't be unduly wary of floating-point! The errors in Python float + operations are inherited from the floating-point hardware, and on most + machines are on the order of no more than 1 part in 2**53 per + operation. That's more than adequate for most tasks, but you do need + to keep in mind that it's not decimal arithmetic, and that every float + operation can suffer a new rounding error. + + While pathological cases do exist, for most casual use of + floating-point arithmetic you'll see the result you expect in the end + if you simply round the display of your final results to the number of + decimal digits you expect. \function{str()} usually suffices, and for + finer control see the discussion of Pythons's \code{\%} format + operator: the \code{\%g}, \code{\%f} and \code{\%e} format codes + supply flexible and easy ways to round float results for display. + + + \section{Representation Error + \label{fp-error}} + + This section explains the ``0.1'' example in detail, and shows how + you can perform an exact analysis of cases like this yourself. Basic + familiarity with binary floating-point representation is assumed. + + \dfn{Representation error} refers to that some (most, actually) + decimal fractions cannot be represented exactly as binary (base 2) + fractions. This is the chief reason why Python (or Perl, C, \Cpp, + Java, Fortran, and many others) often won't display the exact decimal + number you expect: + + \begin{verbatim} + >>> 0.1 + 0.10000000000000001 + \end{verbatim} + + Why is that? 1/10 is not exactly representable as a binary fraction. + Almost all machines today (November 2000) use IEEE-754 floating point + arithmetic, and almost all platforms map Python floats to IEEE-754 + "double precision". 754 doubles contain 53 bits of precision, so on + input the computer strives to convert 0.1 to the closest fraction it can + of the form \var{J}/2**\var{N} where \var{J} is an integer containing + exactly 53 bits. Rewriting + + \begin{verbatim} + 1 / 10 ~= J / (2**N) + \end{verbatim} + + as + + \begin{verbatim} + J ~= 2**N / 10 + \end{verbatim} + + and recalling that \var{J} has exactly 53 bits (is \code{>= 2**52} but + \code{< 2**53}), the best value for \var{N} is 56: + + \begin{verbatim} + >>> 2L**52 + 4503599627370496L + >>> 2L**53 + 9007199254740992L + >>> 2L**56/10 + 7205759403792793L + \end{verbatim} + + That is, 56 is the only value for \var{N} that leaves \var{J} with + exactly 53 bits. The best possible value for \var{J} is then that + quotient rounded: + + \begin{verbatim} + >>> q, r = divmod(2L**56, 10) + >>> r + 6L + \end{verbatim} + + Since the remainder is more than half of 10, the best approximation is + obtained by rounding up: + + \begin{verbatim} + >>> q+1 + 7205759403792794L + \end{verbatim} + + Therefore the best possible approximation to 1/10 in 754 double + precision is that over 2**56, or + + \begin{verbatim} + 7205759403792794 / 72057594037927936 + \end{verbatim} + + Note that since we rounded up, this is actually a little bit larger than + 1/10; if we had not rounded up, the quotient would have been a little + bit smaller than 1/10. But in no case can it be *exactly* 1/10! + + So the computer never ``sees'' 1/10: what it sees is the exact + fraction given above, the best 754 double approximation it can get: + + \begin{verbatim} + >>> .1 * 2L**56 + 7205759403792794.0 + \end{verbatim} + + If we multiply that fraction by 10**30, we can see the (truncated) + value of its 30 most significant decimal digits: + + \begin{verbatim} + >>> 7205759403792794L * 10L**30 / 2L**56 + 100000000000000005551115123125L + \end{verbatim} + + meaning that the exact number stored in the computer is approximately + equal to the decimal value 0.100000000000000005551115123125. Rounding + that to 17 significant digits gives the 0.10000000000000001 that Python + displays (well, will display on any 754-conforming platform that does + best-possible input and output conversions in its C library --- yours may + not!). + \end{document} From fdrake@users.sourceforge.net Fri Jun 8 17:28:55 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Fri, 08 Jun 2001 09:28:55 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/tut tut.tex,1.137,1.138 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tut In directory usw-pr-cvs1:/tmp/cvs-serv14450/tut Modified Files: tut.tex Log Message: Added credits in the right places. Index: tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.137 retrieving revision 1.138 diff -C2 -r1.137 -r1.138 *** tut.tex 2001/06/08 16:24:58 1.137 --- tut.tex 2001/06/08 16:28:53 1.138 *************** *** 4088,4091 **** --- 4088,4092 ---- \chapter{Floating Point Arithmetic: Issues and Limitations \label{fp-issues}} + \sectionauthor{Tim Peters}{tim_one@msn.com} Floating-point numbers are represented in computer hardware as *************** *** 4253,4256 **** --- 4254,4258 ---- \section{Representation Error \label{fp-error}} + \sectionauthor{Guido van Rossum}{guido@python.org} This section explains the ``0.1'' example in detail, and shows how From tim.one@home.com Fri Jun 8 17:58:52 2001 From: tim.one@home.com (Tim Peters) Date: Fri, 8 Jun 2001 12:58:52 -0400 Subject: [Python-checkins] CVS: python/dist/src/Doc/tut tut.tex,1.137,1.138 In-Reply-To: Message-ID: [Fred L. Drake] > Modified Files: > tut.tex > Log Message: > > Added credits in the right places. > > > Index: tut.tex > =================================================================== > RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v > retrieving revision 1.137 > retrieving revision 1.138 > diff -C2 -r1.137 -r1.138 > *** tut.tex 2001/06/08 16:24:58 1.137 > --- tut.tex 2001/06/08 16:28:53 1.138 > *************** > *** 4088,4091 **** > --- 4088,4092 ---- > \chapter{Floating Point Arithmetic: Issues and Limitations > \label{fp-issues}} > + \sectionauthor{Tim Peters}{tim_one@msn.com} tim.one@home.com is a better home address. OTOH, if people have questions about f.p., they're more likely to get further explanation by sending them to, say, floating_point_wizard@hotmail.com instead. > Floating-point numbers are represented in computer hardware as > *************** > *** 4253,4256 **** > --- 4254,4258 ---- > \section{Representation Error > \label{fp-error}} > + \sectionauthor{Guido van Rossum}{guido@python.org} Guido didn't write any of that -- 'twas another Uncle Timmy production. But feel free to attribute the first section to Guido too. the-goal-is-to-avoid-any-followups-to-me-ly y'rs - tim From fdrake@users.sourceforge.net Fri Jun 8 18:09:03 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Fri, 08 Jun 2001 10:09:03 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/tut tut.tex,1.138,1.139 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tut In directory usw-pr-cvs1:/tmp/cvs-serv22259/tut Modified Files: tut.tex Log Message: Fix the attributions for the new floating point text. Index: tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.138 retrieving revision 1.139 diff -C2 -r1.138 -r1.139 *** tut.tex 2001/06/08 16:28:53 1.138 --- tut.tex 2001/06/08 17:09:01 1.139 *************** *** 4088,4092 **** \chapter{Floating Point Arithmetic: Issues and Limitations \label{fp-issues}} ! \sectionauthor{Tim Peters}{tim_one@msn.com} Floating-point numbers are represented in computer hardware as --- 4088,4092 ---- \chapter{Floating Point Arithmetic: Issues and Limitations \label{fp-issues}} ! \sectionauthor{Tim Peters}{tim.one@home.com} Floating-point numbers are represented in computer hardware as *************** *** 4254,4258 **** \section{Representation Error \label{fp-error}} - \sectionauthor{Guido van Rossum}{guido@python.org} This section explains the ``0.1'' example in detail, and shows how --- 4254,4257 ---- From fdrake@acm.org Fri Jun 8 18:12:20 2001 From: fdrake@acm.org (Fred L. Drake, Jr.) Date: Fri, 8 Jun 2001 13:12:20 -0400 (EDT) Subject: [Python-checkins] CVS: python/dist/src/Doc/tut tut.tex,1.137,1.138 In-Reply-To: References: Message-ID: <15137.1908.635915.418543@cj42289-a.reston1.va.home.com> Tim Peters writes: > tim.one@home.com is a better home address. OTOH, if people have questions > about f.p., they're more likely to get further explanation by sending them > to, say, floating_point_wizard@hotmail.com instead. Since your name and email don't appear in the formatted docs, I wouldn't be too worried about yet another email deluge. I'll be sure to forward all the queries I get at python-docs to floating_point_wizard@hotmail.com. ;-) > Guido didn't write any of that -- 'twas another Uncle Timmy production. But > feel free to attribute the first section to Guido too. Fixed; thanks! > the-goal-is-to-avoid-any-followups-to-me-ly y'rs - tim Either that or to give credit where it's due. Thanks! -Fred -- Fred L. Drake, Jr. PythonLabs at Digital Creations From tim.one@home.com Fri Jun 8 18:43:29 2001 From: tim.one@home.com (Tim Peters) Date: Fri, 8 Jun 2001 13:43:29 -0400 Subject: [Python-checkins] CVS: python/dist/src/Doc/tut tut.tex,1.137,1.138 In-Reply-To: <15137.1908.635915.418543@cj42289-a.reston1.va.home.com> Message-ID: [Fred] > Since your name and email don't appear in the formatted docs, I > wouldn't be too worried about yet another email deluge. Ah, excellent! In that case, put my name in every section . From gvanrossum@users.sourceforge.net Fri Jun 8 21:50:33 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 08 Jun 2001 13:50:33 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0252.txt,1.7,1.8 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv1144 Modified Files: pep-0252.txt Log Message: I just figured out how to make automatic hyperlinks to other PEPs. Index: pep-0252.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0252.txt,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -r1.7 -r1.8 *** pep-0252.txt 2001/05/22 03:04:27 1.7 --- pep-0252.txt 2001/06/08 20:50:31 1.8 *************** *** 404,408 **** Note: the code in this branch goes beyond this PEP; it is also ! on the way to implementing PEP 253 (Subtyping Built-in Types). References --- 404,408 ---- Note: the code in this branch goes beyond this PEP; it is also ! on the way to implementing pep-0253 (Subtyping Built-in Types). References From loewis@users.sourceforge.net Sat Jun 9 08:34:07 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sat, 09 Jun 2001 00:34:07 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib UserList.py,1.16,1.17 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv9798/Lib Modified Files: UserList.py Log Message: Patch #424475: Speed-up tp_compare usage, by special-casing the common case of objects with equal types which support tp_compare. Give type objects a tp_compare function. Also add c<0 tests before a few PyErr_Occurred tests. Index: UserList.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/UserList.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -r1.16 -r1.17 *** UserList.py 2001/02/18 03:30:53 1.16 --- UserList.py 2001/06/09 07:34:05 1.17 *************** *** 23,27 **** else: return other def __cmp__(self, other): ! raise RuntimeError, "UserList.__cmp__() is obsolete" def __contains__(self, item): return item in self.data def __len__(self): return len(self.data) --- 23,27 ---- else: return other def __cmp__(self, other): ! return cmp(self.data, self.__cast(other)) def __contains__(self, item): return item in self.data def __len__(self): return len(self.data) From loewis@users.sourceforge.net Sat Jun 9 08:34:07 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sat, 09 Jun 2001 00:34:07 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects object.c,2.131,2.132 typeobject.c,2.16,2.17 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv9798/Objects Modified Files: object.c typeobject.c Log Message: Patch #424475: Speed-up tp_compare usage, by special-casing the common case of objects with equal types which support tp_compare. Give type objects a tp_compare function. Also add c<0 tests before a few PyErr_Occurred tests. Index: object.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v retrieving revision 2.131 retrieving revision 2.132 diff -C2 -r2.131 -r2.132 *** object.c 2001/05/11 03:36:45 2.131 --- object.c 2001/06/09 07:34:05 2.132 *************** *** 478,491 **** return (*w->ob_type->tp_compare)(v, w); - /* If the types are equal, don't bother with coercions etc. */ - if (v->ob_type == w->ob_type) { - if ((f = v->ob_type->tp_compare) == NULL) - return 2; - c = (*f)(v, w); - if (PyErr_Occurred()) - return -2; - return c < 0 ? -1 : c > 0 ? 1 : 0; - } - /* Try coercion; if it fails, give up */ c = PyNumber_CoerceEx(&v, &w); --- 478,481 ---- *************** *** 500,504 **** Py_DECREF(v); Py_DECREF(w); ! if (PyErr_Occurred()) return -2; return c < 0 ? -1 : c > 0 ? 1 : 0; --- 490,494 ---- Py_DECREF(v); Py_DECREF(w); ! if (c < 0 && PyErr_Occurred()) return -2; return c < 0 ? -1 : c > 0 ? 1 : 0; *************** *** 510,514 **** Py_DECREF(v); Py_DECREF(w); ! if (PyErr_Occurred()) return -2; return c < 0 ? 1 : c > 0 ? -1 : 0; /* negated! */ --- 500,504 ---- Py_DECREF(v); Py_DECREF(w); ! if (c < 0 && PyErr_Occurred()) return -2; return c < 0 ? 1 : c > 0 ? -1 : 0; /* negated! */ *************** *** 591,594 **** --- 581,586 ---- 0 if v == w; 1 if v > w; + If the object implements a tp_compare function, it returns + whatever this function returns (whether with an exception or not). */ static int *************** *** 596,600 **** --- 588,596 ---- { int c; + cmpfunc f; + if (v->ob_type == w->ob_type + && (f = v->ob_type->tp_compare) != NULL) + return (*f)(v, w); c = try_rich_to_3way_compare(v, w); if (c < 2) *************** *** 761,774 **** static PyObject * ! try_3way_to_rich_compare(PyObject *v, PyObject *w, int op) { - int c; PyObject *result; - - c = try_3way_compare(v, w); - if (c >= 2) - c = default_3way_compare(v, w); - if (c <= -2) - return NULL; switch (op) { case Py_LT: c = c < 0; break; --- 757,763 ---- static PyObject * ! convert_3way_to_object(int op, int c) { PyObject *result; switch (op) { case Py_LT: c = c < 0; break; *************** *** 783,791 **** --- 772,820 ---- return result; } + static PyObject * + try_3way_to_rich_compare(PyObject *v, PyObject *w, int op) + { + int c; + + c = try_3way_compare(v, w); + if (c >= 2) + c = default_3way_compare(v, w); + if (c <= -2) + return NULL; + return convert_3way_to_object(op, c); + } + + static PyObject * do_richcmp(PyObject *v, PyObject *w, int op) { PyObject *res; + cmpfunc f; + + /* If the types are equal, don't bother with coercions etc. + Instances are special-cased in try_3way_compare, since + a result of 2 does *not* mean one value being greater + than the other. */ + if (v->ob_type == w->ob_type + && (f = v->ob_type->tp_compare) != NULL + && !PyInstance_Check(v)) { + int c; + richcmpfunc f1; + if ((f1 = RICHCOMPARE(v->ob_type)) != NULL) { + /* If the type has richcmp, try it first. + try_rich_compare would try it two-sided, + which is not needed since we've a single + type only. */ + res = (*f1)(v, w, op); + if (res != Py_NotImplemented) + return res; + Py_DECREF(res); + } + c = (*f)(v, w); + if (c < 0 && PyErr_Occurred()) + return NULL; + return convert_3way_to_object(op, c); + } res = try_rich_compare(v, w, op); Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16 retrieving revision 2.17 diff -C2 -r2.16 -r2.17 *** typeobject.c 2000/09/01 23:29:27 2.16 --- typeobject.c 2001/06/09 07:34:05 2.17 *************** *** 24,27 **** --- 24,37 ---- } + static int + type_compare(PyObject *v, PyObject *w) + { + /* This is called with type objects only. So we + can just compare the addresses. */ + Py_uintptr_t vv = (Py_uintptr_t)v; + Py_uintptr_t ww = (Py_uintptr_t)w; + return (vv < ww) ? -1 : (vv > ww) ? 1 : 0; + } + static PyObject * type_repr(PyTypeObject *v) *************** *** 42,51 **** (getattrfunc)type_getattr, /*tp_getattr*/ 0, /*tp_setattr*/ ! 0, /*tp_compare*/ (reprfunc)type_repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ ! 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ --- 52,61 ---- (getattrfunc)type_getattr, /*tp_getattr*/ 0, /*tp_setattr*/ ! type_compare, /*tp_compare*/ (reprfunc)type_repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ ! _Py_HashPointer, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ From loewis@users.sourceforge.net Sat Jun 9 08:59:45 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sat, 09 Jun 2001 00:59:45 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include cStringIO.h,2.14,2.15 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv15182 Modified Files: cStringIO.h Log Message: Cast the result of xxxPyCObject_Import to PycStringIO_CAPI*. This fixes bug #431557. Index: cStringIO.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/cStringIO.h,v retrieving revision 2.14 retrieving revision 2.15 diff -C2 -r2.14 -r2.15 *** cStringIO.h 2000/07/22 19:25:51 2.14 --- cStringIO.h 2001/06/09 07:59:43 2.15 *************** *** 127,131 **** #define PycString_IMPORT \ ! PycStringIO=xxxPyCObject_Import("cStringIO", "cStringIO_CAPI") #endif /* CSTRINGIO_INCLUDED */ --- 127,131 ---- #define PycString_IMPORT \ ! PycStringIO=(struct PycStringIO_CAPI*)xxxPyCObject_Import("cStringIO", "cStringIO_CAPI") #endif /* CSTRINGIO_INCLUDED */ From tim_one@users.sourceforge.net Sat Jun 9 10:26:23 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 09 Jun 2001 02:26:23 -0700 Subject: [Python-checkins] CVS: python/dist/src/Misc ACKS,1.96,1.97 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv30667/python/dist/src/Misc Modified Files: ACKS Log Message: SF bug 430991: wrong co_lnotab Armin Rigo pointed out that the way the line-# table got built didn't work for lines generating more than 255 bytes of bytecode. Fixed as he suggested, plus corresponding changes to pyassem.py, plus added some long overdue docs about this subtle table to compile.c. Bugfix candidate (line numbers may be off in tracebacks under -O). Index: ACKS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/ACKS,v retrieving revision 1.96 retrieving revision 1.97 diff -C2 -r1.96 -r1.97 *** ACKS 2001/04/24 05:16:29 1.96 --- ACKS 2001/06/09 09:26:21 1.97 *************** *** 320,323 **** --- 320,324 ---- Steven Reiz Jan Pieter Riegel + Armin Rigo Nicholas Riley Jean-Claude Rimbault From tim_one@users.sourceforge.net Sat Jun 9 10:26:23 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 09 Jun 2001 02:26:23 -0700 Subject: [Python-checkins] CVS: python/dist/src/Tools/compiler/compiler pyassem.py,1.19,1.20 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/compiler/compiler In directory usw-pr-cvs1:/tmp/cvs-serv30667/python/dist/src/Tools/compiler/compiler Modified Files: pyassem.py Log Message: SF bug 430991: wrong co_lnotab Armin Rigo pointed out that the way the line-# table got built didn't work for lines generating more than 255 bytes of bytecode. Fixed as he suggested, plus corresponding changes to pyassem.py, plus added some long overdue docs about this subtle table to compile.c. Bugfix candidate (line numbers may be off in tracebacks under -O). Index: pyassem.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/compiler/compiler/pyassem.py,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -r1.19 -r1.20 *** pyassem.py 2001/04/12 20:21:39 1.19 --- pyassem.py 2001/06/09 09:26:21 1.20 *************** *** 614,619 **** """lnotab ! This class builds the lnotab, which is undocumented but described ! by com_set_lineno in compile.c. Here's an attempt at explanation: For each SET_LINENO instruction after the first one, two bytes are --- 614,619 ---- """lnotab ! This class builds the lnotab, which is documented in compile.c. ! Here's a brief recap: For each SET_LINENO instruction after the first one, two bytes are *************** *** 622,627 **** instruction for the last SET_LINENO and the current SET_LINENO. The second byte is offset in line numbers. If either offset is ! greater than 255, multiple two-byte entries are added -- one entry ! for each factor of 255. """ --- 622,627 ---- instruction for the last SET_LINENO and the current SET_LINENO. The second byte is offset in line numbers. If either offset is ! greater than 255, multiple two-byte entries are added -- see ! compile.c for the delicate details. """ *************** *** 658,674 **** # for the assignment. if line > 0: ! while addr > 0 or line > 0: ! # write the values in 1-byte chunks that sum ! # to desired value ! trunc_addr = addr ! trunc_line = line ! if trunc_addr > 255: ! trunc_addr = 255 ! if trunc_line > 255: ! trunc_line = 255 ! self.lnotab.append(trunc_addr) ! self.lnotab.append(trunc_line) ! addr = addr - trunc_addr ! line = line - trunc_line self.lastline = lineno self.lastoff = self.codeOffset --- 658,671 ---- # for the assignment. if line > 0: ! push = self.lnotab.append ! while addr > 255: ! push(255); push(0) ! addr -= 255 ! while line > 255: ! push(addr); push(255) ! line -= 255 ! addr = 0 ! if addr > 0 or line > 0: ! push(addr); push(line) self.lastline = lineno self.lastoff = self.codeOffset From tim_one@users.sourceforge.net Sat Jun 9 10:26:23 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 09 Jun 2001 02:26:23 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python compile.c,2.200,2.201 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv30667/python/dist/src/Python Modified Files: compile.c Log Message: SF bug 430991: wrong co_lnotab Armin Rigo pointed out that the way the line-# table got built didn't work for lines generating more than 255 bytes of bytecode. Fixed as he suggested, plus corresponding changes to pyassem.py, plus added some long overdue docs about this subtle table to compile.c. Bugfix candidate (line numbers may be off in tracebacks under -O). Index: compile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v retrieving revision 2.200 retrieving revision 2.201 diff -C2 -r2.200 -r2.201 *** compile.c 2001/05/09 18:53:51 2.200 --- compile.c 2001/06/09 09:26:21 2.201 *************** *** 337,340 **** --- 337,384 ---- */ + /* All about c_lnotab. + + c_lnotab is an array of unsigned bytes disguised as a Python string. In -O + mode, SET_LINENO opcodes aren't generated, and bytecode offsets are mapped + to source code line #s (when needed for tracebacks) via c_lnotab instead. + The array is conceptually a list of + (bytecode offset increment, line number increment) + pairs. The details are important and delicate, best illustrated by example: + + byte code offset source code line number + 0 1 + 6 2 + 50 7 + 350 307 + 361 308 + + The first trick is that these numbers aren't stored, only the increments + from one row to the next (this doesn't really work, but it's a start): + + 0, 1, 6, 1, 44, 5, 300, 300, 11, 1 + + The second trick is that an unsigned byte can't hold negative values, or + values larger than 255, so (a) there's a deep assumption that byte code + offsets and their corresponding line #s both increase monotonically, and (b) + if at least one column jumps by more than 255 from one row to the next, more + than one pair is written to the table. In case #b, there's no way to know + from looking at the table later how many were written. That's the delicate + part. A user of c_lnotab desiring to find the source line number + corresponding to a bytecode address A should do something like this + + lineno = addr = 0 + for addr_incr, line_incr in c_lnotab: + addr += addr_incr + if addr > A: + return lineno + lineno += line_incr + + In order for this to work, when the addr field increments by more than 255, + the line # increment in each pair generated must be 0 until the remaining addr + increment is < 256. So, in the example above, com_set_lineno should not (as + was actually done until 2.2) expand 300, 300 to 255, 255, 45, 45, but to + 255, 0, 45, 255, 0, 45. + */ + struct compiling { PyObject *c_code; /* string */ *************** *** 693,707 **** int incr_addr = c->c_nexti - c->c_last_addr; int incr_line = lineno - c->c_last_line; ! while (incr_addr > 0 || incr_line > 0) { ! int trunc_addr = incr_addr; ! int trunc_line = incr_line; ! if (trunc_addr > 255) ! trunc_addr = 255; ! if (trunc_line > 255) ! trunc_line = 255; ! com_add_lnotab(c, trunc_addr, trunc_line); ! incr_addr -= trunc_addr; ! incr_line -= trunc_line; } c->c_last_addr = c->c_nexti; c->c_last_line = lineno; --- 737,751 ---- int incr_addr = c->c_nexti - c->c_last_addr; int incr_line = lineno - c->c_last_line; ! while (incr_addr > 255) { ! com_add_lnotab(c, 255, 0); ! incr_addr -= 255; ! } ! while (incr_line > 255) { ! com_add_lnotab(c, incr_addr, 255); ! incr_line -=255; ! incr_addr = 0; } + if (incr_addr > 0 || incr_line > 0) + com_add_lnotab(c, incr_addr, incr_line); c->c_last_addr = c->c_nexti; c->c_last_line = lineno; From nowonder@users.sourceforge.net Sun Jun 10 17:45:10 2001 From: nowonder@users.sourceforge.net (Peter Schneider-Kamp) Date: Sun, 10 Jun 2001 09:45:10 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules mathmodule.c,2.58,2.59 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv2707 Modified Files: mathmodule.c Log Message: annoying whitespace inconsistency Index: mathmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/mathmodule.c,v retrieving revision 2.58 retrieving revision 2.59 diff -C2 -r2.58 -r2.59 *** mathmodule.c 2000/10/12 19:42:00 2.58 --- mathmodule.c 2001/06/10 16:45:08 2.59 *************** *** 129,133 **** FUNC1(floor, floor, "floor(x)\n\nReturn the floor of x as a real.") ! FUNC2(fmod, fmod, "fmod(x,y)\n\nReturn fmod(x, y), according to platform C." " x % y may differ.") --- 129,133 ---- FUNC1(floor, floor, "floor(x)\n\nReturn the floor of x as a real.") ! FUNC2(fmod, fmod, "fmod(x,y)\n\nReturn fmod(x, y), according to platform C." " x % y may differ.") From loewis@users.sourceforge.net Sun Jun 10 18:27:38 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 10 Jun 2001 10:27:38 -0700 Subject: [Python-checkins] CVS: python/nondist/i18n/po python.pot,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/i18n/po In directory usw-pr-cvs1:/tmp/cvs-serv8954 Modified Files: python.pot Log Message: Install 2.1 version of doc string catalog. Index: python.pot =================================================================== RCS file: /cvsroot/python/python/nondist/i18n/po/python.pot,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -r1.1 -r1.2 *** python.pot 2000/09/13 19:49:31 1.1 --- python.pot 2001/06/10 17:27:34 1.2 *************** *** 1,18 **** ! # Python Message Catalog ! # Copyright (c) 2000 BeOpen.com. ! # Copyright (c) 1995-2000 Corporation for National Research Initiatives. ! # Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, ! # The Netherlands. ! # # FIRST AUTHOR , YEAR. # # This version of the catalog contains only doc strings, which a # developer can access interactively during development. [...34507 lines suppressed...] ! #: Modules/zlibmodule.c:600 msgid "flush() -- Return a string containing any remaining decompressed data. The decompressor object can no longer be used after this call." msgstr "" ! #: Modules/zlibmodule.c:665 msgid "" "adler32(string) -- Compute an Adler-32 checksum of string, using a default starting value, and returning an integer value.\n" *************** *** 16665,16669 **** msgstr "" ! #: Modules/zlibmodule.c:734 msgid "" "crc32(string) -- Compute a CRC-32 checksum of string, using a default starting value, and returning an integer value.\n" --- 19633,19637 ---- msgstr "" ! #: Modules/zlibmodule.c:687 msgid "" "crc32(string) -- Compute a CRC-32 checksum of string, using a default starting value, and returning an integer value.\n" From tim_one@users.sourceforge.net Sun Jun 10 19:58:28 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 10 Jun 2001 11:58:28 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib traceback.py,1.25,1.26 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv22975/python/dist/src/lib Modified Files: traceback.py Log Message: SF bug 431772: traceback.print_exc() causes traceback Patch from Michael Hundson. format_exception_only() blew up when trying to report a SyntaxError from a string input (line is None in this case, but it assumed a string). Bugfix candidate. Index: traceback.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/traceback.py,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -r1.25 -r1.26 *** traceback.py 2001/03/29 04:36:08 1.25 --- traceback.py 2001/06/10 18:58:26 1.26 *************** *** 172,188 **** list.append(' File "%s", line %d\n' % (filename, lineno)) ! i = 0 ! while i < len(line) and line[i].isspace(): ! i = i+1 ! list.append(' %s\n' % line.strip()) ! if offset is not None: ! s = ' ' ! for c in line[i:offset-1]: ! if c.isspace(): ! s = s + c ! else: ! s = s + ' ' ! list.append('%s^\n' % s) ! value = msg s = _some_str(value) if s: --- 172,189 ---- list.append(' File "%s", line %d\n' % (filename, lineno)) ! if line is not None: ! i = 0 ! while i < len(line) and line[i].isspace(): ! i = i+1 ! list.append(' %s\n' % line.strip()) ! if offset is not None: ! s = ' ' ! for c in line[i:offset-1]: ! if c.isspace(): ! s = s + c ! else: ! s = s + ' ' ! list.append('%s^\n' % s) ! value = msg s = _some_str(value) if s: From jackjansen@users.sourceforge.net Sun Jun 10 22:43:30 2001 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Sun, 10 Jun 2001 14:43:30 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.17,2.18 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv18874/Python/Objects Modified Files: typeobject.c Log Message: Added a missing cast to the hashfunc initializer. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.17 retrieving revision 2.18 diff -C2 -r2.17 -r2.18 *** typeobject.c 2001/06/09 07:34:05 2.17 --- typeobject.c 2001/06/10 21:43:28 2.18 *************** *** 57,61 **** 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ ! _Py_HashPointer, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ --- 57,61 ---- 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ ! (hashfunc)_Py_HashPointer, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ From tim_one@users.sourceforge.net Mon Jun 11 00:40:21 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 10 Jun 2001 16:40:21 -0700 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.181,1.182 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv6496/python/dist/src/Misc Modified Files: NEWS Log Message: Initial support for 'q' and 'Q' struct format codes: for now, only in native mode, and only when config #defines HAVE_LONG_LONG. Standard mode will eventually treat them as 8-byte ints across all platforms, but that likely requires a new set of routines in longobject.c first (while sizeof(long) >= 4 is guaranteed by C, there's nothing in C we can rely on x-platform to hold 8 bytes of int, so we'll have to roll our own; I'm thinking of a simple pair of conversion functions, Python long to/from sized vector of unsigned bytes; that may be useful for GMP conversions too; std q/Q would call them with size fixed at 8). test_struct.py: In addition to adding some native-mode 'q' and 'Q' tests, got rid of unused code, and repaired a non-portable assumption about native sizeof(short) (it isn't 2 on some Cray boxes). libstruct.tex: In addition to adding a bit of 'q'/'Q' docs (more needed later), removed an erroneous footnote about 'I' behavior. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.181 retrieving revision 1.182 diff -C2 -r1.181 -r1.182 *** NEWS 2001/06/06 13:30:54 1.181 --- NEWS 2001/06/10 23:40:19 1.182 *************** *** 141,144 **** --- 141,152 ---- - pprint functions now much faster for large containers (tuple, list, dict). + - New 'q' and 'Q' format codes in the struct module, corresponding to C + types "long long" and "unsigned long long" (on Windows, __int64). In + native mode, these can be used only when the platform C compiler supports + these types (when HAVE_LONG_LONG is #define'd by the Python config + process), and then they inherit the sizes and alignments of the C types. + XXX TODO In standard mode, 'q' and 'Q' are supported on all platforms, and + XXX TODO are 8-byte integral types. + Tests From tim_one@users.sourceforge.net Mon Jun 11 00:40:21 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 10 Jun 2001 16:40:21 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libstruct.tex,1.26,1.27 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv6496/python/dist/src/Doc/lib Modified Files: libstruct.tex Log Message: Initial support for 'q' and 'Q' struct format codes: for now, only in native mode, and only when config #defines HAVE_LONG_LONG. Standard mode will eventually treat them as 8-byte ints across all platforms, but that likely requires a new set of routines in longobject.c first (while sizeof(long) >= 4 is guaranteed by C, there's nothing in C we can rely on x-platform to hold 8 bytes of int, so we'll have to roll our own; I'm thinking of a simple pair of conversion functions, Python long to/from sized vector of unsigned bytes; that may be useful for GMP conversions too; std q/Q would call them with size fixed at 8). test_struct.py: In addition to adding some native-mode 'q' and 'Q' tests, got rid of unused code, and repaired a non-portable assumption about native sizeof(short) (it isn't 2 on some Cray boxes). libstruct.tex: In addition to adding a bit of 'q'/'Q' docs (more needed later), removed an erroneous footnote about 'I' behavior. Index: libstruct.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstruct.tex,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -r1.26 -r1.27 *** libstruct.tex 2001/01/24 17:19:07 1.26 --- libstruct.tex 2001/06/10 23:40:19 1.27 *************** *** 54,60 **** \lineiv{H}{\ctype{unsigned short}}{integer}{} \lineiv{i}{\ctype{int}}{integer}{} ! \lineiv{I}{\ctype{unsigned int}}{long}{(1)} \lineiv{l}{\ctype{long}}{integer}{} \lineiv{L}{\ctype{unsigned long}}{long}{} \lineiv{f}{\ctype{float}}{float}{} \lineiv{d}{\ctype{double}}{float}{} --- 54,62 ---- \lineiv{H}{\ctype{unsigned short}}{integer}{} \lineiv{i}{\ctype{int}}{integer}{} ! \lineiv{I}{\ctype{unsigned int}}{long}{} \lineiv{l}{\ctype{long}}{integer}{} \lineiv{L}{\ctype{unsigned long}}{long}{} + \lineiv{q}{\ctype{long long}}{long}{(1)} + \lineiv{Q}{\ctype{unsigned long long}}{long}{(1)} \lineiv{f}{\ctype{float}}{float}{} \lineiv{d}{\ctype{double}}{float}{} *************** *** 69,76 **** \begin{description} \item[(1)] ! The \character{I} conversion code will convert to a Python long if ! the C \ctype{int} is the same size as a C \ctype{long}, which is ! typical on most modern systems. If a C \ctype{int} is smaller than ! a C \ctype{long}, an Python integer will be created instead. \end{description} --- 71,77 ---- \begin{description} \item[(1)] ! The \character{q} and \character{Q} conversion codes are available in ! native mode only if the platform C compiler supports C \ctype{long long}, ! or, on Windows, \ctype{__int64}. \end{description} From tim_one@users.sourceforge.net Mon Jun 11 00:40:21 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 10 Jun 2001 16:40:21 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules structmodule.c,2.42,2.43 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv6496/python/dist/src/Modules Modified Files: structmodule.c Log Message: Initial support for 'q' and 'Q' struct format codes: for now, only in native mode, and only when config #defines HAVE_LONG_LONG. Standard mode will eventually treat them as 8-byte ints across all platforms, but that likely requires a new set of routines in longobject.c first (while sizeof(long) >= 4 is guaranteed by C, there's nothing in C we can rely on x-platform to hold 8 bytes of int, so we'll have to roll our own; I'm thinking of a simple pair of conversion functions, Python long to/from sized vector of unsigned bytes; that may be useful for GMP conversions too; std q/Q would call them with size fixed at 8). test_struct.py: In addition to adding some native-mode 'q' and 'Q' tests, got rid of unused code, and repaired a non-portable assumption about native sizeof(short) (it isn't 2 on some Cray boxes). libstruct.tex: In addition to adding a bit of 'q'/'Q' docs (more needed later), removed an erroneous footnote about 'I' behavior. Index: structmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/structmodule.c,v retrieving revision 2.42 retrieving revision 2.43 diff -C2 -r2.42 -r2.43 *** structmodule.c 2001/04/08 23:39:38 2.42 --- structmodule.c 2001/06/10 23:40:19 2.43 *************** *** 23,29 **** l:long; L:unsigned long; f:float; d:double.\n\ Special cases (preceding decimal count indicates length):\n\ ! s:string (array of char); p: pascal string (w. count byte).\n\ Special case (only available in native format):\n\ P:an integer type that is wide enough to hold a pointer.\n\ Whitespace between formats is ignored.\n\ \n\ --- 23,31 ---- l:long; L:unsigned long; f:float; d:double.\n\ Special cases (preceding decimal count indicates length):\n\ ! s:string (array of char); p: pascal string (with count byte).\n\ Special case (only available in native format):\n\ P:an integer type that is wide enough to hold a pointer.\n\ + Special case (not in native mode unless 'long long' in platform C):\n\ + q:long long; Q:unsigned long long\n\ Whitespace between formats is ignored.\n\ \n\ *************** *** 66,69 **** --- 68,83 ---- #define VOID_P_ALIGN (sizeof(s_void_p) - sizeof(void *)) + /* We can't support q and Q in native mode unless the compiler does; + in std mode, they're 8 bytes on all platforms. */ + #ifdef HAVE_LONG_LONG + typedef struct { char c; LONG_LONG x; } s_long_long; + #define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(LONG_LONG)) + + #else + static char qQ_error_msg[] = + "q and Q unavailable in native mode on this platform; use a standard mode.\0"; + + #endif + #define STRINGIFY(x) #x *************** *** 107,111 **** --- 121,212 ---- } + #ifdef HAVE_LONG_LONG + + /* Same, but handling native long long. */ + + static int + get_longlong(PyObject *v, LONG_LONG *p) + { + LONG_LONG x; + int v_needs_decref = 0; + + if (PyInt_Check(v)) { + x = (LONG_LONG)PyInt_AS_LONG(v); + *p = x; + return 0; + } + if (!PyLong_Check(v)) { + PyNumberMethods *m = v->ob_type->tp_as_number; + if (m != NULL && m->nb_long != NULL) { + v = m->nb_long(v); + if (v == NULL) + return -1; + v_needs_decref = 1; + } + if (!PyLong_Check(v)) { + PyErr_SetString(StructError, + "cannot convert argument to long"); + if (v_needs_decref) + Py_DECREF(v); + return -1; + } + } + assert(PyLong_Check(v)); + x = PyLong_AsLongLong(v); + if (v_needs_decref) + Py_DECREF(v); + if (x == (LONG_LONG)-1 && PyErr_Occurred()) + return -1; + *p = x; + return 0; + } + + /* Same, but handling native unsigned long long. */ + static int + get_ulonglong(PyObject *v, unsigned LONG_LONG *p) + { + unsigned LONG_LONG x; + int v_needs_decref = 0; + + if (PyInt_Check(v)) { + long i = PyInt_AS_LONG(v); + if (i < 0) { + PyErr_SetString(StructError, "can't convert negative " + "int to unsigned"); + return -1; + } + x = (unsigned LONG_LONG)i; + *p = x; + return 0; + } + if (!PyLong_Check(v)) { + PyNumberMethods *m = v->ob_type->tp_as_number; + if (m != NULL && m->nb_long != NULL) { + v = m->nb_long(v); + if (v == NULL) + return -1; + v_needs_decref = 1; + } + if (!PyLong_Check(v)) { + PyErr_SetString(StructError, + "cannot convert argument to long"); + if (v_needs_decref) + Py_DECREF(v); + return -1; + } + } + assert(PyLong_Check(v)); + x = PyLong_AsUnsignedLongLong(v); + if (v_needs_decref) + Py_DECREF(v); + if (x == (unsigned LONG_LONG)-1 && PyErr_Occurred()) + return -1; + *p = x; + return 0; + } + + #endif + /* Floating point helpers */ *************** *** 396,399 **** --- 497,511 ---- } formatdef; + /* A large number of small routines follow, with names of the form + + [bln][up]_TYPE + + [bln] distiguishes among big-endian, little-endian and native. + [pu] distiguishes between pack (to struct) and unpack (from struct). + TYPE is one of char, byte, ubyte, etc. + */ + + /* Native mode routines. */ + static PyObject * nu_char(const char *p, const formatdef *f) *************** *** 451,454 **** --- 563,594 ---- } + /* Native mode doesn't support q or Q unless the platform C supports + long long (or, on Windows, __int64). */ + + #ifdef HAVE_LONG_LONG + + static PyObject * + nu_longlong(const char *p, const formatdef *f) + { + return PyLong_FromLongLong(*(LONG_LONG *)p); + } + + static PyObject * + nu_ulonglong(const char *p, const formatdef *f) + { + return PyLong_FromUnsignedLongLong(*(unsigned LONG_LONG *)p); + } + + #else + + static PyObject * + nu_qQerror(const char *p, const formatdef *f) + { + PyErr_SetString(StructError, qQ_error_msg); + return NULL; + } + + #endif + static PyObject * nu_float(const char *p, const formatdef *f) *************** *** 586,590 **** --- 726,763 ---- } + #ifdef HAVE_LONG_LONG + static int + np_longlong(char *p, PyObject *v, const formatdef *f) + { + LONG_LONG x; + if (get_longlong(v, &x) < 0) + return -1; + * (LONG_LONG *)p = x; + return 0; + } + + static int + np_ulonglong(char *p, PyObject *v, const formatdef *f) + { + unsigned LONG_LONG x; + if (get_ulonglong(v, &x) < 0) + return -1; + * (unsigned LONG_LONG *)p = x; + return 0; + } + + #else + + static int + np_qQerror(char *p, PyObject *v, const formatdef *f) + { + PyErr_SetString(StructError, qQ_error_msg); + return -1; + } + + #endif + + static int np_float(char *p, PyObject *v, const formatdef *f) { *************** *** 643,646 **** --- 816,831 ---- {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double}, {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p}, + #ifdef HAVE_LONG_LONG + {'q', sizeof(LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong}, + {'Q', sizeof(LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong}, + #else + /* n[pu]_qQerror just raise errors, but give them "the expected" size + and alignment anyway so that calcsize returns something reasonable, + and so unpack code that works on a 'long long' platform ends up in + the error routine instead of with a mysterious "unpack str size + does not match format" msg when run on a non-'long long' box. */ + {'q', 8, 8, nu_qQerror, np_qQerror}, + {'Q', 8, 8, nu_qQerror, np_qQerror}, + #endif {0} }; From tim_one@users.sourceforge.net Mon Jun 11 00:40:21 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 10 Jun 2001 16:40:21 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_struct.py,1.7,1.8 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv6496/python/dist/src/Lib/test Modified Files: test_struct.py Log Message: Initial support for 'q' and 'Q' struct format codes: for now, only in native mode, and only when config #defines HAVE_LONG_LONG. Standard mode will eventually treat them as 8-byte ints across all platforms, but that likely requires a new set of routines in longobject.c first (while sizeof(long) >= 4 is guaranteed by C, there's nothing in C we can rely on x-platform to hold 8 bytes of int, so we'll have to roll our own; I'm thinking of a simple pair of conversion functions, Python long to/from sized vector of unsigned bytes; that may be useful for GMP conversions too; std q/Q would call them with size fixed at 8). test_struct.py: In addition to adding some native-mode 'q' and 'Q' tests, got rid of unused code, and repaired a non-portable assumption about native sizeof(short) (it isn't 2 on some Cray boxes). libstruct.tex: In addition to adding a bit of 'q'/'Q' docs (more needed later), removed an erroneous footnote about 'I' behavior. Index: test_struct.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_struct.py,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -r1.7 -r1.8 *** test_struct.py 2000/12/12 23:11:42 1.7 --- test_struct.py 2001/06/10 23:40:19 1.8 *************** *** 1,3 **** ! from test_support import TestFailed, verbose import struct ## import pdb --- 1,3 ---- ! from test_support import TestFailed, verbose, verify import struct ## import pdb *************** *** 13,17 **** ## pdb.set_trace() ! simple_err(struct.calcsize, 'Q') sz = struct.calcsize('i') --- 13,17 ---- ## pdb.set_trace() ! simple_err(struct.calcsize, 'Z') sz = struct.calcsize('i') *************** *** 94,106 **** ] ! def badpack(fmt, arg, got, exp): ! return - def badunpack(fmt, arg, got, exp): - return "unpack(%s, %s) -> (%s,) # expected (%s,)" % ( - `fmt`, `arg`, `got`, `exp`) - - isbigendian = struct.pack('=h', 1) == '\0\1' - for fmt, arg, big, lil, asy in tests: if verbose: --- 94,99 ---- ] ! isbigendian = struct.pack('=i', 1)[0] == chr(0) for fmt, arg, big, lil, asy in tests: if verbose: *************** *** 120,121 **** --- 113,158 ---- raise TestFailed, "unpack(%s, %s) -> (%s,) # expected (%s,)" % ( `fmt`, `res`, `rev`, `arg`) + + # Some q/Q sanity checks. + + has_native_qQ = 1 + try: + struct.pack("q", 5) + except struct.error: + has_native_qQ = 0 + + if verbose: + print "Platform has native q/Q?", has_native_qQ and "Yes." or "No." + + simple_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless + simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless + simple_err(struct.pack, "Q", "a") # ditto, but 'Q' + + def force_bigendian(value): + if isbigendian: + return value + chars = list(value) + chars.reverse() + return "".join(chars) + + if has_native_qQ: + bytes = struct.calcsize('q') + # The expected values here are in big-endian format, primarily because + # I'm on a little-endian machine and so this is the clearest way (for + # me) to force the code to get exercised. + for format, input, expected in ( + ('q', -1, '\xff' * bytes), + ('q', 0, '\x00' * bytes), + ('Q', 0, '\x00' * bytes), + ('q', 1L, '\x00' * (bytes-1) + '\x01'), + ('Q', (1L << (8*bytes))-1, '\xff' * bytes), + ('q', (1L << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))): + got = struct.pack(format, input) + bigexpected = force_bigendian(expected) + verify(got == bigexpected, + "%r-pack of %r gave %r, not %r" % + (format, input, got, bigexpected)) + retrieved = struct.unpack(format, got)[0] + verify(retrieved == input, + "%r-unpack of %r gave %r, not %r" % + (format, got, retrieved, input)) From tim_one@users.sourceforge.net Mon Jun 11 00:53:01 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 10 Jun 2001 16:53:01 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_struct.py,1.8,1.9 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv9934/python/dist/src/Lib/test Modified Files: test_struct.py Log Message: Renamed some stuff to tell the truth about what it does. Index: test_struct.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_struct.py,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -r1.8 -r1.9 *** test_struct.py 2001/06/10 23:40:19 1.8 --- test_struct.py 2001/06/10 23:52:59 1.9 *************** *** 129,133 **** simple_err(struct.pack, "Q", "a") # ditto, but 'Q' ! def force_bigendian(value): if isbigendian: return value --- 129,133 ---- simple_err(struct.pack, "Q", "a") # ditto, but 'Q' ! def bigendian_to_native(value): if isbigendian: return value *************** *** 149,156 **** ('q', (1L << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))): got = struct.pack(format, input) ! bigexpected = force_bigendian(expected) ! verify(got == bigexpected, "%r-pack of %r gave %r, not %r" % ! (format, input, got, bigexpected)) retrieved = struct.unpack(format, got)[0] verify(retrieved == input, --- 149,156 ---- ('q', (1L << (8*bytes-1))-1, '\x7f' + '\xff' * (bytes - 1))): got = struct.pack(format, input) ! native_expected = bigendian_to_native(expected) ! verify(got == native_expected, "%r-pack of %r gave %r, not %r" % ! (format, input, got, native_expected)) retrieved = struct.unpack(format, got)[0] verify(retrieved == input, From fdrake@users.sourceforge.net Mon Jun 11 15:55:03 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 11 Jun 2001 07:55:03 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libdoctest.tex,1.7,1.8 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv28494/lib Modified Files: libdoctest.tex Log Message: Fix recent changes so that this section will format again. Index: libdoctest.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libdoctest.tex,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -r1.7 -r1.8 *** libdoctest.tex 2001/06/08 14:40:28 1.7 --- libdoctest.tex 2001/06/11 14:55:01 1.8 *************** *** 407,416 **** Simple fractions are also easier for people to understand, and that makes for better documentation. - \end{enumerate} \item Be careful if you have code that must only execute once. If you have module-level code that must only execute once, a more foolproof ! definition of \function{_test} is \begin{verbatim} --- 407,415 ---- Simple fractions are also easier for people to understand, and that makes for better documentation. \item Be careful if you have code that must only execute once. If you have module-level code that must only execute once, a more foolproof ! definition of \function{_test()} is \begin{verbatim} *************** *** 419,422 **** --- 418,423 ---- doctest.testmod(sys.modules["__main__"]) \end{verbatim} + \end{enumerate} + \subsection{Soapbox} From fdrake@users.sourceforge.net Mon Jun 11 15:57:09 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 11 Jun 2001 07:57:09 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libdoctest.tex,1.6,1.6.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv28910 Modified Files: Tag: release21-maint libdoctest.tex Log Message: Merge in recent changes from development branch: add warning about being sure that code only runs once when using the module as both a module and a script. Index: libdoctest.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libdoctest.tex,v retrieving revision 1.6 retrieving revision 1.6.2.1 diff -C2 -r1.6 -r1.6.2.1 *** libdoctest.tex 2001/04/05 18:31:27 1.6 --- libdoctest.tex 2001/06/11 14:57:07 1.6.2.1 *************** *** 407,410 **** --- 407,421 ---- Simple fractions are also easier for people to understand, and that makes for better documentation. + + \item Be careful if you have code that must only execute once. + + If you have module-level code that must only execute once, a more foolproof + definition of \function{_test()} is + + \begin{verbatim} + def _test(): + import doctest, sys + doctest.testmod(sys.modules["__main__"]) + \end{verbatim} \end{enumerate} From twouters@users.sourceforge.net Mon Jun 11 16:21:45 2001 From: twouters@users.sourceforge.net (Thomas Wouters) Date: Mon, 11 Jun 2001 08:21:45 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules termios.c,2.24.2.2,2.24.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv2209/Modules Modified Files: Tag: release21-maint termios.c Log Message: Protect the use of the VWERASE symbol by an #ifdef, it's apparently missing on (some versions of ?) AIX. Index: termios.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/termios.c,v retrieving revision 2.24.2.2 retrieving revision 2.24.2.3 diff -C2 -r2.24.2.2 -r2.24.2.3 *** termios.c 2001/05/23 11:32:06 2.24.2.2 --- termios.c 2001/06/11 15:21:43 2.24.2.3 *************** *** 543,547 **** --- 543,549 ---- {"VDISCARD", VDISCARD}, #endif + #ifdef VWERASE {"VWERASE", VWERASE}, + #endif {"VLNEXT", VLNEXT}, {"VEOL2", VEOL2}, From fdrake@users.sourceforge.net Mon Jun 11 16:21:50 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 11 Jun 2001 08:21:50 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libos.tex,1.56,1.57 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv2313/lib Modified Files: libos.tex Log Message: Fixed parameter order for os.popen2(), os.popen3(), and os.popen(4). Added a reference to these functions and popen() from the "Process Management" section. Based on a suggestion from comp.lang.python. Index: libos.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libos.tex,v retrieving revision 1.56 retrieving revision 1.57 diff -C2 -r1.56 -r1.57 *** libos.tex 2001/06/04 15:31:17 1.56 --- libos.tex 2001/06/11 15:21:48 1.57 *************** *** 315,319 **** for \var{mode} is \code{'t'}. ! \begin{funcdesc}{popen2}{cmd\optional{, bufsize\optional{, mode}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout})}. --- 315,319 ---- for \var{mode} is \code{'t'}. ! \begin{funcdesc}{popen2}{cmd\optional{, mode\optional{, bufsize}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout})}. *************** *** 321,325 **** \end{funcdesc} ! \begin{funcdesc}{popen3}{cmd\optional{, bufsize\optional{, mode}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout}, \var{child_stderr})}. --- 321,325 ---- \end{funcdesc} ! \begin{funcdesc}{popen3}{cmd\optional{, mode\optional{, bufsize}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout}, \var{child_stderr})}. *************** *** 327,331 **** \end{funcdesc} ! \begin{funcdesc}{popen4}{cmd\optional{, bufsize\optional{, mode}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout_and_stderr})}. --- 327,331 ---- \end{funcdesc} ! \begin{funcdesc}{popen4}{cmd\optional{, mode\optional{, bufsize}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout_and_stderr})}. *************** *** 928,931 **** --- 928,939 ---- Availability: \UNIX{}. \end{funcdesc} + + \begin{funcdescni}{popen}{\unspecified} + \funclineni{popen2}{\unspecified} + \funclineni{popen3}{\unspecified} + \funclineni{popen4}{\unspecified} + Run child processes, returning opened pipes for communications. These + functions are described in section \ref{os-newstreams}. + \end{funcdescni} \begin{funcdesc}{spawnv}{mode, path, args} From fdrake@users.sourceforge.net Mon Jun 11 16:22:25 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 11 Jun 2001 08:22:25 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libos.tex,1.53.4.3,1.53.4.4 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv2493/lib Modified Files: Tag: release21-maint libos.tex Log Message: Fixed parameter order for os.popen2(), os.popen3(), and os.popen(4). Added a reference to these functions and popen() from the "Process Management" section. Based on a suggestion from comp.lang.python. Index: libos.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libos.tex,v retrieving revision 1.53.4.3 retrieving revision 1.53.4.4 diff -C2 -r1.53.4.3 -r1.53.4.4 *** libos.tex 2001/06/04 15:30:41 1.53.4.3 --- libos.tex 2001/06/11 15:22:23 1.53.4.4 *************** *** 315,319 **** for \var{mode} is \code{'t'}. ! \begin{funcdesc}{popen2}{cmd\optional{, bufsize\optional{, mode}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout})}. --- 315,319 ---- for \var{mode} is \code{'t'}. ! \begin{funcdesc}{popen2}{cmd\optional{, mode\optional{, bufsize}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout})}. *************** *** 321,325 **** \end{funcdesc} ! \begin{funcdesc}{popen3}{cmd\optional{, bufsize\optional{, mode}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout}, \var{child_stderr})}. --- 321,325 ---- \end{funcdesc} ! \begin{funcdesc}{popen3}{cmd\optional{, mode\optional{, bufsize}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout}, \var{child_stderr})}. *************** *** 327,331 **** \end{funcdesc} ! \begin{funcdesc}{popen4}{cmd\optional{, bufsize\optional{, mode}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout_and_stderr})}. --- 327,331 ---- \end{funcdesc} ! \begin{funcdesc}{popen4}{cmd\optional{, mode\optional{, bufsize}}} Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout_and_stderr})}. *************** *** 928,931 **** --- 928,939 ---- Availability: \UNIX{}. \end{funcdesc} + + \begin{funcdescni}{popen}{\unspecified} + \funclineni{popen2}{\unspecified} + \funclineni{popen3}{\unspecified} + \funclineni{popen4}{\unspecified} + Run child processes, returning opened pipes for communications. These + functions are described in section \ref{os-newstreams}. + \end{funcdescni} \begin{funcdesc}{spawnv}{mode, path, args} From twouters@users.sourceforge.net Mon Jun 11 16:25:18 2001 From: twouters@users.sourceforge.net (Thomas Wouters) Date: Mon, 11 Jun 2001 08:25:18 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules termios.c,2.29,2.30 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv3523/Modules Modified Files: termios.c Log Message: Protect the use of the VWERASE symbol by an #ifdef, it's apparently missing on (some versions of ?) AIX. Index: termios.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/termios.c,v retrieving revision 2.29 retrieving revision 2.30 diff -C2 -r2.29 -r2.30 *** termios.c 2001/05/22 15:44:15 2.29 --- termios.c 2001/06/11 15:25:16 2.30 *************** *** 543,547 **** --- 543,549 ---- {"VDISCARD", VDISCARD}, #endif + #ifdef VWERASE {"VWERASE", VWERASE}, + #endif {"VLNEXT", VLNEXT}, {"VEOL2", VEOL2}, From gvanrossum@users.sourceforge.net Mon Jun 11 16:29:55 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 11 Jun 2001 08:29:55 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.36,2.16.8.37 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv4951 Modified Files: Tag: descr-branch typeobject.c Log Message: More random modifications. Take away the default slots from object again; these were inherited by all other standard types, and that's not right (it was suddenly possible to create and subclass e.g. int, but the resulting objects were time bombs). Instead, type_new() provides some default slots to qualifying derived types. I have yet to develop a theory for this. Some things I'm happier with: best_base(): initialize the bases if needed. type_init(): refuse to re-initialize a previously initialized type object (there's too much damage it could do). type_new(): rename the first argument to metatype, which it is. Implement type_getattro() (the metatype's tp_getattro slot) as a wrapper around PyObject_GenericGetAttr() that initializes the type object first if it has to. Implement type_alloc() (the metatype's tp_alloc slot) as a wrapper around PyType_GenericAlloc() that sets tp_flags correctly, so we don't have to wave our hands so much in type_dealloc(). Inherit tp_getattr and tp_getattro as a pair; ditto for tp_setattr[o]; ditto for tp_compare and tp_richcompare (the latter conditional on Py_TPFLAGS_HAVE_RICHCOMPARE). Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.36 retrieving revision 2.16.8.37 diff -C2 -r2.16.8.36 -r2.16.8.37 *** typeobject.c 2001/06/07 19:14:45 2.16.8.36 --- typeobject.c 2001/06/11 15:29:53 2.16.8.37 *************** *** 295,298 **** --- 295,302 ---- return NULL; } + if (base_i->tp_dict == NULL) { + if (PyType_InitDict(base_i) < 0) + return NULL; + } candidate = solid_base(base_i); if (issubtype(winner, candidate)) *************** *** 316,319 **** --- 320,326 ---- /* TypeType's initializer; called when a type is subclassed */ + staticforward void object_dealloc(PyObject *); + staticforward int object_init(PyObject *, PyObject *, PyObject *); + static int type_init(PyObject *self, PyObject *args, PyObject *kwds) *************** *** 329,332 **** --- 336,346 ---- type = (PyTypeObject *)self; + /* Check this is a virginal type object */ + if (type->tp_dict != NULL) { + PyErr_SetString(PyExc_TypeError, + "can't re-initialize type objects"); + return -1; + } + /* Check arguments */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO:type", kwlist, *************** *** 335,339 **** if (!PyTuple_Check(bases) || !PyDict_Check(dict)) { PyErr_SetString(PyExc_TypeError, ! "usage: TypeType(name, bases, dict) "); return -1; } --- 349,353 ---- if (!PyTuple_Check(bases) || !PyDict_Check(dict)) { PyErr_SetString(PyExc_TypeError, ! "usage: type(name, bases, dict) "); return -1; } *************** *** 354,358 **** if (base == NULL) return -1; ! if (base->tp_init == NULL) { PyErr_SetString(PyExc_TypeError, "base type must have a constructor slot"); --- 368,372 ---- if (base == NULL) return -1; ! if (base->tp_init == NULL && base != &PyBaseObject_Type) { PyErr_SetString(PyExc_TypeError, "base type must have a constructor slot"); *************** *** 366,369 **** --- 380,384 ---- /* Check for a __slots__ sequence variable in dict, and count it */ + /* XXX This should move to type_alloc() */ slots = PyDict_GetItemString(dict, "__slots__"); nslots = 0; *************** *** 411,428 **** type->tp_as_buffer = &et->as_buffer; type->tp_name = PyString_AS_STRING(name); - type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE; - /* Override some slots with specific requirements */ - if (type->tp_dealloc) - type->tp_dealloc = subtype_dealloc; - if (type->tp_getattro == NULL) { - type->tp_getattro = PyObject_GenericGetAttr; - type->tp_getattr = NULL; - } - if (type->tp_setattro == NULL) { - type->tp_setattro = PyObject_GenericSetAttr; - type->tp_setattr = NULL; - } - /* Initialize tp_introduced from passed-in dict */ type->tp_introduced = dict = PyDict_Copy(dict); --- 426,430 ---- *************** *** 454,459 **** type->tp_basicsize = slotoffset; add_members(type, et->members); ! /* Initialize tp_bases, tp_dict, tp_introduced; inherit slots */ if (PyType_InitDict(type) < 0) return -1; --- 456,479 ---- type->tp_basicsize = slotoffset; add_members(type, et->members); + + /* Special case some slots */ + if (type->tp_dictoffset != 0) { + if (base->tp_getattr == NULL && base->tp_getattro == NULL) + type->tp_getattro = PyObject_GenericGetAttr; + if (base->tp_setattr == NULL && base->tp_setattro == NULL) + type->tp_setattro = PyObject_GenericSetAttr; + } + if (base->tp_dealloc == NULL) + type->tp_dealloc = object_dealloc; + else + type->tp_dealloc = subtype_dealloc; + if (base->tp_new == NULL) + type->tp_new = PyType_GenericNew; + if (base->tp_alloc == NULL) + type->tp_alloc = PyType_GenericAlloc; + if (base->tp_init == NULL) + type->tp_init = object_init; ! /* Initialize the rest */ if (PyType_InitDict(type) < 0) return -1; *************** *** 506,511 **** } static PyObject * ! type_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *name, *bases, *dict; --- 526,548 ---- } + static PyObject * + type_alloc(PyTypeObject *metatype, PyObject *args, PyObject *kwds) + { + PyTypeObject *type; + PyObject *name, *bases, *dict; + static char *kwlist[] = {"name", "bases", "dict", 0}; + + /* Check arguments (again?!?! yes, alas -- we need the dict!) */ + if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO:type", kwlist, + &name, &bases, &dict)) + return NULL; + type = (PyTypeObject *)PyType_GenericAlloc(metatype, args, kwds); + if (type != NULL) + type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE; + return (PyObject *)type; + } + static PyObject * ! type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) { PyObject *name, *bases, *dict; *************** *** 525,529 **** return NULL; if (PyTuple_Check(bases)) { - PyTypeObject *metatype = type; int i, n; n = PyTuple_GET_SIZE(bases); --- 562,565 ---- *************** *** 542,550 **** } if (metatype->tp_new != type_new) ! return metatype->tp_new(type, args, kwds); } ! return PyType_GenericNew(type, args, kwds); } static void type_dealloc(PyTypeObject *type) --- 578,596 ---- } if (metatype->tp_new != type_new) ! return metatype->tp_new(metatype, args, kwds); } ! return PyType_GenericNew(metatype, args, kwds); } + static PyObject * + type_getattro(PyTypeObject *type, PyObject *name) + { + if (type->tp_dict == NULL) { + if (PyType_InitDict(type) < 0) + return NULL; + } + return PyObject_GenericGetAttr((PyObject *)type, name); + } + static void type_dealloc(PyTypeObject *type) *************** *** 552,558 **** etype *et; ! /* Assert this is a heap-allocated type object, or uninitialized */ ! if (type->tp_flags != 0) ! assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE); et = (etype *)type; Py_XDECREF(type->tp_base); --- 598,603 ---- etype *et; ! /* Assert this is a heap-allocated type object */ ! assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE); et = (etype *)type; Py_XDECREF(type->tp_base); *************** *** 586,590 **** (ternaryfunc)type_call, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 631,635 ---- (ternaryfunc)type_call, /* tp_call */ 0, /* tp_str */ ! (getattrofunc)type_getattro, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ *************** *** 606,610 **** offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ type_init, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ type_new, /* tp_new */ }; --- 651,655 ---- offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ type_init, /* tp_init */ ! type_alloc, /* tp_alloc */ type_new, /* tp_new */ }; *************** *** 613,616 **** --- 658,667 ---- /* The base type of all types (eventually)... except itself. */ + static int + object_init(PyObject *self, PyObject *args, PyObject *kwds) + { + return 0; + } + static void object_dealloc(PyObject *self) *************** *** 624,633 **** }; - static int - object_init(PyObject *self, PyObject *args, PyObject *kwds) - { - return 0; - } - PyTypeObject PyBaseObject_Type = { PyObject_HEAD_INIT(&PyType_Type) --- 675,678 ---- *************** *** 636,640 **** sizeof(PyObject), /* tp_basicsize */ 0, /* tp_itemsize */ ! (destructor)object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ --- 681,685 ---- sizeof(PyObject), /* tp_basicsize */ 0, /* tp_itemsize */ ! 0/*(destructor)object_dealloc*/, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ *************** *** 648,652 **** 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 693,697 ---- 0, /* tp_call */ 0, /* tp_str */ ! 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ *************** *** 667,673 **** 0, /* tp_descr_set */ 0, /* tp_dictoffset */ ! object_init, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ ! PyType_GenericNew, /* tp_new */ }; --- 712,718 ---- 0, /* tp_descr_set */ 0, /* tp_dictoffset */ ! 0, /* tp_init */ ! 0, /* tp_alloc */ ! 0, /* tp_new */ }; *************** *** 885,902 **** COPYSLOT(tp_dealloc); COPYSLOT(tp_print); ! COPYSLOT(tp_getattr); ! COPYSLOT(tp_setattr); ! COPYSLOT(tp_compare); COPYSLOT(tp_repr); COPYSLOT(tp_hash); COPYSLOT(tp_call); COPYSLOT(tp_str); - COPYSLOT(tp_getattro); - COPYSLOT(tp_setattro); COPYSLOT(tp_as_buffer); COPYSLOT(tp_flags); COPYSLOT(tp_doc); if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE) { ! COPYSLOT(tp_richcompare); } if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_WEAKREFS) { --- 930,957 ---- COPYSLOT(tp_dealloc); COPYSLOT(tp_print); ! if (type->tp_getattr == NULL && type->tp_getattro == NULL) { ! type->tp_getattr = base->tp_getattr; ! type->tp_getattro = base->tp_getattro; ! } ! if (type->tp_setattr == NULL && type->tp_setattro == NULL) { ! type->tp_setattr = base->tp_setattr; ! type->tp_setattro = base->tp_setattro; ! } ! /* tp_compare see tp_richcompare */ COPYSLOT(tp_repr); COPYSLOT(tp_hash); COPYSLOT(tp_call); COPYSLOT(tp_str); COPYSLOT(tp_as_buffer); COPYSLOT(tp_flags); COPYSLOT(tp_doc); if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE) { ! if (type->tp_compare == NULL && type->tp_richcompare == NULL) { ! type->tp_compare = base->tp_compare; ! type->tp_richcompare = base->tp_richcompare; ! } ! } ! else { ! COPYSLOT(tp_compare); } if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_WEAKREFS) { From tim_one@users.sourceforge.net Mon Jun 11 17:45:35 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Jun 2001 09:45:35 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules structmodule.c,2.43,2.44 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv23133/python/dist/src/Modules Modified Files: structmodule.c Log Message: Make clear in the docstring that "std" applies to both size and alignment, not just to alignment. Spotted by Guido. Bugfix candidate. Index: structmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/structmodule.c,v retrieving revision 2.43 retrieving revision 2.44 diff -C2 -r2.43 -r2.44 *** structmodule.c 2001/06/10 23:40:19 2.43 --- structmodule.c 2001/06/11 16:45:33 2.44 *************** *** 10,19 **** and also as format strings to describe the layout of data in the C struct.\n\ \n\ ! The optional first format char indicates byte ordering and alignment:\n\ ! @: native w/native alignment(default)\n\ ! =: native w/standard alignment\n\ ! <: little-endian, std. alignment\n\ ! >: big-endian, std. alignment\n\ ! !: network, std (same as >)\n\ \n\ The remaining chars indicate types of args and must match exactly;\n\ --- 10,19 ---- and also as format strings to describe the layout of data in the C struct.\n\ \n\ ! The optional first format char indicates byte order, size and alignment:\n\ ! @: native order, size & alignment (default)\n\ ! =: native order, std. size & alignment\n\ ! <: little-endian, std. size & alignment\n\ ! >: big-endian, std. size & alignment\n\ ! !: same as >\n\ \n\ The remaining chars indicate types of args and must match exactly;\n\ From tim_one@users.sourceforge.net Mon Jun 11 17:51:58 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Jun 2001 09:51:58 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules structmodule.c,2.44,2.45 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv24678/python/dist/src/Modules Modified Files: structmodule.c Log Message: Simplify some convolution by simply not recognizing 'q' and 'Q' at all in native mode on platforms that don't HAVE_LONG_LONG. Index: structmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/structmodule.c,v retrieving revision 2.44 retrieving revision 2.45 diff -C2 -r2.44 -r2.45 *** structmodule.c 2001/06/11 16:45:33 2.44 --- structmodule.c 2001/06/11 16:51:56 2.45 *************** *** 73,81 **** typedef struct { char c; LONG_LONG x; } s_long_long; #define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(LONG_LONG)) - - #else - static char qQ_error_msg[] = - "q and Q unavailable in native mode on this platform; use a standard mode.\0"; - #endif --- 73,76 ---- *************** *** 579,592 **** return PyLong_FromUnsignedLongLong(*(unsigned LONG_LONG *)p); } - - #else - - static PyObject * - nu_qQerror(const char *p, const formatdef *f) - { - PyErr_SetString(StructError, qQ_error_msg); - return NULL; - } - #endif --- 574,577 ---- *************** *** 747,760 **** return 0; } - - #else - - static int - np_qQerror(char *p, PyObject *v, const formatdef *f) - { - PyErr_SetString(StructError, qQ_error_msg); - return -1; - } - #endif --- 732,735 ---- *************** *** 819,830 **** {'q', sizeof(LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong}, {'Q', sizeof(LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong}, - #else - /* n[pu]_qQerror just raise errors, but give them "the expected" size - and alignment anyway so that calcsize returns something reasonable, - and so unpack code that works on a 'long long' platform ends up in - the error routine instead of with a mysterious "unpack str size - does not match format" msg when run on a non-'long long' box. */ - {'q', 8, 8, nu_qQerror, np_qQerror}, - {'Q', 8, 8, nu_qQerror, np_qQerror}, #endif {0} --- 794,797 ---- From tim_one@users.sourceforge.net Mon Jun 11 17:57:35 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Jun 2001 09:57:35 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules structmodule.c,2.45,2.46 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv25882/python/dist/src/Modules Modified Files: structmodule.c Log Message: Trimmed trailing whitespace. Index: structmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/structmodule.c,v retrieving revision 2.45 retrieving revision 2.46 diff -C2 -r2.45 -r2.46 *** structmodule.c 2001/06/11 16:51:56 2.45 --- structmodule.c 2001/06/11 16:57:33 2.46 *************** *** 47,51 **** /* ** XXXX We have a problem here. There are no unique alignment rules ! ** on the PowerPC mac. */ #ifdef __powerc --- 47,51 ---- /* ** XXXX We have a problem here. There are no unique alignment rules ! ** on the PowerPC mac. */ #ifdef __powerc *************** *** 1113,1117 **** else num = 1; ! e = getentry(c, f); if (e == NULL) --- 1113,1117 ---- else num = 1; ! e = getentry(c, f); if (e == NULL) *************** *** 1173,1177 **** (n = PyTuple_Size(args)) < 1) { ! PyErr_SetString(PyExc_TypeError, "struct.pack requires at least one argument"); return NULL; --- 1173,1177 ---- (n = PyTuple_Size(args)) < 1) { ! PyErr_SetString(PyExc_TypeError, "struct.pack requires at least one argument"); return NULL; From fdrake@users.sourceforge.net Mon Jun 11 19:25:36 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 11 Jun 2001 11:25:36 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libos.tex,1.57,1.58 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv11909/lib Modified Files: libos.tex Log Message: Add the appropriate availability annotations for the popen*() family of functions -- these are not available on traditional Mac OS platforms. Corrected the version annotations for the spawn*() functions and related constants; these were added in Python 1.6, not 1.5.2. Index: libos.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libos.tex,v retrieving revision 1.57 retrieving revision 1.58 diff -C2 -r1.57 -r1.58 *** libos.tex 2001/06/11 15:21:48 1.57 --- libos.tex 2001/06/11 18:25:34 1.58 *************** *** 318,321 **** --- 318,322 ---- Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout})}. + Availability: \UNIX{}, Windows. \versionadded{2.0} \end{funcdesc} *************** *** 324,327 **** --- 325,329 ---- Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout}, \var{child_stderr})}. + Availability: \UNIX{}, Windows. \versionadded{2.0} \end{funcdesc} *************** *** 330,333 **** --- 332,336 ---- Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout_and_stderr})}. + Availability: \UNIX{}, Windows. \versionadded{2.0} \end{funcdesc} *************** *** 945,949 **** listed below. Availability: \UNIX{}, Windows. ! \versionadded{1.5.2} \end{funcdesc} --- 948,952 ---- listed below. Availability: \UNIX{}, Windows. ! \versionadded{1.6} \end{funcdesc} *************** *** 956,960 **** constants are exposed to the Python programmer as listed below. Availability: \UNIX{}, Windows. ! \versionadded{1.5.2} \end{funcdesc} --- 959,963 ---- constants are exposed to the Python programmer as listed below. Availability: \UNIX{}, Windows. ! \versionadded{1.6} \end{funcdesc} *************** *** 965,969 **** and \function{spawnve()}. Availability: \UNIX{}, Windows. ! \versionadded{1.5.2} \end{datadesc} --- 968,972 ---- and \function{spawnve()}. Availability: \UNIX{}, Windows. ! \versionadded{1.6} \end{datadesc} *************** *** 974,978 **** above. Availability: Windows. ! \versionadded{1.5.2} \end{datadesc} --- 977,981 ---- above. Availability: Windows. ! \versionadded{1.6} \end{datadesc} From fdrake@users.sourceforge.net Mon Jun 11 19:26:07 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 11 Jun 2001 11:26:07 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libos.tex,1.53.4.4,1.53.4.5 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv12038/lib Modified Files: Tag: release21-maint libos.tex Log Message: Add the appropriate availability annotations for the popen*() family of functions -- these are not available on traditional Mac OS platforms. Corrected the version annotations for the spawn*() functions and related constants; these were added in Python 1.6, not 1.5.2. Index: libos.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libos.tex,v retrieving revision 1.53.4.4 retrieving revision 1.53.4.5 diff -C2 -r1.53.4.4 -r1.53.4.5 *** libos.tex 2001/06/11 15:22:23 1.53.4.4 --- libos.tex 2001/06/11 18:26:04 1.53.4.5 *************** *** 318,321 **** --- 318,322 ---- Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout})}. + Availability: \UNIX{}, Windows. \versionadded{2.0} \end{funcdesc} *************** *** 324,327 **** --- 325,329 ---- Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout}, \var{child_stderr})}. + Availability: \UNIX{}, Windows. \versionadded{2.0} \end{funcdesc} *************** *** 330,333 **** --- 332,336 ---- Executes \var{cmd} as a sub-process. Returns the file objects \code{(\var{child_stdin}, \var{child_stdout_and_stderr})}. + Availability: \UNIX{}, Windows. \versionadded{2.0} \end{funcdesc} *************** *** 945,949 **** listed below. Availability: \UNIX{}, Windows. ! \versionadded{1.5.2} \end{funcdesc} --- 948,952 ---- listed below. Availability: \UNIX{}, Windows. ! \versionadded{1.6} \end{funcdesc} *************** *** 956,960 **** constants are exposed to the Python programmer as listed below. Availability: \UNIX{}, Windows. ! \versionadded{1.5.2} \end{funcdesc} --- 959,963 ---- constants are exposed to the Python programmer as listed below. Availability: \UNIX{}, Windows. ! \versionadded{1.6} \end{funcdesc} *************** *** 965,969 **** and \function{spawnve()}. Availability: \UNIX{}, Windows. ! \versionadded{1.5.2} \end{datadesc} --- 968,972 ---- and \function{spawnve()}. Availability: \UNIX{}, Windows. ! \versionadded{1.6} \end{datadesc} *************** *** 974,978 **** above. Availability: Windows. ! \versionadded{1.5.2} \end{datadesc} --- 977,981 ---- above. Availability: Windows. ! \versionadded{1.6} \end{datadesc} From gvanrossum@users.sourceforge.net Mon Jun 11 19:40:40 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 11 Jun 2001 11:40:40 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects frameobject.c,2.49.4.3,2.49.4.4 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv14923 Modified Files: Tag: descr-branch frameobject.c Log Message: By mistake there were two definitions for f_locals: a simple descriptor in the list of members, and a getter function. Recent changes in typeobject.c changed the precedence between these, and the one from the memberlist took precedence. But it's bogus, so get rid of it. (This caused test_inspect.py to fail.) Index: frameobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/frameobject.c,v retrieving revision 2.49.4.3 retrieving revision 2.49.4.4 diff -C2 -r2.49.4.3 -r2.49.4.4 *** frameobject.c 2001/06/06 14:27:54 2.49.4.3 --- frameobject.c 2001/06/11 18:40:38 2.49.4.4 *************** *** 16,20 **** {"f_builtins", T_OBJECT, OFF(f_builtins),RO}, {"f_globals", T_OBJECT, OFF(f_globals), RO}, - {"f_locals", T_OBJECT, OFF(f_locals), RO}, {"f_lasti", T_INT, OFF(f_lasti), RO}, {"f_lineno", T_INT, OFF(f_lineno), RO}, --- 16,19 ---- From gvanrossum@users.sourceforge.net Mon Jun 11 19:45:12 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 11 Jun 2001 11:45:12 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.37,2.16.8.38 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv16077 Modified Files: Tag: descr-branch typeobject.c Log Message: The wrapper function for tp_iternext can't be wrap_unaryfunc, because the tp_iternext slot doesn't always set the exception. Fix this by adding a custom wrapper, wrap_next(). Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.37 retrieving revision 2.16.8.38 diff -C2 -r2.16.8.37 -r2.16.8.38 *** typeobject.c 2001/06/11 15:29:53 2.16.8.37 --- typeobject.c 2001/06/11 18:45:10 2.16.8.38 *************** *** 1540,1545 **** }; static struct wrapperbase tab_next[] = { ! {"next", (wrapperfunc)wrap_unaryfunc, "x.next() -> next value"}, {0} }; --- 1540,1559 ---- }; + static PyObject * + wrap_next(PyObject *self, PyObject *args, void *wrapped) + { + unaryfunc func = (unaryfunc)wrapped; + PyObject *res; + + if (!PyArg_ParseTuple(args, "")) + return NULL; + res = (*func)(self); + if (res == NULL && !PyErr_Occurred()) + PyErr_SetNone(PyExc_StopIteration); + return res; + } + static struct wrapperbase tab_next[] = { ! {"next", (wrapperfunc)wrap_next, "x.next() -> next value"}, {0} }; From gvanrossum@users.sourceforge.net Mon Jun 11 20:05:30 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 11 Jun 2001 12:05:30 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_iter.py,1.2,1.2.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv20536 Modified Files: Tag: descr-branch test_iter.py Log Message: Add test_builtin_list() to test that list() of an iterator works. Index: test_iter.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_iter.py,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -C2 -r1.2 -r1.2.2.1 *** test_iter.py 2001/04/21 13:33:54 1.2 --- test_iter.py 2001/06/11 19:05:28 1.2.2.1 *************** *** 244,246 **** --- 244,278 ---- pass + # Test list()'s use of iterators. + def test_builtin_list(self): + self.assertEqual(list(SequenceClass(5)), range(5)) + self.assertEqual(list(SequenceClass(0)), []) + self.assertEqual(list(()), []) + self.assertEqual(list(range(10, -1, -1)), range(10, -1, -1)) + + d = {"one": 1, "two": 2, "three": 3} + self.assertEqual(list(d), d.keys()) + + self.assertRaises(TypeError, list, list) + self.assertRaises(TypeError, list, 42) + + f = open(TESTFN, "w") + try: + for i in range(5): + f.write("%d\n" % i) + finally: + f.close() + f = open(TESTFN, "r") + try: + self.assertEqual(list(f), ["0\n", "1\n", "2\n", "3\n", "4\n"]) + f.seek(0, 0) + self.assertEqual(list(f.xreadlines()), + ["0\n", "1\n", "2\n", "3\n", "4\n"]) + finally: + f.close() + try: + unlink(TESTFN) + except OSError: + pass + run_unittest(TestCase) From gvanrossum@users.sourceforge.net Mon Jun 11 20:06:46 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 11 Jun 2001 12:06:46 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects listobject.c,2.92.6.7,2.92.6.8 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv20784 Modified Files: Tag: descr-branch listobject.c Log Message: list_fill(): initialize the list items after NRESIZE. I would have fixed this sooner had I adopted the additional test in test_iter.py sooner. Index: listobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v retrieving revision 2.92.6.7 retrieving revision 2.92.6.8 diff -C2 -r2.92.6.7 -r2.92.6.8 *** listobject.c 2001/06/06 17:34:14 2.92.6.7 --- listobject.c 2001/06/11 19:06:44 2.92.6.8 *************** *** 1541,1544 **** --- 1541,1546 ---- if (result->ob_item == NULL) goto error; + for (i = 0; i < n; i++) + result->ob_item[i] = NULL; result->ob_size = n; From gvanrossum@users.sourceforge.net Mon Jun 11 20:09:48 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 11 Jun 2001 12:09:48 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects abstract.c,2.60.2.3,2.60.2.4 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv21434 Modified Files: Tag: descr-branch abstract.c Log Message: PyIter_Next(): adopt Tim's improvement, which clears the exception if it was a StopIteration. This is needed by list_fill() in listobject.c. (I have no test to prove it, but it's clear from the code of list_fill() that it makes the assumption that any exception is an error.) Index: abstract.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v retrieving revision 2.60.2.3 retrieving revision 2.60.2.4 diff -C2 -r2.60.2.3 -r2.60.2.4 *** abstract.c 2001/06/06 17:59:41 2.60.2.3 --- abstract.c 2001/06/11 19:09:46 2.60.2.4 *************** *** 1742,1748 **** --- 1742,1756 ---- } + /* 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; if (!PyIter_Check(iter)) { PyErr_Format(PyExc_TypeError, *************** *** 1751,1754 **** return NULL; } ! return (*iter->ob_type->tp_iternext)(iter); } --- 1759,1767 ---- return NULL; } ! result = (*iter->ob_type->tp_iternext)(iter); ! if (result == NULL && ! PyErr_Occurred() && ! PyErr_ExceptionMatches(PyExc_StopIteration)) ! PyErr_Clear(); ! return result; } From gvanrossum@users.sourceforge.net Mon Jun 11 21:07:40 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 11 Jun 2001 13:07:40 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0259.txt,NONE,1.1 pep-0000.txt,1.95,1.96 pep-0253.txt,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv1958 Modified Files: pep-0000.txt pep-0253.txt Added Files: pep-0259.txt Log Message: PEP 259: Omit printing newline after newline --- NEW FILE: pep-0259.txt --- PEP: 259 Title: Omit printing newline after newline Version: $Revision: 1.1 $ Author: guido@python.org (Guido van Rossum) Status: Draft Type: Standards Track Python-Version: 2.2 Created: 11-Jun-2001 Post-History: 11-Jun-2001 Abstract Currently, the print statement always appends a newline, unless a trailing comma is used. This means that if we want to print data that already ends in a newline, we get two newlines, unless special precautions are taken. I propose to skip printing the newline when it follows a newline that came from data. In order to avoid having to add yet another magic variable to file objects, I propose to give the existing 'softspace' variable an extra meaning: a negative value will mean "the last data written ended in a newline so no space *or* newline is required." Problem When printing data that resembles the lines read from a file using a simple loop, double-spacing occurs unless special care is taken: >>> for line in open("/etc/passwd").readlines(): ... print line ... root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin: daemon:x:2:2:daemon:/sbin: (etc.) >>> While there are easy work-arounds, this is often noticed only during testing and requires an extra edit-test roundtrip; the fixed code is uglier and harder to maintain. Proposed Solution In the PRINT_ITEM opcode in ceval.c, when a string object is printed, a check is already made that looks at the last character of that string. Currently, if that last character is a whitespace character other than space, the softspace flag is reset to zero; this suppresses the space between two items if the first item is a string ending in newline, tab, etc. (but not when it ends in a space). Otherwise the softspace flag is set to one. The proposal changes this test slightly so that softspace is set to: -1 -- if the last object written is a string ending in a newline 0 -- if the last object written is a string ending in a whitespace character that's neither space nor newline 1 -- in all other cases (including the case when the last object written is an empty string or not a string) Then, the PRINT_NEWLINE opcode, printing of the newline is suppressed if the value of softspace is negative; in any case the softspace flag is reset to zero. Scope This only affects printing of 8-bit strings. It doesn't affect Unicode, although that could be considered a bug in the Unicode implementation. It doesn't affect other objects whose string representation happens to end in a newline character. Risks This change breaks some existing code. For example: print "Subject: PEP 259\n" print message_body In current Python, this produces a blank line separating the subject from the message body; with the proposed change, the body begins immediately below the subject. This is not very robust code anyway; it is better written as print "Subject: PEP 259" print print message_body In the test suite, only test_StringIO (which explicitly tests for this feature) breaks. Implementation A patch relative to current CVS is here: http://sourceforge.net/tracker/index.php?func=detail&aid=432183&group_id=5470&atid=305470 Copyright This document has been placed in the public domain. Local Variables: mode: indented-text indent-tabs-mode: nil End: Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.95 retrieving revision 1.96 diff -C2 -r1.95 -r1.96 *** pep-0000.txt 2001/06/06 05:56:34 1.95 --- pep-0000.txt 2001/06/11 20:07:37 1.96 *************** *** 61,64 **** --- 61,65 ---- S 257 pep-0257.txt Docstring Conventions Goodger S 258 pep-0258.txt DPS Generic Implementation Details Goodger + S 259 pep-0259.txt Omit printing newline after newline van Rossum Py-in-the-sky PEPs (not ready; may become active yet) *************** *** 185,188 **** --- 186,190 ---- S 257 pep-0257.txt Docstring Conventions Goodger S 258 pep-0258.txt DPS Generic Implementation Details Goodger + S 259 pep-0259.txt Omit printing newline after newline van Rossum Index: pep-0253.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0253.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -r1.2 -r1.3 *** pep-0253.txt 2001/05/15 01:36:46 1.2 --- pep-0253.txt 2001/06/11 20:07:37 1.3 *************** *** 35,51 **** Python types in C. ! This PEP will introduce the following optional features to types: ! - create an instance of a type by calling it ! - create a subtype in C by specifying a base type pointer ! - create a subtype in Python using a class statement ! - multiple inheritance ! This PEP builds on PEP 252, which adds standard introspection to types; in particular, types are assumed to have e.g. a __hash__ ! method when the type object defines the tp_hash slot. PEP 252 also adds a dictionary to type objects which contains all methods. At the Python level, this dictionary is read-only; at the C level, it --- 35,56 ---- Python types in C. ! This PEP will introduce the following features: ! - a type, like a class, can be a factory for its instances ! - types can be subtyped in C by specifying a base type pointer ! - types can be subtyped in Python using the class statement ! - multiple inheritance from types (insofar as practical) ! - the standard coercions (int, tuple, str etc.) will be the ! corresponding type objects ! ! - a standard type hierarchy ! ! This PEP builds on pep-0252, which adds standard introspection to types; in particular, types are assumed to have e.g. a __hash__ ! method when the type object defines the tp_hash slot. pep-0252 also adds a dictionary to type objects which contains all methods. At the Python level, this dictionary is read-only; at the C level, it *************** *** 77,86 **** instances (which are regular types) can be subclassed (really subtyped) using a Python class statement. We will use this rule ! to support subtyping of built-in types, and in the process we will ! introduce some additional metatypes, and a "metametatype". (The ! metametatype is nothing unusual; Python's type system allows any ! number of metalevels.) ! Note that Python uses the concept of metatypes or metaclasses in a different way than Smalltalk. In Smalltalk-80, there is a hierarchy of metaclasses that mirrors the hierarchy of regular --- 82,92 ---- instances (which are regular types) can be subclassed (really subtyped) using a Python class statement. We will use this rule ! to support subtyping of built-in types, and in fact it greatly ! simplifies the logic of class creation to always simply call the ! metatype. When no base class is specified, a default metatype is ! called -- the default metatype is the "ClassType" object, so the ! class statement will behave as before in the normal case. ! Python uses the concept of metatypes or metaclasses in a different way than Smalltalk. In Smalltalk-80, there is a hierarchy of metaclasses that mirrors the hierarchy of regular *************** *** 105,109 **** Traditionally, for each type there is at least one C function that ! creates instances of the type. This function has to take care of both allocating memory for the object and initializing that memory. As of Python 2.0, it also has to interface with the --- 111,116 ---- Traditionally, for each type there is at least one C function that ! creates instances of the type (e.g. PyInt_FromLong(), ! PyTuple_New() and so on). This function has to take care of both allocating memory for the object and initializing that memory. As of Python 2.0, it also has to interface with the *************** *** 128,149 **** which makes all types "callable" in a trivial sense. But obviously the metatype's tp_call implementation doesn't know how ! to initialize individual types. So the type defines a new slot, ! tp_construct, which is invoked by the metatype's tp_call slot. If ! the tp_construct slot is NULL, the metatype's tp_call issues a ! nice error message: the type isn't callable. ! ! We already know that tp_construct is responsible for initializing ! the object (this will be important for subtyping too). Who should ! be responsible for allocation of the new object? Either the ! metatype's tp_call can allocate the object, or the type's ! tp_construct can allocate it. The solution is copied from typical ! C++ implementations: if the metatype's tp_call allocates storage ! for the object it passes the storage as a pointer to the type's ! tp_construct; if the metatype's tp_call does not allocate storage, ! it passes a NULL pointer to the type's tp_call in which case the ! type allocates the storage itself. This moves the policy decision ! to the metatype, and different metatypes may have different ! policies. The mechanisms are fixed though: either the metatype's ! tp_call allocates storage, or the type's tp_construct allocates. The deallocation mechanism chosen should match the allocation --- 135,149 ---- which makes all types "callable" in a trivial sense. But obviously the metatype's tp_call implementation doesn't know how ! to initialize the instances of individual types. So the type ! defines a new slot, tp_new, which is invoked by the metatype's ! tp_call slot. If the tp_new slot is NULL, the metatype's tp_call ! issues a nice error message: the type isn't callable. ! ! This mechanism gives the maximum freedom to the type: a type's ! tp_new doesn't necessarily have to return a new object, or even an ! object that is an instance of the type (although the latter should ! be rare). ! ! HIRO The deallocation mechanism chosen should match the allocation *************** *** 280,284 **** subtype with the value of the corresponding base type slots. It also fills in tp_dict, the type's dictionary; this is more a ! matter of PEP 252. The subtype's tp_dealloc slot deserves special attention. It must --- 280,284 ---- subtype with the value of the corresponding base type slots. It also fills in tp_dict, the type's dictionary; this is more a ! matter of pep-0252. The subtype's tp_dealloc slot deserves special attention. It must *************** *** 330,334 **** every object has a type, B has a type. B's type is accessible via type(B) or B.__class__ (the latter notation is new for types; it ! is introduced in PEP 252). Let's say B's type is M (for Metatype). The class statement will create a new type, C. Since C will be a type object just like B, we view the creation of C as --- 330,334 ---- every object has a type, B has a type. B's type is accessible via type(B) or B.__class__ (the latter notation is new for types; it ! is introduced in pep-0252). Let's say B's type is M (for Metatype). The class statement will create a new type, C. Since C will be a type object just like B, we view the creation of C as *************** *** 372,375 **** --- 372,398 ---- tp_dict slot is updated with the contents of the namespace dictionary (the third argument to the call to M). + + + Implementation + + A prototype implementation of this PEP is available from CVS as a + branch named "descr-branch". To experiment with this + implementation, proceed to check out Python from CVS according to + the instructions at http://sourceforge.net/cvs/?group_id=5470 but + add the arguments "-r descr-branch" to the cvs checkout command. + (You can also start with an existing checkout and do "cvs update + -r descr-branch".) For some examples of the features described + here, see the file Lib/test/test_descr.py and the extension module + Modules/spam.c. + + Note: the code in this branch is for pep-0252, pep-0253, and + pep-254. + + + References + + [1] "Putting Metaclasses to Work", by Ira R. Forman and Scott + H. Danforth, Addison-Wesley 1999. + (http://www.aw.com/product/0,2627,0201433052,00.html) From gvanrossum@users.sourceforge.net Mon Jun 11 22:06:05 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 11 Jun 2001 14:06:05 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects intobject.c,2.56.6.3,2.56.6.4 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv14124/Objects Modified Files: Tag: descr-branch intobject.c Log Message: Another one bites the dust: built-in 'int' is now the integer type. (Still not subtypable though.) Index: intobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/intobject.c,v retrieving revision 2.56.6.3 retrieving revision 2.56.6.4 diff -C2 -r2.56.6.3 -r2.56.6.4 *** intobject.c 2001/06/06 14:27:54 2.56.6.3 --- intobject.c 2001/06/11 21:06:03 2.56.6.4 *************** *** 751,754 **** --- 751,788 ---- } + static PyObject * + int_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + PyObject *x = NULL; + int base = -909; + static char *kwlist[] = {"x", "base", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist, + &x, &base)) + return NULL; + if (x == NULL) + return PyInt_FromLong(0L); + if (base == -909) + return PyNumber_Int(x); + if (PyString_Check(x)) + return PyInt_FromString(PyString_AS_STRING(x), NULL, base); + if (PyUnicode_Check(x)) + return PyInt_FromUnicode(PyUnicode_AS_UNICODE(x), + PyUnicode_GET_SIZE(x), + base); + PyErr_SetString(PyExc_TypeError, + "int() can't convert non-string with explicit base"); + return NULL; + } + + static char int_doc[] = + "int(x[, base]) -> integer\n\ + \n\ + Convert a string or number to an integer, if possible. A floating point\n\ + argument will be truncated towards zero (this does not include a string\n\ + representation of a floating point number!) When converting a string, use\n\ + the optional base. It is an error to supply a base when converting a\n\ + non-string."; + static PyNumberMethods int_as_number = { (binaryfunc)int_add, /*nb_add*/ *************** *** 809,813 **** 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */ }; --- 843,865 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ ! int_doc, /* tp_doc */ ! 0, /* tp_traverse */ ! 0, /* tp_clear */ ! 0, /* tp_richcompare */ ! 0, /* tp_weaklistoffset */ ! 0, /* tp_iter */ ! 0, /* tp_iternext */ ! 0, /* tp_methods */ ! 0, /* tp_members */ ! 0, /* tp_getset */ ! 0, /* tp_base */ ! 0, /* tp_dict */ ! 0, /* tp_descr_get */ ! 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! 0, /* tp_init */ ! 0, /* tp_alloc */ ! int_new, /* tp_new */ }; From gvanrossum@users.sourceforge.net Mon Jun 11 22:06:05 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 11 Jun 2001 14:06:05 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python bltinmodule.c,2.198.2.1,2.198.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv14124/Python Modified Files: Tag: descr-branch bltinmodule.c Log Message: Another one bites the dust: built-in 'int' is now the integer type. (Still not subtypable though.) Index: bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.198.2.1 retrieving revision 2.198.2.2 diff -C2 -r2.198.2.1 -r2.198.2.2 *** bltinmodule.c 2001/06/06 17:43:42 2.198.2.1 --- bltinmodule.c 2001/06/11 21:06:03 2.198.2.2 *************** *** 1228,1264 **** static PyObject * - builtin_int(PyObject *self, PyObject *args) - { - PyObject *v; - int base = -909; /* unlikely! */ - - if (!PyArg_ParseTuple(args, "O|i:int", &v, &base)) - return NULL; - if (base == -909) - return PyNumber_Int(v); - else if (PyString_Check(v)) - return PyInt_FromString(PyString_AS_STRING(v), NULL, base); - else if (PyUnicode_Check(v)) - return PyInt_FromUnicode(PyUnicode_AS_UNICODE(v), - PyUnicode_GET_SIZE(v), - base); - else { - PyErr_SetString(PyExc_TypeError, - "int() can't convert non-string with explicit base"); - return NULL; - } - } - - static char int_doc[] = - "int(x[, base]) -> integer\n\ - \n\ - Convert a string or number to an integer, if possible. A floating point\n\ - argument will be truncated towards zero (this does not include a string\n\ - representation of a floating point number!) When converting a string, use\n\ - the optional base. It is an error to supply a base when converting a\n\ - non-string."; - - - static PyObject * builtin_long(PyObject *self, PyObject *args) { --- 1228,1231 ---- *************** *** 2138,2142 **** {"input", builtin_input, 1, input_doc}, {"intern", builtin_intern, 1, intern_doc}, - {"int", builtin_int, 1, int_doc}, {"isinstance", builtin_isinstance, 1, isinstance_doc}, {"issubclass", builtin_issubclass, 1, issubclass_doc}, --- 2105,2108 ---- *************** *** 2196,2199 **** --- 2162,2167 ---- return NULL; if (PyDict_SetItemString(dict, "list", (PyObject *) &PyList_Type) < 0) + return NULL; + if (PyDict_SetItemString(dict, "int", (PyObject *) &PyInt_Type) < 0) return NULL; if (PyDict_SetItemString(dict, "object", From tim_one@users.sourceforge.net Mon Jun 11 22:24:00 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Jun 2001 14:24:00 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include longobject.h,2.19,2.20 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv17866/python/dist/src/Include Modified Files: longobject.h Log Message: Two new private longobject API functions, _PyLong_FromByteArray _PyLong_AsByteArray Untested and probably buggy -- they compile OK, but nothing calls them yet. Will soon be called by the struct module, to implement x-platform 'q' and 'Q'. If other people have uses for them, we could move them into the public API. See longobject.h for usage details. Index: longobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/longobject.h,v retrieving revision 2.19 retrieving revision 2.20 diff -C2 -r2.19 -r2.20 *** longobject.h 2000/09/26 05:45:59 2.19 --- longobject.h 2001/06/11 21:23:58 2.20 *************** *** 45,48 **** --- 45,88 ---- DL_IMPORT(PyObject *) PyLong_FromUnicode(Py_UNICODE*, int, int); + /* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in + base 256, and return a Python long with the same numeric value. + If n is 0, the integer is 0. Else: + If little_endian is 1/true, bytes[n-1] is the MSB and bytes[0] the LSB; + else (little_endian is 0/false) bytes[0] is the MSB and bytes[n-1] the + LSB. + If is_signed is 0/false, view the bytes as a non-negative integer. + If is_signed is 1/true, view the bytes as a 2's-complement integer, + non-negative if bit 0x80 of the MSB is clear, negative if set. + Error returns: + + Return NULL with the appropriate exception set if there's not + enough memory to create the Python long. + */ + extern DL_IMPORT(PyObject *) _PyLong_FromByteArray( + const unsigned char* bytes, size_t n, + int little_endian, int is_signed); + + /* _PyLong_AsByteArray: Convert the least-significant 8*n bits of long + v to a base-256 integer, stored in array bytes. Normally return 0, + return -1 on error. + If little_endian is 1/true, store the MSB at bytes[n-1] and the LSB at + bytes[0]; else (little_endian is 0/false) store the MSB at bytes[0] and + the LSB at bytes[n-1]. + If is_signed is 0/false, it's an error if v < 0; else (v >= 0) n bytes + are filled and there's nothing special about bit 0x80 of the MSB. + If is_signed is 1/true, bytes is filled with the 2's-complement + representation of v's value. Bit 0x80 of the MSB is the sign bit. + Error returns (-1): + + is_signed is 0 and v < 0. TypeError is set in this case, and bytes + isn't altered. + + n isn't big enough to hold the full mathematical value of v. For + example, if is_signed is 0 and there are more digits in the v than + fit in n; or if is_signed is 1, v < 0, and n is just 1 bit shy of + being large enough to hold a sign bit. OverflowError is set in this + case, but bytes holds the least-signficant n bytes of the true value. + */ + extern DL_IMPORT(int) _PyLong_AsByteArray(PyLongObject* v, + unsigned char* bytes, size_t n, + int little_endian, int is_signed); + #ifdef __cplusplus } From tim_one@users.sourceforge.net Mon Jun 11 22:24:00 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Jun 2001 14:24:00 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.71,1.72 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv17866/python/dist/src/Objects Modified Files: longobject.c Log Message: Two new private longobject API functions, _PyLong_FromByteArray _PyLong_AsByteArray Untested and probably buggy -- they compile OK, but nothing calls them yet. Will soon be called by the struct module, to implement x-platform 'q' and 'Q'. If other people have uses for them, we could move them into the public API. See longobject.h for usage details. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.71 retrieving revision 1.72 diff -C2 -r1.71 -r1.72 *** longobject.c 2001/01/17 15:33:18 1.71 --- longobject.c 2001/06/11 21:23:58 1.72 *************** *** 212,215 **** --- 212,428 ---- } + PyObject * + _PyLong_FromByteArray(const unsigned char* bytes, size_t n, + int little_endian, int is_signed) + { + const unsigned char* pstartbyte;/* LSB of bytes */ + int incr; /* direction to move pstartbyte */ + const unsigned char* pendbyte; /* MSB of bytes */ + size_t numsignificantbytes; /* number of bytes that matter */ + size_t ndigits; /* number of Python long digits */ + PyLongObject* v; /* result */ + int idigit = 0; /* next free index in v->ob_digit */ + + if (n == 0) + return PyLong_FromLong(0L); + + if (little_endian) { + pstartbyte = bytes; + pendbyte = bytes + n - 1; + incr = 1; + } + else { + pstartbyte = bytes + n - 1; + pendbyte = bytes; + incr = -1; + } + + if (is_signed) + is_signed = *pendbyte >= 0x80; + + /* Compute numsignificantbytes. This consists of finding the most + significant byte. Leading 0 bytes are insignficant if the number + is positive, and leading 0xff bytes if negative. */ + { + size_t i; + const unsigned char* p = pendbyte; + const int pincr = -incr; /* search MSB to LSB */ + const unsigned char insignficant = is_signed ? 0xff : 0x00; + + for (i = 0; i < n; ++i, p += pincr) { + if (*p != insignficant) + break; + } + numsignificantbytes = n - i; + /* 2's-comp is a bit tricky here, e.g. 0xff00 == -0x0100, so + actually has 2 significant bytes. OTOH, 0xff0001 == + -0x00ffff, so we wouldn't *need* to bump it there; but we + do for 0xffff = -0x0001. To be safe without bothering to + check every case, bump it regardless. */ + if (is_signed && numsignificantbytes < n) + ++numsignificantbytes; + } + + /* How many Python long digits do we need? We have + 8*numsignificantbytes bits, and each Python long digit has SHIFT + bits, so it's the ceiling of the quotient. */ + ndigits = (numsignificantbytes * 8 + SHIFT - 1) / SHIFT; + if (ndigits > (size_t)INT_MAX) + return PyErr_NoMemory(); + v = _PyLong_New((int)ndigits); + if (v == NULL) + return NULL; + + /* Copy the bits over. The tricky parts are computing 2's-comp on + the fly for signed numbers, and dealing with the mismatch between + 8-bit bytes and (probably) 15-bit Python digits.*/ + { + size_t i; + unsigned int carry = 1; /* for 2's-comp calculation */ + twodigits accum = 0; /* sliding register */ + unsigned int accumbits = 0; /* number of bits in accum */ + const unsigned char* p = pstartbyte; + + for (i = 0; i < numsignificantbytes; ++i, p += incr) { + unsigned int thisbyte = *p; + /* Compute correction for 2's comp, if needed. */ + if (is_signed) { + thisbyte = (0xff ^ thisbyte) + carry; + carry = thisbyte >> 8; + thisbyte &= 0xff; + } + /* Because we're going LSB to MSB, thisbyte is + more significant than what's already in accum, + so needs to be prepended to accum. */ + accum |= thisbyte << accumbits; + accumbits += 8; + if (accumbits >= SHIFT) { + /* There's enough to fill a Python digit. */ + assert(idigit < (int)ndigits); + v->ob_digit[idigit] = (digit)(accum & MASK); + ++idigit; + accum >>= SHIFT; + accumbits -= SHIFT; + assert(accumbits < SHIFT); + } + } + assert(accumbits < SHIFT); + if (accumbits) { + assert(idigit < (int)ndigits); + v->ob_digit[idigit] = (digit)accum; + ++idigit; + } + } + + v->ob_size = is_signed ? -idigit : idigit; + return (PyObject *)long_normalize(v); + } + + int + _PyLong_AsByteArray(PyLongObject* v, + unsigned char* bytes, size_t n, + int little_endian, int is_signed) + { + int i; /* index into v->ob_digit */ + int ndigits; /* |v->ob_size| */ + twodigits accum; /* sliding register */ + unsigned int accumbits; /* # bits in accum */ + int do_twos_comp; /* store 2's-comp? is_signed and v < 0 */ + twodigits carry; /* for computing 2's-comp */ + size_t j; /* # bytes filled */ + unsigned char* p; /* pointer to next byte in bytes */ + int pincr; /* direction to move p */ + + assert(v != NULL && PyLong_Check(v)); + + if (v->ob_size < 0) { + ndigits = -(v->ob_size); + if (!is_signed) { + PyErr_SetString(PyExc_TypeError, + "can't convert negative long to unsigned"); + return -1; + } + do_twos_comp = 1; + } + else { + ndigits = v->ob_size; + do_twos_comp = 0; + } + + if (little_endian) { + p = bytes; + pincr = 1; + } + else { + p = bytes + n - 1; + pincr = -1; + } + + /* Copy over all the Python digits. */ + j = 0; + accum = 0; + accumbits = 0; + carry = do_twos_comp ? 1 : 0; + for (i = 0; i < ndigits; ++i) { + twodigits thisdigit = v->ob_digit[i]; + if (do_twos_comp) { + thisdigit = (thisdigit ^ MASK) + carry; + carry = thisdigit >> SHIFT; + thisdigit &= MASK; + } + /* Because we're going LSB to MSB, thisdigit is more + significant than what's already in accum, so needs to be + prepended to accum. */ + accum |= thisdigit << accumbits; + accumbits += SHIFT; + /* Store as many bytes as possible. */ + assert(accumbits >= 8); + do { + if (j >= n) + goto Overflow; + ++j; + *p = (unsigned char)(accum & 0xff); + p += pincr; + accumbits -= 8; + accum >>= 8; + } while (accumbits >= 8); + } + + /* Store the straggler (if any). */ + assert(accumbits < 8); + assert(carry == 0); /* else do_twos_comp and *every* digit was 0 */ + if (accum) { + if (j >= n) + goto Overflow; + ++j; + if (do_twos_comp) { + /* Fill leading bits of the byte with sign bits + (appropriately pretending that the long had an + infinite supply of sign bits). */ + accum |= (~(twodigits)0) << accumbits; + } + *p = (unsigned char)(accum & 0xff); + p += pincr; + } + + /* Fill remaining bytes with copies of the sign bit. */ + for ( ; j < n; ++j, p += pincr) + *p = (unsigned char)(do_twos_comp ? 0xff : 0); + + /* Check for delicate overflow (not enough room for the sign bit). */ + if (j > 0 && is_signed) { + unsigned char msb = *(p - pincr); + int sign_bit_set = (msb & 0x80) != 0; + if (sign_bit_set != do_twos_comp) + goto Overflow; + } + return 0; + + Overflow: + PyErr_SetString(PyExc_OverflowError, "long too big to convert"); + return -1; + + } + /* Get a C double from a long int object. */ From gvanrossum@users.sourceforge.net Tue Jun 12 01:30:36 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 11 Jun 2001 17:30:36 -0700 Subject: [Python-checkins] CVS: python/dist/src/Tools/idle keydefs.py,1.2,1.3 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/idle In directory usw-pr-cvs1:/tmp/cvs-serv1944 Modified Files: keydefs.py Log Message: Make copy, cut and paste events case insensitive. Reported by Patrick K. O'Brien on idle-dev. (Should other bindings follow suit?) Index: keydefs.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/idle/keydefs.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -r1.2 -r1.3 *** keydefs.py 1999/01/04 16:35:02 1.2 --- keydefs.py 2001/06/12 00:30:33 1.3 *************** *** 1,6 **** windows_keydefs = \ ! {'<>': [''], ! '<>': [''], ! '<>': [''], '<>': ['', ''], '<>': [''], --- 1,6 ---- windows_keydefs = \ ! {'<>': ['', ''], ! '<>': ['', ''], ! '<>': ['', ''], '<>': ['', ''], '<>': [''], From tim_one@users.sourceforge.net Tue Jun 12 02:22:23 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Jun 2001 18:22:23 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libstruct.tex,1.27,1.28 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv15300/python/dist/src/Doc/lib Modified Files: libstruct.tex Log Message: Added q/Q standard (x-platform 8-byte ints) mode in struct module. This completes the q/Q project. longobject.c _PyLong_AsByteArray: The original code had a gross bug: the most-significant Python digit doesn't necessarily have SHIFT significant bits, and you really need to count how many copies of the sign bit it has else spurious overflow errors result. test_struct.py: This now does exhaustive std q/Q testing at, and on both sides of, all relevant power-of-2 boundaries, both positive and negative. NEWS: Added brief dict news while I was at it. Index: libstruct.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstruct.tex,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -r1.27 -r1.28 *** libstruct.tex 2001/06/10 23:40:19 1.27 --- libstruct.tex 2001/06/12 01:22:21 1.28 *************** *** 73,77 **** The \character{q} and \character{Q} conversion codes are available in native mode only if the platform C compiler supports C \ctype{long long}, ! or, on Windows, \ctype{__int64}. \end{description} --- 73,78 ---- The \character{q} and \character{Q} conversion codes are available in native mode only if the platform C compiler supports C \ctype{long long}, ! or, on Windows, \ctype{__int64}. They're always available in standard ! modes. \end{description} *************** *** 101,106 **** that exactly enough bytes are used to satisfy the count. ! For the \character{I} and \character{L} format characters, the return ! value is a Python long integer. For the \character{P} format character, the return value is a Python --- 102,107 ---- that exactly enough bytes are used to satisfy the count. ! For the \character{I}, \character{L}, \character{q} and \character{Q} ! format characters, the return value is a Python long integer. For the \character{P} format character, the return value is a Python *************** *** 140,147 **** Standard size and alignment are as follows: no alignment is required ! for any type (so you have to use pad bytes); \ctype{short} is 2 bytes; ! \ctype{int} and \ctype{long} are 4 bytes. \ctype{float} and ! \ctype{double} are 32-bit and 64-bit IEEE floating point numbers, ! respectively. Note the difference between \character{@} and \character{=}: both use --- 141,150 ---- Standard size and alignment are as follows: no alignment is required ! for any type (so you have to use pad bytes); ! \ctype{short} is 2 bytes; ! \ctype{int} and \ctype{long} are 4 bytes; ! \ctype{long long} (\ctype{__int64} on Windows) is 8 bytes; ! \ctype{float} and \ctype{double} are 32-bit and 64-bit ! IEEE floating point numbers, respectively. Note the difference between \character{@} and \character{=}: both use From tim_one@users.sourceforge.net Tue Jun 12 02:22:24 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Jun 2001 18:22:24 -0700 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.182,1.183 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv15300/python/dist/src/Misc Modified Files: NEWS Log Message: Added q/Q standard (x-platform 8-byte ints) mode in struct module. This completes the q/Q project. longobject.c _PyLong_AsByteArray: The original code had a gross bug: the most-significant Python digit doesn't necessarily have SHIFT significant bits, and you really need to count how many copies of the sign bit it has else spurious overflow errors result. test_struct.py: This now does exhaustive std q/Q testing at, and on both sides of, all relevant power-of-2 boundaries, both positive and negative. NEWS: Added brief dict news while I was at it. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.182 retrieving revision 1.183 diff -C2 -r1.182 -r1.183 *** NEWS 2001/06/10 23:40:19 1.182 --- NEWS 2001/06/12 01:22:21 1.183 *************** *** 85,88 **** --- 85,91 ---- order. + - Many other small changes to dicts were made, resulting in faster + operation along the most common code paths. + - Dictionary objects now support the "in" operator: "x in dict" means the same as dict.has_key(x). *************** *** 120,124 **** - Collisions in dicts are resolved via a new approach, which can help dramatically in bad cases. For example, looking up every key in a dict ! d with d.keys() = [i << 16 for i in range(20000)] is approximately 500x faster now. Thanks to Christian Tismer for pointing out the cause and the nature of an effective cure (last December! better late than never). --- 123,127 ---- - Collisions in dicts are resolved via a new approach, which can help dramatically in bad cases. For example, looking up every key in a dict ! d with d.keys() == [i << 16 for i in range(20000)] is approximately 500x faster now. Thanks to Christian Tismer for pointing out the cause and the nature of an effective cure (last December! better late than never). *************** *** 146,151 **** these types (when HAVE_LONG_LONG is #define'd by the Python config process), and then they inherit the sizes and alignments of the C types. ! XXX TODO In standard mode, 'q' and 'Q' are supported on all platforms, and ! XXX TODO are 8-byte integral types. Tests --- 149,154 ---- these types (when HAVE_LONG_LONG is #define'd by the Python config process), and then they inherit the sizes and alignments of the C types. ! In standard mode, 'q' and 'Q' are supported on all platforms, and are ! 8-byte integral types. Tests From tim_one@users.sourceforge.net Tue Jun 12 02:22:24 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Jun 2001 18:22:24 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules structmodule.c,2.46,2.47 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv15300/python/dist/src/Modules Modified Files: structmodule.c Log Message: Added q/Q standard (x-platform 8-byte ints) mode in struct module. This completes the q/Q project. longobject.c _PyLong_AsByteArray: The original code had a gross bug: the most-significant Python digit doesn't necessarily have SHIFT significant bits, and you really need to count how many copies of the sign bit it has else spurious overflow errors result. test_struct.py: This now does exhaustive std q/Q testing at, and on both sides of, all relevant power-of-2 boundaries, both positive and negative. NEWS: Added brief dict news while I was at it. Index: structmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/structmodule.c,v retrieving revision 2.46 retrieving revision 2.47 diff -C2 -r2.46 -r2.47 *** structmodule.c 2001/06/11 16:57:33 2.46 --- structmodule.c 2001/06/12 01:22:21 2.47 *************** *** 81,84 **** --- 81,112 ---- #endif + /* Helper to get a PyLongObject by hook or by crook. Caller should decref. */ + + static PyObject * + get_pylong(PyObject *v) + { + PyNumberMethods *m; + + assert(v != NULL); + if (PyInt_Check(v)) + return PyLong_FromLong(PyInt_AS_LONG(v)); + if (PyLong_Check(v)) { + Py_INCREF(v); + return v; + } + m = v->ob_type->tp_as_number; + if (m != NULL && m->nb_long != NULL) { + v = m->nb_long(v); + if (v == NULL) + return NULL; + if (PyLong_Check(v)) + return v; + Py_DECREF(v); + } + PyErr_SetString(StructError, + "cannot convert argument to long"); + return NULL; + } + /* Helper routine to get a Python integer and raise the appropriate error if it isn't one */ *************** *** 124,154 **** { LONG_LONG x; - int v_needs_decref = 0; ! if (PyInt_Check(v)) { ! x = (LONG_LONG)PyInt_AS_LONG(v); ! *p = x; ! return 0; ! } ! if (!PyLong_Check(v)) { ! PyNumberMethods *m = v->ob_type->tp_as_number; ! if (m != NULL && m->nb_long != NULL) { ! v = m->nb_long(v); ! if (v == NULL) ! return -1; ! v_needs_decref = 1; ! } ! if (!PyLong_Check(v)) { ! PyErr_SetString(StructError, ! "cannot convert argument to long"); ! if (v_needs_decref) ! Py_DECREF(v); ! return -1; ! } ! } assert(PyLong_Check(v)); x = PyLong_AsLongLong(v); ! if (v_needs_decref) ! Py_DECREF(v); if (x == (LONG_LONG)-1 && PyErr_Occurred()) return -1; --- 152,162 ---- { LONG_LONG x; ! v = get_pylong(v); ! if (v == NULL) ! return -1; assert(PyLong_Check(v)); x = PyLong_AsLongLong(v); ! Py_DECREF(v); if (x == (LONG_LONG)-1 && PyErr_Occurred()) return -1; *************** *** 163,199 **** { unsigned LONG_LONG x; - int v_needs_decref = 0; ! if (PyInt_Check(v)) { ! long i = PyInt_AS_LONG(v); ! if (i < 0) { ! PyErr_SetString(StructError, "can't convert negative " ! "int to unsigned"); ! return -1; ! } ! x = (unsigned LONG_LONG)i; ! *p = x; ! return 0; ! } ! if (!PyLong_Check(v)) { ! PyNumberMethods *m = v->ob_type->tp_as_number; ! if (m != NULL && m->nb_long != NULL) { ! v = m->nb_long(v); ! if (v == NULL) ! return -1; ! v_needs_decref = 1; ! } ! if (!PyLong_Check(v)) { ! PyErr_SetString(StructError, ! "cannot convert argument to long"); ! if (v_needs_decref) ! Py_DECREF(v); ! return -1; ! } ! } assert(PyLong_Check(v)); x = PyLong_AsUnsignedLongLong(v); ! if (v_needs_decref) ! Py_DECREF(v); if (x == (unsigned LONG_LONG)-1 && PyErr_Occurred()) return -1; --- 171,181 ---- { unsigned LONG_LONG x; ! v = get_pylong(v); ! if (v == NULL) ! return -1; assert(PyLong_Check(v)); x = PyLong_AsUnsignedLongLong(v); ! Py_DECREF(v); if (x == (unsigned LONG_LONG)-1 && PyErr_Occurred()) return -1; *************** *** 501,505 **** */ ! /* Native mode routines. */ static PyObject * --- 483,487 ---- */ ! /* Native mode routines. ****************************************************/ static PyObject * *************** *** 798,801 **** --- 780,785 ---- }; + /* Big-endian routines. *****************************************************/ + static PyObject * bu_int(const char *p, const formatdef *f) *************** *** 827,830 **** --- 811,832 ---- static PyObject * + bu_longlong(const char *p, const formatdef *f) + { + return _PyLong_FromByteArray((const unsigned char *)p, + 8, + 0, /* little-endian */ + 1 /* signed */); + } + + static PyObject * + bu_ulonglong(const char *p, const formatdef *f) + { + return _PyLong_FromByteArray((const unsigned char *)p, + 8, + 0, /* little-endian */ + 0 /* signed */); + } + + static PyObject * bu_float(const char *p, const formatdef *f) { *************** *** 869,872 **** --- 871,902 ---- static int + bp_longlong(char *p, PyObject *v, const formatdef *f) + { + int res; + v = get_pylong(v); + res = _PyLong_AsByteArray((PyLongObject *)v, + (unsigned char *)p, + 8, + 0, /* little_endian */ + 1 /* signed */); + Py_DECREF(v); + return res; + } + + static int + bp_ulonglong(char *p, PyObject *v, const formatdef *f) + { + int res; + v = get_pylong(v); + res = _PyLong_AsByteArray((PyLongObject *)v, + (unsigned char *)p, + 8, + 0, /* little_endian */ + 0 /* signed */); + Py_DECREF(v); + return res; + } + + static int bp_float(char *p, PyObject *v, const formatdef *f) { *************** *** 905,908 **** --- 935,940 ---- {'l', 4, 0, bu_int, bp_int}, {'L', 4, 0, bu_uint, bp_uint}, + {'q', 8, 0, bu_longlong, bp_longlong}, + {'Q', 8, 0, bu_ulonglong, bp_ulonglong}, {'f', 4, 0, bu_float, bp_float}, {'d', 8, 0, bu_double, bp_double}, *************** *** 910,913 **** --- 942,947 ---- }; + /* Little-endian routines. *****************************************************/ + static PyObject * lu_int(const char *p, const formatdef *f) *************** *** 939,942 **** --- 973,994 ---- static PyObject * + lu_longlong(const char *p, const formatdef *f) + { + return _PyLong_FromByteArray((const unsigned char *)p, + 8, + 1, /* little-endian */ + 1 /* signed */); + } + + static PyObject * + lu_ulonglong(const char *p, const formatdef *f) + { + return _PyLong_FromByteArray((const unsigned char *)p, + 8, + 1, /* little-endian */ + 0 /* signed */); + } + + static PyObject * lu_float(const char *p, const formatdef *f) { *************** *** 981,984 **** --- 1033,1064 ---- static int + lp_longlong(char *p, PyObject *v, const formatdef *f) + { + int res; + v = get_pylong(v); + res = _PyLong_AsByteArray((PyLongObject*)v, + (unsigned char *)p, + 8, + 1, /* little_endian */ + 1 /* signed */); + Py_DECREF(v); + return res; + } + + static int + lp_ulonglong(char *p, PyObject *v, const formatdef *f) + { + int res; + v = get_pylong(v); + res = _PyLong_AsByteArray((PyLongObject*)v, + (unsigned char *)p, + 8, + 1, /* little_endian */ + 0 /* signed */); + Py_DECREF(v); + return res; + } + + static int lp_float(char *p, PyObject *v, const formatdef *f) { *************** *** 1017,1020 **** --- 1097,1102 ---- {'l', 4, 0, lu_int, lp_int}, {'L', 4, 0, lu_uint, lp_uint}, + {'q', 8, 0, lu_longlong, lp_longlong}, + {'Q', 8, 0, lu_ulonglong, lp_ulonglong}, {'f', 4, 0, lu_float, lp_float}, {'d', 8, 0, lu_double, lp_double}, From tim_one@users.sourceforge.net Tue Jun 12 02:22:24 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Jun 2001 18:22:24 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.72,1.73 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv15300/python/dist/src/Objects Modified Files: longobject.c Log Message: Added q/Q standard (x-platform 8-byte ints) mode in struct module. This completes the q/Q project. longobject.c _PyLong_AsByteArray: The original code had a gross bug: the most-significant Python digit doesn't necessarily have SHIFT significant bits, and you really need to count how many copies of the sign bit it has else spurious overflow errors result. test_struct.py: This now does exhaustive std q/Q testing at, and on both sides of, all relevant power-of-2 boundaries, both positive and negative. NEWS: Added brief dict news while I was at it. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.72 retrieving revision 1.73 diff -C2 -r1.72 -r1.73 *** longobject.c 2001/06/11 21:23:58 1.72 --- longobject.c 2001/06/12 01:22:22 1.73 *************** *** 365,368 **** --- 365,369 ---- carry = do_twos_comp ? 1 : 0; for (i = 0; i < ndigits; ++i) { + unsigned int oldaccumbits = accumbits; twodigits thisdigit = v->ob_digit[i]; if (do_twos_comp) { *************** *** 371,382 **** thisdigit &= MASK; } /* Because we're going LSB to MSB, thisdigit is more significant than what's already in accum, so needs to be prepended to accum. */ ! accum |= thisdigit << accumbits; ! accumbits += SHIFT; /* Store as many bytes as possible. */ ! assert(accumbits >= 8); ! do { if (j >= n) goto Overflow; --- 372,395 ---- thisdigit &= MASK; } + if (i < ndigits - 1) + accumbits += SHIFT; + else { + /* The most-significant digit may be partly empty. */ + twodigits bitmask = 1 << (SHIFT - 1); + twodigits signbit = do_twos_comp << (SHIFT - 1); + unsigned int nsignbits = 0; + while ((thisdigit & bitmask) == signbit && bitmask) { + ++nsignbits; + bitmask >>= 1; + signbit >>= 1; + } + accumbits += SHIFT - nsignbits; + } /* Because we're going LSB to MSB, thisdigit is more significant than what's already in accum, so needs to be prepended to accum. */ ! accum |= thisdigit << oldaccumbits; /* Store as many bytes as possible. */ ! while (accumbits >= 8) { if (j >= n) goto Overflow; *************** *** 386,390 **** accumbits -= 8; accum >>= 8; ! } while (accumbits >= 8); } --- 399,403 ---- accumbits -= 8; accum >>= 8; ! } } *************** *** 392,396 **** assert(accumbits < 8); assert(carry == 0); /* else do_twos_comp and *every* digit was 0 */ ! if (accum) { if (j >= n) goto Overflow; --- 405,409 ---- assert(accumbits < 8); assert(carry == 0); /* else do_twos_comp and *every* digit was 0 */ ! if (accumbits > 0) { if (j >= n) goto Overflow; From tim_one@users.sourceforge.net Tue Jun 12 02:22:23 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Jun 2001 18:22:23 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_struct.py,1.9,1.10 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv15300/python/dist/src/Lib/test Modified Files: test_struct.py Log Message: Added q/Q standard (x-platform 8-byte ints) mode in struct module. This completes the q/Q project. longobject.c _PyLong_AsByteArray: The original code had a gross bug: the most-significant Python digit doesn't necessarily have SHIFT significant bits, and you really need to count how many copies of the sign bit it has else spurious overflow errors result. test_struct.py: This now does exhaustive std q/Q testing at, and on both sides of, all relevant power-of-2 boundaries, both positive and negative. NEWS: Added brief dict news while I was at it. Index: test_struct.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_struct.py,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -r1.9 -r1.10 *** test_struct.py 2001/06/10 23:52:59 1.9 --- test_struct.py 2001/06/12 01:22:21 1.10 *************** *** 13,16 **** --- 13,26 ---- ## pdb.set_trace() + def any_err(func, *args): + try: + apply(func, args) + except (struct.error, OverflowError, TypeError): + pass + else: + raise TestFailed, "%s%s did not raise error" % ( + func.__name__, args) + ## pdb.set_trace() + simple_err(struct.calcsize, 'Z') *************** *** 114,118 **** `fmt`, `res`, `rev`, `arg`) ! # Some q/Q sanity checks. has_native_qQ = 1 --- 124,129 ---- `fmt`, `res`, `rev`, `arg`) ! ########################################################################### ! # q/Q tests. has_native_qQ = 1 *************** *** 125,140 **** print "Platform has native q/Q?", has_native_qQ and "Yes." or "No." ! simple_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless simple_err(struct.pack, "Q", "a") # ditto, but 'Q' def bigendian_to_native(value): if isbigendian: return value ! chars = list(value) ! chars.reverse() ! return "".join(chars) ! if has_native_qQ: bytes = struct.calcsize('q') # The expected values here are in big-endian format, primarily because --- 136,155 ---- print "Platform has native q/Q?", has_native_qQ and "Yes." or "No." ! any_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless simple_err(struct.pack, "Q", "a") # ditto, but 'Q' + def string_reverse(s): + chars = list(s) + chars.reverse() + return "".join(chars) + def bigendian_to_native(value): if isbigendian: return value ! else: ! return string_reverse(value) ! def test_native_qQ(): bytes = struct.calcsize('q') # The expected values here are in big-endian format, primarily because *************** *** 157,158 **** --- 172,317 ---- "%r-unpack of %r gave %r, not %r" % (format, got, retrieved, input)) + + if has_native_qQ: + test_native_qQ() + + # Standard q/Q (8 bytes; should work on all platforms). + + MIN_Q, MAX_Q = 0, 2L**64 - 1 + MIN_q, MAX_q = -(2L**63), 2L**63 - 1 + + import binascii + def test_one_qQ(x, pack=struct.pack, + unpack=struct.unpack, + unhexlify=binascii.unhexlify): + if verbose: + print "trying std q/Q on", x, "==", hex(x) + + # Try 'q'. + if MIN_q <= x <= MAX_q: + # Try '>q'. + expected = long(x) + if x < 0: + expected += 1L << 64 + assert expected > 0 + expected = hex(expected)[2:-1] # chop "0x" and trailing 'L' + if len(expected) & 1: + expected = "0" + expected + expected = unhexlify(expected) + expected = "\x00" * (8 - len(expected)) + expected + + # >q pack work? + got = pack(">q", x) + verify(got == expected, + "'>q'-pack of %r gave %r, not %r" % + (x, got, expected)) + + # >q unpack work? + retrieved = unpack(">q", got)[0] + verify(x == retrieved, + "'>q'-unpack of %r gave %r, not %r" % + (got, retrieved, x)) + + # Adding any byte should cause a "too big" error. + any_err(unpack, ">q", '\x01' + got) + + # Try 'q', x) + any_err(pack, 'Q'. + expected = long(x) + expected = hex(expected)[2:-1] # chop "0x" and trailing 'L' + if len(expected) & 1: + expected = "0" + expected + expected = unhexlify(expected) + expected = "\x00" * (8 - len(expected)) + expected + + # >Q pack work? + got = pack(">Q", x) + verify(got == expected, + "'>Q'-pack of %r gave %r, not %r" % + (x, got, expected)) + + # >Q unpack work? + retrieved = unpack(">Q", got)[0] + verify(x == retrieved, + "'>Q'-unpack of %r gave %r, not %r" % + (got, retrieved, x)) + + # Adding any byte should cause a "too big" error. + any_err(unpack, ">Q", '\x01' + got) + + # Try 'Q', x) + any_err(pack, ' Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv3692/lib Modified Files: libstdtypes.tex Log Message: Fixed reference to table notes for {}.keys() and {}.items() -- these references did not get updated when the notes were renumbered in a previous update. This fixes SF bug #432208. Index: libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.59 retrieving revision 1.60 diff -C2 -r1.59 -r1.60 *** libstdtypes.tex 2001/05/25 04:24:37 1.59 --- libstdtypes.tex 2001/06/12 03:31:56 1.60 *************** *** 931,939 **** {a copy of \var{a}'s list of (\var{key}, \var{value}) pairs} {(3)} ! \lineiii{\var{a}.keys()}{a copy of \var{a}'s list of keys}{(2)} \lineiii{\var{a}.update(\var{b})} {\code{for k in \var{b}.keys(): \var{a}[k] = \var{b}[k]}} {(4)} ! \lineiii{\var{a}.values()}{a copy of \var{a}'s list of values}{(2)} \lineiii{\var{a}.get(\var{k}\optional{, \var{x}})} {\code{\var{a}[\var{k}]} if \code{\var{k} in \var{a}}, --- 931,939 ---- {a copy of \var{a}'s list of (\var{key}, \var{value}) pairs} {(3)} ! \lineiii{\var{a}.keys()}{a copy of \var{a}'s list of keys}{(3)} \lineiii{\var{a}.update(\var{b})} {\code{for k in \var{b}.keys(): \var{a}[k] = \var{b}[k]}} {(4)} ! \lineiii{\var{a}.values()}{a copy of \var{a}'s list of values}{(3)} \lineiii{\var{a}.get(\var{k}\optional{, \var{x}})} {\code{\var{a}[\var{k}]} if \code{\var{k} in \var{a}}, *************** *** 970,975 **** modifications to the dictionary, the two lists will directly correspond. This allows the creation of \code{(\var{value}, ! \var{key})} pairs using \function{map()}: \samp{pairs = map(None, ! \var{a}.values(), \var{a}.keys())}. \item[(4)] \var{b} must be of the same type as \var{a}. --- 970,975 ---- modifications to the dictionary, the two lists will directly correspond. This allows the creation of \code{(\var{value}, ! \var{key})} pairs using \function{zip()}: \samp{pairs = ! zip(\var{a}.values(), \var{a}.keys())}. \item[(4)] \var{b} must be of the same type as \var{a}. From mal@lemburg.com Tue Jun 12 08:13:26 2001 From: mal@lemburg.com (M.-A. Lemburg) Date: Tue, 12 Jun 2001 09:13:26 +0200 Subject: [Python-checkins] CVS: python/dist/src/Include longobject.h,2.19,2.20 References: Message-ID: <3B25C116.3E65A32D@lemburg.com> Tim, I have tried to compile longobject.c/h on a HP-UX box and am getting warnings about MIN/MAX being redefined. Perhaps you should add an #undef for these before the #define ?! -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.lemburg.com/python/ From lemburg@users.sourceforge.net Tue Jun 12 14:14:12 2001 From: lemburg@users.sourceforge.net (M.-A. Lemburg) Date: Tue, 12 Jun 2001 06:14:12 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects stringobject.c,2.117,2.118 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv20984 Modified Files: stringobject.c Log Message: Fix for bug #432384: Recursion in PyString_AsEncodedString? Index: stringobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v retrieving revision 2.117 retrieving revision 2.118 diff -C2 -r2.117 -r2.118 *** stringobject.c 2001/05/24 16:56:35 2.117 --- stringobject.c 2001/06/12 13:14:10 2.118 *************** *** 266,270 **** PyObject *v; ! v = PyString_AsEncodedString(str, encoding, errors); if (v == NULL) goto onError; --- 266,270 ---- PyObject *v; ! v = PyString_AsEncodedObject(str, encoding, errors); if (v == NULL) goto onError; From fdrake@users.sourceforge.net Tue Jun 12 14:31:39 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 12 Jun 2001 06:31:39 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/tools push-docs.sh,1.8,1.9 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tools In directory usw-pr-cvs1:/tmp/cvs-serv25316/tools Modified Files: push-docs.sh Log Message: Make the option processing more robust. Add a -F option similar to "cvs commit -F ". Add a -t option to allow specifying the prefix to the directory into which the docs should be unpacked (useful when I start trying out new styles for the presentation). Index: push-docs.sh =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tools/push-docs.sh,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -r1.8 -r1.9 *** push-docs.sh 2001/05/09 16:33:34 1.8 --- push-docs.sh 2001/06/12 13:31:37 1.9 *************** *** 20,29 **** EXPLANATION='' ! if [ "$1" = '-m' ] ; then ! EXPLANATION="$2" ! shift 2 ! elif [ "$1" ] ; then ! EXPLANATION="`cat $1`" ! shift 1 fi --- 20,53 ---- EXPLANATION='' ! while [ "$#" -gt 0 ] ; do ! case "$1" in ! -m) ! EXPLANATION="$2" ! shift 2 ! ;; ! -t) ! DOCTYPE="$2" ! shift 2 ! ;; ! -F) ! EXPLANATION="`cat $2`" ! shift 2 ! ;; ! -*) ! echo "Unknown option: $1" >&2 ! exit 2 ! ;; ! *) ! break ! ;; ! esac ! done ! if [ "$1" ] ; then ! if [ "$EXPLANATION" ] ; then ! echo "Explanation may only be given once!" >&2 ! exit 2 ! fi ! EXPLANATION="$1" ! shift fi *************** *** 46,50 **** The development version of the documentation has been updated: ! http://python.sourceforge.net/$DOCTYPE-docs/ $EXPLANATION --- 70,74 ---- The development version of the documentation has been updated: ! http://python.sourceforge.net/$DOCTYPE-docs/ $EXPLANATION From lemburg@users.sourceforge.net Tue Jun 12 17:13:54 2001 From: lemburg@users.sourceforge.net (M.-A. Lemburg) Date: Tue, 12 Jun 2001 09:13:54 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules main.c,1.52,1.53 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv4171 Modified Files: main.c Log Message: Removed the Python version from the PYTHONHOMEHELP string. It was still set to python2.0 ... Index: main.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/main.c,v retrieving revision 1.52 retrieving revision 1.53 diff -C2 -r1.52 -r1.53 *** main.c 2001/04/10 22:07:07 1.52 --- main.c 2001/06/12 16:13:51 1.53 *************** *** 15,19 **** #define PYTHONHOMEHELP "\\lib" #else ! #define PYTHONHOMEHELP "/python2.0" #endif --- 15,19 ---- #define PYTHONHOMEHELP "\\lib" #else ! #define PYTHONHOMEHELP "/pythonX.X" #endif From gvanrossum@users.sourceforge.net Tue Jun 12 17:29:14 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 12 Jun 2001 09:29:14 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules main.c,1.52,1.52.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv8396 Modified Files: Tag: release21-maint main.c Log Message: Incorporating MAL's bugfix into the 2.1.1 branch: revision 1.53 date: 2001/06/12 16:13:51; author: lemburg; state: Exp; lines: +1 -1 Removed the Python version from the PYTHONHOMEHELP string. It was still set to python2.0 ... Index: main.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/main.c,v retrieving revision 1.52 retrieving revision 1.52.2.1 diff -C2 -r1.52 -r1.52.2.1 *** main.c 2001/04/10 22:07:07 1.52 --- main.c 2001/06/12 16:29:12 1.52.2.1 *************** *** 15,19 **** #define PYTHONHOMEHELP "\\lib" #else ! #define PYTHONHOMEHELP "/python2.0" #endif --- 15,19 ---- #define PYTHONHOMEHELP "\\lib" #else ! #define PYTHONHOMEHELP "/pythonX.X" #endif From gvanrossum@users.sourceforge.net Tue Jun 12 17:48:54 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 12 Jun 2001 09:48:54 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib site.py,1.26,1.27 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv12111/Lib Modified Files: site.py Log Message: Add new built-in 'help' which invokes pydoc.help (with a twist). Index: site.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/site.py,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -r1.26 -r1.27 *** site.py 2001/03/23 17:53:49 1.26 --- site.py 2001/06/12 16:48:52 1.27 *************** *** 237,240 **** --- 237,254 ---- + # Define new built-in 'help'. + # This is a wrapper around pydoc.help (with a twist). + + class _Helper: + def __repr__(self): + return "Type help() for interactive help, " \ + "or help(object) for help about object." + def __call__(self, *args, **kwds): + import pydoc + return pydoc.help(*args, **kwds) + + __builtin__.help = _Helper() + + # Set the string encoding used by the Unicode implementation. The # default is 'ascii', but if you're willing to experiment, you can From gvanrossum@users.sourceforge.net Tue Jun 12 17:48:54 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 12 Jun 2001 09:48:54 -0700 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.183,1.184 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv12111/Misc Modified Files: NEWS Log Message: Add new built-in 'help' which invokes pydoc.help (with a twist). Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.183 retrieving revision 1.184 diff -C2 -r1.183 -r1.184 *** NEWS 2001/06/12 01:22:21 1.183 --- NEWS 2001/06/12 16:48:52 1.184 *************** *** 152,155 **** --- 152,160 ---- 8-byte integral types. + - The site module installs a new built-in function 'help' that invokes + pydoc.help. It must be invoked as 'help()'; when invoked as 'help', + it displays a message reminding the user to use 'help()' or + 'help(object)'. + Tests From tim_one@users.sourceforge.net Tue Jun 12 20:17:05 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 12 Jun 2001 12:17:05 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.73,1.74 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv12556/python/dist/src/Objects Modified Files: longobject.c Log Message: _PyLong_{As,From}ByteArray: Minor code rearrangement aimed at improving clarity. Should have no effect visible to callers. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.73 retrieving revision 1.74 diff -C2 -r1.73 -r1.74 *** longobject.c 2001/06/12 01:22:22 1.73 --- longobject.c 2001/06/12 19:17:03 1.74 *************** *** 285,289 **** for (i = 0; i < numsignificantbytes; ++i, p += incr) { ! unsigned int thisbyte = *p; /* Compute correction for 2's comp, if needed. */ if (is_signed) { --- 285,289 ---- for (i = 0; i < numsignificantbytes; ++i, p += incr) { ! twodigits thisbyte = *p; /* Compute correction for 2's comp, if needed. */ if (is_signed) { *************** *** 365,369 **** carry = do_twos_comp ? 1 : 0; for (i = 0; i < ndigits; ++i) { ! unsigned int oldaccumbits = accumbits; twodigits thisdigit = v->ob_digit[i]; if (do_twos_comp) { --- 365,369 ---- carry = do_twos_comp ? 1 : 0; for (i = 0; i < ndigits; ++i) { ! unsigned int numnewbits = SHIFT; twodigits thisdigit = v->ob_digit[i]; if (do_twos_comp) { *************** *** 372,379 **** thisdigit &= MASK; } ! if (i < ndigits - 1) ! accumbits += SHIFT; ! else { ! /* The most-significant digit may be partly empty. */ twodigits bitmask = 1 << (SHIFT - 1); twodigits signbit = do_twos_comp << (SHIFT - 1); --- 372,383 ---- thisdigit &= MASK; } ! /* Because we're going LSB to MSB, thisdigit is more ! significant than what's already in accum, so needs to be ! prepended to accum. */ ! accum |= thisdigit << accumbits; ! ! /* How many new bits did we add? The most-significant digit ! may be (probably is) at least partly empty. */ ! if (i == ndigits - 1) { twodigits bitmask = 1 << (SHIFT - 1); twodigits signbit = do_twos_comp << (SHIFT - 1); *************** *** 384,393 **** signbit >>= 1; } ! accumbits += SHIFT - nsignbits; } ! /* Because we're going LSB to MSB, thisdigit is more ! significant than what's already in accum, so needs to be ! prepended to accum. */ ! accum |= thisdigit << oldaccumbits; /* Store as many bytes as possible. */ while (accumbits >= 8) { --- 388,396 ---- signbit >>= 1; } ! assert(nsignbits <= SHIFT); ! numnewbits -= nsignbits; } ! accumbits += numnewbits; ! /* Store as many bytes as possible. */ while (accumbits >= 8) { From tim_one@users.sourceforge.net Tue Jun 12 21:10:04 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 12 Jun 2001 13:10:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules _testcapimodule.c,1.3,1.4 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv21117/python/dist/src/Modules Modified Files: _testcapimodule.c Log Message: The merest start of a test for the PyLong_{As,From}{Unsigned,}LongLong() functions. I intend to replace their guts with calls to the new _PyLong_{As,From}ByteArray() functions, but AFAICT there's no tests for them at all now; I also suspect PyLong_AsLongLong() isn't catching all overflow cases, but without a std test to demonstrate that why should you believe me . Also added a raiseTestError() utility function. Index: _testcapimodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_testcapimodule.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -r1.3 -r1.4 *** _testcapimodule.c 2001/04/13 17:08:15 1.3 --- _testcapimodule.c 2001/06/12 20:10:01 1.4 *************** *** 10,13 **** --- 10,29 ---- static PyObject *TestError; /* set to exception object in init */ + /* Raise TestError with test_name + ": " + msg, and return NULL. */ + + static PyObject * + raiseTestError(const char* test_name, const char* msg) + { + char buf[2048]; + + if (strlen(test_name) + strlen(msg) > sizeof(buf) - 50) + PyErr_SetString(TestError, "internal error msg too large"); + else { + sprintf(buf, "%s: %s", test_name, msg); + PyErr_SetString(TestError, buf); + } + return NULL; + } + /* Test #defines from config.h (particularly the SIZEOF_* defines). *************** *** 146,150 **** if (!PyArg_ParseTuple(args, ":test_dict_iteration")) return NULL; ! for (i = 0; i < 200; i++) { if (test_dict_inner(i) < 0) { --- 162,166 ---- if (!PyArg_ParseTuple(args, ":test_dict_iteration")) return NULL; ! for (i = 0; i < 200; i++) { if (test_dict_inner(i) < 0) { *************** *** 157,164 **** } static PyMethodDef TestMethods[] = { ! {"test_config", test_config, METH_VARARGS}, ! {"test_list_api", test_list_api, METH_VARARGS}, ! {"test_dict_iteration", test_dict_iteration, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; --- 173,217 ---- } + #ifdef HAVE_LONG_LONG + + /* Basic sanity checks for PyLong_{As, From}{Unsigned,}LongLong(). */ + + static PyObject * + test_longlong_api(PyObject* self, PyObject* args) + { + /* unsigned LONG_LONG uinput, uoutput; */ + LONG_LONG input, output; + PyObject *pyresult; + + if (!PyArg_ParseTuple(args, ":test_longlong_api")) + return NULL; + + input = 0; + pyresult = PyLong_FromLongLong(input); + if (pyresult == NULL) + return raiseTestError("test_longlong_api", + "unexpected null result"); + output = PyLong_AsLongLong(pyresult); + if (output == (LONG_LONG)-1 && PyErr_Occurred()) + return raiseTestError("test_longlong_api", + "unexpected -1 result"); + if (output != input) + return raiseTestError("test_longlong_api", + "output != input"); + Py_DECREF(pyresult); + + Py_INCREF(Py_None); + return Py_None; + } + + #endif + static PyMethodDef TestMethods[] = { ! {"test_config", test_config, METH_VARARGS}, ! {"test_list_api", test_list_api, METH_VARARGS}, ! {"test_dict_iteration", test_dict_iteration, METH_VARARGS}, ! #ifdef HAVE_LONG_LONG ! {"test_longlong_api", test_longlong_api, METH_VARARGS}, ! #endif {NULL, NULL} /* sentinel */ }; From tim_one@users.sourceforge.net Wed Jun 13 01:36:00 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 12 Jun 2001 17:36:00 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules _testcapimodule.c,1.4,1.5 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv10010/python/dist/src/Modules Modified Files: _testcapimodule.c Log Message: longobject.c: Replaced PyLong_{As,From}{Unsigned,}LongLong guts with calls to _PyLong_{As,From}ByteArray. _testcapimodule.c: Added strong tests of PyLong_{As,From}{Unsigned,}LongLong. Fixes SF bug #432552 PyLong_AsLongLong() problems. Possible bugfix candidate, but the fix relies on code added to longobject to support the new q/Q structmodule format codes. Index: _testcapimodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_testcapimodule.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -r1.4 -r1.5 *** _testcapimodule.c 2001/06/12 20:10:01 1.4 --- _testcapimodule.c 2001/06/13 00:35:57 1.5 *************** *** 178,203 **** static PyObject * test_longlong_api(PyObject* self, PyObject* args) { ! /* unsigned LONG_LONG uinput, uoutput; */ ! LONG_LONG input, output; PyObject *pyresult; if (!PyArg_ParseTuple(args, ":test_longlong_api")) return NULL; ! input = 0; ! pyresult = PyLong_FromLongLong(input); ! if (pyresult == NULL) ! return raiseTestError("test_longlong_api", ! "unexpected null result"); ! output = PyLong_AsLongLong(pyresult); ! if (output == (LONG_LONG)-1 && PyErr_Occurred()) ! return raiseTestError("test_longlong_api", ! "unexpected -1 result"); ! if (output != input) ! return raiseTestError("test_longlong_api", ! "output != input"); ! Py_DECREF(pyresult); Py_INCREF(Py_None); --- 178,346 ---- static PyObject * + raise_test_longlong_error(const char* msg) + { + return raiseTestError("test_longlong_api", msg); + } + + #define UNBIND(X) Py_DECREF(X); (X) = NULL + + static PyObject * test_longlong_api(PyObject* self, PyObject* args) { ! const int NBITS = SIZEOF_LONG_LONG * 8; ! unsigned LONG_LONG base; PyObject *pyresult; + int i; if (!PyArg_ParseTuple(args, ":test_longlong_api")) return NULL; + + + /* Note: This test lets PyObjects leak if an error is raised. Since + an error should never be raised, leaks are impossible . */ + + /* Test native -> PyLong -> native roundtrip identity. + * Generate all powers of 2, and test them and their negations, + * plus the numbers +-1 off from them. + */ + base = 1; + for (i = 0; + i < NBITS + 1; /* on last, base overflows to 0 */ + ++i, base <<= 1) + { + int j; + for (j = 0; j < 6; ++j) { + LONG_LONG in, out; + unsigned LONG_LONG uin, uout; + + /* For 0, 1, 2 use base; for 3, 4, 5 use -base */ + uin = j < 3 ? base + : (unsigned LONG_LONG)(-(LONG_LONG)base); + + /* For 0 & 3, subtract 1. + * For 1 & 4, leave alone. + * For 2 & 5, add 1. + */ + uin += (unsigned LONG_LONG)(LONG_LONG)(j % 3 - 1); + + pyresult = PyLong_FromUnsignedLongLong(uin); + if (pyresult == NULL) + return raise_test_longlong_error( + "unsigned unexpected null result"); + + uout = PyLong_AsUnsignedLongLong(pyresult); + if (uout == (unsigned LONG_LONG)-1 && PyErr_Occurred()) + return raise_test_longlong_error( + "unsigned unexpected -1 result"); + if (uout != uin) + return raise_test_longlong_error( + "unsigned output != input"); + UNBIND(pyresult); + + in = (LONG_LONG)uin; + pyresult = PyLong_FromLongLong(in); + if (pyresult == NULL) + return raise_test_longlong_error( + "signed unexpected null result"); + + out = PyLong_AsLongLong(pyresult); + if (out == (LONG_LONG)-1 && PyErr_Occurred()) + return raise_test_longlong_error( + "signed unexpected -1 result"); + if (out != in) + return raise_test_longlong_error( + "signed output != input"); + UNBIND(pyresult); + } + } + + /* Overflow tests. The loop above ensured that all limit cases that + * should not overflow don't overflow, so all we need to do here is + * provoke one-over-the-limit cases (not exhaustive, but sharp). + */ + { + PyObject *one, *x, *y; + LONG_LONG out; + unsigned LONG_LONG uout; + + one = PyLong_FromLong(1); + if (one == NULL) + return raise_test_longlong_error( + "unexpected NULL from PyLong_FromLong"); + + /* Unsigned complains about -1? */ + x = PyNumber_Negative(one); + if (x == NULL) + return raise_test_longlong_error( + "unexpected NULL from PyNumber_Negative"); + + uout = PyLong_AsUnsignedLongLong(x); + if (uout != (unsigned LONG_LONG)-1 || !PyErr_Occurred()) + return raise_test_longlong_error( + "PyLong_AsUnsignedLongLong(-1) didn't " + "complain"); + PyErr_Clear(); + UNBIND(x); + + /* Unsigned complains about 2**NBITS? */ + y = PyLong_FromLong((long)NBITS); + if (y == NULL) + return raise_test_longlong_error( + "unexpected NULL from PyLong_FromLong"); + + x = PyNumber_Lshift(one, y); /* 1L << NBITS, == 2**NBITS */ + UNBIND(y); + if (x == NULL) + return raise_test_longlong_error( + "unexpected NULL from PyNumber_Lshift"); + + uout = PyLong_AsUnsignedLongLong(x); + if (uout != (unsigned LONG_LONG)-1 || !PyErr_Occurred()) + return raise_test_longlong_error( + "PyLong_AsUnsignedLongLong(2**NBITS) didn't " + "complain"); + PyErr_Clear(); + + /* Signed complains about 2**(NBITS-1)? + x still has 2**NBITS. */ + y = PyNumber_Rshift(x, one); /* 2**(NBITS-1) */ + UNBIND(x); + if (y == NULL) + return raise_test_longlong_error( + "unexpected NULL from PyNumber_Rshift"); + + out = PyLong_AsLongLong(y); + if (out != (LONG_LONG)-1 || !PyErr_Occurred()) + return raise_test_longlong_error( + "PyLong_AsLongLong(2**(NBITS-1)) didn't " + "complain"); + PyErr_Clear(); + + /* Signed complains about -2**(NBITS-1)-1?; + y still has 2**(NBITS-1). */ + x = PyNumber_Negative(y); /* -(2**(NBITS-1)) */ + UNBIND(y); + if (x == NULL) + return raise_test_longlong_error( + "unexpected NULL from PyNumber_Negative"); + + y = PyNumber_Subtract(x, one); /* -(2**(NBITS-1))-1 */ + UNBIND(x); + if (y == NULL) + return raise_test_longlong_error( + "unexpected NULL from PyNumber_Subtract"); + + out = PyLong_AsLongLong(y); + if (out != (LONG_LONG)-1 || !PyErr_Occurred()) + return raise_test_longlong_error( + "PyLong_AsLongLong(-2**(NBITS-1)-1) didn't " + "complain"); + PyErr_Clear(); + UNBIND(y); ! Py_XDECREF(x); ! Py_XDECREF(y); ! Py_DECREF(one); ! } Py_INCREF(Py_None); From tim_one@users.sourceforge.net Wed Jun 13 01:36:00 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 12 Jun 2001 17:36:00 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.74,1.75 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv10010/python/dist/src/Objects Modified Files: longobject.c Log Message: longobject.c: Replaced PyLong_{As,From}{Unsigned,}LongLong guts with calls to _PyLong_{As,From}ByteArray. _testcapimodule.c: Added strong tests of PyLong_{As,From}{Unsigned,}LongLong. Fixes SF bug #432552 PyLong_AsLongLong() problems. Possible bugfix candidate, but the fix relies on code added to longobject to support the new q/Q structmodule format codes. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.74 retrieving revision 1.75 diff -C2 -r1.74 -r1.75 *** longobject.c 2001/06/12 19:17:03 1.74 --- longobject.c 2001/06/13 00:35:57 1.75 *************** *** 523,688 **** #ifdef HAVE_LONG_LONG ! /* ! * LONG_LONG support by Chris Herborth (chrish@qnx.com) ! * ! * For better or worse :-), I tried to follow the coding style already ! * here. */ ! /* Create a new long int object from a C LONG_LONG int */ PyObject * PyLong_FromLongLong(LONG_LONG ival) { ! #if SIZEOF_LONG_LONG == SIZEOF_LONG ! /* In case the compiler is faking it. */ ! return PyLong_FromLong( (long)ival ); ! #else ! if ((LONG_LONG)LONG_MIN <= ival && ival <= (LONG_LONG)LONG_MAX) { ! return PyLong_FromLong( (long)ival ); ! } ! else if (0 <= ival && ival <= (unsigned LONG_LONG)ULONG_MAX) { ! return PyLong_FromUnsignedLong( (unsigned long)ival ); ! } ! else { ! /* Assume a C LONG_LONG fits in at most 10 'digits'. ! * Should be OK if we're assuming long fits in 5. ! */ ! PyLongObject *v = _PyLong_New(10); ! ! if (v != NULL) { ! unsigned LONG_LONG t = ival; ! int i; ! if (ival < 0) { ! t = -ival; ! v->ob_size = -(v->ob_size); ! } ! ! for (i = 0; i < 10; i++) { ! v->ob_digit[i] = (digit) (t & MASK); ! t >>= SHIFT; ! } ! ! v = long_normalize(v); ! } ! ! return (PyObject *)v; ! } ! #endif } - /* Create a new long int object from a C unsigned LONG_LONG int */ PyObject * PyLong_FromUnsignedLongLong(unsigned LONG_LONG ival) { ! #if SIZEOF_LONG_LONG == SIZEOF_LONG ! /* In case the compiler is faking it. */ ! return PyLong_FromUnsignedLong( (unsigned long)ival ); ! #else ! if( ival <= (unsigned LONG_LONG)ULONG_MAX ) { ! return PyLong_FromUnsignedLong( (unsigned long)ival ); ! } ! else { ! /* Assume a C long fits in at most 10 'digits'. */ ! PyLongObject *v = _PyLong_New(10); ! ! if (v != NULL) { ! unsigned LONG_LONG t = ival; ! int i; ! for (i = 0; i < 10; i++) { ! v->ob_digit[i] = (digit) (t & MASK); ! t >>= SHIFT; ! } ! ! v = long_normalize(v); ! } ! ! return (PyObject *)v; ! } ! #endif } /* Get a C LONG_LONG int from a long int object. ! Returns -1 and sets an error condition if overflow occurs. */ LONG_LONG PyLong_AsLongLong(PyObject *vv) { ! #if SIZEOF_LONG_LONG == SIZEOF_LONG ! /* In case the compiler is faking it. */ ! return (LONG_LONG)PyLong_AsLong( vv ); ! #else ! register PyLongObject *v; ! LONG_LONG x, prev; ! int i, sign; ! if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); return -1; } - - v = (PyLongObject *)vv; - i = v->ob_size; - sign = 1; - x = 0; - - if (i < 0) { - sign = -1; - i = -(i); - } ! while (--i >= 0) { ! prev = x; ! x = (x << SHIFT) + v->ob_digit[i]; ! if ((x >> SHIFT) != prev) { ! PyErr_SetString(PyExc_OverflowError, ! "long int too long to convert"); ! return -1; ! } ! } ! return x * sign; ! #endif } unsigned LONG_LONG PyLong_AsUnsignedLongLong(PyObject *vv) { ! #if SIZEOF_LONG_LONG == 4 ! /* In case the compiler is faking it. */ ! return (unsigned LONG_LONG)PyLong_AsUnsignedLong( vv ); ! #else ! register PyLongObject *v; ! unsigned LONG_LONG x, prev; ! int i; ! if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); ! return (unsigned LONG_LONG) -1; ! } ! ! v = (PyLongObject *)vv; ! i = v->ob_size; ! x = 0; ! ! if (i < 0) { ! PyErr_SetString(PyExc_OverflowError, ! "can't convert negative value to unsigned long"); ! return (unsigned LONG_LONG) -1; } ! while (--i >= 0) { ! prev = x; ! x = (x << SHIFT) + v->ob_digit[i]; ! if ((x >> SHIFT) != prev) { ! PyErr_SetString(PyExc_OverflowError, ! "long int too long to convert"); ! return (unsigned LONG_LONG) -1; ! } ! } ! return x; ! #endif } #endif /* HAVE_LONG_LONG */ --- 523,603 ---- #ifdef HAVE_LONG_LONG ! ! /* Initial LONG_LONG support by Chris Herborth (chrish@qnx.com), later ! * rewritten to use the newer PyLong_{As,From}ByteArray API. */ + + #define IS_LITTLE_ENDIAN *(char*)&one != '\0' ! /* Create a new long int object from a C LONG_LONG int. */ PyObject * PyLong_FromLongLong(LONG_LONG ival) { ! LONG_LONG bytes = ival; ! int one = 1; ! return _PyLong_FromByteArray( ! (unsigned char *)&bytes, ! SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1); } + + /* Create a new long int object from a C unsigned LONG_LONG int. */ PyObject * PyLong_FromUnsignedLongLong(unsigned LONG_LONG ival) { ! unsigned LONG_LONG bytes = ival; ! int one = 1; ! return _PyLong_FromByteArray( ! (unsigned char *)&bytes, ! SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0); } /* Get a C LONG_LONG int from a long int object. ! Return -1 and set an error if overflow occurs. */ LONG_LONG PyLong_AsLongLong(PyObject *vv) { ! LONG_LONG bytes; ! int one = 1; ! int res; ! if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); return -1; } ! res = _PyLong_AsByteArray( ! (PyLongObject *)vv, (unsigned char *)&bytes, ! SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1); ! return (LONG_LONG)(res < 0 ? res : bytes); } + /* Get a C unsigned LONG_LONG int from a long int object. + Return -1 and set an error if overflow occurs. */ + unsigned LONG_LONG PyLong_AsUnsignedLongLong(PyObject *vv) { ! unsigned LONG_LONG bytes; ! int one = 1; ! int res; ! if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); ! return -1; } ! res = _PyLong_AsByteArray( ! (PyLongObject *)vv, (unsigned char *)&bytes, ! SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0); ! return (unsigned LONG_LONG)(res < 0 ? res : bytes); } + + #undef IS_LITTLE_ENDIAN + #endif /* HAVE_LONG_LONG */ From tim_one@users.sourceforge.net Wed Jun 13 02:26:37 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 12 Jun 2001 18:26:37 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules structmodule.c,2.47,2.48 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv17987/python/dist/src/Modules Modified Files: structmodule.c Log Message: The new {b,l}p_{u,}longlong() didn't check get_pylong()'s return for NULL. Repaired that, and added appropriate tests for it to test_struct.py. Index: structmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/structmodule.c,v retrieving revision 2.47 retrieving revision 2.48 diff -C2 -r2.47 -r2.48 *** structmodule.c 2001/06/12 01:22:21 2.47 --- structmodule.c 2001/06/13 01:26:35 2.48 *************** *** 875,878 **** --- 875,880 ---- int res; v = get_pylong(v); + if (v == NULL) + return -1; res = _PyLong_AsByteArray((PyLongObject *)v, (unsigned char *)p, *************** *** 889,892 **** --- 891,896 ---- int res; v = get_pylong(v); + if (v == NULL) + return -1; res = _PyLong_AsByteArray((PyLongObject *)v, (unsigned char *)p, *************** *** 1037,1040 **** --- 1041,1046 ---- int res; v = get_pylong(v); + if (v == NULL) + return -1; res = _PyLong_AsByteArray((PyLongObject*)v, (unsigned char *)p, *************** *** 1051,1054 **** --- 1057,1062 ---- int res; v = get_pylong(v); + if (v == NULL) + return -1; res = _PyLong_AsByteArray((PyLongObject*)v, (unsigned char *)p, From tim_one@users.sourceforge.net Wed Jun 13 02:26:37 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 12 Jun 2001 18:26:37 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_struct.py,1.10,1.11 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv17987/python/dist/src/Lib/test Modified Files: test_struct.py Log Message: The new {b,l}p_{u,}longlong() didn't check get_pylong()'s return for NULL. Repaired that, and added appropriate tests for it to test_struct.py. Index: test_struct.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_struct.py,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -r1.10 -r1.11 *** test_struct.py 2001/06/12 01:22:21 1.10 --- test_struct.py 2001/06/13 01:26:35 1.11 *************** *** 315,317 **** --- 315,323 ---- test_one_qQ(x) + # Some error cases. + for direction in "<>": + for letter in "qQ": + for badobject in "a string", 3+42j, randrange: + any_err(struct.pack, direction + letter, badobject) + test_std_qQ() From jackjansen@users.sourceforge.net Wed Jun 13 13:38:49 2001 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Wed, 13 Jun 2001 05:38:49 -0700 Subject: [Python-checkins] CVS: python/dist/src/Mac/Modules/qd Qdmodule.c,1.39,1.40 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/qd In directory usw-pr-cvs1:/tmp/cvs-serv27006/python/Mac/Modules/qd Modified Files: Qdmodule.c Log Message: Fixed an error in the signature of the QdRGB converter routines. Index: Qdmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/qd/Qdmodule.c,v retrieving revision 1.39 retrieving revision 1.40 diff -C2 -r1.39 -r1.40 *** Qdmodule.c 2001/05/22 21:53:41 1.39 --- Qdmodule.c 2001/06/13 12:38:47 1.40 *************** *** 21,25 **** extern int _BMObj_Convert(PyObject *, BitMapPtr *); extern PyObject *_QdRGB_New(RGBColorPtr); ! extern int _QdRGB_Convert(PyObject *, RGBColorPtr *); #define GrafObj_New _GrafObj_New --- 21,25 ---- extern int _BMObj_Convert(PyObject *, BitMapPtr *); extern PyObject *_QdRGB_New(RGBColorPtr); ! extern int _QdRGB_Convert(PyObject *, RGBColorPtr); #define GrafObj_New _GrafObj_New *************** *** 5651,5655 **** PyMac_INIT_TOOLBOX_OBJECT_CONVERT(GrafPtr, GrafObj_Convert); PyMac_INIT_TOOLBOX_OBJECT_NEW(RGBColorPtr, QdRGB_New); ! PyMac_INIT_TOOLBOX_OBJECT_CONVERT(RGBColorPtr, QdRGB_Convert); --- 5651,5655 ---- PyMac_INIT_TOOLBOX_OBJECT_CONVERT(GrafPtr, GrafObj_Convert); PyMac_INIT_TOOLBOX_OBJECT_NEW(RGBColorPtr, QdRGB_New); ! PyMac_INIT_TOOLBOX_OBJECT_CONVERT(RGBColor, QdRGB_Convert); From jackjansen@users.sourceforge.net Wed Jun 13 13:39:05 2001 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Wed, 13 Jun 2001 05:39:05 -0700 Subject: [Python-checkins] CVS: python/dist/src/Mac/Modules/qd qdsupport.py,1.31,1.32 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/qd In directory usw-pr-cvs1:/tmp/cvs-serv27084/python/Mac/Modules/qd Modified Files: qdsupport.py Log Message: Fixed an error in the signature of the QdRGB converter routines. Index: qdsupport.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/qd/qdsupport.py,v retrieving revision 1.31 retrieving revision 1.32 diff -C2 -r1.31 -r1.32 *** qdsupport.py 2001/05/22 21:54:12 1.31 --- qdsupport.py 2001/06/13 12:39:02 1.32 *************** *** 74,78 **** extern int _BMObj_Convert(PyObject *, BitMapPtr *); extern PyObject *_QdRGB_New(RGBColorPtr); ! extern int _QdRGB_Convert(PyObject *, RGBColorPtr *); #define GrafObj_New _GrafObj_New --- 74,78 ---- extern int _BMObj_Convert(PyObject *, BitMapPtr *); extern PyObject *_QdRGB_New(RGBColorPtr); ! extern int _QdRGB_Convert(PyObject *, RGBColorPtr); #define GrafObj_New _GrafObj_New *************** *** 223,227 **** PyMac_INIT_TOOLBOX_OBJECT_CONVERT(GrafPtr, GrafObj_Convert); PyMac_INIT_TOOLBOX_OBJECT_NEW(RGBColorPtr, QdRGB_New); ! PyMac_INIT_TOOLBOX_OBJECT_CONVERT(RGBColorPtr, QdRGB_Convert); """ --- 223,227 ---- PyMac_INIT_TOOLBOX_OBJECT_CONVERT(GrafPtr, GrafObj_Convert); PyMac_INIT_TOOLBOX_OBJECT_NEW(RGBColorPtr, QdRGB_New); ! PyMac_INIT_TOOLBOX_OBJECT_CONVERT(RGBColor, QdRGB_Convert); """ From jackjansen@users.sourceforge.net Wed Jun 13 13:41:27 2001 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Wed, 13 Jun 2001 05:41:27 -0700 Subject: [Python-checkins] CVS: python/dist/src/Mac/Build PythonCore.mcp,1.21,1.22 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Build In directory usw-pr-cvs1:/tmp/cvs-serv27500/python/Mac/Build Modified Files: PythonCore.mcp Log Message: Got rid of mactoolboxglue.c Index: PythonCore.mcp =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Build/PythonCore.mcp,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -r1.21 -r1.22 Binary files /tmp/cvs6vXXwK and /tmp/cvsKa5Ovm differ From gvanrossum@users.sourceforge.net Wed Jun 13 16:15:04 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 13 Jun 2001 08:15:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.81.2.41,1.81.2.42 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv31452/Misc Modified Files: Tag: release20-maint NEWS Log Message: Bring SRE up do date with Python 2.1 Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.81.2.41 retrieving revision 1.81.2.42 diff -C2 -r1.81.2.41 -r1.81.2.42 *** NEWS 2001/04/13 15:52:40 1.81.2.41 --- NEWS 2001/06/13 15:15:02 1.81.2.42 *************** *** 14,17 **** --- 14,19 ---- http://sourceforge.net/tracker/index.php?func=detail&aid=&group_id=5470&atid=105470 + - Brought SRE up to date with Python 2.1 + - #117278, #117167: _tkinter From gvanrossum@users.sourceforge.net Wed Jun 13 16:15:04 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 13 Jun 2001 08:15:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib sre.py,1.25,1.25.2.1 sre_compile.py,1.31,1.31.2.1 sre_constants.py,1.21,1.21.2.1 sre_parse.py,1.37,1.37.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv31452/Lib Modified Files: Tag: release20-maint sre.py sre_compile.py sre_constants.py sre_parse.py Log Message: Bring SRE up do date with Python 2.1 Index: sre.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/sre.py,v retrieving revision 1.25 retrieving revision 1.25.2.1 diff -C2 -r1.25 -r1.25.2.1 *** sre.py 2000/09/21 17:03:24 1.25 --- sre.py 2001/06/13 15:15:02 1.25.2.1 *************** *** 4,8 **** # re-compatible interface for the sre matching engine # ! # Copyright (c) 1998-2000 by Secret Labs AB. All rights reserved. # # This version of the SRE library can be redistributed under CNRI's --- 4,8 ---- # re-compatible interface for the sre matching engine # ! # Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. # # This version of the SRE library can be redistributed under CNRI's *************** *** 15,35 **** # - # FIXME: change all FIXME's to XXX ;-) - import sre_compile import sre_parse import string # flags ! I = IGNORECASE = sre_compile.SRE_FLAG_IGNORECASE ! L = LOCALE = sre_compile.SRE_FLAG_LOCALE ! M = MULTILINE = sre_compile.SRE_FLAG_MULTILINE ! S = DOTALL = sre_compile.SRE_FLAG_DOTALL ! X = VERBOSE = sre_compile.SRE_FLAG_VERBOSE ! ! # sre extensions (may or may not be in 1.6/2.0 final) ! T = TEMPLATE = sre_compile.SRE_FLAG_TEMPLATE ! U = UNICODE = sre_compile.SRE_FLAG_UNICODE # sre exception --- 15,43 ---- # import sre_compile import sre_parse + # public symbols + __all__ = [ "match", "search", "sub", "subn", "split", "findall", + "compile", "purge", "template", "escape", "I", "L", "M", "S", "X", + "U", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE", + "UNICODE", "error" ] + + __version__ = "2.1b2" + + # this module works under 1.5.2 and later. don't use string methods import string # flags ! I = IGNORECASE = sre_compile.SRE_FLAG_IGNORECASE # ignore case ! L = LOCALE = sre_compile.SRE_FLAG_LOCALE # assume current 8-bit locale ! U = UNICODE = sre_compile.SRE_FLAG_UNICODE # assume unicode locale ! M = MULTILINE = sre_compile.SRE_FLAG_MULTILINE # make anchors look for newline ! S = DOTALL = sre_compile.SRE_FLAG_DOTALL # make dot match newline ! X = VERBOSE = sre_compile.SRE_FLAG_VERBOSE # ignore whitespace and comments ! ! # sre extensions (experimental, don't rely on these) ! T = TEMPLATE = sre_compile.SRE_FLAG_TEMPLATE # disable backtracking ! DEBUG = sre_compile.SRE_FLAG_DEBUG # dump pattern after compilation # sre exception *************** *** 39,72 **** # public interface - # FIXME: add docstrings - def match(pattern, string, flags=0): return _compile(pattern, flags).match(string) def search(pattern, string, flags=0): return _compile(pattern, flags).search(string) def sub(pattern, repl, string, count=0): return _compile(pattern, 0).sub(repl, string, count) def subn(pattern, repl, string, count=0): return _compile(pattern, 0).subn(repl, string, count) def split(pattern, string, maxsplit=0): return _compile(pattern, 0).split(string, maxsplit) def findall(pattern, string, maxsplit=0): return _compile(pattern, 0).findall(string, maxsplit) def compile(pattern, flags=0): return _compile(pattern, flags) def purge(): _cache.clear() def template(pattern, flags=0): return _compile(pattern, flags|T) def escape(pattern): s = list(pattern) for i in range(len(pattern)): --- 47,104 ---- # public interface def match(pattern, string, flags=0): + """Try to apply the pattern at the start of the string, returning + a match object, or None if no match was found.""" return _compile(pattern, flags).match(string) def search(pattern, string, flags=0): + """Scan through string looking for a match to the pattern, returning + a match object, or None if no match was found.""" return _compile(pattern, flags).search(string) def sub(pattern, repl, string, count=0): + """Return the string obtained by replacing the leftmost + non-overlapping occurrences of the pattern in string by the + replacement repl""" return _compile(pattern, 0).sub(repl, string, count) def subn(pattern, repl, string, count=0): + """Return a 2-tuple containing (new_string, number). + new_string is the string obtained by replacing the leftmost + non-overlapping occurrences of the pattern in the source + string by the replacement repl. number is the number of + substitutions that were made.""" return _compile(pattern, 0).subn(repl, string, count) def split(pattern, string, maxsplit=0): + """Split the source string by the occurrences of the pattern, + returning a list containing the resulting substrings.""" return _compile(pattern, 0).split(string, maxsplit) def findall(pattern, string, maxsplit=0): + """Return a list of all non-overlapping matches in the string. + + If one or more groups are present in the pattern, return a + list of groups; this will be a list of tuples if the pattern + has more than one group. + + Empty matches are included in the result.""" return _compile(pattern, 0).findall(string, maxsplit) def compile(pattern, flags=0): + "Compile a regular expression pattern, returning a pattern object." return _compile(pattern, flags) def purge(): + "Clear the regular expression cache" _cache.clear() + _cache_repl.clear() def template(pattern, flags=0): + "Compile a template pattern, returning a pattern object" return _compile(pattern, flags|T) def escape(pattern): + "Escape all non-alphanumeric characters in pattern." s = list(pattern) for i in range(len(pattern)): *************** *** 83,86 **** --- 115,120 ---- _cache = {} + _cache_repl = {} + _MAXCACHE = 100 *************** *** 106,109 **** --- 140,158 ---- return p + def _compile_repl(*key): + # internal: compile replacement pattern + p = _cache_repl.get(key) + if p is not None: + return p + repl, pattern = key + try: + p = sre_parse.parse_template(repl, pattern) + except error, v: + raise error, v # invalid expression + if len(_cache_repl) >= _MAXCACHE: + _cache_repl.clear() + _cache_repl[key] = p + return p + def _expand(pattern, match, template): # internal: match.expand implementation hook *************** *** 120,124 **** filter = template else: ! template = sre_parse.parse_template(template, pattern) def filter(match, template=template): return sre_parse.expand_template(template, match) --- 169,173 ---- filter = template else: ! template = _compile_repl(template, pattern) def filter(match, template=template): return sre_parse.expand_template(template, match) *************** *** 159,163 **** append(string[i:b]) if g and b != e: ! extend(m.groups()) i = e n = n + 1 --- 208,212 ---- append(string[i:b]) if g and b != e: ! extend(list(m.groups())) i = e n = n + 1 *************** *** 205,209 **** action = self.lexicon[m.lastindex][1] if callable(action): ! self.match = match action = action(self, m.group()) if action is not None: --- 254,258 ---- action = self.lexicon[m.lastindex][1] if callable(action): ! self.match = m action = action(self, m.group()) if action is not None: Index: sre_compile.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/sre_compile.py,v retrieving revision 1.31 retrieving revision 1.31.2.1 diff -C2 -r1.31 -r1.31.2.1 *** sre_compile.py 2000/10/07 17:38:22 1.31 --- sre_compile.py 2001/06/13 15:15:02 1.31.2.1 *************** *** 4,8 **** # convert template to internal format # ! # Copyright (c) 1997-2000 by Secret Labs AB. All rights reserved. # # See the sre.py file for information on usage and redistribution. --- 4,8 ---- # convert template to internal format # ! # Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. # # See the sre.py file for information on usage and redistribution. *************** *** 13,16 **** --- 13,18 ---- from sre_constants import * + assert _sre.MAGIC == MAGIC, "SRE module mismatch" + MAXCODE = 65535 *************** *** 22,28 **** if flags & SRE_FLAG_IGNORECASE: emit(OPCODES[OP_IGNORE[op]]) else: emit(OPCODES[op]) ! emit(av) elif op is IN: if flags & SRE_FLAG_IGNORECASE: --- 24,31 ---- if flags & SRE_FLAG_IGNORECASE: emit(OPCODES[OP_IGNORE[op]]) + emit(_sre.getlower(av, flags)) else: emit(OPCODES[op]) ! emit(av) elif op is IN: if flags & SRE_FLAG_IGNORECASE: *************** *** 103,109 **** emit(OPCODES[op]) if flags & SRE_FLAG_MULTILINE: ! emit(ATCODES[AT_MULTILINE.get(av, av)]) ! else: ! emit(ATCODES[av]) elif op is BRANCH: emit(OPCODES[op]) --- 106,115 ---- emit(OPCODES[op]) if flags & SRE_FLAG_MULTILINE: ! av = AT_MULTILINE.get(av, av) ! if flags & SRE_FLAG_LOCALE: ! av = AT_LOCALE.get(av, av) ! elif flags & SRE_FLAG_UNICODE: ! av = AT_UNICODE.get(av, av) ! emit(ATCODES[av]) elif op is BRANCH: emit(OPCODES[op]) *************** *** 122,130 **** emit(OPCODES[op]) if flags & SRE_FLAG_LOCALE: ! emit(CHCODES[CH_LOCALE[av]]) elif flags & SRE_FLAG_UNICODE: ! emit(CHCODES[CH_UNICODE[av]]) ! else: ! emit(CHCODES[av]) elif op is GROUPREF: if flags & SRE_FLAG_IGNORECASE: --- 128,135 ---- emit(OPCODES[op]) if flags & SRE_FLAG_LOCALE: ! av = CH_LOCALE[av] elif flags & SRE_FLAG_UNICODE: ! av = CH_UNICODE[av] ! emit(CHCODES[av]) elif op is GROUPREF: if flags & SRE_FLAG_IGNORECASE: *************** *** 177,181 **** charmap[i] = 1 elif op is CATEGORY: ! # FIXME: could append to charmap tail return charset # cannot compress except IndexError: --- 182,186 ---- charmap[i] = 1 elif op is CATEGORY: ! # XXX: could append to charmap tail return charset # cannot compress except IndexError: *************** *** 365,369 **** # print code ! # FIXME: get rid of this limitation! assert p.pattern.groups <= 100,\ "sorry, but this version only supports 100 named groups" --- 370,374 ---- # print code ! # XXX: get rid of this limitation! assert p.pattern.groups <= 100,\ "sorry, but this version only supports 100 named groups" Index: sre_constants.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/sre_constants.py,v retrieving revision 1.21 retrieving revision 1.21.2.1 diff -C2 -r1.21 -r1.21.2.1 *** sre_constants.py 2000/10/07 17:38:22 1.21 --- sre_constants.py 2001/06/13 15:15:02 1.21.2.1 *************** *** 5,15 **** # run this script to update the _sre include files! # ! # Copyright (c) 1998-2000 by Secret Labs AB. All rights reserved. # # See the sre.py file for information on usage and redistribution. # MAXREPEAT = 65535 # should this really be here? --- 5,22 ---- # run this script to update the _sre include files! # ! # Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. # # See the sre.py file for information on usage and redistribution. # + # update when constants are added or removed + + MAGIC = 20010320 + + # max code word in this release + MAXREPEAT = 65535 + # SRE standard exception (access as sre.error) # should this really be here? *************** *** 55,62 **** --- 62,75 ---- AT_BEGINNING = "at_beginning" AT_BEGINNING_LINE = "at_beginning_line" + AT_BEGINNING_STRING = "at_beginning_string" AT_BOUNDARY = "at_boundary" AT_NON_BOUNDARY = "at_non_boundary" AT_END = "at_end" AT_END_LINE = "at_end_line" + AT_END_STRING = "at_end_string" + AT_LOC_BOUNDARY = "at_loc_boundary" + AT_LOC_NON_BOUNDARY = "at_loc_non_boundary" + AT_UNI_BOUNDARY = "at_uni_boundary" + AT_UNI_NON_BOUNDARY = "at_uni_non_boundary" # categories *************** *** 110,115 **** ATCODES = [ ! AT_BEGINNING, AT_BEGINNING_LINE, AT_BOUNDARY, ! AT_NON_BOUNDARY, AT_END, AT_END_LINE ] --- 123,130 ---- ATCODES = [ ! AT_BEGINNING, AT_BEGINNING_LINE, AT_BEGINNING_STRING, AT_BOUNDARY, ! AT_NON_BOUNDARY, AT_END, AT_END_LINE, AT_END_STRING, ! AT_LOC_BOUNDARY, AT_LOC_NON_BOUNDARY, AT_UNI_BOUNDARY, ! AT_UNI_NON_BOUNDARY ] *************** *** 149,152 **** --- 164,177 ---- } + AT_LOCALE = { + AT_BOUNDARY: AT_LOC_BOUNDARY, + AT_NON_BOUNDARY: AT_LOC_NON_BOUNDARY + } + + AT_UNICODE = { + AT_BOUNDARY: AT_UNI_BOUNDARY, + AT_NON_BOUNDARY: AT_UNI_NON_BOUNDARY + } + CH_LOCALE = { CATEGORY_DIGIT: CATEGORY_DIGIT, *************** *** 179,182 **** --- 204,208 ---- SRE_FLAG_UNICODE = 32 # use unicode locale SRE_FLAG_VERBOSE = 64 # ignore whitespace and comments + SRE_FLAG_DEBUG = 128 # debugging # flags for INFO primitive *************** *** 202,206 **** * to change anything in here, edit sre_constants.py and run it. * ! * Copyright (c) 1997-2000 by Secret Labs AB. All rights reserved. * * See the _sre.c file for information on usage and redistribution. --- 228,232 ---- * to change anything in here, edit sre_constants.py and run it. * ! * Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. * * See the _sre.c file for information on usage and redistribution. *************** *** 208,211 **** --- 234,239 ---- """) + + f.write("#define SRE_MAGIC %d\n" % MAGIC) dump(f, OPCODES, "SRE_OP") Index: sre_parse.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/sre_parse.py,v retrieving revision 1.37 retrieving revision 1.37.2.1 diff -C2 -r1.37 -r1.37.2.1 *** sre_parse.py 2000/10/07 17:38:22 1.37 --- sre_parse.py 2001/06/13 15:15:02 1.37.2.1 *************** *** 4,12 **** # convert re-style regular expression to sre pattern # ! # Copyright (c) 1998-2000 by Secret Labs AB. All rights reserved. # # See the sre.py file for information on usage and redistribution. # import string, sys --- 4,15 ---- # convert re-style regular expression to sre pattern # ! # Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. # # See the sre.py file for information on usage and redistribution. # + # XXX: show string offset and offending character for all errors + + # this module works under 1.5.2 and later. don't use string methods import string, sys *************** *** 24,39 **** ESCAPES = { ! r"\a": (LITERAL, 7), ! r"\b": (LITERAL, 8), ! r"\f": (LITERAL, 12), ! r"\n": (LITERAL, 10), ! r"\r": (LITERAL, 13), ! r"\t": (LITERAL, 9), ! r"\v": (LITERAL, 11), r"\\": (LITERAL, ord("\\")) } CATEGORIES = { ! r"\A": (AT, AT_BEGINNING), # start of string r"\b": (AT, AT_BOUNDARY), r"\B": (AT, AT_NON_BOUNDARY), --- 27,42 ---- ESCAPES = { ! r"\a": (LITERAL, ord("\a")), ! r"\b": (LITERAL, ord("\b")), ! r"\f": (LITERAL, ord("\f")), ! r"\n": (LITERAL, ord("\n")), ! r"\r": (LITERAL, ord("\r")), ! r"\t": (LITERAL, ord("\t")), ! r"\v": (LITERAL, ord("\v")), r"\\": (LITERAL, ord("\\")) } CATEGORIES = { ! r"\A": (AT, AT_BEGINNING_STRING), # start of string r"\b": (AT, AT_BOUNDARY), r"\B": (AT, AT_NON_BOUNDARY), *************** *** 44,48 **** r"\w": (IN, [(CATEGORY, CATEGORY_WORD)]), r"\W": (IN, [(CATEGORY, CATEGORY_NOT_WORD)]), ! r"\Z": (AT, AT_END), # end of string } --- 47,51 ---- r"\w": (IN, [(CATEGORY, CATEGORY_WORD)]), r"\W": (IN, [(CATEGORY, CATEGORY_NOT_WORD)]), ! r"\Z": (AT, AT_END_STRING), # end of string } *************** *** 59,74 **** } class Pattern: # master pattern object. keeps track of global attributes def __init__(self): self.flags = 0 self.groups = 1 self.groupdict = {} ! def getgroup(self, name=None): gid = self.groups self.groups = gid + 1 if name: self.groupdict[name] = gid return gid class SubPattern: --- 62,90 ---- } + # figure out best way to convert hex/octal numbers to integers + try: + int("10", 8) + atoi = int # 2.0 and later + except TypeError: + atoi = string.atoi # 1.5.2 + class Pattern: # master pattern object. keeps track of global attributes def __init__(self): self.flags = 0 + self.open = [] self.groups = 1 self.groupdict = {} ! def opengroup(self, name=None): gid = self.groups self.groups = gid + 1 if name: self.groupdict[name] = gid + self.open.append(gid) return gid + def closegroup(self, gid): + self.open.remove(gid) + def checkgroup(self, gid): + return gid < self.groups and gid not in self.open class SubPattern: *************** *** 209,213 **** # check if the escape string represents a valid group try: ! gid = int(escape[1:]) if gid and gid < groups: return gid --- 225,229 ---- # check if the escape string represents a valid group try: ! gid = atoi(escape[1:]) if gid and gid < groups: return gid *************** *** 232,236 **** if len(escape) != 2: raise error, "bogus escape: %s" % repr("\\" + escape) ! return LITERAL, int(escape, 16) & 0xff elif str(escape[1:2]) in OCTDIGITS: # octal escape (up to three digits) --- 248,252 ---- if len(escape) != 2: raise error, "bogus escape: %s" % repr("\\" + escape) ! return LITERAL, atoi(escape, 16) & 0xff elif str(escape[1:2]) in OCTDIGITS: # octal escape (up to three digits) *************** *** 238,242 **** escape = escape + source.get() escape = escape[1:] ! return LITERAL, int(escape, 8) & 0xff if len(escape) == 2: return LITERAL, ord(escape[1]) --- 254,258 ---- escape = escape + source.get() escape = escape[1:] ! return LITERAL, atoi(escape, 8) & 0xff if len(escape) == 2: return LITERAL, ord(escape[1]) *************** *** 260,269 **** if len(escape) != 4: raise ValueError ! return LITERAL, int(escape[2:], 16) & 0xff elif escape[1:2] == "0": # octal escape while source.next in OCTDIGITS and len(escape) < 4: escape = escape + source.get() ! return LITERAL, int(escape[1:], 8) & 0xff elif escape[1:2] in DIGITS: # octal escape *or* decimal group reference (sigh) --- 276,285 ---- if len(escape) != 4: raise ValueError ! return LITERAL, atoi(escape[2:], 16) & 0xff elif escape[1:2] == "0": # octal escape while source.next in OCTDIGITS and len(escape) < 4: escape = escape + source.get() ! return LITERAL, atoi(escape[1:], 8) & 0xff elif escape[1:2] in DIGITS: # octal escape *or* decimal group reference (sigh) *************** *** 275,282 **** # got three octal digits; this is an octal escape escape = escape + source.get() ! return LITERAL, int(escape[1:], 8) & 0xff # got at least one decimal digit; this is a group reference group = _group(escape, state.groups) if group: return GROUPREF, group raise ValueError --- 291,300 ---- # got three octal digits; this is an octal escape escape = escape + source.get() ! return LITERAL, atoi(escape[1:], 8) & 0xff # got at least one decimal digit; this is a group reference group = _group(escape, state.groups) if group: + if not state.checkgroup(group): + raise error, "cannot refer to open group" return GROUPREF, group raise ValueError *************** *** 403,411 **** code2 = LITERAL, ord(this) if code1[0] != LITERAL or code2[0] != LITERAL: ! raise error, "illegal range" lo = code1[1] hi = code2[1] if hi < lo: ! raise error, "illegal range" set.append((RANGE, (lo, hi))) else: --- 421,429 ---- code2 = LITERAL, ord(this) if code1[0] != LITERAL or code2[0] != LITERAL: ! raise error, "bad character range" lo = code1[1] hi = code2[1] if hi < lo: ! raise error, "bad character range" set.append((RANGE, (lo, hi))) else: *************** *** 414,418 **** set.append(code1) ! # FIXME: move set optimization to compiler! if len(set)==1 and set[0][0] is LITERAL: subpattern.append(set[0]) # optimization --- 432,436 ---- set.append(code1) ! # XXX: should move set optimization to compiler! if len(set)==1 and set[0][0] is LITERAL: subpattern.append(set[0]) # optimization *************** *** 420,424 **** subpattern.append((NOT_LITERAL, set[1][1])) # optimization else: ! # FIXME: add charmap optimization subpattern.append((IN, set)) --- 438,442 ---- subpattern.append((NOT_LITERAL, set[1][1])) # optimization else: ! # XXX: should add charmap optimization here subpattern.append((IN, set)) *************** *** 429,432 **** --- 447,451 ---- elif this == "*": min, max = 0, MAXREPEAT + elif this == "+": min, max = 1, MAXREPEAT *************** *** 447,454 **** continue if lo: ! min = int(lo) if hi: ! max = int(hi) ! # FIXME: check that hi >= lo! else: raise error, "not supported" --- 466,474 ---- continue if lo: ! min = atoi(lo) if hi: ! max = atoi(hi) ! if max < min: ! raise error, "bad repeat interval" else: raise error, "not supported" *************** *** 457,461 **** --- 477,485 ---- item = subpattern[-1:] else: + item = None + if not item or (len(item) == 1 and item[0][0] == AT): raise error, "nothing to repeat" + if item[0][0] in (MIN_REPEAT, MAX_REPEAT): + raise error, "multiple repeat" if source.match("?"): subpattern[-1] = (MIN_REPEAT, (min, max, item)) *************** *** 486,490 **** group = 1 if not isname(name): ! raise error, "illegal character in group name" elif source.match("="): # named backreference --- 510,514 ---- group = 1 if not isname(name): ! raise error, "bad character in group name" elif source.match("="): # named backreference *************** *** 498,502 **** name = name + char if not isname(name): ! raise error, "illegal character in group name" gid = state.groupdict.get(name) if gid is None: --- 522,526 ---- name = name + char if not isname(name): ! raise error, "bad character in group name" gid = state.groupdict.get(name) if gid is None: *************** *** 540,543 **** --- 564,569 ---- else: # flags + if not FLAGS.has_key(source.next): + raise error, "unexpected end of pattern" while FLAGS.has_key(source.next): state.flags = state.flags | FLAGS[source.get()] *************** *** 548,560 **** group = None else: ! group = state.getgroup(name) p = _parse_sub(source, state) if not source.match(")"): raise error, "unbalanced parenthesis" subpattern.append((SUBPATTERN, (group, p))) else: while 1: char = source.get() ! if char is None or char == ")": break raise error, "unknown extension" --- 574,590 ---- group = None else: ! group = state.opengroup(name) p = _parse_sub(source, state) if not source.match(")"): raise error, "unbalanced parenthesis" + if group is not None: + state.closegroup(group) subpattern.append((SUBPATTERN, (group, p))) else: while 1: char = source.get() ! if char is None: ! raise error, "unexpected end of pattern" ! if char == ")": break raise error, "unknown extension" *************** *** 583,586 **** --- 613,617 ---- pattern = Pattern() pattern.flags = flags + pattern.str = str p = _parse_sub(source, pattern, 0) *************** *** 592,596 **** raise error, "bogus characters at end of regular expression" ! # p.dump() if not (flags & SRE_FLAG_VERBOSE) and p.pattern.flags & SRE_FLAG_VERBOSE: --- 623,628 ---- raise error, "bogus characters at end of regular expression" ! if flags & SRE_FLAG_DEBUG: ! p.dump() if not (flags & SRE_FLAG_VERBOSE) and p.pattern.flags & SRE_FLAG_VERBOSE: *************** *** 607,610 **** --- 639,652 ---- p = [] a = p.append + def literal(literal, p=p): + if p and p[-1][0] is LITERAL: + p[-1] = LITERAL, p[-1][1] + literal + else: + p.append((LITERAL, literal)) + sep = source[:0] + if type(sep) is type(""): + char = chr + else: + char = unichr while 1: this = s.get() *************** *** 626,633 **** raise error, "bad group name" try: ! index = int(name) except ValueError: if not isname(name): ! raise error, "illegal character in group name" try: index = pattern.groupindex[name] --- 668,675 ---- raise error, "bad group name" try: ! index = atoi(name) except ValueError: if not isname(name): ! raise error, "bad character in group name" try: index = pattern.groupindex[name] *************** *** 642,646 **** if (s.next not in DIGITS or not _group(this + s.next, pattern.groups+1)): ! code = MARK, int(group) break elif s.next in OCTDIGITS: --- 684,688 ---- if (s.next not in DIGITS or not _group(this + s.next, pattern.groups+1)): ! code = MARK, group break elif s.next in OCTDIGITS: *************** *** 650,682 **** if not code: this = this[1:] ! code = LITERAL, int(this[-6:], 8) & 0xff ! a(code) else: try: ! a(ESCAPES[this]) except KeyError: ! for c in this: ! a((LITERAL, ord(c))) else: ! a((LITERAL, ord(this))) ! return p def expand_template(template, match): ! # FIXME: this is sooooo slow. drop in the slicelist ! # code instead ! p = [] ! a = p.append sep = match.string[:0] ! if type(sep) is type(""): ! char = chr ! else: ! char = unichr ! for c, s in template: ! if c is LITERAL: ! a(char(s)) ! elif c is MARK: ! s = match.group(s) if s is None: ! raise error, "empty group" ! a(s) ! return string.join(p, sep) --- 692,732 ---- if not code: this = this[1:] ! code = LITERAL, char(atoi(this[-6:], 8) & 0xff) ! if code[0] is LITERAL: ! literal(code[1]) ! else: ! a(code) else: try: ! this = char(ESCAPES[this][1]) except KeyError: ! pass ! literal(this) else: ! literal(this) ! # convert template to groups and literals lists ! i = 0 ! groups = [] ! literals = [] ! for c, s in p: ! if c is MARK: ! groups.append((i, s)) ! literals.append(None) ! else: ! literals.append(s) ! i = i + 1 ! return groups, literals def expand_template(template, match): ! g = match.group sep = match.string[:0] ! groups, literals = template ! literals = literals[:] ! try: ! for index, group in groups: ! literals[index] = s = g(group) if s is None: ! raise IndexError ! except IndexError: ! raise error, "empty group" ! return string.join(literals, sep) From gvanrossum@users.sourceforge.net Wed Jun 13 16:15:05 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 13 Jun 2001 08:15:05 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules _sre.c,2.45,2.45.2.1 sre_constants.h,2.9,2.9.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv31452/Modules Modified Files: Tag: release20-maint _sre.c sre_constants.h Log Message: Bring SRE up do date with Python 2.1 Index: _sre.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_sre.c,v retrieving revision 2.45 retrieving revision 2.45.2.1 diff -C2 -r2.45 -r2.45.2.1 *** _sre.c 2000/10/03 20:43:34 2.45 --- _sre.c 2001/06/13 15:15:02 2.45.2.1 *************** *** 6,17 **** * partial history: * 1999-10-24 fl created (based on existing template matcher code) ! * 2000-03-06 fl first alpha, sort of (0.5) ! * 2000-06-30 fl added fast search optimization (0.9.3) ! * 2000-06-30 fl added assert (lookahead) primitives, etc (0.9.4) ! * 2000-07-02 fl added charset optimizations, etc (0.9.5) * 2000-07-03 fl store code in pattern object, lookbehind, etc * 2000-07-08 fl added regs attribute ! * 2000-07-21 fl reset lastindex in scanner methods (0.9.6) ! * 2000-08-01 fl fixes for 1.6b1 (0.9.8) * 2000-08-03 fl added recursion limit * 2000-08-07 fl use PyOS_CheckStack() if available --- 6,17 ---- * partial history: * 1999-10-24 fl created (based on existing template matcher code) ! * 2000-03-06 fl first alpha, sort of ! * 2000-06-30 fl added fast search optimization ! * 2000-06-30 fl added assert (lookahead) primitives, etc ! * 2000-07-02 fl added charset optimizations, etc * 2000-07-03 fl store code in pattern object, lookbehind, etc * 2000-07-08 fl added regs attribute ! * 2000-07-21 fl reset lastindex in scanner methods ! * 2000-08-01 fl fixes for 1.6b1 * 2000-08-03 fl added recursion limit * 2000-08-07 fl use PyOS_CheckStack() if available *************** *** 22,27 **** * 2000-09-21 fl don't use the buffer interface for unicode strings * 2000-10-03 fl fixed assert_not primitive; support keyword arguments * ! * Copyright (c) 1997-2000 by Secret Labs AB. All rights reserved. * * This version of the SRE library can be redistributed under CNRI's --- 22,34 ---- * 2000-09-21 fl don't use the buffer interface for unicode strings * 2000-10-03 fl fixed assert_not primitive; support keyword arguments + * 2000-10-24 fl really fixed assert_not; reset groups in findall + * 2000-12-21 fl fixed memory leak in groupdict + * 2001-01-02 fl properly reset pointer after failed assertion in MIN_UNTIL + * 2001-01-15 fl avoid recursion for MIN_UNTIL; fixed uppercase literal bug + * 2001-01-16 fl fixed memory leak in pattern destructor + * 2001-03-20 fl lots of fixes for 2.1b2 + * 2001-04-15 fl export copyright as Python attribute, not global * ! * Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. * * This version of the SRE library can be redistributed under CNRI's *************** *** 36,40 **** #ifndef SRE_RECURSIVE ! char copyright[] = " SRE 0.9.8 Copyright (c) 1997-2000 by Secret Labs AB "; #include "Python.h" --- 43,48 ---- #ifndef SRE_RECURSIVE ! static char copyright[] = ! " SRE 2.1b2 Copyright (c) 1997-2001 by Secret Labs AB "; #include "Python.h" *************** *** 45,49 **** /* name of this module, minus the leading underscore */ ! #define MODULE "sre" /* defining this one enables tracing */ --- 53,59 ---- /* name of this module, minus the leading underscore */ ! #if !defined(SRE_MODULE) ! #define SRE_MODULE "sre" ! #endif /* defining this one enables tracing */ *************** *** 77,80 **** --- 87,94 ---- #undef USE_INLINE + #if PY_VERSION_HEX < 0x01060000 + #define PyObject_DEL(op) PyMem_DEL((op)) + #endif + /* -------------------------------------------------------------------- */ *************** *** 131,139 **** 120, 121, 122, 123, 124, 125, 126, 127 }; - static unsigned int sre_lower(unsigned int ch) - { - return ((ch) < 128 ? sre_char_lower[ch] : ch); - } - #define SRE_IS_DIGIT(ch)\ ((ch) < 128 ? (sre_char_info[(ch)] & SRE_DIGIT_MASK) : 0) --- 145,148 ---- *************** *** 147,156 **** ((ch) < 128 ? (sre_char_info[(ch)] & SRE_WORD_MASK) : 0) ! /* locale-specific character predicates */ ! ! static unsigned int sre_lower_locale(unsigned int ch) { ! return ((ch) < 256 ? tolower((ch)) : ch); } #define SRE_LOC_IS_DIGIT(ch) ((ch) < 256 ? isdigit((ch)) : 0) #define SRE_LOC_IS_SPACE(ch) ((ch) < 256 ? isspace((ch)) : 0) --- 156,166 ---- ((ch) < 128 ? (sre_char_info[(ch)] & SRE_WORD_MASK) : 0) ! static unsigned int sre_lower(unsigned int ch) { ! return ((ch) < 128 ? sre_char_lower[ch] : ch); } + + /* locale-specific character predicates */ + #define SRE_LOC_IS_DIGIT(ch) ((ch) < 256 ? isdigit((ch)) : 0) #define SRE_LOC_IS_SPACE(ch) ((ch) < 256 ? isspace((ch)) : 0) *************** *** 159,169 **** #define SRE_LOC_IS_WORD(ch) (SRE_LOC_IS_ALNUM((ch)) || (ch) == '_') /* unicode-specific character predicates */ #if defined(HAVE_UNICODE) ! static unsigned int sre_lower_unicode(unsigned int ch) ! { ! return (unsigned int) Py_UNICODE_TOLOWER((Py_UNICODE)(ch)); ! } #define SRE_UNI_IS_DIGIT(ch) Py_UNICODE_ISDIGIT((Py_UNICODE)(ch)) #define SRE_UNI_IS_SPACE(ch) Py_UNICODE_ISSPACE((Py_UNICODE)(ch)) --- 169,181 ---- #define SRE_LOC_IS_WORD(ch) (SRE_LOC_IS_ALNUM((ch)) || (ch) == '_') + static unsigned int sre_lower_locale(unsigned int ch) + { + return ((ch) < 256 ? tolower((ch)) : ch); + } + /* unicode-specific character predicates */ #if defined(HAVE_UNICODE) ! #define SRE_UNI_IS_DIGIT(ch) Py_UNICODE_ISDIGIT((Py_UNICODE)(ch)) #define SRE_UNI_IS_SPACE(ch) Py_UNICODE_ISSPACE((Py_UNICODE)(ch)) *************** *** 171,174 **** --- 183,192 ---- #define SRE_UNI_IS_ALNUM(ch) Py_UNICODE_ISALNUM((Py_UNICODE)(ch)) #define SRE_UNI_IS_WORD(ch) (SRE_UNI_IS_ALNUM((ch)) || (ch) == '_') + + static unsigned int sre_lower_unicode(unsigned int ch) + { + return (unsigned int) Py_UNICODE_TOLOWER((Py_UNICODE)(ch)); + } + #endif *************** *** 217,220 **** --- 235,255 ---- case SRE_CATEGORY_UNI_NOT_LINEBREAK: return !SRE_UNI_IS_LINEBREAK(ch); + #else + case SRE_CATEGORY_UNI_DIGIT: + return SRE_IS_DIGIT(ch); + case SRE_CATEGORY_UNI_NOT_DIGIT: + return !SRE_IS_DIGIT(ch); + case SRE_CATEGORY_UNI_SPACE: + return SRE_IS_SPACE(ch); + case SRE_CATEGORY_UNI_NOT_SPACE: + return !SRE_IS_SPACE(ch); + case SRE_CATEGORY_UNI_WORD: + return SRE_LOC_IS_WORD(ch); + case SRE_CATEGORY_UNI_NOT_WORD: + return !SRE_LOC_IS_WORD(ch); + case SRE_CATEGORY_UNI_LINEBREAK: + return SRE_IS_LINEBREAK(ch); + case SRE_CATEGORY_UNI_NOT_LINEBREAK: + return !SRE_IS_LINEBREAK(ch); #endif } *************** *** 355,358 **** --- 390,394 ---- case SRE_AT_BEGINNING: + case SRE_AT_BEGINNING_STRING: return ((void*) ptr == state->beginning); *************** *** 370,373 **** --- 406,412 ---- SRE_IS_LINEBREAK((int) ptr[0])); + case SRE_AT_END_STRING: + return ((void*) ptr == state->end); + case SRE_AT_BOUNDARY: if (state->beginning == state->end) *************** *** 387,390 **** --- 426,465 ---- SRE_IS_WORD((int) ptr[0]) : 0; return this == that; + + case SRE_AT_LOC_BOUNDARY: + if (state->beginning == state->end) + return 0; + that = ((void*) ptr > state->beginning) ? + SRE_LOC_IS_WORD((int) ptr[-1]) : 0; + this = ((void*) ptr < state->end) ? + SRE_LOC_IS_WORD((int) ptr[0]) : 0; + return this != that; + + case SRE_AT_LOC_NON_BOUNDARY: + if (state->beginning == state->end) + return 0; + that = ((void*) ptr > state->beginning) ? + SRE_LOC_IS_WORD((int) ptr[-1]) : 0; + this = ((void*) ptr < state->end) ? + SRE_LOC_IS_WORD((int) ptr[0]) : 0; + return this == that; + + case SRE_AT_UNI_BOUNDARY: + if (state->beginning == state->end) + return 0; + that = ((void*) ptr > state->beginning) ? + SRE_UNI_IS_WORD((int) ptr[-1]) : 0; + this = ((void*) ptr < state->end) ? + SRE_UNI_IS_WORD((int) ptr[0]) : 0; + return this != that; + + case SRE_AT_UNI_NON_BOUNDARY: + if (state->beginning == state->end) + return 0; + that = ((void*) ptr > state->beginning) ? + SRE_UNI_IS_WORD((int) ptr[-1]) : 0; + this = ((void*) ptr < state->end) ? + SRE_UNI_IS_WORD((int) ptr[0]) : 0; + return this == that; } *************** *** 784,794 **** TRACE(("|%p|%p|ASSERT_NOT %d\n", pattern, ptr, pattern[1])); state->ptr = ptr - pattern[1]; ! if (state->ptr < state->beginning) ! return 0; ! i = SRE_MATCH(state, pattern + 2, level + 1); ! if (i < 0) ! return i; ! if (i) ! return 0; pattern += pattern[0]; break; --- 859,869 ---- TRACE(("|%p|%p|ASSERT_NOT %d\n", pattern, ptr, pattern[1])); state->ptr = ptr - pattern[1]; ! if (state->ptr >= state->beginning) { ! i = SRE_MATCH(state, pattern + 2, level + 1); ! if (i < 0) ! return i; ! if (i) ! return 0; ! } pattern += pattern[0]; break; *************** *** 826,830 **** exactly one character wide, and we're not already collecting backtracking points. for other cases, ! use the MAX_REPEAT operator instead */ /* <1=min> <2=max> item tail */ --- 901,905 ---- exactly one character wide, and we're not already collecting backtracking points. for other cases, ! use the MAX_REPEAT operator */ /* <1=min> <2=max> item tail */ *************** *** 900,904 **** case SRE_OP_REPEAT: /* create repeat context. all the hard work is done ! by the UNTIL operator */ /* <1=min> <2=max> item tail */ TRACE(("|%p|%p|REPEAT %d %d\n", pattern, ptr, --- 975,979 ---- case SRE_OP_REPEAT: /* create repeat context. all the hard work is done ! by the UNTIL operator (MAX_UNTIL, MIN_UNTIL) */ /* <1=min> <2=max> item tail */ TRACE(("|%p|%p|REPEAT %d %d\n", pattern, ptr, *************** *** 974,977 **** --- 1049,1053 ---- return i; state->repeat = rp; + state->ptr = ptr; return 0; *************** *** 986,990 **** count = rp->count + 1; ! TRACE(("|%p|%p|MIN_UNTIL %d\n", pattern, ptr, count)); state->ptr = ptr; --- 1062,1067 ---- count = rp->count + 1; ! TRACE(("|%p|%p|MIN_UNTIL %d %p\n", pattern, ptr, count, ! rp->pattern)); state->ptr = ptr; *************** *** 1004,1012 **** /* see if the tail matches */ state->repeat = rp->prev; ! i = SRE_MATCH(state, pattern, level + 1); if (i) { /* free(rp); */ return i; } state->repeat = rp; --- 1081,1101 ---- /* see if the tail matches */ state->repeat = rp->prev; ! /* FIXME: the following fix doesn't always work (#133283) */ ! if (0 && rp->pattern[2] == 65535) { ! /* unbounded repeat */ ! for (;;) { ! i = SRE_MATCH(state, pattern, level + 1); ! if (i || ptr >= end) ! break; ! state->ptr = ++ptr; ! } ! } else ! i = SRE_MATCH(state, pattern, level + 1); if (i) { /* free(rp); */ return i; } + + state->ptr = ptr; state->repeat = rp; *************** *** 1020,1023 **** --- 1109,1113 ---- return i; rp->count = count - 1; + state->ptr = ptr; return 0; *************** *** 1186,1218 **** PyObject* groupindex = NULL; PyObject* indexgroup = NULL; ! if (!PyArg_ParseTuple(args, "OiO|iOO", &pattern, &flags, &code, ! &groups, &groupindex, &indexgroup)) ! return NULL; ! ! code = PySequence_Fast(code, "code argument must be a sequence"); ! if (!code) return NULL; ! #if PY_VERSION_HEX >= 0x01060000 ! n = PySequence_Size(code); ! #else ! n = PySequence_Length(code); ! #endif ! self = PyObject_NEW_VAR(PatternObject, &Pattern_Type, 100*n); ! if (!self) { ! Py_DECREF(code); return NULL; - } for (i = 0; i < n; i++) { ! PyObject *o = PySequence_Fast_GET_ITEM(code, i); self->code[i] = (SRE_CODE) PyInt_AsLong(o); } - - Py_DECREF(code); ! if (PyErr_Occurred()) return NULL; Py_INCREF(pattern); --- 1276,1299 ---- PyObject* groupindex = NULL; PyObject* indexgroup = NULL; ! if (!PyArg_ParseTuple(args, "OiO!|iOO", &pattern, &flags, ! &PyList_Type, &code, &groups, ! &groupindex, &indexgroup)) return NULL; ! n = PyList_GET_SIZE(code); ! self = PyObject_NEW_VAR(PatternObject, &Pattern_Type, n); ! if (!self) return NULL; for (i = 0; i < n; i++) { ! PyObject *o = PyList_GET_ITEM(code, i); self->code[i] = (SRE_CODE) PyInt_AsLong(o); } ! if (PyErr_Occurred()) { ! PyObject_DEL(self); return NULL; + } Py_INCREF(pattern); *************** *** 1246,1252 **** if (flags & SRE_FLAG_LOCALE) return Py_BuildValue("i", sre_lower_locale(character)); - #if defined(HAVE_UNICODE) if (flags & SRE_FLAG_UNICODE) return Py_BuildValue("i", sre_lower_unicode(character)); #endif return Py_BuildValue("i", sre_lower(character)); --- 1327,1335 ---- if (flags & SRE_FLAG_LOCALE) return Py_BuildValue("i", sre_lower_locale(character)); if (flags & SRE_FLAG_UNICODE) + #if defined(HAVE_UNICODE) return Py_BuildValue("i", sre_lower_unicode(character)); + #else + return Py_BuildValue("i", sre_lower_locale(character)); #endif return Py_BuildValue("i", sre_lower(character)); *************** *** 1356,1362 **** if (pattern->flags & SRE_FLAG_LOCALE) state->lower = sre_lower_locale; - #if defined(HAVE_UNICODE) else if (pattern->flags & SRE_FLAG_UNICODE) state->lower = sre_lower_unicode; #endif else --- 1439,1447 ---- if (pattern->flags & SRE_FLAG_LOCALE) state->lower = sre_lower_locale; else if (pattern->flags & SRE_FLAG_UNICODE) + #if defined(HAVE_UNICODE) state->lower = sre_lower_unicode; + #else + state->lower = sre_lower_locale; #endif else *************** *** 1496,1500 **** string = state_init(&self->state, pattern, string, start, end); if (!string) { ! PyObject_Del(self); return NULL; } --- 1581,1585 ---- string = state_init(&self->state, pattern, string, start, end); if (!string) { ! PyObject_DEL(self); return NULL; } *************** *** 1511,1514 **** --- 1596,1600 ---- Py_XDECREF(self->pattern); Py_XDECREF(self->groupindex); + Py_XDECREF(self->indexgroup); PyObject_DEL(self); } *************** *** 1594,1598 **** PyObject* result; ! name = PyString_FromString(MODULE); if (!name) return NULL; --- 1680,1684 ---- PyObject* result; ! name = PyString_FromString(SRE_MODULE); if (!name) return NULL; *************** *** 1681,1684 **** --- 1767,1772 ---- PyObject* item; + state_reset(&state); + state.ptr = state.start; *************** *** 1963,1967 **** PyObject* def = Py_None; static char* kwlist[] = { "default", NULL }; ! if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:groups", kwlist, &def)) return NULL; --- 2051,2055 ---- PyObject* def = Py_None; static char* kwlist[] = { "default", NULL }; ! if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:groupdict", kwlist, &def)) return NULL; *************** *** 1971,1997 **** keys = PyMapping_Keys(self->pattern->groupindex); ! if (!keys) { ! Py_DECREF(result); ! return NULL; ! } for (index = 0; index < PyList_GET_SIZE(keys); index++) { PyObject* key; ! PyObject* item; key = PyList_GET_ITEM(keys, index); ! if (!key) { ! Py_DECREF(keys); ! Py_DECREF(result); ! return NULL; ! } ! item = match_getslice(self, key, def); ! if (!item) { Py_DECREF(key); ! Py_DECREF(keys); ! Py_DECREF(result); ! return NULL; } ! /* FIXME: this can fail, right? */ ! PyDict_SetItem(result, key, item); } --- 2059,2081 ---- keys = PyMapping_Keys(self->pattern->groupindex); ! if (!keys) ! goto failed; for (index = 0; index < PyList_GET_SIZE(keys); index++) { + int status; PyObject* key; ! PyObject* value; key = PyList_GET_ITEM(keys, index); ! if (!key) ! goto failed; ! value = match_getslice(self, key, def); ! if (!value) { Py_DECREF(key); ! goto failed; } ! status = PyDict_SetItem(result, key, value); ! Py_DECREF(value); ! if (status < 0) ! goto failed; } *************** *** 1999,2002 **** --- 2083,2091 ---- return result; + + failed: + Py_DECREF(keys); + Py_DECREF(result); + return NULL; } *************** *** 2325,2339 **** }; ! void ! #if defined(WIN32) ! __declspec(dllexport) ! #endif init_sre(void) { /* Patch object types */ Pattern_Type.ob_type = Match_Type.ob_type = Scanner_Type.ob_type = &PyType_Type; - Py_InitModule("_" MODULE, _functions); } --- 2414,2438 ---- }; ! DL_EXPORT(void) init_sre(void) { + PyObject* m; + PyObject* d; + /* Patch object types */ Pattern_Type.ob_type = Match_Type.ob_type = Scanner_Type.ob_type = &PyType_Type; + + m = Py_InitModule("_" SRE_MODULE, _functions); + d = PyModule_GetDict(m); + + PyDict_SetItemString( + d, "MAGIC", (PyObject*) PyInt_FromLong(SRE_MAGIC) + ); + + PyDict_SetItemString( + d, "copyright", (PyObject*) PyString_FromString(copyright) + ); } Index: sre_constants.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/sre_constants.h,v retrieving revision 2.9 retrieving revision 2.9.4.1 diff -C2 -r2.9 -r2.9.4.1 *** sre_constants.h 2000/08/01 22:47:49 2.9 --- sre_constants.h 2001/06/13 15:15:02 2.9.4.1 *************** *** 7,15 **** * to change anything in here, edit sre_constants.py and run it. * ! * Copyright (c) 1997-2000 by Secret Labs AB. All rights reserved. * * See the _sre.c file for information on usage and redistribution. */ #define SRE_OP_FAILURE 0 #define SRE_OP_SUCCESS 1 --- 7,16 ---- * to change anything in here, edit sre_constants.py and run it. * ! * Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. * * See the _sre.c file for information on usage and redistribution. */ + #define SRE_MAGIC 20010320 #define SRE_OP_FAILURE 0 #define SRE_OP_SUCCESS 1 *************** *** 43,50 **** #define SRE_AT_BEGINNING 0 #define SRE_AT_BEGINNING_LINE 1 ! #define SRE_AT_BOUNDARY 2 ! #define SRE_AT_NON_BOUNDARY 3 ! #define SRE_AT_END 4 ! #define SRE_AT_END_LINE 5 #define SRE_CATEGORY_DIGIT 0 #define SRE_CATEGORY_NOT_DIGIT 1 --- 44,57 ---- #define SRE_AT_BEGINNING 0 #define SRE_AT_BEGINNING_LINE 1 ! #define SRE_AT_BEGINNING_STRING 2 ! #define SRE_AT_BOUNDARY 3 ! #define SRE_AT_NON_BOUNDARY 4 ! #define SRE_AT_END 5 ! #define SRE_AT_END_LINE 6 ! #define SRE_AT_END_STRING 7 ! #define SRE_AT_LOC_BOUNDARY 8 ! #define SRE_AT_LOC_NON_BOUNDARY 9 ! #define SRE_AT_UNI_BOUNDARY 10 ! #define SRE_AT_UNI_NON_BOUNDARY 11 #define SRE_CATEGORY_DIGIT 0 #define SRE_CATEGORY_NOT_DIGIT 1 From gvanrossum@users.sourceforge.net Wed Jun 13 17:02:11 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 13 Jun 2001 09:02:11 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include patchlevel.h,2.42.2.1,2.42.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv10985 Modified Files: Tag: release20-maint patchlevel.h Log Message: Change the version to 2.0.1c1 -- release candidate 1, that is. Index: patchlevel.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/patchlevel.h,v retrieving revision 2.42.2.1 retrieving revision 2.42.2.2 diff -C2 -r2.42.2.1 -r2.42.2.2 *** patchlevel.h 2001/05/08 19:02:27 2.42.2.1 --- patchlevel.h 2001/06/13 16:02:09 2.42.2.2 *************** *** 23,34 **** #define PY_MINOR_VERSION 0 #define PY_MICRO_VERSION 1 ! #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA #define PY_RELEASE_SERIAL 1 /* Version as a string */ ! #define PY_VERSION "2.0.1a1" /* Historic */ ! #define PATCHLEVEL "2.0.1a1" /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. --- 23,34 ---- #define PY_MINOR_VERSION 0 #define PY_MICRO_VERSION 1 ! #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA #define PY_RELEASE_SERIAL 1 /* Version as a string */ ! #define PY_VERSION "2.0.1c1" /* Historic */ ! #define PATCHLEVEL "2.0.1c1" /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. From fdrake@users.sourceforge.net Wed Jun 13 17:07:28 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Wed, 13 Jun 2001 09:07:28 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc Makefile,1.203,1.203.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc In directory usw-pr-cvs1:/tmp/cvs-serv11943 Modified Files: Tag: release20-maint Makefile Log Message: Update version number for patch release candidate. Index: Makefile =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/Makefile,v retrieving revision 1.203 retrieving revision 1.203.2.1 diff -C2 -r1.203 -r1.203.2.1 *** Makefile 2000/10/13 15:35:26 1.203 --- Makefile 2001/06/13 16:07:26 1.203.2.1 *************** *** 65,69 **** # This is the *documentation* release, and is used to construct the file # names of the downloadable tarballs. ! RELEASE=2.0 --- 65,69 ---- # This is the *documentation* release, and is used to construct the file # names of the downloadable tarballs. ! RELEASE=2.0.1c1 From fdrake@users.sourceforge.net Wed Jun 13 17:08:16 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Wed, 13 Jun 2001 09:08:16 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/texinputs boilerplate.tex,1.50,1.50.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/texinputs In directory usw-pr-cvs1:/tmp/cvs-serv12172/texinputs Modified Files: Tag: release20-maint boilerplate.tex Log Message: Update version number and date for patch release candidate. Index: boilerplate.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/texinputs/boilerplate.tex,v retrieving revision 1.50 retrieving revision 1.50.2.1 diff -C2 -r1.50 -r1.50.2.1 *** boilerplate.tex 2000/10/13 15:35:27 1.50 --- boilerplate.tex 2001/06/13 16:08:13 1.50.2.1 *************** *** 2,10 **** Fred L. Drake, Jr., editor} \authoraddress{ ! BeOpen PythonLabs\\ E-mail: \email{python-docs@python.org} } ! \date{October 16, 2000} % XXX update before release! ! \release{2.0} % software release, not documentation \setshortversion{2.0} % major.minor only for software --- 2,10 ---- Fred L. Drake, Jr., editor} \authoraddress{ ! PythonLabs\\ E-mail: \email{python-docs@python.org} } ! \date{June 15, 2001} % XXX update before release! ! \release{2.0.1c1} % software release, not documentation \setshortversion{2.0} % major.minor only for software From gvanrossum@users.sourceforge.net Wed Jun 13 17:22:07 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 13 Jun 2001 09:22:07 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.96,1.97 pep-0259.txt,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv15984 Modified Files: pep-0000.txt pep-0259.txt Log Message: PEP 259 rejected by user community with record unanimity. Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.96 retrieving revision 1.97 diff -C2 -r1.96 -r1.97 *** pep-0000.txt 2001/06/11 20:07:37 1.96 --- pep-0000.txt 2001/06/13 16:22:05 1.97 *************** *** 61,65 **** S 257 pep-0257.txt Docstring Conventions Goodger S 258 pep-0258.txt DPS Generic Implementation Details Goodger - S 259 pep-0259.txt Omit printing newline after newline van Rossum Py-in-the-sky PEPs (not ready; may become active yet) --- 61,64 ---- *************** *** 109,113 **** SR 224 pep-0224.txt Attribute Docstrings Lemburg SR 231 pep-0231.txt __findattr__() Warsaw ! S 233 pep-0233.txt Python Online Help Prescod --- 108,113 ---- SR 224 pep-0224.txt Attribute Docstrings Lemburg SR 231 pep-0231.txt __findattr__() Warsaw ! SD 233 pep-0233.txt Python Online Help Prescod ! SR 259 pep-0259.txt Omit printing newline after newline van Rossum *************** *** 160,164 **** SR 231 pep-0231.txt __findattr__() Warsaw SF 232 pep-0232.txt Function Attributes Warsaw ! S 233 pep-0233.txt Python Online Help Prescod S 234 pep-0234.txt Iterators Yee, van Rossum SF 235 pep-0235.txt Import on Case-Insensitive Platforms Peters --- 160,164 ---- SR 231 pep-0231.txt __findattr__() Warsaw SF 232 pep-0232.txt Function Attributes Warsaw ! SD 233 pep-0233.txt Python Online Help Prescod S 234 pep-0234.txt Iterators Yee, van Rossum SF 235 pep-0235.txt Import on Case-Insensitive Platforms Peters *************** *** 186,190 **** S 257 pep-0257.txt Docstring Conventions Goodger S 258 pep-0258.txt DPS Generic Implementation Details Goodger ! S 259 pep-0259.txt Omit printing newline after newline van Rossum --- 186,190 ---- S 257 pep-0257.txt Docstring Conventions Goodger S 258 pep-0258.txt DPS Generic Implementation Details Goodger ! SR 259 pep-0259.txt Omit printing newline after newline van Rossum Index: pep-0259.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0259.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -r1.1 -r1.2 *** pep-0259.txt 2001/06/11 20:07:37 1.1 --- pep-0259.txt 2001/06/13 16:22:05 1.2 *************** *** 3,7 **** Version: $Revision$ Author: guido@python.org (Guido van Rossum) ! Status: Draft Type: Standards Track Python-Version: 2.2 --- 3,7 ---- Version: $Revision$ Author: guido@python.org (Guido van Rossum) ! Status: Rejected Type: Standards Track Python-Version: 2.2 *************** *** 108,111 **** --- 108,123 ---- http://sourceforge.net/tracker/index.php?func=detail&aid=432183&group_id=5470&atid=305470 + + + Rejected + + The user community unanimously rejected this, so I won't pursue + this idea any further. Frequently heard arguments against + included: + + - It it likely to break thousands of CGI scripts. + + - Enough magic already (also: no more tinkering with 'print' + please). From lemburg@users.sourceforge.net Wed Jun 13 18:18:08 2001 From: lemburg@users.sourceforge.net (M.-A. Lemburg) Date: Wed, 13 Jun 2001 10:18:08 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python pythonrun.c,2.133,2.134 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv28226 Modified Files: pythonrun.c Log Message: Temporarily disable the message to stderr. Jeremy will know what to do about this... Index: pythonrun.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/pythonrun.c,v retrieving revision 2.133 retrieving revision 2.134 diff -C2 -r2.133 -r2.134 *** pythonrun.c 2001/03/26 19:53:38 2.133 --- pythonrun.c 2001/06/13 17:18:06 2.134 *************** *** 1077,1082 **** if (co->co_flags & CO_NESTED) flags->cf_nested_scopes = 1; fprintf(stderr, "run_pyc_file: nested_scopes: %d\n", ! flags->cf_nested_scopes); } Py_DECREF(co); --- 1077,1084 ---- if (co->co_flags & CO_NESTED) flags->cf_nested_scopes = 1; + #if 0 fprintf(stderr, "run_pyc_file: nested_scopes: %d\n", ! flags->cf_nested_scopes); ! #endif } Py_DECREF(co); From tim_one@users.sourceforge.net Wed Jun 13 20:11:26 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 12:11:26 -0700 Subject: [Python-checkins] CVS: python/dist/src/PCbuild python20.wse,1.21,1.21.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/PCbuild In directory usw-pr-cvs1:/tmp/cvs-serv23548/python/dist/src/PCbuild Modified Files: Tag: release20-maint python20.wse Log Message: Change installer dialog titles to say Python 2.0.1c1. Index: python20.wse =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/python20.wse,v retrieving revision 1.21 retrieving revision 1.21.2.1 diff -C2 -r1.21 -r1.21.2.1 *** python20.wse 2000/10/14 07:35:15 1.21 --- python20.wse 2001/06/13 19:11:24 1.21.2.1 *************** *** 2,6 **** item: Global Version=5.0 ! Title=Python 2.0 Flags=00010100 Languages=65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --- 2,6 ---- item: Global Version=5.0 ! Title=Python 2.0.1c1 Flags=00010100 Languages=65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 *************** *** 65,69 **** item: Set Variable Variable=APPTITLE ! Value=Python 2.0 end item: Set Variable --- 65,69 ---- item: Set Variable Variable=APPTITLE ! Value=Python 2.0.1c1 end item: Set Variable From tim_one@users.sourceforge.net Wed Jun 13 20:17:34 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 12:17:34 -0700 Subject: [Python-checkins] CVS: python/dist/src/PCbuild BUILDno.txt,1.12,1.13 Message-ID: Update of /cvsroot/python/python/dist/src/PCbuild In directory usw-pr-cvs1:/tmp/cvs-serv25186 Modified Files: BUILDno.txt Log Message: Record Windows buildno for 2.0.1c1. Index: BUILDno.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/BUILDno.txt,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -r1.12 -r1.13 *** BUILDno.txt 2001/04/18 21:12:25 1.12 --- BUILDno.txt 2001/06/13 19:17:32 1.13 *************** *** 34,37 **** --- 34,39 ---- Windows Python BUILD numbers ---------------------------- + 17 2.0.1c1 + 13-Jun-2001 16 CVS development 18-Apr-2001 From tim_one@users.sourceforge.net Wed Jun 13 20:19:54 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 12:19:54 -0700 Subject: [Python-checkins] CVS: python/dist/src/PCbuild python20.dsp,1.14,1.14.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/PCbuild In directory usw-pr-cvs1:/tmp/cvs-serv25640/python/dist/src/PCbuild Modified Files: Tag: release20-maint python20.dsp Log Message: Set Windows buildno to 17 for 2.0.1c1. Index: python20.dsp =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/Attic/python20.dsp,v retrieving revision 1.14 retrieving revision 1.14.2.1 diff -C2 -r1.14 -r1.14.2.1 *** python20.dsp 2000/10/14 07:35:15 1.14 --- python20.dsp 2001/06/13 19:19:52 1.14.2.1 *************** *** 695,703 **** !IF "$(CFG)" == "python20 - Win32 Release" ! # ADD CPP /D BUILD=8 !ELSEIF "$(CFG)" == "python20 - Win32 Debug" ! # ADD CPP /D BUILD=8 !ELSEIF "$(CFG)" == "python20 - Win32 Alpha Debug" --- 695,703 ---- !IF "$(CFG)" == "python20 - Win32 Release" ! # ADD CPP /D BUILD=17 !ELSEIF "$(CFG)" == "python20 - Win32 Debug" ! # ADD CPP /D BUILD=17 !ELSEIF "$(CFG)" == "python20 - Win32 Alpha Debug" From tim_one@users.sourceforge.net Wed Jun 13 20:26:02 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 12:26:02 -0700 Subject: [Python-checkins] CVS: python/dist/src/PCbuild BUILDno.txt,1.4,1.4.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/PCbuild In directory usw-pr-cvs1:/tmp/cvs-serv27123/python/dist/src/PCbuild Modified Files: Tag: release20-maint BUILDno.txt Log Message: Also record the 2.0.1c1 Windows buildno in the branch, although the 9-number gap looks odd here. Index: BUILDno.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/BUILDno.txt,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -C2 -r1.4 -r1.4.2.1 *** BUILDno.txt 2000/10/14 07:35:14 1.4 --- BUILDno.txt 2001/06/13 19:26:00 1.4.2.1 *************** *** 34,37 **** --- 34,39 ---- Windows Python BUILD numbers ---------------------------- + 17 2.0.1c1 + 13-Jun-2001 8 2.0 (final) 14-Oct-2000 From tim_one@users.sourceforge.net Wed Jun 13 21:45:19 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 13:45:19 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.75,1.76 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv15184/python/dist/src/Objects Modified Files: longobject.c Log Message: PyLong_As{Unsigned,}LongLong: fiddled final result casting. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.75 retrieving revision 1.76 diff -C2 -r1.75 -r1.76 *** longobject.c 2001/06/13 00:35:57 1.75 --- longobject.c 2001/06/13 20:45:17 1.76 *************** *** 573,577 **** SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1); ! return (LONG_LONG)(res < 0 ? res : bytes); } --- 573,577 ---- SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1); ! return res < 0 ? (LONG_LONG)res : bytes; } *************** *** 595,599 **** SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0); ! return (unsigned LONG_LONG)(res < 0 ? res : bytes); } --- 595,599 ---- SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0); ! return res < 0 ? (unsigned LONG_LONG)res : bytes; } From tim_one@users.sourceforge.net Wed Jun 13 21:50:10 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 13:50:10 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.76,1.77 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv16247/python/dist/src/Objects Modified Files: longobject.c Log Message: _PyLong_AsByteArray: added assert that the input is normalized. This is outside the function's control, but is crucial to correct operation. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.76 retrieving revision 1.77 diff -C2 -r1.76 -r1.77 *** longobject.c 2001/06/13 20:45:17 1.76 --- longobject.c 2001/06/13 20:50:08 1.77 *************** *** 359,363 **** } ! /* Copy over all the Python digits. */ j = 0; accum = 0; --- 359,367 ---- } ! /* Copy over all the Python digits. ! It's crucial that every Python digit except for the MSD contribute ! exactly SHIFT bits to the total, so first assert that the long is ! normalized. */ ! assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0); j = 0; accum = 0; From tim_one@users.sourceforge.net Wed Jun 13 22:01:29 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 14:01:29 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.77,1.78 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv19167/python/dist/src/Objects Modified Files: longobject.c Log Message: _PyLong_AsByteArray: Don't do the "delicate overflow" check unless it's truly needed; usually saves a little time, but no change in semantics. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.77 retrieving revision 1.78 diff -C2 -r1.77 -r1.78 *** longobject.c 2001/06/13 20:50:08 1.77 --- longobject.c 2001/06/13 21:01:27 1.78 *************** *** 425,440 **** p += pincr; } ! ! /* Fill remaining bytes with copies of the sign bit. */ ! for ( ; j < n; ++j, p += pincr) ! *p = (unsigned char)(do_twos_comp ? 0xff : 0); ! ! /* Check for delicate overflow (not enough room for the sign bit). */ ! if (j > 0 && is_signed) { unsigned char msb = *(p - pincr); ! int sign_bit_set = (msb & 0x80) != 0; ! if (sign_bit_set != do_twos_comp) goto Overflow; } return 0; --- 425,449 ---- p += pincr; } ! else if (j == n && n > 0 && is_signed) { ! /* The main loop filled the byte array exactly, so the code ! just above didn't get to ensure there's a sign bit, and the ! loop below wouldn't add one either. Make sure a sign bit ! exists. */ unsigned char msb = *(p - pincr); ! int sign_bit_set = msb >= 0x80; ! assert(accumbits == 0); ! if (sign_bit_set == do_twos_comp) ! return 0; ! else goto Overflow; } + + /* Fill remaining bytes with copies of the sign bit. */ + { + unsigned char signbyte = do_twos_comp ? 0xffU : 0U; + for ( ; j < n; ++j, p += pincr) + *p = signbyte; + } + return 0; From tim_one@users.sourceforge.net Wed Jun 13 22:09:17 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 14:09:17 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.78,1.79 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv20769/python/dist/src/Objects Modified Files: longobject.c Log Message: _PyLong_FromByteArray: changed decl of "carry" to match "thisbyte". No semantic change, but a bit clearer and may help a really stupid compiler avoid pointless runtime length conversions. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.78 retrieving revision 1.79 diff -C2 -r1.78 -r1.79 *** longobject.c 2001/06/13 21:01:27 1.78 --- longobject.c 2001/06/13 21:09:15 1.79 *************** *** 279,283 **** { size_t i; ! unsigned int carry = 1; /* for 2's-comp calculation */ twodigits accum = 0; /* sliding register */ unsigned int accumbits = 0; /* number of bits in accum */ --- 279,283 ---- { size_t i; ! twodigits carry = 1; /* for 2's-comp calculation */ twodigits accum = 0; /* sliding register */ unsigned int accumbits = 0; /* number of bits in accum */ From gvanrossum@users.sourceforge.net Wed Jun 13 22:48:33 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 13 Jun 2001 14:48:33 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0253.txt,1.3,1.4 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv30297 Modified Files: pep-0253.txt Log Message: Another intermediate update. I've rewritten the requirements for a base type to be subtypable. Needs way more work! Index: pep-0253.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0253.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -r1.3 -r1.4 *** pep-0253.txt 2001/06/11 20:07:37 1.3 --- pep-0253.txt 2001/06/13 21:48:31 1.4 *************** *** 11,22 **** Abstract ! This PEP proposes ways for creating subtypes of existing built-in ! types, either in C or in Python. The text is currently long and ! rambling; I'll go over it again later to make it shorter. Traditionally, types in Python have been created statically, by declaring a global variable of type PyTypeObject and initializing it with a static initializer. The fields in the type object ! describe all aspects of a Python object that are relevant to the Python interpreter. A few fields contain dimensional information (e.g. the basic allocation size of instances), others contain --- 11,24 ---- Abstract ! This PEP proposes additions to the type object API that will allow ! the creation of subtypes of built-in types, in C and in Python. + + Introduction + Traditionally, types in Python have been created statically, by declaring a global variable of type PyTypeObject and initializing it with a static initializer. The fields in the type object ! describe all aspects of a Python type that are relevant to the Python interpreter. A few fields contain dimensional information (e.g. the basic allocation size of instances), others contain *************** *** 27,34 **** exception when the behavior is invoked. Some collections of functions pointers that are usually defined together are obtained ! indirectly via a pointer to an additional structure containing. While the details of initializing a PyTypeObject structure haven't ! been documented as such, they are easily glanced from the examples in the source code, and I am assuming that the reader is sufficiently familiar with the traditional way of creating new --- 29,37 ---- exception when the behavior is invoked. Some collections of functions pointers that are usually defined together are obtained ! indirectly via a pointer to an additional structure containing ! more function pointers. While the details of initializing a PyTypeObject structure haven't ! been documented as such, they are easily gleaned from the examples in the source code, and I am assuming that the reader is sufficiently familiar with the traditional way of creating new *************** *** 36,63 **** This PEP will introduce the following features: ! - a type, like a class, can be a factory for its instances ! - types can be subtyped in C by specifying a base type pointer ! - types can be subtyped in Python using the class statement ! - multiple inheritance from types (insofar as practical) ! - the standard coercions (int, tuple, str etc.) will be the ! corresponding type objects ! - a standard type hierarchy This PEP builds on pep-0252, which adds standard introspection to ! types; in particular, types are assumed to have e.g. a __hash__ ! method when the type object defines the tp_hash slot. pep-0252 also ! adds a dictionary to type objects which contains all methods. At ! the Python level, this dictionary is read-only; at the C level, it ! is accessible directly (but modifying it is not recommended except ! as part of initialization). ! Metatypes Inevitably the following discussion will come to mention metatypes --- 39,83 ---- This PEP will introduce the following features: + + - a type can be a factory function for its instances + + - types can be subtyped in C ! - types can be subtyped in Python with the class statement ! - multiple inheritance from types is supported (insofar as ! practical) ! - the standard coercions functions (int, tuple, str etc.) will be ! redefined to be the corresponding type objects, which serve as ! their own factory functions ! - there will be a standard type hierarchy ! - a class statement can contain a metaclass declaration, ! specifying the metaclass to be used to create the new class ! - a class statement can contain a slots declaration, specifying ! the specific names of the instance variables supported This PEP builds on pep-0252, which adds standard introspection to ! types; e.g., when the type object defines the tp_hash slot, the ! type object has a __hash__ method. pep-0252 also adds a ! dictionary to type objects which contains all methods. At the ! Python level, this dictionary is read-only for built-in types; at ! the C level, it is accessible directly (but it should not be ! modified except as part of initialization). ! ! For binary compatibility, a flag bit in the tp_flags slot ! indicates the existence of the various new slots in the type ! object introduced below. Types that don't have the ! Py_TPFLAGS_HAVE_CLASS bit set in their tp_flags field are assumed ! to have NULL values for all the subtyping slots. (Warning: the ! current implementation prototype is not yet consistent in its ! checking of this flag bit. This should be fixed before the final ! release.) ! About metatypes Inevitably the following discussion will come to mention metatypes *************** *** 76,99 **** In this example, type(a) is a "regular" type, and type(type(a)) is a metatype. While as distributed all types have the same metatype ! (which is also its own metatype), this is not a requirement, and ! in fact a useful 3rd party extension (ExtensionClasses by Jim ! Fulton) creates an additional metatype. A related feature is the ! "Don Beaudry hook", which says that if a metatype is callable, its ! instances (which are regular types) can be subclassed (really ! subtyped) using a Python class statement. We will use this rule ! to support subtyping of built-in types, and in fact it greatly ! simplifies the logic of class creation to always simply call the ! metatype. When no base class is specified, a default metatype is ! called -- the default metatype is the "ClassType" object, so the ! class statement will behave as before in the normal case. ! ! Python uses the concept of metatypes or metaclasses in a ! different way than Smalltalk. In Smalltalk-80, there is a ! hierarchy of metaclasses that mirrors the hierarchy of regular ! classes, metaclasses map 1-1 to classes (except for some funny ! business at the root of the hierarchy), and each class statement ! creates both a regular class and its metaclass, putting class ! methods in the metaclass and instance methods in the regular ! class. Nice though this may be in the context of Smalltalk, it's not --- 96,120 ---- In this example, type(a) is a "regular" type, and type(type(a)) is a metatype. While as distributed all types have the same metatype ! (PyType_Type, which is also its own metatype), this is not a ! requirement, and in fact a useful and relevant 3rd party extension ! (ExtensionClasses by Jim Fulton) creates an additional metatype. ! ! A related feature is the "Don Beaudry hook", which says that if a ! metatype is callable, its instances (which are regular types) can ! be subclassed (really subtyped) using a Python class statement. ! I will use this rule to support subtyping of built-in types, and ! in fact it greatly simplifies the logic of class creation to ! always simply call the metatype. When no base class is specified, ! a default metatype is called -- the default metatype is the ! "ClassType" object, so the class statement will behave as before ! in the normal case. ! ! Python uses the concept of metatypes or metaclasses in a different ! way than Smalltalk. In Smalltalk-80, there is a hierarchy of ! metaclasses that mirrors the hierarchy of regular classes, ! metaclasses map 1-1 to classes (except for some funny business at ! the root of the hierarchy), and each class statement creates both ! a regular class and its metaclass, putting class methods in the ! metaclass and instance methods in the regular class. Nice though this may be in the context of Smalltalk, it's not *************** *** 107,118 **** initialize it at will.) - Instantiation by calling the type object ! Traditionally, for each type there is at least one C function that ! creates instances of the type (e.g. PyInt_FromLong(), ! PyTuple_New() and so on). This function has to take care of both allocating memory for the object and initializing that ! memory. As of Python 2.0, it also has to interface with the garbage collection subsystem, if the type chooses to participate in garbage collection (which is optional, but strongly recommended --- 128,154 ---- initialize it at will.) + Metatypes determine various *policies* for types, e.g. what + happens when a type is called, how dynamic types are (whether a + type's __dict__ can be modified after it is created), what the + method resolution order is, how instance attributes are looked + up, and so on. + + I'll argue that left-to-right depth-first is not the best + solution when you want to get the most use from multiple + inheritance. + + I'll argue that with multiple inheritance, the metatype of the + subtype must be a descendant of the metatypes of all base types. + + I'll come back to metatypes later. ! Making a type a factory for its instances ! ! Traditionally, for each type there is at least one C factory ! function that creates instances of the type (PyTuple_New(), ! PyInt_FromLong() and so on). These factory functions take care of both allocating memory for the object and initializing that ! memory. As of Python 2.0, they also have to interface with the garbage collection subsystem, if the type chooses to participate in garbage collection (which is optional, but strongly recommended *************** *** 120,202 **** references to other objects, and hence may participate in reference cycles). - - If we're going to implement subtyping, we must separate allocation - and initialization: typically, the most derived subtype is in - charge of allocation (and hence deallocation!), but in most cases - each base type's initializer (constructor) must still be called, - from the "most base" type to the most derived type. - - But let's first get the interface for instantiation right. If we - call an object, the tp_call slot if its type gets invoked. Thus, - if we call a type, this invokes the tp_call slot of the type's - type: in other words, the tp_call slot of the metatype. - Traditionally this has been a NULL pointer, meaning that types - can't be called. Now we're adding a tp_call slot to the metatype, - which makes all types "callable" in a trivial sense. But - obviously the metatype's tp_call implementation doesn't know how - to initialize the instances of individual types. So the type - defines a new slot, tp_new, which is invoked by the metatype's - tp_call slot. If the tp_new slot is NULL, the metatype's tp_call - issues a nice error message: the type isn't callable. - - This mechanism gives the maximum freedom to the type: a type's - tp_new doesn't necessarily have to return a new object, or even an - object that is an instance of the type (although the latter should - be rare). - - HIRO - - The deallocation mechanism chosen should match the allocation - mechanism: an allocation policy should prescribe both the - allocation and deallocation mechanism. And again, planning ahead - for subtyping would be nice. But the available mechanisms are - different. The deallocation function has always been part of the - type structure, as tp_dealloc, which combines the - "uninitialization" with deallocation. This was good enough for - the traditional situation, where it matched the combined - allocation and initialization of the creation function. But now - imagine a type whose creation function uses a special free list - for allocation. It's deallocation function puts the object's - memory back on the same free list. But when allocation and - creation are separate, the object may have been allocated from the - regular heap, and it would be wrong (in some cases disastrous) if - it were placed on the free list by the deallocation function. ! A solution would be for the tp_construct function to somehow mark ! whether the object was allocated from the special free list, so ! that the tp_dealloc function can choose the right deallocation ! method (assuming that the only two alternatives are a special free ! list or the regular heap). A variant that doesn't require space ! for an allocation flag bit would be to have two type objects, ! identical in the contents of all their slots except for their ! deallocation slot. But this requires that all type-checking code ! (e.g. the PyDict_Check()) recognizes both types. We'll come back ! to this solution in the context of subtyping. Another alternative ! is to require the metatype's tp_call to leave the allocation to ! the tp_construct method, by passing in a NULL pointer. But this ! doesn't work once we allow subtyping. ! ! Eventually, when we add any form of subtyping, we'll have to ! separate deallocation from uninitialization. The way to do this ! is to add a separate slot to the type object that does the ! uninitialization without the deallocation. Fortunately, there is ! already such a slot: tp_clear, currently used by the garbage ! collection subsystem. A simple rule makes this slot reusable as ! an uninitialization: for types that support separate allocation ! and initialization, tp_clear must be defined (even if the object ! doesn't support garbage collection) and it must DECREF all ! contained objects and FREE all other memory areas the object owns. ! It must also be reentrant: it must be possible to clear an already ! cleared object. The easiest way to do this is to replace all ! pointers DECREFed or FREEd with NULL pointers. ! Subtyping in C The simplest form of subtyping is subtyping in C. It is the simplest form because we can require the C code to be aware of the various problems, and it's acceptable for C code that doesn't ! follow the rules to dump core; while for Python subtyping we would ! need to catch all errors before they become core dumps. The idea behind subtyping is very similar to that of single --- 156,200 ---- references to other objects, and hence may participate in reference cycles). ! In this proposal, type objects can be factory functions for their ! instances, making the types directly callable from Python. This ! mimics the way classes are instantiated. Of course, the C APIs ! for creating instances of various built-in types will remain valid ! and probably the most common; and not all types will become their ! own factory functions. ! ! The type object has a new slot, tp_new, which can act as a factory ! for instances of the type. Types are made callable by providing a ! tp_call slot in PyType_Type (the metatype); the slot ! implementation function looks for the tp_new slot of the type that ! is being called. ! ! If the type's tp_new slot is NULL, an exception is raised. ! Otherwise, the tp_new slot is called. The signature for the ! tp_new slot is ! ! PyObject *tp_new(PyTypeObject *type, ! PyObject *args, ! PyObject *kwds) ! ! where 'type' is the type whose tp_new slot is called, and 'args' ! and 'kwds' are the sequential and keyword arguments to the call, ! passed unchanged from tp_call. (The 'type' argument is used in ! combination with inheritance, see below.) ! ! There are no constraints on the object type that is returned, ! although by convention it should be an instance of the given ! type. It is not necessary that a new object is returned; a ! reference to an existing object is fine too. The return value ! should always be a new reference, owned by the caller. ! Requirements for a type to allow subtyping The simplest form of subtyping is subtyping in C. It is the simplest form because we can require the C code to be aware of the various problems, and it's acceptable for C code that doesn't ! follow the rules to dump core. For added simplicity, it is ! limited to single inheritance. The idea behind subtyping is very similar to that of single *************** *** 207,236 **** the type object, leaving others the same. ! Not every type can serve as a base type. The base type must ! support separation of allocation and initialization by having a ! tp_construct slot that can be called with a preallocated object, ! and it must support uninitialization without deallocation by ! having a tp_clear slot as described above. The derived type must ! also export the structure declaration for its instances through a ! header file, as it is needed in order to derive a subtype. The ! type object for the base type must also be exported. If the base type has a type-checking macro (e.g. PyDict_Check()), ! this macro may be changed to recognize subtypes. This can be done ! by using the new PyObject_TypeCheck(object, type) macro, which ! calls a function that follows the base class links. There are ! arguments for and against changing the type-checking macro in this ! way. The argument for the change should be clear: it allows ! subtypes to be used in places where the base type is required, ! which is often the prime attraction of subtyping (as opposed to ! sharing implementation). An argument against changing the ! type-checking macro could be that the type check is used ! frequently and a function call would slow things down too much ! (hard to believe); or one could fear that a subtype might break an ! invariant assumed by the support functions of the base type. ! Sometimes it would be wise to change the base type to remove this ! reliance; other times, it would be better to require that derived ! types (implemented in C) maintain the invariants. The derived type begins by declaring a type structure which contains the base type's structure. For example, here's the type --- 205,372 ---- the type object, leaving others the same. ! Most issues have to do with construction and destruction of ! instances of derived types. + Creation of a new object is separated into allocation and + initialization: allocation allocates the memory, and + initialization fill it with appropriate initial values. The + separation is needed for the convenience of subtypes. + Instantiation of a subtype goes as follows: + + 1. allocate memory for the whole (subtype) instance + 2. initialize the base type + 3. initialize the subtype's instance variables + + If allocation and initialization were done by the same function, + you would need a way to tell the base type's constructor to + allocate additional memory for the subtype's instance variables, + and there would be no way to change the allocation method for a + subtype (without giving up on calling the base type to initialize + its part of the instance structure). + + A similar reasoning applies to destruction: if a subtype changes + the instance allocator (e.g. to use a different heap), it must + also change the instance deallocator; but it must still call on + the base type's destructor to DECREF the base type's instance + variables. + + In this proposal, I assign stricter meanings to two existing + slots for deallocation and deinitialization, and I add two new + slots for allocation and initialization. + + The tp_clear slot gets the new task of deinitializing an object so + that all that remains to be done is free its memory. Originally, + all it had to do was clear object references. The difference is + subtle: the list and dictionary objects contain references to an + additional heap-allocated piece of memory that isn't freed by + tp_clear in Python 2.1, but which must be freed by tp_clear under + this proposal. It should be safe to call tp_clear repeatedly on + the same object. If an object contains no references to other + objects or heap-allocated memory, the tp_clear slot may be NULL. + + The only additional requirement for the tp_dealloc slot is that it + should do the right thing whether or not tp_clear has been called. + + The new slots are tp_alloc for allocation and tp_init for + initialization. Their signatures: + + PyObject *tp_alloc(PyTypeObject *type, + PyObject *args, + PyObject *kwds) + + int tp_init(PyObject *self, + PyObject *args, + PyObject *kwds) + + The arguments for tp_alloc are the same as for tp_new, described + above. The arguments for tp_init are the same except that the + first argument is replaced with the instance to be initialized. + Its return value is 0 for success or -1 for failure. + + It is possible that tp_init is called more than once or not at + all. The implementation should allow this usage. The object may + be non-functional until tp_init is called, and a second call to + tp_init may raise an exception, but it should not be possible to + cause a core dump or memory leakage this way. + + Because tp_init is in a sense optional, tp_alloc is required to do + *some* initialization of the object. It is required to initialize + ob_refcnt to 1 and ob_type to its type argument. To be safe, it + should probably zero out the rest of the object. + + The constructor arguments are passed to tp_alloc so that for + variable-size objects (like tuples and strings) it knows to + allocate the right amount of memory. + + For immutable types, tp_alloc may have to do the full + initialization; otherwise, different calls to tp_init might cause + an immutable object to be modified, which is considered a grave + offense in Python (unlike in Fortran :-). + + Not every type can serve as a base type. The assumption is made + that if a type has a non-NULL value in its tp_init slot, it is + ready to be subclassed; otherwise, it is not, and using it as a + base class will raise an exception. + + In order to be usefully subtyped in C, a type must also export the + structure declaration for its instances through a header file, as + it is needed in order to derive a subtype. The type object for + the base type must also be exported. + If the base type has a type-checking macro (e.g. PyDict_Check()), ! this macro probably should be changed to recognize subtypes. This ! can be done by using the new PyObject_TypeCheck(object, type) ! macro, which calls a function that follows the base class links. ! ! (An argument against changing the type-checking macro could be ! that the type check is used frequently and a function call would ! slow things down too much, but I find this hard to believe. One ! could also fear that a subtype might break an invariant assumed by ! the support functions of the base type. Usually it is best to ! change the base type to remove this reliance, at least to the ! point of raising an exception rather than dumping core when the ! invariant is broken.) ! ! Here are the inteactions between, tp_alloc, tp_clear, tp_dealloc ! and subtypes; all assuming that the base type defines tp_init ! (otherwise it cannot be subtyped anyway): ! ! - If the base type's allocation scheme doesn't use the standard ! heap, it should not define tp_alloc. This is a signal for the ! subclass to provide its own tp_alloc *and* tp_dealloc ! implementation (probably using the standard heap). ! ! - If the base type's tp_dealloc does anything besides calling ! PyObject_DEL() (typically, calling Py_XDECREF() on contained ! objects or freeing dependent memory blocks), it should define a ! tp_clear that does the same without calling PyObject_DEL(), and ! which checks for zero pointers before and zeros the pointers ! afterwards, so that calling tp_clear more than once or calling ! tp_dealloc after tp_clear will not attempt to DECREF or free the ! same object/memory twice. (It should also be allowed to ! continue using the object after tp_clear -- tp_clear should ! simply reset the object to its pristine state.) ! ! - If the derived type overrides tp_alloc, it should also override ! tp_dealloc, and tp_dealloc should call the derived type's ! tp_clear if non-NULL (or its own tp_clear). ! ! - If the derived type overrides tp_clear, it should call the base ! type's tp_clear if non-NULL. ! ! - If the base type defines tp_init as well as tp_new, its tp_new ! should be inheritable: it should call the tp_alloc and the ! tp_init of the type passed in as its first argument. ! ! - If the base type defines tp_init as well as tp_alloc, its ! tp_alloc should be inheritable: it should look in the ! tp_basicsize slot of the type passed in for the amount of memory ! to allocate, and it should initialize all allocated bytes to ! zero. ! ! - For types whose tp_itemsize is nonzero, the allocation size used ! in tp_alloc should be tp_basicsize + n*tp_itemsize, rounded up ! to the next integral multiple of sizeof(PyObject *), where n is ! the number of items determined by the arguments to tp_alloc. ! ! - Things are further complicated by the garbage collection API. ! This affects tp_basicsize, and the actions to be taken by ! tp_alloc. tp_alloc should look at the Py_TPFLAGS_GC flag bit in ! the tp_flags field of the type passed in, and not assume that ! this is the same as the corresponding bit in the base type. (In ! part, the GC API is at fault; Neil Schemenauer has a patch that ! fixes the API, but it is currently backwards incompatible.) ! ! Note: the rules here are very complicated -- probably too ! complicated. It may be better to give up on subtyping immutable ! types, types with custom allocators, and types with variable size ! allocation (such as int, string and tuple) -- then the rules can ! be much simplified because you can assume allocation on the ! standard heap, no requirement beyond zeroing memory in tp_alloc, ! and no variable length allocation. ! + Creating a subtype of a built-in type in C + The derived type begins by declaring a type structure which contains the base type's structure. For example, here's the type *************** *** 400,403 **** --- 536,586 ---- This document has been placed in the public domain. + + + Junk text (to be reused somewhere above) + + The deallocation mechanism chosen should match the allocation + mechanism: an allocation policy should prescribe both the + allocation and deallocation mechanism. And again, planning ahead + for subtyping would be nice. But the available mechanisms are + different. The deallocation function has always been part of the + type structure, as tp_dealloc, which combines the + "uninitialization" with deallocation. This was good enough for + the traditional situation, where it matched the combined + allocation and initialization of the creation function. But now + imagine a type whose creation function uses a special free list + for allocation. It's deallocation function puts the object's + memory back on the same free list. But when allocation and + creation are separate, the object may have been allocated from the + regular heap, and it would be wrong (in some cases disastrous) if + it were placed on the free list by the deallocation function. + + A solution would be for the tp_construct function to somehow mark + whether the object was allocated from the special free list, so + that the tp_dealloc function can choose the right deallocation + method (assuming that the only two alternatives are a special free + list or the regular heap). A variant that doesn't require space + for an allocation flag bit would be to have two type objects, + identical in the contents of all their slots except for their + deallocation slot. But this requires that all type-checking code + (e.g. the PyDict_Check()) recognizes both types. We'll come back + to this solution in the context of subtyping. Another alternative + is to require the metatype's tp_call to leave the allocation to + the tp_construct method, by passing in a NULL pointer. But this + doesn't work once we allow subtyping. + + Eventually, when we add any form of subtyping, we'll have to + separate deallocation from uninitialization. The way to do this + is to add a separate slot to the type object that does the + uninitialization without the deallocation. Fortunately, there is + already such a slot: tp_clear, currently used by the garbage + collection subsystem. A simple rule makes this slot reusable as + an uninitialization: for types that support separate allocation + and initialization, tp_clear must be defined (even if the object + doesn't support garbage collection) and it must DECREF all + contained objects and FREE all other memory areas the object owns. + It must also be reentrant: it must be possible to clear an already + cleared object. The easiest way to do this is to replace all + pointers DECREFed or FREEd with NULL pointers. From tim_one@users.sourceforge.net Wed Jun 13 23:45:29 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 15:45:29 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_struct.py,1.11,1.12 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv12079/python/dist/src/Lib/test Modified Files: test_struct.py Log Message: Generalize the new qQ std-mode tests to all int codes (bBhHiIlLqQ). Unfortunately, the std-mode bBhHIL codes don't do any range-checking; if and when some of those get fixed, remove their letters from the IntTester.BUGGY_RANGE_CHECK string. In the meantime, a msg saying that range-tests are getting skipped is printed to stdout whenever one is skipped. Index: test_struct.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_struct.py,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -r1.11 -r1.12 *** test_struct.py 2001/06/13 01:26:35 1.11 --- test_struct.py 2001/06/13 22:45:27 1.12 *************** *** 3,6 **** --- 3,23 ---- ## import pdb + import sys + ISBIGENDIAN = sys.byteorder == "big" + del sys + verify((struct.pack('=i', 1)[0] == chr(0)) == ISBIGENDIAN, + "bigendian determination appears wrong") + + def string_reverse(s): + chars = list(s) + chars.reverse() + return "".join(chars) + + def bigendian_to_native(value): + if ISBIGENDIAN: + return value + else: + return string_reverse(value) + def simple_err(func, *args): try: *************** *** 23,26 **** --- 40,44 ---- ## pdb.set_trace() + simple_err(struct.calcsize, 'Z') *************** *** 104,114 **** ] - isbigendian = struct.pack('=i', 1)[0] == chr(0) - for fmt, arg, big, lil, asy in tests: if verbose: print `fmt`, `arg`, `big`, `lil` for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil), ! ('='+fmt, isbigendian and big or lil)]: res = struct.pack(xfmt, arg) if res != exp: --- 122,130 ---- ] for fmt, arg, big, lil, asy in tests: if verbose: print `fmt`, `arg`, `big`, `lil` for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil), ! ('='+fmt, ISBIGENDIAN and big or lil)]: res = struct.pack(xfmt, arg) if res != exp: *************** *** 125,129 **** ########################################################################### ! # q/Q tests. has_native_qQ = 1 --- 141,145 ---- ########################################################################### ! # Simple native q/Q tests. has_native_qQ = 1 *************** *** 140,154 **** simple_err(struct.pack, "Q", "a") # ditto, but 'Q' - def string_reverse(s): - chars = list(s) - chars.reverse() - return "".join(chars) - - def bigendian_to_native(value): - if isbigendian: - return value - else: - return string_reverse(value) - def test_native_qQ(): bytes = struct.calcsize('q') --- 156,159 ---- *************** *** 176,323 **** test_native_qQ() ! # Standard q/Q (8 bytes; should work on all platforms). ! ! MIN_Q, MAX_Q = 0, 2L**64 - 1 ! MIN_q, MAX_q = -(2L**63), 2L**63 - 1 import binascii - def test_one_qQ(x, pack=struct.pack, - unpack=struct.unpack, - unhexlify=binascii.unhexlify): - if verbose: - print "trying std q/Q on", x, "==", hex(x) ! # Try 'q'. ! if MIN_q <= x <= MAX_q: ! # Try '>q'. ! expected = long(x) ! if x < 0: ! expected += 1L << 64 ! assert expected > 0 ! expected = hex(expected)[2:-1] # chop "0x" and trailing 'L' ! if len(expected) & 1: ! expected = "0" + expected ! expected = unhexlify(expected) ! expected = "\x00" * (8 - len(expected)) + expected ! ! # >q pack work? ! got = pack(">q", x) ! verify(got == expected, ! "'>q'-pack of %r gave %r, not %r" % ! (x, got, expected)) ! ! # >q unpack work? ! retrieved = unpack(">q", got)[0] ! verify(x == retrieved, ! "'>q'-unpack of %r gave %r, not %r" % ! (got, retrieved, x)) ! ! # Adding any byte should cause a "too big" error. ! any_err(unpack, ">q", '\x01' + got) ! ! # Try 'q', x) ! any_err(pack, 'Q'. ! expected = long(x) ! expected = hex(expected)[2:-1] # chop "0x" and trailing 'L' ! if len(expected) & 1: ! expected = "0" + expected ! expected = unhexlify(expected) ! expected = "\x00" * (8 - len(expected)) + expected ! ! # >Q pack work? ! got = pack(">Q", x) ! verify(got == expected, ! "'>Q'-pack of %r gave %r, not %r" % ! (x, got, expected)) ! ! # >Q unpack work? ! retrieved = unpack(">Q", got)[0] ! verify(x == retrieved, ! "'>Q'-unpack of %r gave %r, not %r" % ! (got, retrieved, x)) ! ! # Adding any byte should cause a "too big" error. ! any_err(unpack, ">Q", '\x01' + got) ! ! # Try 'Q', x) ! any_err(pack, '": ! for letter in "qQ": ! for badobject in "a string", 3+42j, randrange: ! any_err(struct.pack, direction + letter, badobject) ! ! test_std_qQ() --- 181,367 ---- test_native_qQ() ! ########################################################################### ! # Standard integer tests (bBhHiIlLqQ). import binascii ! class IntTester: ! # XXX Most std integer modes fail to test for out-of-range. ! BUGGY_RANGE_CHECK = "bBhHIL" ! def __init__(self, formatpair, bytesize): ! assert len(formatpair) == 2 ! self.formatpair = formatpair ! for direction in "<>!=": ! for code in formatpair: ! format = direction + code ! verify(struct.calcsize(format) == bytesize) ! self.bytesize = bytesize ! self.bitsize = bytesize * 8 ! self.signed_code, self.unsigned_code = formatpair ! self.unsigned_min = 0 ! self.unsigned_max = 2L**self.bitsize - 1 ! self.signed_min = -(2L**(self.bitsize-1)) ! self.signed_max = 2L**(self.bitsize-1) - 1 ! ! def test_one(self, x, pack=struct.pack, ! unpack=struct.unpack, ! unhexlify=binascii.unhexlify): ! if verbose: ! print "trying std", self.formatpair, "on", x, "==", hex(x) ! # Try signed. ! code = self.signed_code ! if self.signed_min <= x <= self.signed_max: ! # Try big-endian. ! expected = long(x) ! if x < 0: ! expected += 1L << self.bitsize ! assert expected > 0 ! expected = hex(expected)[2:-1] # chop "0x" and trailing 'L' ! if len(expected) & 1: ! expected = "0" + expected ! expected = unhexlify(expected) ! expected = "\x00" * (self.bytesize - len(expected)) + expected ! ! # Pack work? ! format = ">" + code ! got = pack(format, x) ! verify(got == expected, ! "'%s'-pack of %r gave %r, not %r" % ! (format, x, got, expected)) ! ! # Unpack work? ! retrieved = unpack(format, got)[0] ! verify(x == retrieved, ! "'%s'-unpack of %r gave %r, not %r" % ! (format, got, retrieved, x)) ! ! # Adding any byte should cause a "too big" error. ! any_err(unpack, format, '\x01' + got) ! ! # Try little-endian. ! format = "<" + code ! expected = string_reverse(expected) ! ! # Pack work? ! got = pack(format, x) ! verify(got == expected, ! "'%s'-pack of %r gave %r, not %r" % ! (format, x, got, expected)) ! ! # Unpack work? ! retrieved = unpack(format, got)[0] ! verify(x == retrieved, ! "'%s'-unpack of %r gave %r, not %r" % ! (format, got, retrieved, x)) ! ! # Adding any byte should cause a "too big" error. ! any_err(unpack, format, '\x01' + got) ! ! else: ! # x is out of range -- verify pack realizes that. ! if code in self.BUGGY_RANGE_CHECK: ! if verbose: ! print "Skipping buggy range check for code", code ! else: ! any_err(pack, ">" + code, x) ! any_err(pack, "<" + code, x) ! ! # Much the same for unsigned. ! code = self.unsigned_code ! if self.unsigned_min <= x <= self.unsigned_max: ! # Try big-endian. ! format = ">" + code ! expected = long(x) ! expected = hex(expected)[2:-1] # chop "0x" and trailing 'L' ! if len(expected) & 1: ! expected = "0" + expected ! expected = unhexlify(expected) ! expected = "\x00" * (self.bytesize - len(expected)) + expected ! ! # Pack work? ! got = pack(format, x) ! verify(got == expected, ! "'%s'-pack of %r gave %r, not %r" % ! (format, x, got, expected)) ! ! # Unpack work? ! retrieved = unpack(format, got)[0] ! verify(x == retrieved, ! "'%s'-unpack of %r gave %r, not %r" % ! (format, got, retrieved, x)) ! ! # Adding any byte should cause a "too big" error. ! any_err(unpack, format, '\x01' + got) ! ! # Try little-endian. ! format = "<" + code ! expected = string_reverse(expected) ! ! # Pack work? ! got = pack(format, x) ! verify(got == expected, ! "'%s'-pack of %r gave %r, not %r" % ! (format, x, got, expected)) ! ! # Unpack work? ! retrieved = unpack(format, got)[0] ! verify(x == retrieved, ! "'%s'-unpack of %r gave %r, not %r" % ! (format, got, retrieved, x)) ! ! # Adding any byte should cause a "too big" error. ! any_err(unpack, format, '\x01' + got) ! ! else: ! # x is out of range -- verify pack realizes that. ! if code in self.BUGGY_RANGE_CHECK: ! if verbose: ! print "Skipping buggy range check for code", code ! else: ! any_err(pack, ">" + code, x) ! any_err(pack, "<" + code, x) ! ! def run(self): ! from random import randrange ! ! # Create all interesting powers of 2. ! values = [] ! for exp in range(self.bitsize + 3): ! values.append(1L << exp) ! ! # Add some random values. ! for i in range(self.bitsize): ! val = 0L ! for j in range(self.bytesize): ! val = (val << 8) | randrange(256) ! values.append(val) ! ! # Try all those, and their negations, and +-1 from them. Note ! # that this tests all power-of-2 boundaries in range, and a few out ! # of range, plus +-(2**n +- 1). ! for base in values: ! for val in -base, base: ! for incr in -1, 0, 1: ! x = val + incr ! try: ! x = int(x) ! except OverflowError: ! pass ! self.test_one(x) ! ! # Some error cases. ! for direction in "<>": ! for code in self.formatpair: ! for badobject in "a string", 3+42j, randrange: ! any_err(struct.pack, direction + code, badobject) ! ! for args in [("bB", 1), ! ("hH", 2), ! ("iI", 4), ! ("lL", 4), ! ("qQ", 8)]: ! t = IntTester(*args) ! t.run() From gvanrossum@users.sourceforge.net Thu Jun 14 01:53:36 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 13 Jun 2001 17:53:36 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects intobject.c,2.56.6.4,2.56.6.5 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv10258 Modified Files: Tag: descr-branch intobject.c Log Message: In int_new(), assert that the type argument is &PyInt_Type. Index: intobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/intobject.c,v retrieving revision 2.56.6.4 retrieving revision 2.56.6.5 diff -C2 -r2.56.6.4 -r2.56.6.5 *** intobject.c 2001/06/11 21:06:03 2.56.6.4 --- intobject.c 2001/06/14 00:53:34 2.56.6.5 *************** *** 758,761 **** --- 758,762 ---- static char *kwlist[] = {"x", "base", 0}; + assert(type == &PyInt_Type); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist, &x, &base)) From gvanrossum@users.sourceforge.net Thu Jun 14 01:54:08 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 13 Jun 2001 17:54:08 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.38,2.16.8.39 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv10353 Modified Files: Tag: descr-branch typeobject.c Log Message: Don't inherit tp_doc -- it would be misleading. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.38 retrieving revision 2.16.8.39 diff -C2 -r2.16.8.38 -r2.16.8.39 *** typeobject.c 2001/06/11 18:45:10 2.16.8.38 --- typeobject.c 2001/06/14 00:54:06 2.16.8.39 *************** *** 945,949 **** COPYSLOT(tp_as_buffer); COPYSLOT(tp_flags); - COPYSLOT(tp_doc); if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE) { if (type->tp_compare == NULL && type->tp_richcompare == NULL) { --- 945,948 ---- From gvanrossum@users.sourceforge.net Thu Jun 14 01:54:30 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 13 Jun 2001 17:54:30 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.80.2.10,2.80.2.11 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv10482 Modified Files: Tag: descr-branch dictobject.c Log Message: Ad a minimal doc string. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.80.2.10 retrieving revision 2.80.2.11 diff -C2 -r2.80.2.10 -r2.80.2.11 *** dictobject.c 2001/06/07 11:50:05 2.80.2.10 --- dictobject.c 2001/06/14 00:54:28 2.80.2.11 *************** *** 1477,1481 **** 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ --- 1477,1481 ---- 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! "dictionary type", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ From tim_one@users.sourceforge.net Thu Jun 14 01:55:43 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 17:55:43 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules testcapi_long.h,NONE,1.1 _testcapimodule.c,1.5,1.6 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv9814/python/dist/src/Modules Modified Files: _testcapimodule.c Added Files: testcapi_long.h Log Message: Add tests of PyLong_{As,From}{Unsigned,}Long. These are very much like the new PyLong_{As,From}{Unsigned,}LongLong tests, so the bulk of the code is in the new #include file testcapi_long.h, which generates different code depending on how macros are set. This sucks, but I couldn't think of anything that sucked less. UNIX headache? If we still maintain dependencies by hand, someone who knows what they're doing should teach whatever needs it that _testcapimodule.c includes testcapi_long.h. --- NEW FILE: testcapi_long.h --- /* Poor-man's template. Macros used: TESTNAME name of the test (like test_long_api_inner) TYPENAME the signed type (like long) F_S_TO_PY convert signed to pylong; TYPENAME -> PyObject* F_PY_TO_S convert pylong to signed; PyObject* -> TYPENAME F_U_TO_PY convert unsigned to pylong; unsigned TYPENAME -> PyObject* F_PY_TO_U convert pylong to unsigned; PyObject* -> TypeError F_ERROR error-report function; char* -> PyObject* (returns NULL) */ static PyObject * TESTNAME() { const int NBITS = sizeof(TYPENAME) * 8; unsigned TYPENAME base; PyObject *pyresult; int i; /* Note: This test lets PyObjects leak if an error is raised. Since an error should never be raised, leaks are impossible . */ /* Test native -> PyLong -> native roundtrip identity. * Generate all powers of 2, and test them and their negations, * plus the numbers +-1 off from them. */ base = 1; for (i = 0; i < NBITS + 1; /* on last, base overflows to 0 */ ++i, base <<= 1) { int j; for (j = 0; j < 6; ++j) { TYPENAME in, out; unsigned TYPENAME uin, uout; /* For 0, 1, 2 use base; for 3, 4, 5 use -base */ uin = j < 3 ? base : (unsigned TYPENAME)(-(TYPENAME)base); /* For 0 & 3, subtract 1. * For 1 & 4, leave alone. * For 2 & 5, add 1. */ uin += (unsigned TYPENAME)(TYPENAME)(j % 3 - 1); pyresult = F_U_TO_PY(uin); if (pyresult == NULL) return F_ERROR( "unsigned unexpected null result"); uout = F_PY_TO_U(pyresult); if (uout == (unsigned TYPENAME)-1 && PyErr_Occurred()) return F_ERROR( "unsigned unexpected -1 result"); if (uout != uin) return F_ERROR( "unsigned output != input"); UNBIND(pyresult); in = (TYPENAME)uin; pyresult = F_S_TO_PY(in); if (pyresult == NULL) return F_ERROR( "signed unexpected null result"); out = F_PY_TO_S(pyresult); if (out == (TYPENAME)-1 && PyErr_Occurred()) return F_ERROR( "signed unexpected -1 result"); if (out != in) return F_ERROR( "signed output != input"); UNBIND(pyresult); } } /* Overflow tests. The loop above ensured that all limit cases that * should not overflow don't overflow, so all we need to do here is * provoke one-over-the-limit cases (not exhaustive, but sharp). */ { PyObject *one, *x, *y; TYPENAME out; unsigned TYPENAME uout; one = PyLong_FromLong(1); if (one == NULL) return F_ERROR( "unexpected NULL from PyLong_FromLong"); /* Unsigned complains about -1? */ x = PyNumber_Negative(one); if (x == NULL) return F_ERROR( "unexpected NULL from PyNumber_Negative"); uout = F_PY_TO_U(x); if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) return F_ERROR( "PyLong_AsUnsignedXXX(-1) didn't complain"); PyErr_Clear(); UNBIND(x); /* Unsigned complains about 2**NBITS? */ y = PyLong_FromLong((long)NBITS); if (y == NULL) return F_ERROR( "unexpected NULL from PyLong_FromLong"); x = PyNumber_Lshift(one, y); /* 1L << NBITS, == 2**NBITS */ UNBIND(y); if (x == NULL) return F_ERROR( "unexpected NULL from PyNumber_Lshift"); uout = F_PY_TO_U(x); if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) return F_ERROR( "PyLong_AsUnsignedXXX(2**NBITS) didn't " "complain"); PyErr_Clear(); /* Signed complains about 2**(NBITS-1)? x still has 2**NBITS. */ y = PyNumber_Rshift(x, one); /* 2**(NBITS-1) */ UNBIND(x); if (y == NULL) return F_ERROR( "unexpected NULL from PyNumber_Rshift"); out = F_PY_TO_S(y); if (out != (TYPENAME)-1 || !PyErr_Occurred()) return F_ERROR( "PyLong_AsXXX(2**(NBITS-1)) didn't " "complain"); PyErr_Clear(); /* Signed complains about -2**(NBITS-1)-1?; y still has 2**(NBITS-1). */ x = PyNumber_Negative(y); /* -(2**(NBITS-1)) */ UNBIND(y); if (x == NULL) return F_ERROR( "unexpected NULL from PyNumber_Negative"); y = PyNumber_Subtract(x, one); /* -(2**(NBITS-1))-1 */ UNBIND(x); if (y == NULL) return F_ERROR( "unexpected NULL from PyNumber_Subtract"); out = F_PY_TO_S(y); if (out != (TYPENAME)-1 || !PyErr_Occurred()) return F_ERROR( "PyLong_AsXXX(-2**(NBITS-1)-1) didn't " "complain"); PyErr_Clear(); UNBIND(y); Py_XDECREF(x); Py_XDECREF(y); Py_DECREF(one); } Py_INCREF(Py_None); return Py_None; } Index: _testcapimodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_testcapimodule.c,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -r1.5 -r1.6 *** _testcapimodule.c 2001/06/13 00:35:57 1.5 --- _testcapimodule.c 2001/06/14 00:55:41 1.6 *************** *** 173,181 **** } ! #ifdef HAVE_LONG_LONG ! /* Basic sanity checks for PyLong_{As, From}{Unsigned,}LongLong(). */ static PyObject * raise_test_longlong_error(const char* msg) { --- 173,230 ---- } ! ! /* Tests of PyLong_{As, From}{Unsigned,}Long(), and (#ifdef HAVE_LONG_LONG) ! PyLong_{As, From}{Unsigned,}LongLong()/ ! Note that the meat of the test is contained in testcapi_long.h. ! This is revolting, but delicate code duplication is worse: "almost ! exactly the same" code is needed to test LONG_LONG, but the ubiquitous ! dependence on type names makes it impossible to use a parameterized ! function. A giant macro would be even worse than this. A C++ template ! would be perfect. ! ! The "report an error" functions are deliberately not part of the #include ! file: if the test fails, you can set a breakpoint in the appropriate ! error function directly, and crawl back from there in the debugger. ! */ ! ! #define UNBIND(X) Py_DECREF(X); (X) = NULL static PyObject * + raise_test_long_error(const char* msg) + { + return raiseTestError("test_long_api", msg); + } + + #define TESTNAME test_long_api_inner + #define TYPENAME long + #define F_S_TO_PY PyLong_FromLong + #define F_PY_TO_S PyLong_AsLong + #define F_U_TO_PY PyLong_FromUnsignedLong + #define F_PY_TO_U PyLong_AsUnsignedLong + #define F_ERROR raise_test_long_error + + #include "testcapi_long.h" + + static PyObject * + test_long_api(PyObject* self, PyObject* args) + { + if (!PyArg_ParseTuple(args, ":test_long_api")) + return NULL; + + return TESTNAME(); + } + + #undef TESTNAME + #undef TYPENAME + #undef F_S_TO_PY + #undef F_PY_TO_S + #undef F_U_TO_PY + #undef F_PY_TO_U + #undef F_ERROR + + #ifdef HAVE_LONG_LONG + + static PyObject * raise_test_longlong_error(const char* msg) { *************** *** 183,352 **** } ! #define UNBIND(X) Py_DECREF(X); (X) = NULL static PyObject * test_longlong_api(PyObject* self, PyObject* args) { - const int NBITS = SIZEOF_LONG_LONG * 8; - unsigned LONG_LONG base; - PyObject *pyresult; - int i; - if (!PyArg_ParseTuple(args, ":test_longlong_api")) return NULL; ! ! /* Note: This test lets PyObjects leak if an error is raised. Since ! an error should never be raised, leaks are impossible . */ ! /* Test native -> PyLong -> native roundtrip identity. ! * Generate all powers of 2, and test them and their negations, ! * plus the numbers +-1 off from them. ! */ ! base = 1; ! for (i = 0; ! i < NBITS + 1; /* on last, base overflows to 0 */ ! ++i, base <<= 1) ! { ! int j; ! for (j = 0; j < 6; ++j) { ! LONG_LONG in, out; ! unsigned LONG_LONG uin, uout; ! ! /* For 0, 1, 2 use base; for 3, 4, 5 use -base */ ! uin = j < 3 ? base ! : (unsigned LONG_LONG)(-(LONG_LONG)base); ! ! /* For 0 & 3, subtract 1. ! * For 1 & 4, leave alone. ! * For 2 & 5, add 1. ! */ ! uin += (unsigned LONG_LONG)(LONG_LONG)(j % 3 - 1); ! ! pyresult = PyLong_FromUnsignedLongLong(uin); ! if (pyresult == NULL) ! return raise_test_longlong_error( ! "unsigned unexpected null result"); ! ! uout = PyLong_AsUnsignedLongLong(pyresult); ! if (uout == (unsigned LONG_LONG)-1 && PyErr_Occurred()) ! return raise_test_longlong_error( ! "unsigned unexpected -1 result"); ! if (uout != uin) ! return raise_test_longlong_error( ! "unsigned output != input"); ! UNBIND(pyresult); ! ! in = (LONG_LONG)uin; ! pyresult = PyLong_FromLongLong(in); ! if (pyresult == NULL) ! return raise_test_longlong_error( ! "signed unexpected null result"); ! ! out = PyLong_AsLongLong(pyresult); ! if (out == (LONG_LONG)-1 && PyErr_Occurred()) ! return raise_test_longlong_error( ! "signed unexpected -1 result"); ! if (out != in) ! return raise_test_longlong_error( ! "signed output != input"); ! UNBIND(pyresult); ! } ! } ! ! /* Overflow tests. The loop above ensured that all limit cases that ! * should not overflow don't overflow, so all we need to do here is ! * provoke one-over-the-limit cases (not exhaustive, but sharp). ! */ ! { ! PyObject *one, *x, *y; ! LONG_LONG out; ! unsigned LONG_LONG uout; ! ! one = PyLong_FromLong(1); ! if (one == NULL) ! return raise_test_longlong_error( ! "unexpected NULL from PyLong_FromLong"); ! ! /* Unsigned complains about -1? */ ! x = PyNumber_Negative(one); ! if (x == NULL) ! return raise_test_longlong_error( ! "unexpected NULL from PyNumber_Negative"); ! ! uout = PyLong_AsUnsignedLongLong(x); ! if (uout != (unsigned LONG_LONG)-1 || !PyErr_Occurred()) ! return raise_test_longlong_error( ! "PyLong_AsUnsignedLongLong(-1) didn't " ! "complain"); ! PyErr_Clear(); ! UNBIND(x); ! ! /* Unsigned complains about 2**NBITS? */ ! y = PyLong_FromLong((long)NBITS); ! if (y == NULL) ! return raise_test_longlong_error( ! "unexpected NULL from PyLong_FromLong"); ! ! x = PyNumber_Lshift(one, y); /* 1L << NBITS, == 2**NBITS */ ! UNBIND(y); ! if (x == NULL) ! return raise_test_longlong_error( ! "unexpected NULL from PyNumber_Lshift"); ! ! uout = PyLong_AsUnsignedLongLong(x); ! if (uout != (unsigned LONG_LONG)-1 || !PyErr_Occurred()) ! return raise_test_longlong_error( ! "PyLong_AsUnsignedLongLong(2**NBITS) didn't " ! "complain"); ! PyErr_Clear(); ! ! /* Signed complains about 2**(NBITS-1)? ! x still has 2**NBITS. */ ! y = PyNumber_Rshift(x, one); /* 2**(NBITS-1) */ ! UNBIND(x); ! if (y == NULL) ! return raise_test_longlong_error( ! "unexpected NULL from PyNumber_Rshift"); ! ! out = PyLong_AsLongLong(y); ! if (out != (LONG_LONG)-1 || !PyErr_Occurred()) ! return raise_test_longlong_error( ! "PyLong_AsLongLong(2**(NBITS-1)) didn't " ! "complain"); ! PyErr_Clear(); ! ! /* Signed complains about -2**(NBITS-1)-1?; ! y still has 2**(NBITS-1). */ ! x = PyNumber_Negative(y); /* -(2**(NBITS-1)) */ ! UNBIND(y); ! if (x == NULL) ! return raise_test_longlong_error( ! "unexpected NULL from PyNumber_Negative"); ! ! y = PyNumber_Subtract(x, one); /* -(2**(NBITS-1))-1 */ ! UNBIND(x); ! if (y == NULL) ! return raise_test_longlong_error( ! "unexpected NULL from PyNumber_Subtract"); ! ! out = PyLong_AsLongLong(y); ! if (out != (LONG_LONG)-1 || !PyErr_Occurred()) ! return raise_test_longlong_error( ! "PyLong_AsLongLong(-2**(NBITS-1)-1) didn't " ! "complain"); ! PyErr_Clear(); ! UNBIND(y); ! ! Py_XDECREF(x); ! Py_XDECREF(y); ! Py_DECREF(one); ! } ! Py_INCREF(Py_None); ! return Py_None; ! } - #endif static PyMethodDef TestMethods[] = { --- 232,264 ---- } ! #define TESTNAME test_longlong_api_inner ! #define TYPENAME LONG_LONG ! #define F_S_TO_PY PyLong_FromLongLong ! #define F_PY_TO_S PyLong_AsLongLong ! #define F_U_TO_PY PyLong_FromUnsignedLongLong ! #define F_PY_TO_U PyLong_AsUnsignedLongLong ! #define F_ERROR raise_test_longlong_error ! ! #include "testcapi_long.h" static PyObject * test_longlong_api(PyObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, ":test_longlong_api")) return NULL; ! return TESTNAME(); ! } ! #undef TESTNAME ! #undef TYPENAME ! #undef F_S_TO_PY ! #undef F_PY_TO_S ! #undef F_U_TO_PY ! #undef F_PY_TO_U ! #undef F_ERROR ! #endif /* ifdef HAVE_LONG_LONG */ static PyMethodDef TestMethods[] = { *************** *** 354,357 **** --- 266,270 ---- {"test_list_api", test_list_api, METH_VARARGS}, {"test_dict_iteration", test_dict_iteration, METH_VARARGS}, + {"test_long_api", test_long_api, METH_VARARGS}, #ifdef HAVE_LONG_LONG {"test_longlong_api", test_longlong_api, METH_VARARGS}, From gvanrossum@users.sourceforge.net Thu Jun 14 02:01:18 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Wed, 13 Jun 2001 18:01:18 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.71.6.2,1.71.6.3 floatobject.c,2.81.6.3,2.81.6.4 stringobject.c,2.103.2.4,2.103.2.5 tupleobject.c,2.48.6.2,2.48.6.3 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv11831/Objects Modified Files: Tag: descr-branch longobject.c floatobject.c stringobject.c tupleobject.c Log Message: Four more built-in types bite the dust: the built-ins long, float, string and tuple are now type objects. These can't be subtyped yet! Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.71.6.2 retrieving revision 1.71.6.3 diff -C2 -r1.71.6.2 -r1.71.6.3 *** longobject.c 2001/06/06 14:27:54 1.71.6.2 --- longobject.c 2001/06/14 01:01:16 1.71.6.3 *************** *** 1813,1816 **** --- 1813,1853 ---- } + static PyObject * + long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + PyObject *x = NULL; + int base = -909; /* unlikely! */ + static char *kwlist[] = {"x", "base", 0}; + + assert(type == &PyLong_Type); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:long", kwlist, + &x, &base)) + return NULL; + if (x == NULL) + return PyLong_FromLong(0L); + if (base == -909) + return PyNumber_Long(x); + else if (PyString_Check(x)) + return PyLong_FromString(PyString_AS_STRING(x), NULL, base); + else if (PyUnicode_Check(x)) + return PyLong_FromUnicode(PyUnicode_AS_UNICODE(x), + PyUnicode_GET_SIZE(x), + base); + else { + PyErr_SetString(PyExc_TypeError, + "long() can't convert non-string with explicit base"); + return NULL; + } + } + + static char long_doc[] = + "long(x[, base]) -> integer\n\ + \n\ + Convert a string or number to a long integer, if possible. A floating\n\ + point argument will be truncated towards zero (this does not include a\n\ + string representation of a floating point number!) When converting a\n\ + string, use the optional base. It is an error to supply a base when\n\ + converting a non-string."; + static PyNumberMethods long_as_number = { (binaryfunc) long_add, /*nb_add*/ *************** *** 1853,1857 **** PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ ! "long int", /* tp_name */ sizeof(PyLongObject) - sizeof(digit), /* tp_basicsize */ sizeof(digit), /* tp_itemsize */ --- 1890,1894 ---- PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ ! "long", /* tp_name */ sizeof(PyLongObject) - sizeof(digit), /* tp_basicsize */ sizeof(digit), /* tp_itemsize */ *************** *** 1872,1874 **** --- 1909,1929 ---- 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ + long_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + long_new, /* tp_new */ }; Index: floatobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/floatobject.c,v retrieving revision 2.81.6.3 retrieving revision 2.81.6.4 diff -C2 -r2.81.6.3 -r2.81.6.4 *** floatobject.c 2001/06/06 14:27:54 2.81.6.3 --- floatobject.c 2001/06/14 01:01:16 2.81.6.4 *************** *** 625,628 **** --- 625,648 ---- + static PyObject * + float_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + PyObject *x; + static char *kwlist[] = {"x", 0}; + + assert(type == &PyFloat_Type); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x)) + return NULL; + if (PyString_Check(x)) + return PyFloat_FromString(x, NULL); + return PyNumber_Float(x); + } + + static char float_doc[] = + "float(x) -> floating point number\n\ + \n\ + Convert a string or number to a floating point number, if possible."; + + static PyNumberMethods float_as_number = { (binaryfunc)float_add, /*nb_add*/ *************** *** 683,687 **** 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */ }; --- 703,725 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ ! float_doc, /* tp_doc */ ! 0, /* tp_traverse */ ! 0, /* tp_clear */ ! 0, /* tp_richcompare */ ! 0, /* tp_weaklistoffset */ ! 0, /* tp_iter */ ! 0, /* tp_iternext */ ! 0, /* tp_methods */ ! 0, /* tp_members */ ! 0, /* tp_getset */ ! 0, /* tp_base */ ! 0, /* tp_dict */ ! 0, /* tp_descr_get */ ! 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! 0, /* tp_init */ ! 0, /* tp_alloc */ ! float_new, /* tp_new */ }; Index: stringobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v retrieving revision 2.103.2.4 retrieving revision 2.103.2.5 diff -C2 -r2.103.2.4 -r2.103.2.5 *** stringobject.c 2001/06/06 14:27:54 2.103.2.4 --- stringobject.c 2001/06/14 01:01:16 2.103.2.5 *************** *** 2358,2362 **** --- 2358,2381 ---- }; + static PyObject * + string_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + PyObject *x = NULL; + static char *kwlist[] = {"object", 0}; + assert(type == &PyString_Type); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:str", kwlist, &x)) + return NULL; + if (x == NULL) + return PyString_FromString(""); + return PyObject_Str(x); + } + + static char string_doc[] = + "str(object) -> string\n\ + \n\ + Return a nice string representation of the object.\n\ + If the argument is a string, the return value is the same object."; + PyTypeObject PyString_Type = { PyObject_HEAD_INIT(&PyType_Type) *************** *** 2381,2385 **** &string_as_buffer, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ --- 2400,2404 ---- &string_as_buffer, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! string_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ *************** *** 2393,2396 **** --- 2412,2421 ---- 0, /* tp_base */ 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + string_new, /* tp_new */ }; Index: tupleobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/tupleobject.c,v retrieving revision 2.48.6.2 retrieving revision 2.48.6.3 diff -C2 -r2.48.6.2 -r2.48.6.3 *** tupleobject.c 2001/06/06 14:27:54 2.48.6.2 --- tupleobject.c 2001/06/14 01:01:16 2.48.6.3 *************** *** 444,447 **** --- 444,469 ---- } + static PyObject * + tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + PyObject *arg = NULL; + static char *kwlist[] = {"sequence", 0}; + + assert(type == &PyTuple_Type); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg)) + return NULL; + + if (arg == NULL) + return PyTuple_New(0); + else + return PySequence_Tuple(arg); + } + + static char tuple_doc[] = + "tuple(sequence) -> list\n\ + \n\ + Return a tuple whose items are the same as those of the argument sequence.\n\ + If the argument is a tuple, the return value is the same object."; + static PySequenceMethods tuple_as_sequence = { (inquiry)tuplelength, /* sq_length */ *************** *** 477,484 **** 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ ! 0, /* tp_doc */ (traverseproc)tupletraverse, /* tp_traverse */ 0, /* tp_clear */ tuplerichcompare, /* tp_richcompare */ }; --- 499,520 ---- 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ ! tuple_doc, /* tp_doc */ (traverseproc)tupletraverse, /* tp_traverse */ 0, /* tp_clear */ tuplerichcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + tuple_new, /* tp_new */ }; From tim_one@users.sourceforge.net Thu Jun 14 02:11:05 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 18:11:05 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules _testcapimodule.c,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv14056/python/dist/src/Modules Modified Files: _testcapimodule.c Log Message: Fixed typo in comment. Index: _testcapimodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_testcapimodule.c,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -r1.6 -r1.7 *** _testcapimodule.c 2001/06/14 00:55:41 1.6 --- _testcapimodule.c 2001/06/14 01:11:03 1.7 *************** *** 175,179 **** /* Tests of PyLong_{As, From}{Unsigned,}Long(), and (#ifdef HAVE_LONG_LONG) ! PyLong_{As, From}{Unsigned,}LongLong()/ Note that the meat of the test is contained in testcapi_long.h. --- 175,179 ---- /* Tests of PyLong_{As, From}{Unsigned,}Long(), and (#ifdef HAVE_LONG_LONG) ! PyLong_{As, From}{Unsigned,}LongLong(). Note that the meat of the test is contained in testcapi_long.h. From tim_one@users.sourceforge.net Thu Jun 14 05:56:21 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 21:56:21 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.79,1.80 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv10246/python/dist/src/Objects Modified Files: longobject.c Log Message: PyLong_From{Unsigned,}Long: count the # of digits first, so no more space is allocated than needed (used to allocate 80 bytes of digit space no matter how small the long input). This also runs faster, at least on 32- bit boxes. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.79 retrieving revision 1.80 diff -C2 -r1.79 -r1.80 *** longobject.c 2001/06/13 21:09:15 1.79 --- longobject.c 2001/06/14 04:56:19 1.80 *************** *** 58,76 **** PyLong_FromLong(long ival) { ! /* Assume a C long fits in at most 5 'digits' */ ! /* Works on both 32- and 64-bit machines */ ! PyLongObject *v = _PyLong_New(5); if (v != NULL) { ! unsigned long t = ival; ! int i; ! if (ival < 0) { ! t = -ival; ! v->ob_size = -(v->ob_size); ! } ! for (i = 0; i < 5; i++) { ! v->ob_digit[i] = (digit) (t & MASK); t >>= SHIFT; } - v = long_normalize(v); } return (PyObject *)v; --- 58,89 ---- PyLong_FromLong(long ival) { ! PyLongObject *v; ! unsigned long t; /* unsigned so >> doesn't propagate sign bit */ ! int ndigits = 0; ! int negative = 0; ! ! if (ival < 0) { ! ival = -ival; ! negative = 1; ! } ! ! /* Count the number of Python digits. ! We used to pick 5 ("big enough for anything"), but that's a ! waste of time and space given that 5*15 = 75 bits are rarely ! needed. */ ! t = (unsigned long)ival; ! while (t) { ! ++ndigits; ! t >>= SHIFT; ! } ! v = _PyLong_New(ndigits); if (v != NULL) { ! digit *p = v->ob_digit; ! v->ob_size = negative ? -ndigits : ndigits; ! t = (unsigned long)ival; ! while (t) { ! *p++ = (digit)(t & MASK); t >>= SHIFT; } } return (PyObject *)v; *************** *** 82,96 **** PyLong_FromUnsignedLong(unsigned long ival) { ! /* Assume a C long fits in at most 5 'digits' */ ! /* Works on both 32- and 64-bit machines */ ! PyLongObject *v = _PyLong_New(5); if (v != NULL) { ! unsigned long t = ival; ! int i; ! for (i = 0; i < 5; i++) { ! v->ob_digit[i] = (digit) (t & MASK); ! t >>= SHIFT; } - v = long_normalize(v); } return (PyObject *)v; --- 95,116 ---- PyLong_FromUnsignedLong(unsigned long ival) { ! PyLongObject *v; ! unsigned long t; ! int ndigits = 0; ! ! /* Count the number of Python digits. */ ! t = (unsigned long)ival; ! while (t) { ! ++ndigits; ! t >>= SHIFT; ! } ! v = _PyLong_New(ndigits); if (v != NULL) { ! digit *p = v->ob_digit; ! v->ob_size = ndigits; ! while (ival) { ! *p++ = (digit)(ival & MASK); ! ival >>= SHIFT; } } return (PyObject *)v; From tim_one@users.sourceforge.net Thu Jun 14 07:57:31 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Wed, 13 Jun 2001 23:57:31 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0255.txt,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv8864/python/nondist/peps Modified Files: pep-0255.txt Log Message: Substantial rewriting. Index: pep-0255.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0255.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -r1.1 -r1.2 *** pep-0255.txt 2001/06/05 17:11:30 1.1 --- pep-0255.txt 2001/06/14 06:57:29 1.2 *************** *** 92,96 **** very simple example: ! def fib(): a, b = 0, 1 while 1: yield b --- 92,97 ---- very simple example: ! def fib(): ! a, b = 0, 1 while 1: yield b *************** *** 119,161 **** Specification ! A new statement, the "yield" statement, is introduced: ! yield_stmt: "yield" [expression_list] ! This statement may only be used inside functions. A function which ! contains a yield statement is a so-called "generator function". A ! generator function may not contain return statements of the form: ! "return" expression_list ! It may, however, contain return statements of the form: "return" ! When a generator function is called, an iterator[6] is returned. ! Each time the .next() method of this iterator is called, the code ! in the body of the generator function is executed until a yield ! statement or a return statement is encountered, or until the end ! of the body is reached. ! ! If a yield statement is encountered during this execution, the ! state of the function is frozen, and a value is returned to the ! object calling .next(). If an empty yield statement was ! encountered, None is returned; otherwise, the given expression(s) ! is (are) returned. ! ! If an empty return statement is encountered, nothing is returned; ! however, a StopIteration exception is raised, signalling that the ! iterator is exhausted. ! An example of how generators may be used is given below: ! # A binary tree class class Tree: def __init__(self, label, left=None, right=None): self.label = label self.left = left self.right = right ! def __repr__(self, level=0, indent=" "): s = level*indent + `self.label` if self.left: --- 120,183 ---- Specification ! A new statement is introduced: ! yield_stmt: "yield" expression_list ! "yield" is a new keyword, so a future statement[8] is needed to phase ! this in. [XXX spell this out] ! The yield statement may only be used inside functions. A function that ! contains a yield statement is called a generator function. ! ! When a generator function is called, the actual arguments are bound to ! function-local formal argument names in the usual way, but no code in ! the body of the function is executed. Instead a generator-iterator ! object is returned; this conforms to the iterator protocol[6], so in ! particular can be used in for-loops in a natural way. Note that when ! the intent is clear from context, the unqualified name "generator" may ! be used to refer either to a generator-function or a generator- ! iterator. ! ! Each time the .next() method of a generator-iterator is invoked, the ! code in the body of the generator-function is executed until a yield ! or return statement (see below) is encountered, or until the end of ! the body is reached. ! ! If a yield statement is encountered, the state of the function is ! frozen, and the value of expression_list is returned to .next()'s ! caller. By "frozen" we mean that all local state is retained, ! including the current bindings of local variables, the instruction ! pointer, and the internal evaluation stack: enough information is ! saved so that the next time .next() is invoked, the function can ! proceed exactly is if the yield statement were just another external ! call. ! A generator function can also contain return statements of the form: "return" ! Note that an expression_list is not allowed on return statements ! in the body of a generator (although, of course, they may appear in ! the bodies of non-generator functions nested within the generator). ! When a return statement is encountered, nothing is returned, but a ! StopIteration exception is raised, signalling that the iterator is ! exhausted. The same is true if control flows off the end of the ! function. Note that return means "I'm done, and have nothing ! interesting to return", for both generator functions and non-generator ! functions. ! ! Example ! ! # A binary tree class. class Tree: + def __init__(self, label, left=None, right=None): self.label = label self.left = left self.right = right ! ! def __repr__(self, level=0, indent=" "): s = level*indent + `self.label` if self.left: *************** *** 164,208 **** s = s + "\n" + self.right.__repr__(level+1, indent) return s def __iter__(self): return inorder(self) ! ! # A function that creates a tree from a list def tree(list): ! if not len(list): return [] ! i = len(list)/2 return Tree(list[i], tree(list[:i]), tree(list[i+1:])) ! ! # A recursive generator that generates the tree leaves in in-order def inorder(t): if t: ! for x in inorder(t.left): yield x yield t.label ! for x in inorder(t.right): yield x ! ! # Show it off: create a tree t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ") ! # Print the nodes of the tree in in-order ! for x in t: print x, print ! # A non-recursive generator. def inorder(node): ! stack = [] ! while node: ! while node.left: ! stack.append(node) ! node = node.left ! yield node.label ! while not node.right: ! try: ! node = stack.pop() ! except IndexError: ! return ! yield node.label ! node = node.right ! ! # Exercise the non-recursive generator ! for x in t: print x, print --- 186,236 ---- s = s + "\n" + self.right.__repr__(level+1, indent) return s + def __iter__(self): return inorder(self) ! ! # Create a Tree from a list. def tree(list): ! n = len(list) ! if n == 0: return [] ! i = n / 2 return Tree(list[i], tree(list[:i]), tree(list[i+1:])) ! ! # A recursive generator that generates Tree leaves in in-order. def inorder(t): if t: ! for x in inorder(t.left): ! yield x yield t.label ! for x in inorder(t.right): ! yield x ! ! # Show it off: create a tree. t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ") ! # Print the nodes of the tree in in-order. ! for x in t: ! print x, print ! # A non-recursive generator. def inorder(node): ! stack = [] ! while node: ! while node.left: ! stack.append(node) ! node = node.left ! yield node.label ! while not node.right: ! try: ! node = stack.pop() ! except IndexError: ! return ! yield node.label ! node = node.right ! ! # Exercise the non-recursive generator. ! for x in t: ! print x, print *************** *** 215,221 **** Footnotes and References ! [1] PEP 234, http://python.sourceforge.net/peps/pep-0234.html [2] http://www.stackless.com/ ! [3] PEP 219, http://python.sourceforge.net/peps/pep-0219.html [4] "Iteration Abstraction in Sather" Murer , Omohundro, Stoutamire and Szyperski --- 243,249 ---- Footnotes and References ! [1] PEP 234, http://python.sf.net/peps/pep-0234.html [2] http://www.stackless.com/ ! [3] PEP 219, http://python.sf.net/peps/pep-0219.html [4] "Iteration Abstraction in Sather" Murer , Omohundro, Stoutamire and Szyperski *************** *** 223,228 **** [5] http://www.cs.arizona.edu/icon/ [6] The concept of iterators is described in PEP 234 ! http://python.sourceforge.net/peps/pep-0234.html [7] http://python.ca/nas/python/generator.diff --- 251,257 ---- [5] http://www.cs.arizona.edu/icon/ [6] The concept of iterators is described in PEP 234 ! http://python.sf.net/peps/pep-0234.html [7] http://python.ca/nas/python/generator.diff + [8] http://python.sf.net/peps/pep-0236.html From tim_one@users.sourceforge.net Thu Jun 14 09:53:40 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Thu, 14 Jun 2001 01:53:40 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.80,1.81 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv2492/python/dist/src/Objects Modified Files: longobject.c Log Message: _PyLong_AsByteArray: simplify the logic for dealing with the most- significant digits sign bits. Again no change in semantics. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.80 retrieving revision 1.81 diff -C2 -r1.80 -r1.81 *** longobject.c 2001/06/14 04:56:19 1.80 --- longobject.c 2001/06/14 08:53:38 1.81 *************** *** 389,393 **** carry = do_twos_comp ? 1 : 0; for (i = 0; i < ndigits; ++i) { - unsigned int numnewbits = SHIFT; twodigits thisdigit = v->ob_digit[i]; if (do_twos_comp) { --- 389,392 ---- *************** *** 400,419 **** prepended to accum. */ accum |= thisdigit << accumbits; ! /* How many new bits did we add? The most-significant digit ! may be (probably is) at least partly empty. */ if (i == ndigits - 1) { ! twodigits bitmask = 1 << (SHIFT - 1); ! twodigits signbit = do_twos_comp << (SHIFT - 1); unsigned int nsignbits = 0; ! while ((thisdigit & bitmask) == signbit && bitmask) { ++nsignbits; ! bitmask >>= 1; ! signbit >>= 1; } ! assert(nsignbits <= SHIFT); ! numnewbits -= nsignbits; } - accumbits += numnewbits; /* Store as many bytes as possible. */ --- 399,421 ---- prepended to accum. */ accum |= thisdigit << accumbits; + accumbits += SHIFT; ! /* The most-significant digit may be (probably is) at least ! partly empty. */ if (i == ndigits - 1) { ! /* Count # of sign bits -- they needn't be stored, ! * although for signed conversion we need later to ! * make sure at least one sign bit gets stored. ! * First shift conceptual sign bit to real sign bit. ! */ ! stwodigits s = (stwodigits)(thisdigit << ! (8*sizeof(stwodigits) - SHIFT)); unsigned int nsignbits = 0; ! while ((s < 0) == do_twos_comp && nsignbits < SHIFT) { ++nsignbits; ! s <<= 1; } ! accumbits -= nsignbits; } /* Store as many bytes as possible. */ From gvanrossum@users.sourceforge.net Thu Jun 14 12:26:47 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 14 Jun 2001 04:26:47 -0700 Subject: [Python-checkins] CVS: python/dist/src LICENSE,1.7.2.3,1.7.2.4 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv23464 Modified Files: Tag: release20-maint LICENSE Log Message: Fix two mentions of 2.1 instead of 2.0.1. Not worth fixing this in the 2.0.1c1 release (which has already been built and pushed out to SF and py.org), but will be correct in the 2.0.1 final release. Does this require a matching update in the license as quoted in the docs? Index: LICENSE =================================================================== RCS file: /cvsroot/python/python/dist/src/LICENSE,v retrieving revision 1.7.2.3 retrieving revision 1.7.2.4 diff -C2 -r1.7.2.3 -r1.7.2.4 *** LICENSE 2001/05/04 18:50:14 1.7.2.3 --- LICENSE 2001/06/14 11:26:45 1.7.2.4 *************** *** 21,25 **** Python license. Python 1.6.1 is essentially the same as Python 1.6, with a few minor bug fixes, and with a different license that enables ! later versions to be GPL-compatible. Python 2.1 is a derivative work of Python 1.6.1, as well as of Python 2.0. --- 21,25 ---- Python license. Python 1.6.1 is essentially the same as Python 1.6, with a few minor bug fixes, and with a different license that enables ! later versions to be GPL-compatible. Python 2.0.1 is a derivative work of Python 1.6.1, as well as of Python 2.0. *************** *** 83,87 **** products or services of Licensee, or any third party. ! 8. By copying, installing or otherwise using Python 2.1, Licensee agrees to be bound by the terms and conditions of this License Agreement. --- 83,87 ---- products or services of Licensee, or any third party. ! 8. By copying, installing or otherwise using Python 2.0.1, Licensee agrees to be bound by the terms and conditions of this License Agreement. From gvanrossum@users.sourceforge.net Thu Jun 14 14:37:47 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 14 Jun 2001 06:37:47 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0253.txt,1.4,1.5 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv10803 Modified Files: pep-0253.txt Log Message: Clarified the paragraph about creating a subtype in C. Index: pep-0253.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0253.txt,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -r1.4 -r1.5 *** pep-0253.txt 2001/06/13 21:48:31 1.4 --- pep-0253.txt 2001/06/14 13:37:45 1.5 *************** *** 369,372 **** --- 369,377 ---- Creating a subtype of a built-in type in C + Let's assume we're deriving from a mutable base type whose + tp_itemsize is zero. The subtype code is not GC-aware, although + it may inherit GC-awareness from the base type (this is + automatic). The base type's allocation uses the standard heap. + The derived type begins by declaring a type structure which contains the base type's structure. For example, here's the type *************** *** 391,433 **** into it. Some fields that must be initialized properly: ! - the object header must be filled in as usual; the type should be ! PyType_Type ! - the tp_basicsize field must be set to the size of the subtype ! instances ! - the tp_base field must be set to the address of the base type's ! type object ! - the tp_dealloc slot function must be a deallocation function for ! the subtype ! - the tp_flags field must be set to the usual Py_TPFLAGS_DEFAULT ! value ! - the tp_name field must be set (otherwise it will be inherited, ! which is wrong) Exception: if the subtype defines no additional fields in its structure (i.e., it only defines new behavior, no new data), the ! tp_basicsize and the tp_dealloc fields may be set to zero. In ! order to complete the initialization of the type, PyType_InitDict() must be called. This replaces zero slots in the ! subtype with the value of the corresponding base type slots. It ! also fills in tp_dict, the type's dictionary; this is more a ! matter of pep-0252. ! ! The subtype's tp_dealloc slot deserves special attention. It must ! uninitialize and deallocate the object in an orderly manner: first ! it must uninitialize the fields added by the extension type; then ! it must call the base type's tp_clear function; finally it must ! deallocate the memory of the object. Usually, the base type's ! tp_clear function has no global name; it is permissible to call it ! via the base type's tp_clear slot, e.g. PyListType.tp_clear(obj). ! Only if it is known that the base type uses the same allocation ! method as the subtype and the subtype requires no uninitialization ! (e.g. it adds no data fields or all its data fields are numbers) ! is it permissible to leave tp_dealloc set to zero in the subtype's ! type object; it will be copied from the base type. A subtype is not usable until PyType_InitDict() is called for it; --- 396,447 ---- into it. Some fields that must be initialized properly: ! - The object header must be filled in as usual; the type should be ! &PyType_Type. ! - The tp_basicsize field must be set to the size of the subtype ! instance struct (in the above example: sizeof(spamlistobject)). ! - The tp_base field must be set to the address of the base type's ! type object. ! - If the derived slot defines any pointer fields, the tp_dealloc ! slot function requires special attention, see below; otherwise, ! it can be set to zero, to inherit the base type's deallocation ! function. ! - The tp_flags field must be set to the usual Py_TPFLAGS_DEFAULT ! value. ! - The tp_name field must be set; it is recommended to set tp_doc ! as well (these are not inherited). Exception: if the subtype defines no additional fields in its structure (i.e., it only defines new behavior, no new data), the ! tp_basicsize and the tp_dealloc fields may be set to zero. ! ! In order to complete the initialization of the type, PyType_InitDict() must be called. This replaces zero slots in the ! subtype with the value of the corresponding base type slots. (It ! also fills in tp_dict, the type's dictionary, and does various ! other initializations necessary for type objects.) ! ! The subtype's tp_dealloc slot deserves special attention. If the ! derived type defines no additional pointers that need to be ! DECREF'ed or freed when the object is deallocated, it can be set ! to zero. Otherwise, the subtype's deallocation function must call ! Py_XDECREF() for any PyObject * fields and the correct memory ! freeing function for any other pointers it owns, and then call the ! base class's tp_dealloc slot. Because deallocation functions ! typically are not exported, this call has to be made via the base ! type's type structure, e.g., when deriving from the standard list ! type: ! ! PyList_Type.tp_dealloc(self); ! ! (If the subtype uses a different allocation heap than the base ! type, the subtype must call the base type's tp_clear() slot ! instead, followed by a call to free the object's memory from the ! appropriate heap, e.g. PyObject_DEL(self) if the subtype uses the ! standard heap. But in this case subtyping is not recommended.) A subtype is not usable until PyType_InitDict() is called for it; *************** *** 440,448 **** calls, a test for tp_dict==NULL can be made. ! If the subtype itself should be subtypable (usually desirable), it ! should follow the same rules are given above for base types: have ! a tp_construct that accepts a preallocated object and calls the ! base type's tp_construct, and have a tp_clear that calls the base ! type's tp_clear. --- 454,464 ---- calls, a test for tp_dict==NULL can be made. ! To create a subtype instance, the base type's tp_alloc slot must ! be called with the subtype as its first argument. Then, if the ! base type has a tp_init slot, that must be called to initialize ! the base portion of the instance; finally the subtype's own fields ! must be initialized. After allocation, the initialization can ! also be done by calling the subtype's tp_init slot, assuming this ! correctly calls its base type's tp_init slot. From fdrake@users.sourceforge.net Thu Jun 14 14:57:18 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Thu, 14 Jun 2001 06:57:18 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libprofile.tex,1.33,1.34 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv17442/lib Modified Files: libprofile.tex Log Message: Fix an improperly placed comma. Index: libprofile.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libprofile.tex,v retrieving revision 1.33 retrieving revision 1.34 diff -C2 -r1.33 -r1.34 *** libprofile.tex 2001/06/08 05:04:19 1.33 --- libprofile.tex 2001/06/14 13:57:16 1.34 *************** *** 617,621 **** profiler will actually run equally fast!!), but the above method is the simplest to use. I could have made the profiler ``self ! calibrating'', but it would have made the initialization of the profiler class slower, and would have required some \emph{very} fancy coding, or else the use of a variable where the constant \samp{.00053} --- 617,621 ---- profiler will actually run equally fast!!), but the above method is the simplest to use. I could have made the profiler ``self ! calibrating,'' but it would have made the initialization of the profiler class slower, and would have required some \emph{very} fancy coding, or else the use of a variable where the constant \samp{.00053} From fdrake@users.sourceforge.net Thu Jun 14 14:57:51 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Thu, 14 Jun 2001 06:57:51 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libprofile.tex,1.32,1.32.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv17663/lib Modified Files: Tag: release21-maint libprofile.tex Log Message: Fix an improperly placed comma. Index: libprofile.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libprofile.tex,v retrieving revision 1.32 retrieving revision 1.32.2.1 diff -C2 -r1.32 -r1.32.2.1 *** libprofile.tex 2001/04/13 14:34:58 1.32 --- libprofile.tex 2001/06/14 13:57:49 1.32.2.1 *************** *** 617,621 **** profiler will actually run equally fast!!), but the above method is the simplest to use. I could have made the profiler ``self ! calibrating'', but it would have made the initialization of the profiler class slower, and would have required some \emph{very} fancy coding, or else the use of a variable where the constant \samp{.00053} --- 617,621 ---- profiler will actually run equally fast!!), but the above method is the simplest to use. I could have made the profiler ``self ! calibrating,'' but it would have made the initialization of the profiler class slower, and would have required some \emph{very} fancy coding, or else the use of a variable where the constant \samp{.00053} From fdrake@users.sourceforge.net Thu Jun 14 14:58:46 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Thu, 14 Jun 2001 06:58:46 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libprofile.tex,1.30,1.30.8.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv18050/lib Modified Files: Tag: release20-maint libprofile.tex Log Message: Fix an improperly placed comma. Index: libprofile.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libprofile.tex,v retrieving revision 1.30 retrieving revision 1.30.8.1 diff -C2 -r1.30 -r1.30.8.1 *** libprofile.tex 1999/04/22 21:23:22 1.30 --- libprofile.tex 2001/06/14 13:58:44 1.30.8.1 *************** *** 612,616 **** profiler will actually run equally fast!!), but the above method is the simplest to use. I could have made the profiler ``self ! calibrating'', but it would have made the initialization of the profiler class slower, and would have required some \emph{very} fancy coding, or else the use of a variable where the constant \samp{.00053} --- 612,616 ---- profiler will actually run equally fast!!), but the above method is the simplest to use. I could have made the profiler ``self ! calibrating,'' but it would have made the initialization of the profiler class slower, and would have required some \emph{very} fancy coding, or else the use of a variable where the constant \samp{.00053} From gvanrossum@users.sourceforge.net Thu Jun 14 15:10:18 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 14 Jun 2001 07:10:18 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.80.2.11,2.80.2.12 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv22266 Modified Files: Tag: descr-branch dictobject.c Log Message: Oops, I added the doc string to the wrong type object. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.80.2.11 retrieving revision 2.80.2.12 diff -C2 -r2.80.2.11 -r2.80.2.12 *** dictobject.c 2001/06/14 00:54:28 2.80.2.11 --- dictobject.c 2001/06/14 14:10:16 2.80.2.12 *************** *** 1314,1318 **** 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ ! 0, /* tp_doc */ (traverseproc)dict_traverse, /* tp_traverse */ (inquiry)dict_tp_clear, /* tp_clear */ --- 1314,1318 ---- 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ ! "dictionary type", /* tp_doc */ (traverseproc)dict_traverse, /* tp_traverse */ (inquiry)dict_tp_clear, /* tp_clear */ *************** *** 1477,1481 **** 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! "dictionary type", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ --- 1477,1481 ---- 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ From gvanrossum@users.sourceforge.net Thu Jun 14 15:13:48 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 14 Jun 2001 07:13:48 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.39,2.16.8.40 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv23801 Modified Files: Tag: descr-branch typeobject.c Log Message: Don't inherit tp_name -- like tp_doc, it would be a lie. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.39 retrieving revision 2.16.8.40 diff -C2 -r2.16.8.39 -r2.16.8.40 *** typeobject.c 2001/06/14 00:54:06 2.16.8.39 --- typeobject.c 2001/06/14 14:13:46 2.16.8.40 *************** *** 904,909 **** } - COPYSLOT(tp_name); - /* Copying basicsize is connected to the GC flags */ oldsize = base->tp_basicsize; --- 904,907 ---- From gvanrossum@users.sourceforge.net Thu Jun 14 15:19:53 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 14 Jun 2001 07:19:53 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python bltinmodule.c,2.198.2.2,2.198.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv27255 Modified Files: Tag: descr-branch bltinmodule.c Log Message: Builtins float, long, str and tuple are now also type objects. Still to do: complex, unicode, buffer, slice, xrange; and iter? Index: bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.198.2.2 retrieving revision 2.198.2.3 diff -C2 -r2.198.2.2 -r2.198.2.3 *** bltinmodule.c 2001/06/11 21:06:03 2.198.2.2 --- bltinmodule.c 2001/06/14 14:19:51 2.198.2.3 *************** *** 1228,1283 **** static PyObject * - builtin_long(PyObject *self, PyObject *args) - { - PyObject *v; - int base = -909; /* unlikely! */ - - if (!PyArg_ParseTuple(args, "O|i:long", &v, &base)) - return NULL; - if (base == -909) - return PyNumber_Long(v); - else if (PyString_Check(v)) - return PyLong_FromString(PyString_AS_STRING(v), NULL, base); - else if (PyUnicode_Check(v)) - return PyLong_FromUnicode(PyUnicode_AS_UNICODE(v), - PyUnicode_GET_SIZE(v), - base); - else { - PyErr_SetString(PyExc_TypeError, - "long() can't convert non-string with explicit base"); - return NULL; - } - } - - static char long_doc[] = - "long(x) -> long integer\n\ - long(x, base) -> long integer\n\ - \n\ - Convert a string or number to a long integer, if possible. A floating\n\ - point argument will be truncated towards zero (this does not include a\n\ - string representation of a floating point number!) When converting a\n\ - string, use the given base. It is an error to supply a base when\n\ - converting a non-string."; - - - static PyObject * - builtin_float(PyObject *self, PyObject *args) - { - PyObject *v; - - if (!PyArg_ParseTuple(args, "O:float", &v)) - return NULL; - if (PyString_Check(v)) - return PyFloat_FromString(v, NULL); - return PyNumber_Float(v); - } - - static char float_doc[] = - "float(x) -> floating point number\n\ - \n\ - Convert a string or number to a floating point number, if possible."; - - - static PyObject * builtin_iter(PyObject *self, PyObject *args) { --- 1228,1231 ---- *************** *** 1909,1946 **** static PyObject * - builtin_str(PyObject *self, PyObject *args) - { - PyObject *v; - - if (!PyArg_ParseTuple(args, "O:str", &v)) - return NULL; - return PyObject_Str(v); - } - - static char str_doc[] = - "str(object) -> string\n\ - \n\ - Return a nice string representation of the object.\n\ - If the argument is a string, the return value is the same object."; - - - static PyObject * - builtin_tuple(PyObject *self, PyObject *args) - { - PyObject *v; - - if (!PyArg_ParseTuple(args, "O:tuple", &v)) - return NULL; - return PySequence_Tuple(v); - } - - static char tuple_doc[] = - "tuple(sequence) -> list\n\ - \n\ - Return a tuple whose items are the same as those of the argument sequence.\n\ - If the argument is a tuple, the return value is the same object."; - - - static PyObject * builtin_vars(PyObject *self, PyObject *args) { --- 1857,1860 ---- *************** *** 2096,2100 **** {"execfile", builtin_execfile, 1, execfile_doc}, {"filter", builtin_filter, 1, filter_doc}, - {"float", builtin_float, 1, float_doc}, {"getattr", builtin_getattr, 1, getattr_doc}, {"globals", builtin_globals, 1, globals_doc}, --- 2010,2013 ---- *************** *** 2110,2114 **** {"len", builtin_len, 1, len_doc}, {"locals", builtin_locals, 1, locals_doc}, - {"long", builtin_long, 1, long_doc}, {"map", builtin_map, 1, map_doc}, {"max", builtin_max, 1, max_doc}, --- 2023,2026 ---- *************** *** 2126,2131 **** {"setattr", builtin_setattr, 1, setattr_doc}, {"slice", builtin_slice, 1, slice_doc}, - {"str", builtin_str, 1, str_doc}, - {"tuple", builtin_tuple, 1, tuple_doc}, {"unicode", builtin_unicode, 1, unicode_doc}, {"unichr", builtin_unichr, 1, unichr_doc}, --- 2038,2041 ---- *************** *** 2161,2170 **** (PyObject *) &PyDict_Type) < 0) return NULL; ! if (PyDict_SetItemString(dict, "list", (PyObject *) &PyList_Type) < 0) return NULL; if (PyDict_SetItemString(dict, "int", (PyObject *) &PyInt_Type) < 0) return NULL; if (PyDict_SetItemString(dict, "object", (PyObject *) &PyBaseObject_Type) < 0) return NULL; if (PyDict_SetItemString(dict, "type", (PyObject *) &PyType_Type) < 0) --- 2071,2090 ---- (PyObject *) &PyDict_Type) < 0) return NULL; ! if (PyDict_SetItemString(dict, "float", ! (PyObject *) &PyFloat_Type) < 0) return NULL; if (PyDict_SetItemString(dict, "int", (PyObject *) &PyInt_Type) < 0) return NULL; + if (PyDict_SetItemString(dict, "list", (PyObject *) &PyList_Type) < 0) + return NULL; + if (PyDict_SetItemString(dict, "long", (PyObject *) &PyLong_Type) < 0) + return NULL; if (PyDict_SetItemString(dict, "object", (PyObject *) &PyBaseObject_Type) < 0) + return NULL; + if (PyDict_SetItemString(dict, "str", (PyObject *) &PyString_Type) < 0) + return NULL; + if (PyDict_SetItemString(dict, "tuple", + (PyObject *) &PyTuple_Type) < 0) return NULL; if (PyDict_SetItemString(dict, "type", (PyObject *) &PyType_Type) < 0) From tim_one@users.sourceforge.net Thu Jun 14 17:06:04 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Thu, 14 Jun 2001 09:06:04 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0255.txt,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv2239/python/nondist/peps Modified Files: pep-0255.txt Log Message: Minor changes; added "why a keyword?" Q&A; added Post-History. Index: pep-0255.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0255.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -r1.2 -r1.3 *** pep-0255.txt 2001/06/14 06:57:29 1.2 --- pep-0255.txt 2001/06/14 16:06:02 1.3 *************** *** 11,15 **** Created: 18-May-2001 Python-Version: 2.2 ! Post-History: --- 11,15 ---- Created: 18-May-2001 Python-Version: 2.2 ! Post-History: 14-Jun-2001 *************** *** 75,84 **** Python instead, which supports lightweight coroutines. This has much the same programmatic benefits as the thread option, but is much more ! efficient. However, Stackless is a radical and controversial ! rethinking of the Python core, and it may not be possible for Jython to ! implement the same semantics. This PEP isn't the place to debate that, ! so suffice it to say here that generators provide a useful subset of ! Stackless functionality in a way that fits easily into the current ! Python implementation. That exhausts the current alternatives. Some other high-level --- 75,85 ---- Python instead, which supports lightweight coroutines. This has much the same programmatic benefits as the thread option, but is much more ! efficient. However, Stackless is a controversial rethinking of the ! Python core, and it may not be possible for Jython to implement the ! same semantics. This PEP isn't the place to debate that, so suffice it ! to say here that generators provide a useful subset of Stackless ! functionality in a way that fits easily into the current CPython ! implementation, and is believed to be relatively straightforward for ! other Python implementations. That exhausts the current alternatives. Some other high-level *************** *** 150,154 **** pointer, and the internal evaluation stack: enough information is saved so that the next time .next() is invoked, the function can ! proceed exactly is if the yield statement were just another external call. --- 151,155 ---- pointer, and the internal evaluation stack: enough information is saved so that the next time .next() is invoked, the function can ! proceed exactly as if the yield statement were just another external call. *************** *** 234,237 **** --- 235,249 ---- print x, print + + + Q & A + + Q. Why a new keyword? Why not a builtin function instead? + + A. Control flow is much better expressed via keyword in Python, and + yield is a control construct. It's also believed that efficient + implementation in Jython requires that the compiler be able to + determine potential suspension points at compile-time, and a new + keyword makes that easy. From gvanrossum@users.sourceforge.net Thu Jun 14 18:47:23 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 14 Jun 2001 10:47:23 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib types.py,1.14.10.4,1.14.10.5 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv31809 Modified Files: Tag: descr-branch types.py Log Message: Get rid of TurtleType -- it doesn't exist any more. Index: types.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/types.py,v retrieving revision 1.14.10.4 retrieving revision 1.14.10.5 diff -C2 -r1.14.10.4 -r1.14.10.5 *** types.py 2001/06/07 19:03:08 1.14.10.4 --- types.py 2001/06/14 17:47:21 1.14.10.5 *************** *** 71,75 **** FunctionIterType = type(iter(lambda: 0, 0)) DictProxyType = type(TypeType.__dict__) - TurtleType = type(TypeType) del sys, _f, _C, _x # Not for export --- 71,74 ---- From gvanrossum@users.sourceforge.net Thu Jun 14 18:52:05 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 14 Jun 2001 10:52:05 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects unicodeobject.c,2.93,2.94 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv483 Modified Files: unicodeobject.c Log Message: Fix a mis-indentation in _PyUnicode_New() that caused me to stare at some code for longer than needed. Index: unicodeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/unicodeobject.c,v retrieving revision 2.93 retrieving revision 2.94 diff -C2 -r2.93 -r2.94 *** unicodeobject.c 2001/06/07 12:26:56 2.93 --- unicodeobject.c 2001/06/14 17:52:02 2.94 *************** *** 184,191 **** } } ! else { unicode->str = PyMem_NEW(Py_UNICODE, length + 1); ! } ! PyObject_INIT(unicode, &PyUnicode_Type); } else { --- 184,191 ---- } } ! else { unicode->str = PyMem_NEW(Py_UNICODE, length + 1); ! } ! PyObject_INIT(unicode, &PyUnicode_Type); } else { From gvanrossum@users.sourceforge.net Thu Jun 14 19:12:04 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 14 Jun 2001 11:12:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects unicodeobject.c,2.87.2.3,2.87.2.4 complexobject.c,2.35.4.3,2.35.4.4 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv5083/Objects Modified Files: Tag: descr-branch unicodeobject.c complexobject.c Log Message: Two more bite the dust: built-ins unicode and complex are now also types. Index: unicodeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/unicodeobject.c,v retrieving revision 2.87.2.3 retrieving revision 2.87.2.4 diff -C2 -r2.87.2.3 -r2.87.2.4 *** unicodeobject.c 2001/06/06 14:27:54 2.87.2.3 --- unicodeobject.c 2001/06/14 18:12:02 2.87.2.4 *************** *** 184,191 **** } } ! else { unicode->str = PyMem_NEW(Py_UNICODE, length + 1); ! } ! PyObject_INIT(unicode, &PyUnicode_Type); } else { --- 184,191 ---- } } ! else { unicode->str = PyMem_NEW(Py_UNICODE, length + 1); ! } ! PyObject_INIT(unicode, &PyUnicode_Type); } else { *************** *** 5220,5223 **** --- 5220,5247 ---- }; + static PyObject * + unicode_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + PyObject *x = NULL; + static char *kwlist[] = {"string", "encoding", "errors", 0}; + char *encoding = NULL; + char *errors = NULL; + + assert(type == &PyUnicode_Type); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:unicode", + kwlist, &x, &encoding, &errors)) + return NULL; + if (x == NULL) + return (PyObject *)_PyUnicode_New(0); + return PyUnicode_FromEncodedObject(x, encoding, errors); + } + + static char unicode_doc[] = + "unicode(string [, encoding[, errors]]) -> object\n\ + \n\ + Create a new Unicode object from the given encoded string.\n\ + encoding defaults to the current default string encoding and \n\ + errors, defining the error handling, to 'strict'."; + PyTypeObject PyUnicode_Type = { PyObject_HEAD_INIT(&PyType_Type) *************** *** 5243,5247 **** &unicode_as_buffer, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ --- 5267,5271 ---- &unicode_as_buffer, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! unicode_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ *************** *** 5255,5258 **** --- 5279,5288 ---- 0, /* tp_base */ 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + unicode_new, /* tp_new */ }; Index: complexobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/complexobject.c,v retrieving revision 2.35.4.3 retrieving revision 2.35.4.4 diff -C2 -r2.35.4.3 -r2.35.4.4 *** complexobject.c 2001/06/06 14:27:54 2.35.4.3 --- complexobject.c 2001/06/14 18:12:02 2.35.4.4 *************** *** 567,570 **** --- 567,820 ---- }; + static PyObject * + complex_from_string(PyObject *v) + { + extern double strtod(const char *, char **); + const char *s, *start; + char *end; + double x=0.0, y=0.0, z; + int got_re=0, got_im=0, done=0; + int digit_or_dot; + int sw_error=0; + int sign; + char buffer[256]; /* For errors */ + char s_buffer[256]; + int len; + + if (PyString_Check(v)) { + s = PyString_AS_STRING(v); + len = PyString_GET_SIZE(v); + } + else if (PyUnicode_Check(v)) { + if (PyUnicode_GET_SIZE(v) >= sizeof(s_buffer)) { + PyErr_SetString(PyExc_ValueError, + "complex() literal too large to convert"); + return NULL; + } + if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v), + PyUnicode_GET_SIZE(v), + s_buffer, + NULL)) + return NULL; + s = s_buffer; + len = (int)strlen(s); + } + else if (PyObject_AsCharBuffer(v, &s, &len)) { + PyErr_SetString(PyExc_TypeError, + "complex() arg is not a string"); + return NULL; + } + + /* position on first nonblank */ + start = s; + while (*s && isspace(Py_CHARMASK(*s))) + s++; + if (s[0] == '\0') { + PyErr_SetString(PyExc_ValueError, + "complex() arg is an empty string"); + return NULL; + } + + z = -1.0; + sign = 1; + do { + + switch (*s) { + + case '\0': + if (s-start != len) { + PyErr_SetString( + PyExc_ValueError, + "complex() arg contains a null byte"); + return NULL; + } + if(!done) sw_error=1; + break; + + case '-': + sign = -1; + /* Fallthrough */ + case '+': + if (done) sw_error=1; + s++; + if ( *s=='\0'||*s=='+'||*s=='-' || + isspace(Py_CHARMASK(*s)) ) sw_error=1; + break; + + case 'J': + case 'j': + if (got_im || done) { + sw_error = 1; + break; + } + if (z<0.0) { + y=sign; + } + else{ + y=sign*z; + } + got_im=1; + s++; + if (*s!='+' && *s!='-' ) + done=1; + break; + + default: + if (isspace(Py_CHARMASK(*s))) { + while (*s && isspace(Py_CHARMASK(*s))) + s++; + if (s[0] != '\0') + sw_error=1; + else + done = 1; + break; + } + digit_or_dot = + (*s=='.' || isdigit(Py_CHARMASK(*s))); + if (done||!digit_or_dot) { + sw_error=1; + break; + } + errno = 0; + PyFPE_START_PROTECT("strtod", return 0) + z = strtod(s, &end) ; + PyFPE_END_PROTECT(z) + if (errno != 0) { + sprintf(buffer, + "float() out of range: %.150s", s); + PyErr_SetString( + PyExc_ValueError, + buffer); + return NULL; + } + s=end; + if (*s=='J' || *s=='j') { + + break; + } + if (got_re) { + sw_error=1; + break; + } + + /* accept a real part */ + x=sign*z; + got_re=1; + if (got_im) done=1; + z = -1.0; + sign = 1; + break; + + } /* end of switch */ + + } while (*s!='\0' && !sw_error); + + if (sw_error) { + PyErr_SetString(PyExc_ValueError, + "complex() arg is a malformed string"); + return NULL; + } + + return PyComplex_FromDoubles(x,y); + } + + static PyObject * + complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + PyObject *r, *i, *tmp; + PyNumberMethods *nbr, *nbi = NULL; + Py_complex cr, ci; + int own_r = 0; + static char *kwlist[] = {"real", "imag", 0}; + + assert(type == &PyComplex_Type); + r = Py_False; + i = NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:complex", kwlist, + &r, &i)) + return NULL; + if (PyString_Check(r) || PyUnicode_Check(r)) + return complex_from_string(r); + if ((nbr = r->ob_type->tp_as_number) == NULL || + nbr->nb_float == NULL || + (i != NULL && + ((nbi = i->ob_type->tp_as_number) == NULL || + nbi->nb_float == NULL))) { + PyErr_SetString(PyExc_TypeError, + "complex() arg can't be converted to complex"); + return NULL; + } + /* XXX Hack to support classes with __complex__ method */ + if (PyInstance_Check(r)) { + static PyObject *complexstr; + PyObject *f; + if (complexstr == NULL) { + complexstr = PyString_InternFromString("__complex__"); + if (complexstr == NULL) + return NULL; + } + f = PyObject_GetAttr(r, complexstr); + if (f == NULL) + PyErr_Clear(); + else { + PyObject *args = Py_BuildValue("()"); + if (args == NULL) + return NULL; + r = PyEval_CallObject(f, args); + Py_DECREF(args); + Py_DECREF(f); + if (r == NULL) + return NULL; + own_r = 1; + } + } + if (PyComplex_Check(r)) { + cr = ((PyComplexObject*)r)->cval; + if (own_r) { + Py_DECREF(r); + } + } + else { + tmp = PyNumber_Float(r); + if (own_r) { + Py_DECREF(r); + } + if (tmp == NULL) + return NULL; + if (!PyFloat_Check(tmp)) { + PyErr_SetString(PyExc_TypeError, + "float(r) didn't return a float"); + Py_DECREF(tmp); + return NULL; + } + cr.real = PyFloat_AsDouble(tmp); + Py_DECREF(tmp); + cr.imag = 0.0; + } + if (i == NULL) { + ci.real = 0.0; + ci.imag = 0.0; + } + else if (PyComplex_Check(i)) + ci = ((PyComplexObject*)i)->cval; + else { + tmp = (*nbi->nb_float)(i); + if (tmp == NULL) + return NULL; + ci.real = PyFloat_AsDouble(tmp); + Py_DECREF(tmp); + ci.imag = 0.; + } + cr.real -= ci.imag; + cr.imag += ci.real; + return PyComplex_FromCComplex(cr); + } + + static char complex_doc[] = + "complex(real[, imag]) -> complex number\n\ + \n\ + Create a complex number from a real part and an optional imaginary part.\n\ + This is equivalent to (real + imag*1j) where imag defaults to 0."; + static PyNumberMethods complex_as_number = { (binaryfunc)complex_add, /* nb_add */ *************** *** 615,619 **** 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ --- 865,869 ---- 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ ! complex_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ *************** *** 627,630 **** --- 877,886 ---- 0, /* tp_base */ 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + complex_new, /* tp_new */ }; From gvanrossum@users.sourceforge.net Thu Jun 14 19:12:04 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 14 Jun 2001 11:12:04 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python bltinmodule.c,2.198.2.3,2.198.2.4 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv5083/Python Modified Files: Tag: descr-branch bltinmodule.c Log Message: Two more bite the dust: built-ins unicode and complex are now also types. Index: bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.198.2.3 retrieving revision 2.198.2.4 diff -C2 -r2.198.2.3 -r2.198.2.4 *** bltinmodule.c 2001/06/14 14:19:51 2.198.2.3 --- bltinmodule.c 2001/06/14 18:12:02 2.198.2.4 *************** *** 124,147 **** static PyObject * - builtin_unicode(PyObject *self, PyObject *args) - { - PyObject *v; - char *encoding = NULL; - char *errors = NULL; - - if ( !PyArg_ParseTuple(args, "O|ss:unicode", &v, &encoding, &errors) ) - return NULL; - return PyUnicode_FromEncodedObject(v, encoding, errors); - } - - static char unicode_doc[] = - "unicode(string [, encoding[, errors]]) -> object\n\ - \n\ - Create a new Unicode object from the given encoded string.\n\ - encoding defaults to the current default string encoding and \n\ - errors, defining the error handling, to 'strict'."; - - - static PyObject * builtin_callable(PyObject *self, PyObject *args) { --- 124,127 ---- *************** *** 392,647 **** - #ifndef WITHOUT_COMPLEX - static PyObject * - complex_from_string(PyObject *v) - { - extern double strtod(const char *, char **); - const char *s, *start; - char *end; - double x=0.0, y=0.0, z; - int got_re=0, got_im=0, done=0; - int digit_or_dot; - int sw_error=0; - int sign; - char buffer[256]; /* For errors */ - char s_buffer[256]; - int len; - - if (PyString_Check(v)) { - s = PyString_AS_STRING(v); - len = PyString_GET_SIZE(v); - } - else if (PyUnicode_Check(v)) { - if (PyUnicode_GET_SIZE(v) >= sizeof(s_buffer)) { - PyErr_SetString(PyExc_ValueError, - "complex() literal too large to convert"); - return NULL; - } - if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v), - PyUnicode_GET_SIZE(v), - s_buffer, - NULL)) - return NULL; - s = s_buffer; - len = (int)strlen(s); - } - else if (PyObject_AsCharBuffer(v, &s, &len)) { - PyErr_SetString(PyExc_TypeError, - "complex() arg is not a string"); - return NULL; - } - - /* position on first nonblank */ - start = s; - while (*s && isspace(Py_CHARMASK(*s))) - s++; - if (s[0] == '\0') { - PyErr_SetString(PyExc_ValueError, - "complex() arg is an empty string"); - return NULL; - } - - z = -1.0; - sign = 1; - do { - - switch (*s) { - - case '\0': - if (s-start != len) { - PyErr_SetString( - PyExc_ValueError, - "complex() arg contains a null byte"); - return NULL; - } - if(!done) sw_error=1; - break; - - case '-': - sign = -1; - /* Fallthrough */ - case '+': - if (done) sw_error=1; - s++; - if ( *s=='\0'||*s=='+'||*s=='-' || - isspace(Py_CHARMASK(*s)) ) sw_error=1; - break; - - case 'J': - case 'j': - if (got_im || done) { - sw_error = 1; - break; - } - if (z<0.0) { - y=sign; - } - else{ - y=sign*z; - } - got_im=1; - s++; - if (*s!='+' && *s!='-' ) - done=1; - break; - - default: - if (isspace(Py_CHARMASK(*s))) { - while (*s && isspace(Py_CHARMASK(*s))) - s++; - if (s[0] != '\0') - sw_error=1; - else - done = 1; - break; - } - digit_or_dot = - (*s=='.' || isdigit(Py_CHARMASK(*s))); - if (done||!digit_or_dot) { - sw_error=1; - break; - } - errno = 0; - PyFPE_START_PROTECT("strtod", return 0) - z = strtod(s, &end) ; - PyFPE_END_PROTECT(z) - if (errno != 0) { - sprintf(buffer, - "float() out of range: %.150s", s); - PyErr_SetString( - PyExc_ValueError, - buffer); - return NULL; - } - s=end; - if (*s=='J' || *s=='j') { - - break; - } - if (got_re) { - sw_error=1; - break; - } - - /* accept a real part */ - x=sign*z; - got_re=1; - if (got_im) done=1; - z = -1.0; - sign = 1; - break; - - } /* end of switch */ - - } while (*s!='\0' && !sw_error); - - if (sw_error) { - PyErr_SetString(PyExc_ValueError, - "complex() arg is a malformed string"); - return NULL; - } - - return PyComplex_FromDoubles(x,y); - } - - static PyObject * - builtin_complex(PyObject *self, PyObject *args) - { - PyObject *r, *i, *tmp; - PyNumberMethods *nbr, *nbi = NULL; - Py_complex cr, ci; - int own_r = 0; - - i = NULL; - if (!PyArg_ParseTuple(args, "O|O:complex", &r, &i)) - return NULL; - if (PyString_Check(r) || PyUnicode_Check(r)) - return complex_from_string(r); - if ((nbr = r->ob_type->tp_as_number) == NULL || - nbr->nb_float == NULL || - (i != NULL && - ((nbi = i->ob_type->tp_as_number) == NULL || - nbi->nb_float == NULL))) { - PyErr_SetString(PyExc_TypeError, - "complex() arg can't be converted to complex"); - return NULL; - } - /* XXX Hack to support classes with __complex__ method */ - if (PyInstance_Check(r)) { - static PyObject *complexstr; - PyObject *f; - if (complexstr == NULL) { - complexstr = PyString_InternFromString("__complex__"); - if (complexstr == NULL) - return NULL; - } - f = PyObject_GetAttr(r, complexstr); - if (f == NULL) - PyErr_Clear(); - else { - PyObject *args = Py_BuildValue("()"); - if (args == NULL) - return NULL; - r = PyEval_CallObject(f, args); - Py_DECREF(args); - Py_DECREF(f); - if (r == NULL) - return NULL; - own_r = 1; - } - } - if (PyComplex_Check(r)) { - cr = ((PyComplexObject*)r)->cval; - if (own_r) { - Py_DECREF(r); - } - } - else { - tmp = PyNumber_Float(r); - if (own_r) { - Py_DECREF(r); - } - if (tmp == NULL) - return NULL; - if (!PyFloat_Check(tmp)) { - PyErr_SetString(PyExc_TypeError, - "float(r) didn't return a float"); - Py_DECREF(tmp); - return NULL; - } - cr.real = PyFloat_AsDouble(tmp); - Py_DECREF(tmp); - cr.imag = 0.0; - } - if (i == NULL) { - ci.real = 0.0; - ci.imag = 0.0; - } - else if (PyComplex_Check(i)) - ci = ((PyComplexObject*)i)->cval; - else { - tmp = (*nbi->nb_float)(i); - if (tmp == NULL) - return NULL; - ci.real = PyFloat_AsDouble(tmp); - Py_DECREF(tmp); - ci.imag = 0.; - } - cr.real -= ci.imag; - cr.imag += ci.real; - return PyComplex_FromCComplex(cr); - } - - static char complex_doc[] = - "complex(real[, imag]) -> complex number\n\ - \n\ - Create a complex number from a real part and an optional imaginary part.\n\ - This is equivalent to (real + imag*1j) where imag defaults to 0."; - - - #endif - - static PyObject * builtin_dir(PyObject *self, PyObject *args) { --- 372,376 ---- *************** *** 2001,2007 **** {"coerce", builtin_coerce, 1, coerce_doc}, {"compile", builtin_compile, 1, compile_doc}, - #ifndef WITHOUT_COMPLEX - {"complex", builtin_complex, 1, complex_doc}, - #endif {"delattr", builtin_delattr, 1, delattr_doc}, {"dir", builtin_dir, 1, dir_doc}, --- 1730,1733 ---- *************** *** 2038,2042 **** {"setattr", builtin_setattr, 1, setattr_doc}, {"slice", builtin_slice, 1, slice_doc}, - {"unicode", builtin_unicode, 1, unicode_doc}, {"unichr", builtin_unichr, 1, unichr_doc}, {"vars", builtin_vars, 1, vars_doc}, --- 1764,1767 ---- *************** *** 2068,2071 **** --- 1793,1801 ---- Py_NotImplemented) < 0) return NULL; + #ifndef WITHOUT_COMPLEX + if (PyDict_SetItemString(dict, "complex", + (PyObject *) &PyComplex_Type) < 0) + return NULL; + #endif if (PyDict_SetItemString(dict, "dictionary", (PyObject *) &PyDict_Type) < 0) *************** *** 2089,2092 **** --- 1819,1825 ---- return NULL; if (PyDict_SetItemString(dict, "type", (PyObject *) &PyType_Type) < 0) + return NULL; + if (PyDict_SetItemString(dict, "unicode", + (PyObject *) &PyUnicode_Type) < 0) return NULL; debug = PyInt_FromLong(Py_OptimizeFlag == 0); From tim_one@users.sourceforge.net Thu Jun 14 19:42:52 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Thu, 14 Jun 2001 11:42:52 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.81,1.82 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv12185/python/dist/src/Objects Modified Files: longobject.c Log Message: Change IS_LITTLE_ENDIAN macro -- a little faster now. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.81 retrieving revision 1.82 diff -C2 -r1.81 -r1.82 *** longobject.c 2001/06/14 08:53:38 1.81 --- longobject.c 2001/06/14 18:42:50 1.82 *************** *** 563,567 **** */ ! #define IS_LITTLE_ENDIAN *(char*)&one != '\0' /* Create a new long int object from a C LONG_LONG int. */ --- 563,567 ---- */ ! #define IS_LITTLE_ENDIAN (int)*(unsigned char*)&one /* Create a new long int object from a C LONG_LONG int. */ From gvanrossum@users.sourceforge.net Thu Jun 14 20:37:01 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 14 Jun 2001 12:37:01 -0700 Subject: [Python-checkins] CVS: python/dist/src LICENSE,1.16,1.17 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv24930 Modified Files: LICENSE Log Message: Note that 2.0.1 is also a PSF release. (Gregor Hoffleit, SF #433223.) Index: LICENSE =================================================================== RCS file: /cvsroot/python/python/dist/src/LICENSE,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -r1.16 -r1.17 *** LICENSE 2001/05/04 18:49:06 1.16 --- LICENSE 2001/06/14 19:36:59 1.17 *************** *** 26,34 **** After Python 2.0 was released by BeOpen.com, Guido van Rossum and the other PythonLabs developers joined Digital Creations. All ! intellectual property added from this point on, starting with Python ! 2.1 and its alpha and beta releases, is owned by the Python Software ! Foundation (PSF), a non-profit modeled after the Apache Software ! Foundation. See http://www.python.org/psf/ for more information about ! the PSF. Thanks to the many outside volunteers who have worked under Guido's --- 26,33 ---- After Python 2.0 was released by BeOpen.com, Guido van Rossum and the other PythonLabs developers joined Digital Creations. All ! intellectual property added from this point on, including Python ! 2.0.1, is owned by the Python Software Foundation (PSF), a non-profit ! modeled after the Apache Software Foundation. See ! http://www.python.org/psf/ for more information about the PSF. Thanks to the many outside volunteers who have worked under Guido's From gvanrossum@users.sourceforge.net Thu Jun 14 21:48:45 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Thu, 14 Jun 2001 13:48:45 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0253.txt,1.5,1.6 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv8108 Modified Files: pep-0253.txt Log Message: More good stuff. Consider this just a checkpoint. Index: pep-0253.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0253.txt,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -r1.5 -r1.6 *** pep-0253.txt 2001/06/14 13:37:45 1.5 --- pep-0253.txt 2001/06/14 20:48:43 1.6 *************** *** 78,82 **** --- 78,97 ---- release.) + In current Python, a distinction is made between types and + classes. This PEP together with pep-0254 will remove that + distinction. However, for backwards compatibility there will + probably remain a bit of a distinction for years to come, and + without pep-0254, the distinction is still large: types ultimately + have a built-in type as a base class, while classes ultimately + derive from a user-defined class. Therefore, in the rest of this + PEP, I will use the word type whenever I can -- including base + type or supertype, derived type or subtype, and metatype. + However, sometimes the terminology necessarily blends, e.g. an + object's type is given by its __class__ attribute, and subtyping + in Python is spelled with a class statement. If further + distinction is necessary, user-defined classes can be referred to + as "classic" classes. + About metatypes *************** *** 259,262 **** --- 274,280 ---- PyObject *kwds) + [XXX We'll have to rename tp_alloc to something else, because in + debug mode there's already a tp_alloc field.] + The arguments for tp_alloc are the same as for tp_new, described above. The arguments for tp_init are the same except that the *************** *** 271,277 **** Because tp_init is in a sense optional, tp_alloc is required to do ! *some* initialization of the object. It is required to initialize ! ob_refcnt to 1 and ob_type to its type argument. To be safe, it ! should probably zero out the rest of the object. The constructor arguments are passed to tp_alloc so that for --- 289,295 ---- Because tp_init is in a sense optional, tp_alloc is required to do ! *some* initialization of the object. It must initialize ob_refcnt ! to 1 and ob_type to its type argument. It should zero out the ! rest of the object. The constructor arguments are passed to tp_alloc so that for *************** *** 489,506 **** the string "C"); the list of base classes (a singleton tuple containing B); and the results of executing the class body, in the ! form of a dictionary (e.g. {"var1": 1, "method1": , ! ...}). ! According to the Don Beaudry hook, the following call is made: ! C = M("C", (B,), dict) (where dict is the dictionary resulting from execution of the ! class body). In other words, the metatype (M) is called. Note ! that even though we currently require there to be exactly one base ! class, we still pass in a (singleton) sequence of base classes; ! this makes it possible to support multiple inheritance later (or ! for types with a different metaclass!) without changing this ! interface. Note that calling M requires that M itself has a type: the --- 507,568 ---- the string "C"); the list of base classes (a singleton tuple containing B); and the results of executing the class body, in the ! form of a dictionary (e.g. {"var1": 1, "method1": , ...}). ! I propose to rig the class statement to make the following call: ! C = M("C", (B,), dict) (where dict is the dictionary resulting from execution of the ! class body). In other words, the metatype (M) is called. ! ! Note that even though we currently require there to be exactly one ! base class, we still pass in a (singleton) sequence of base ! classes; this makes it possible to support multiple inheritance ! later (or for types with a different metaclass!) without changing ! this interface. ! ! In current Python, this is called the "Don Beaudry hook" after its ! inventor; it is an exceptional case that is only invoked when a ! base class is not a regular class. For a regular base class (or ! when no base class is specified), current Python calls ! PyClass_New(), the C level factory function for classes, directly. ! I propose to change this so that Python *always* determines a ! metaclass and calls it as given above. When one or more bases are ! given, the type of the first base is used as the metatype; ! when no base class is given, a default metaclass is chosen. By ! setting the default metaclass to PyClass_Type, the metatype of ! "classic" classes, the classic behavior of the class statement is ! retained. ! ! There are two further refinements here. First, a useful feature ! is to be able to specify a metatype directly. If the class ! statement defines a variable __metaclass__, that is the metatype ! to call. ! ! Second, with multiple bases, not all bases need to have the same ! metatype. This is called a metaclass conflict [1]. Some ! metaclass conflicts can be resolved by searching through the set ! of bases for a metatype that derives from all other given ! metatypes. If such a metatype cannot be found, an exception is ! raised and the class statement fails. ! ! This conflict resultion can be implemented in the metatypes ! itself: the class statement just calls the metatype of the first ! base, and this metatype's constructor looks for the most derived ! metatype. If that is itself, it proceeds; otherwise, it calls ! that metatype's constructor. (Ultimate flexibility: another ! metatype might choose to require that all bases have the same ! metatype, or that there's only one base class, or whatever.) ! ! (Theoretically, it might be possible to automatically derive a new ! metatype that is a subtype of all given metatypes; but since it is ! questionable how conflicting method definitions of the various ! metatypes should be merged, I don't think this is useful or ! feasible. Should the need arise, the user can derive such a ! metatype and specify it using the __metaclass__ variable. It is ! also possible to have a new metatype that does this.) ! ! HIRO Note that calling M requires that M itself has a type: the From twouters@users.sourceforge.net Fri Jun 15 12:58:51 2001 From: twouters@users.sourceforge.net (Thomas Wouters) Date: Fri, 15 Jun 2001 04:58:51 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules termios.c,2.24.2.3,2.24.2.4 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv18439 Modified Files: Tag: release21-maint termios.c Log Message: Protect several more uses of constants with #ifdefs; these are necessary on (at least) SCO OpenServer 5. Fixes a non-SF-submitted bugreport by Michael Kent. Index: termios.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/termios.c,v retrieving revision 2.24.2.3 retrieving revision 2.24.2.4 diff -C2 -r2.24.2.3 -r2.24.2.4 *** termios.c 2001/06/11 15:21:43 2.24.2.3 --- termios.c 2001/06/15 11:58:49 2.24.2.4 *************** *** 380,384 **** --- 380,386 ---- {"IXANY", IXANY}, {"IXOFF", IXOFF}, + #ifdef IMAXBEL {"IMAXBEL", IMAXBEL}, + #endif /* struct termios.c_oflag constants */ *************** *** 506,515 **** --- 508,523 ---- {"ECHOK", ECHOK}, {"ECHONL", ECHONL}, + #ifdef ECHOCTL {"ECHOCTL", ECHOCTL}, + #endif #ifdef ECHOPRT {"ECHOPRT", ECHOPRT}, #endif + #ifdef ECHOKE {"ECHOKE", ECHOKE}, + #endif + #endif FLUSHO {"FLUSHO", FLUSHO}, + #endif {"NOFLSH", NOFLSH}, {"TOSTOP", TOSTOP}, *************** *** 546,550 **** --- 554,560 ---- {"VWERASE", VWERASE}, #endif + #ifdef VLNEXT {"VLNEXT", VLNEXT}, + #endif {"VEOL2", VEOL2}, From twouters@users.sourceforge.net Fri Jun 15 13:05:46 2001 From: twouters@users.sourceforge.net (Thomas Wouters) Date: Fri, 15 Jun 2001 05:05:46 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules termios.c,2.30,2.31 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv19567 Modified Files: termios.c Log Message: Forward-port revision 2.24.2.4 from the release21-maint branch: Protect several more uses of constants with #ifdefs; these are necessary on (at least) SCO OpenServer 5. Fixes a non-SF-submitted bugreport by Michael Kent. Index: termios.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/termios.c,v retrieving revision 2.30 retrieving revision 2.31 diff -C2 -r2.30 -r2.31 *** termios.c 2001/06/11 15:25:16 2.30 --- termios.c 2001/06/15 12:05:44 2.31 *************** *** 380,384 **** --- 380,386 ---- {"IXANY", IXANY}, {"IXOFF", IXOFF}, + #ifdef IMAXBEL {"IMAXBEL", IMAXBEL}, + #endif /* struct termios.c_oflag constants */ *************** *** 506,515 **** --- 508,523 ---- {"ECHOK", ECHOK}, {"ECHONL", ECHONL}, + #ifdef ECHOCTL {"ECHOCTL", ECHOCTL}, + #endif #ifdef ECHOPRT {"ECHOPRT", ECHOPRT}, #endif + #ifdef ECHOKE {"ECHOKE", ECHOKE}, + #endif + #ifdef FLUSHO {"FLUSHO", FLUSHO}, + #endif {"NOFLSH", NOFLSH}, {"TOSTOP", TOSTOP}, *************** *** 546,550 **** --- 554,560 ---- {"VWERASE", VWERASE}, #endif + #ifdef VLNEXT {"VLNEXT", VLNEXT}, + #endif {"VEOL2", VEOL2}, From fdrake@users.sourceforge.net Fri Jun 15 15:13:09 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Fri, 15 Jun 2001 07:13:09 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libstruct.tex,1.28,1.29 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv11214/lib Modified Files: libstruct.tex Log Message: Add a version annotation for the Q and q format codes. Index: libstruct.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstruct.tex,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -r1.28 -r1.29 *** libstruct.tex 2001/06/12 01:22:21 1.28 --- libstruct.tex 2001/06/15 14:13:07 1.29 *************** *** 73,78 **** The \character{q} and \character{Q} conversion codes are available in native mode only if the platform C compiler supports C \ctype{long long}, ! or, on Windows, \ctype{__int64}. They're always available in standard modes. \end{description} --- 73,79 ---- The \character{q} and \character{Q} conversion codes are available in native mode only if the platform C compiler supports C \ctype{long long}, ! or, on Windows, \ctype{__int64}. They are always available in standard modes. + \versionadded{2.2} \end{description} From gvanrossum@users.sourceforge.net Fri Jun 15 17:43:56 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 15 Jun 2001 09:43:56 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib statcache.py,1.7.4.1,1.7.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv11217 Modified Files: Tag: release20-maint statcache.py Log Message: Fix SF #433233: syntax error. Index: statcache.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/statcache.py,v retrieving revision 1.7.4.1 retrieving revision 1.7.4.2 diff -C2 -r1.7.4.1 -r1.7.4.2 *** statcache.py 2001/03/31 13:46:33 1.7.4.1 --- statcache.py 2001/06/15 16:43:54 1.7.4.2 *************** *** 50,55 **** forget(prefix) for path in cache.keys(): ! if path.startswith(prefix) and os.path.dirname(path) == prefix: ! forget(path) def forget_except_prefix(prefix): --- 50,55 ---- forget(prefix) for path in cache.keys(): ! if path.startswith(prefix) and os.path.dirname(path) == prefix: ! forget(path) def forget_except_prefix(prefix): From gvanrossum@users.sourceforge.net Fri Jun 15 19:38:15 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 15 Jun 2001 11:38:15 -0700 Subject: [Python-checkins] CVS: python/dist/src/Grammar Grammar,1.42,1.43 Message-ID: Update of /cvsroot/python/python/dist/src/Grammar In directory usw-pr-cvs1:/tmp/cvs-serv2419 Modified Files: Grammar Log Message: Neil's generator patch, in the gen-branch. Index: Grammar =================================================================== RCS file: /cvsroot/python/python/dist/src/Grammar/Grammar,v retrieving revision 1.42 retrieving revision 1.43 diff -C2 -r1.42 -r1.43 *** Grammar 2001/02/27 18:36:14 1.42 --- Grammar 2001/06/15 18:38:13 1.43 *************** *** 44,51 **** del_stmt: 'del' exprlist pass_stmt: 'pass' ! flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] raise_stmt: 'raise' [test [',' test [',' test]]] import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*) --- 44,52 ---- del_stmt: 'del' exprlist pass_stmt: 'pass' ! flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] + yield_stmt: 'yield' testlist raise_stmt: 'raise' [test [',' test [',' test]]] import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*) From gvanrossum@users.sourceforge.net Fri Jun 15 19:48:48 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 15 Jun 2001 11:48:48 -0700 Subject: [Python-checkins] CVS: python/dist/src/Grammar Grammar,1.42,1.42.8.1 Message-ID: Update of /cvsroot/python/python/dist/src/Grammar In directory usw-pr-cvs1:/tmp/cvs-serv4170 Modified Files: Tag: gen-branch Grammar Log Message: Neil's generator patch, in the gen-branch. Index: Grammar =================================================================== RCS file: /cvsroot/python/python/dist/src/Grammar/Grammar,v retrieving revision 1.42 retrieving revision 1.42.8.1 diff -C2 -r1.42 -r1.42.8.1 *** Grammar 2001/02/27 18:36:14 1.42 --- Grammar 2001/06/15 18:48:46 1.42.8.1 *************** *** 44,51 **** del_stmt: 'del' exprlist pass_stmt: 'pass' ! flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] raise_stmt: 'raise' [test [',' test [',' test]]] import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*) --- 44,52 ---- del_stmt: 'del' exprlist pass_stmt: 'pass' ! flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] + yield_stmt: 'yield' testlist raise_stmt: 'raise' [test [',' test [',' test]]] import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*) From gvanrossum@users.sourceforge.net Fri Jun 15 19:56:46 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 15 Jun 2001 11:56:46 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects frameobject.c,2.50,2.50.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv5899/Objects Modified Files: Tag: gen-branch frameobject.c Log Message: Neil's generator patch, in the gen-branch. Index: frameobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/frameobject.c,v retrieving revision 2.50 retrieving revision 2.50.2.1 diff -C2 -r2.50 -r2.50.2.1 *** frameobject.c 2001/05/08 04:08:20 2.50 --- frameobject.c 2001/06/15 18:56:44 2.50.2.1 *************** *** 68,71 **** --- 68,72 ---- int i, slots; PyObject **fastlocals; + PyObject **p; Py_TRASHCAN_SAFE_BEGIN(f) *************** *** 77,80 **** --- 78,85 ---- } + /* Free stack */ + for (p = f->f_valuestack; p < f->f_stackbottom; p++) { + Py_XDECREF(*p); + } Py_XDECREF(f->f_back); Py_XDECREF(f->f_code); *************** *** 222,225 **** --- 227,231 ---- f->f_valuestack = f->f_localsplus + (f->f_nlocals + ncells + nfrees); + f->f_stackbottom = f->f_valuestack; return f; From gvanrossum@users.sourceforge.net Fri Jun 15 19:56:46 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 15 Jun 2001 11:56:46 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include compile.h,2.29,2.29.6.1 frameobject.h,2.31,2.31.6.1 graminit.h,2.16,2.16.10.1 opcode.h,2.35,2.35.4.1 symtable.h,2.7,2.7.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv5899/Include Modified Files: Tag: gen-branch compile.h frameobject.h graminit.h opcode.h symtable.h Log Message: Neil's generator patch, in the gen-branch. Index: compile.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/compile.h,v retrieving revision 2.29 retrieving revision 2.29.6.1 diff -C2 -r2.29 -r2.29.6.1 *** compile.h 2001/03/22 02:32:48 2.29 --- compile.h 2001/06/15 18:56:44 2.29.6.1 *************** *** 34,37 **** --- 34,38 ---- #define CO_VARKEYWORDS 0x0008 #define CO_NESTED 0x0010 + #define CO_GENERATOR 0x0020 extern DL_IMPORT(PyTypeObject) PyCode_Type; Index: frameobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/frameobject.h,v retrieving revision 2.31 retrieving revision 2.31.6.1 diff -C2 -r2.31 -r2.31.6.1 *** frameobject.h 2001/03/13 01:58:21 2.31 --- frameobject.h 2001/06/15 18:56:44 2.31.6.1 *************** *** 22,25 **** --- 22,27 ---- PyObject *f_locals; /* local symbol table (PyDictObject) */ PyObject **f_valuestack; /* points after the last local */ + PyObject **f_stackbottom; /* points to the last item on the stack if + frame has yielded. */ PyObject *f_trace; /* Trace function */ PyObject *f_exc_type, *f_exc_value, *f_exc_traceback; Index: graminit.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/graminit.h,v retrieving revision 2.16 retrieving revision 2.16.10.1 diff -C2 -r2.16 -r2.16.10.1 *** graminit.h 2000/08/24 20:09:45 2.16 --- graminit.h 2001/06/15 18:56:44 2.16.10.1 *************** *** 19,64 **** #define continue_stmt 274 #define return_stmt 275 ! #define raise_stmt 276 ! #define import_stmt 277 ! #define import_as_name 278 ! #define dotted_as_name 279 ! #define dotted_name 280 ! #define global_stmt 281 ! #define exec_stmt 282 ! #define assert_stmt 283 ! #define compound_stmt 284 ! #define if_stmt 285 ! #define while_stmt 286 ! #define for_stmt 287 ! #define try_stmt 288 ! #define except_clause 289 ! #define suite 290 ! #define test 291 ! #define and_test 292 ! #define not_test 293 ! #define comparison 294 ! #define comp_op 295 ! #define expr 296 ! #define xor_expr 297 ! #define and_expr 298 ! #define shift_expr 299 ! #define arith_expr 300 ! #define term 301 ! #define factor 302 ! #define power 303 ! #define atom 304 ! #define listmaker 305 ! #define lambdef 306 ! #define trailer 307 ! #define subscriptlist 308 ! #define subscript 309 ! #define sliceop 310 ! #define exprlist 311 ! #define testlist 312 ! #define dictmaker 313 ! #define classdef 314 ! #define arglist 315 ! #define argument 316 ! #define list_iter 317 ! #define list_for 318 ! #define list_if 319 --- 19,65 ---- #define continue_stmt 274 #define return_stmt 275 ! #define yield_stmt 276 ! #define raise_stmt 277 ! #define import_stmt 278 ! #define import_as_name 279 ! #define dotted_as_name 280 ! #define dotted_name 281 ! #define global_stmt 282 ! #define exec_stmt 283 ! #define assert_stmt 284 ! #define compound_stmt 285 ! #define if_stmt 286 ! #define while_stmt 287 ! #define for_stmt 288 ! #define try_stmt 289 ! #define except_clause 290 ! #define suite 291 ! #define test 292 ! #define and_test 293 ! #define not_test 294 ! #define comparison 295 ! #define comp_op 296 ! #define expr 297 ! #define xor_expr 298 ! #define and_expr 299 ! #define shift_expr 300 ! #define arith_expr 301 ! #define term 302 ! #define factor 303 ! #define power 304 ! #define atom 305 ! #define listmaker 306 ! #define lambdef 307 ! #define trailer 308 ! #define subscriptlist 309 ! #define subscript 310 ! #define sliceop 311 ! #define exprlist 312 ! #define testlist 313 ! #define dictmaker 314 ! #define classdef 315 ! #define arglist 316 ! #define argument 317 ! #define list_iter 318 ! #define list_for 319 ! #define list_if 320 Index: opcode.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/opcode.h,v retrieving revision 2.35 retrieving revision 2.35.4.1 diff -C2 -r2.35 -r2.35.4.1 *** opcode.h 2001/04/20 19:13:01 2.35 --- opcode.h 2001/06/15 18:56:44 2.35.4.1 *************** *** 72,75 **** --- 72,76 ---- #define IMPORT_STAR 84 #define EXEC_STMT 85 + #define YIELD_VALUE 86 #define POP_BLOCK 87 Index: symtable.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/symtable.h,v retrieving revision 2.7 retrieving revision 2.7.6.1 diff -C2 -r2.7 -r2.7.6.1 *** symtable.h 2001/03/22 03:57:58 2.7 --- symtable.h 2001/06/15 18:56:44 2.7.6.1 *************** *** 47,50 **** --- 47,51 ---- int ste_child_free; /* true if a child scope has free variables, including free refs to globals */ + int ste_generator; /* true if namespace is a generator */ int ste_opt_lineno; /* lineno of last exec or import * */ struct symtable *ste_table; From gvanrossum@users.sourceforge.net Fri Jun 15 19:56:46 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 15 Jun 2001 11:56:46 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib dis.py,1.34,1.34.4.1 inspect.py,1.16,1.16.6.1 tabnanny.py,1.13,1.13.6.1 tokenize.py,1.22,1.22.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv5899/Lib Modified Files: Tag: gen-branch dis.py inspect.py tabnanny.py tokenize.py Log Message: Neil's generator patch, in the gen-branch. Index: dis.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/dis.py,v retrieving revision 1.34 retrieving revision 1.34.4.1 diff -C2 -r1.34 -r1.34.4.1 *** dis.py 2001/04/20 19:13:01 1.34 --- dis.py 2001/06/15 18:56:44 1.34.4.1 *************** *** 224,227 **** --- 224,228 ---- def_op('IMPORT_STAR', 84) def_op('EXEC_STMT', 85) + def_op('YIELD_STMT', 86) def_op('POP_BLOCK', 87) Index: inspect.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/inspect.py,v retrieving revision 1.16 retrieving revision 1.16.6.1 diff -C2 -r1.16 -r1.16.6.1 *** inspect.py 2001/04/13 14:04:02 1.16 --- inspect.py 2001/06/15 18:56:44 1.16.6.1 *************** *** 350,379 **** else: return '' ! class EndOfBlock(Exception): pass ! class BlockFinder: ! """Provide a tokeneater() method to detect the end of a code block.""" ! def __init__(self): ! self.indent = 0 ! self.started = 0 ! self.last = 0 ! def tokeneater(self, type, token, (srow, scol), (erow, ecol), line): ! if not self.started: ! if type == tokenize.NAME: self.started = 1 elif type == tokenize.NEWLINE: ! self.last = srow elif type == tokenize.INDENT: ! self.indent = self.indent + 1 elif type == tokenize.DEDENT: ! self.indent = self.indent - 1 ! if self.indent == 0: raise EndOfBlock, self.last ! ! def getblock(lines): ! """Extract the block of code at the top of the given list of lines.""" ! try: ! tokenize.tokenize(ListReader(lines).readline, BlockFinder().tokeneater) ! except EndOfBlock, eob: ! return lines[:eob.args[0]] def getsourcelines(object): --- 350,375 ---- else: return '' ! def getblock(lines): ! """Extract the block of code at the top of the given list of lines.""" ! indent = 0 ! started = 0 ! last = 0 ! tokens = tokenize.generate_tokens(ListReader(lines).readline) ! for (type, token, (srow, scol), (erow, ecol), line) in tokens: ! if not started: ! if type == tokenize.NAME: ! started = 1 elif type == tokenize.NEWLINE: ! last = srow elif type == tokenize.INDENT: ! indent = indent + 1 elif type == tokenize.DEDENT: ! indent = indent - 1 ! if self.indent == 0: ! return lines[:last] ! else: ! raise ValueError, "unable to find block" def getsourcelines(object): Index: tabnanny.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/tabnanny.py,v retrieving revision 1.13 retrieving revision 1.13.6.1 diff -C2 -r1.13 -r1.13.6.1 *** tabnanny.py 2001/04/08 00:38:42 1.13 --- tabnanny.py 2001/06/15 18:56:44 1.13.6.1 *************** *** 78,84 **** print "checking", `file`, "..." - reset_globals() try: ! tokenize.tokenize(f.readline, tokeneater) except tokenize.TokenError, msg: --- 78,83 ---- print "checking", `file`, "..." try: ! process_tokens(tokenize.generate_tokens(f.readline)) except tokenize.TokenError, msg: *************** *** 245,270 **** return prefix + " " + string.join(firsts, ', ') ! # The collection of globals, the reset_globals() function, and the ! # tokeneater() function, depend on which version of tokenize is ! # in use. ! if hasattr(tokenize, 'NL'): ! # take advantage of Guido's patch! ! ! indents = [] ! check_equal = 0 ! ! def reset_globals(): ! global indents, check_equal ! check_equal = 0 ! indents = [Whitespace("")] ! ! def tokeneater(type, token, start, end, line, INDENT=tokenize.INDENT, DEDENT=tokenize.DEDENT, NEWLINE=tokenize.NEWLINE, ! JUNK=(tokenize.COMMENT, tokenize.NL) ): ! global indents, check_equal if type == NEWLINE: # a program statement, or ENDMARKER, will eventually follow, --- 244,260 ---- return prefix + " " + string.join(firsts, ', ') ! # Need Guido's enhancement ! assert hasattr(tokenize, 'NL'), "tokenize module too old" ! def process_tokens(tokens, INDENT=tokenize.INDENT, DEDENT=tokenize.DEDENT, NEWLINE=tokenize.NEWLINE, ! JUNK=(tokenize.COMMENT, tokenize.NL)): + indents = [Whitespace("")] + check_equal = 0 + + for (type, token, start, end, line) in tokens: if type == NEWLINE: # a program statement, or ENDMARKER, will eventually follow, *************** *** 312,371 **** raise NannyNag(start[0], msg, line) - else: - # unpatched version of tokenize - - nesting_level = 0 - indents = [] - check_equal = 0 - - def reset_globals(): - global nesting_level, indents, check_equal - nesting_level = check_equal = 0 - indents = [Whitespace("")] - - def tokeneater(type, token, start, end, line, - INDENT=tokenize.INDENT, - DEDENT=tokenize.DEDENT, - NEWLINE=tokenize.NEWLINE, - COMMENT=tokenize.COMMENT, - OP=tokenize.OP): - global nesting_level, indents, check_equal - - if type == INDENT: - check_equal = 0 - thisguy = Whitespace(token) - if not indents[-1].less(thisguy): - witness = indents[-1].not_less_witness(thisguy) - msg = "indent not greater e.g. " + format_witnesses(witness) - raise NannyNag(start[0], msg, line) - indents.append(thisguy) - - elif type == DEDENT: - del indents[-1] - - elif type == NEWLINE: - if nesting_level == 0: - check_equal = 1 - - elif type == COMMENT: - pass - - elif check_equal: - check_equal = 0 - thisguy = Whitespace(line) - if not indents[-1].equal(thisguy): - witness = indents[-1].not_equal_witness(thisguy) - msg = "indent not equal e.g. " + format_witnesses(witness) - raise NannyNag(start[0], msg, line) - - if type == OP and token in ('{', '[', '('): - nesting_level = nesting_level + 1 - - elif type == OP and token in ('}', ']', ')'): - if nesting_level == 0: - raise NannyNag(start[0], - "unbalanced bracket '" + token + "'", - line) - nesting_level = nesting_level - 1 if __name__ == '__main__': --- 302,305 ---- Index: tokenize.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/tokenize.py,v retrieving revision 1.22 retrieving revision 1.22.6.1 diff -C2 -r1.22 -r1.22.6.1 *** tokenize.py 2001/03/23 05:22:49 1.22 --- tokenize.py 2001/06/15 18:56:44 1.22.6.1 *************** *** 112,116 **** --- 112,121 ---- pass + # backwards compatible interface, probably not used def tokenize_loop(readline, tokeneater): + for token_info in generate_tokens(readline): + apply(tokeneater, token_info) + + def generate_tokens(readline): lnum = parenlev = continued = 0 namechars, numchars = string.letters + '_', string.digits *************** *** 130,139 **** if endmatch: pos = end = endmatch.end(0) ! tokeneater(STRING, contstr + line[:end], strstart, (lnum, end), contline + line) contstr, needcont = '', 0 contline = None elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': ! tokeneater(ERRORTOKEN, contstr + line, strstart, (lnum, len(line)), contline) contstr = '' --- 135,144 ---- if endmatch: pos = end = endmatch.end(0) ! yield (STRING, contstr + line[:end], strstart, (lnum, end), contline + line) contstr, needcont = '', 0 contline = None elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': ! yield (ERRORTOKEN, contstr + line, strstart, (lnum, len(line)), contline) contstr = '' *************** *** 157,161 **** if line[pos] in '#\r\n': # skip comments or blank lines ! tokeneater((NL, COMMENT)[line[pos] == '#'], line[pos:], (lnum, pos), (lnum, len(line)), line) continue --- 162,166 ---- if line[pos] in '#\r\n': # skip comments or blank lines ! yield ((NL, COMMENT)[line[pos] == '#'], line[pos:], (lnum, pos), (lnum, len(line)), line) continue *************** *** 163,170 **** if column > indents[-1]: # count indents or dedents indents.append(column) ! tokeneater(INDENT, line[:pos], (lnum, 0), (lnum, pos), line) while column < indents[-1]: indents = indents[:-1] ! tokeneater(DEDENT, '', (lnum, pos), (lnum, pos), line) else: # continued statement --- 168,175 ---- if column > indents[-1]: # count indents or dedents indents.append(column) ! yield (INDENT, line[:pos], (lnum, 0), (lnum, pos), line) while column < indents[-1]: indents = indents[:-1] ! yield (DEDENT, '', (lnum, pos), (lnum, pos), line) else: # continued statement *************** *** 182,191 **** if initial in numchars or \ (initial == '.' and token != '.'): # ordinary number ! tokeneater(NUMBER, token, spos, epos, line) elif initial in '\r\n': ! tokeneater(parenlev > 0 and NL or NEWLINE, token, spos, epos, line) elif initial == '#': ! tokeneater(COMMENT, token, spos, epos, line) elif token in ("'''", '"""', # triple-quoted "r'''", 'r"""', "R'''", 'R"""', --- 187,196 ---- if initial in numchars or \ (initial == '.' and token != '.'): # ordinary number ! yield (NUMBER, token, spos, epos, line) elif initial in '\r\n': ! yield (parenlev > 0 and NL or NEWLINE, token, spos, epos, line) elif initial == '#': ! yield (COMMENT, token, spos, epos, line) elif token in ("'''", '"""', # triple-quoted "r'''", 'r"""', "R'''", 'R"""', *************** *** 198,202 **** pos = endmatch.end(0) token = line[start:pos] ! tokeneater(STRING, token, spos, (lnum, pos), line) else: strstart = (lnum, start) # multiple lines --- 203,207 ---- pos = endmatch.end(0) token = line[start:pos] ! yield (STRING, token, spos, (lnum, pos), line) else: strstart = (lnum, start) # multiple lines *************** *** 217,223 **** break else: # ordinary string ! tokeneater(STRING, token, spos, epos, line) elif initial in namechars: # ordinary name ! tokeneater(NAME, token, spos, epos, line) elif initial == '\\': # continued stmt continued = 1 --- 222,228 ---- break else: # ordinary string ! yield (STRING, token, spos, epos, line) elif initial in namechars: # ordinary name ! yield (NAME, token, spos, epos, line) elif initial == '\\': # continued stmt continued = 1 *************** *** 225,237 **** if initial in '([{': parenlev = parenlev + 1 elif initial in ')]}': parenlev = parenlev - 1 ! tokeneater(OP, token, spos, epos, line) else: ! tokeneater(ERRORTOKEN, line[pos], (lnum, pos), (lnum, pos+1), line) pos = pos + 1 for indent in indents[1:]: # pop remaining indent levels ! tokeneater(DEDENT, '', (lnum, 0), (lnum, 0), '') ! tokeneater(ENDMARKER, '', (lnum, 0), (lnum, 0), '') if __name__ == '__main__': # testing --- 230,242 ---- if initial in '([{': parenlev = parenlev + 1 elif initial in ')]}': parenlev = parenlev - 1 ! yield (OP, token, spos, epos, line) else: ! yield (ERRORTOKEN, line[pos], (lnum, pos), (lnum, pos+1), line) pos = pos + 1 for indent in indents[1:]: # pop remaining indent levels ! yield (DEDENT, '', (lnum, 0), (lnum, 0), '') ! yield (ENDMARKER, '', (lnum, 0), (lnum, 0), '') if __name__ == '__main__': # testing From gvanrossum@users.sourceforge.net Fri Jun 15 19:56:47 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 15 Jun 2001 11:56:47 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python ceval.c,2.246,2.246.2.1 compile.c,2.201,2.201.2.1 graminit.c,2.28,2.28.10.1 marshal.c,1.63,1.63.2.1 symtable.c,2.4,2.4.8.1 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv5899/Python Modified Files: Tag: gen-branch ceval.c compile.c graminit.c marshal.c symtable.c Log Message: Neil's generator patch, in the gen-branch. Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.246 retrieving revision 2.246.2.1 diff -C2 -r2.246 -r2.246.2.1 *** ceval.c 2001/06/08 04:33:09 2.246 --- ceval.c 2001/06/15 18:56:44 2.246.2.1 *************** *** 41,44 **** --- 41,45 ---- PyObject *); + static PyObject *eval_frame(PyFrameObject *); static char *get_func_name(PyObject *); static char *get_func_desc(PyObject *); *************** *** 107,110 **** --- 108,229 ---- + staticforward PyTypeObject gentype; + + typedef struct { + PyObject_HEAD + PyFrameObject *frame; + int running; /* true if generator is being executed */ + } genobject; + + static PyObject * + gen_new(PyFrameObject *f) + { + genobject *gen = PyObject_New(genobject, &gentype); + if (gen == NULL) { + Py_DECREF(f); + return NULL; + } + gen->frame = f; + gen->running = 0; + return (PyObject *)gen; + } + + static void + gen_dealloc(genobject *gen) + { + Py_DECREF(gen->frame); + PyObject_DEL(gen); + } + + static PyObject * + gen_iternext(genobject *gen) + { + PyFrameObject *f = gen->frame; + PyObject *result; + + if (gen->running) { + PyErr_SetString(PyExc_ValueError, + "generator already executing"); + return NULL; + } + if (f->f_stackbottom == NULL) { + return NULL; + } + gen->running = 1; + result = eval_frame(f); + gen->running = 0; + return result; + } + + static PyObject * + gen_next(genobject *gen, PyObject *args) + { + PyObject *result; + + if (!PyArg_ParseTuple(args, ":next")) + return NULL; + + result = gen_iternext(gen); + + if (result == NULL && !PyErr_Occurred()) { + PyErr_SetObject(PyExc_StopIteration, Py_None); + return NULL; + } + + return result; + } + + static PyObject * + gen_getiter(PyObject *gen) + { + Py_INCREF(gen); + return gen; + } + + static struct PyMethodDef gen_methods[] = { + {"next", (PyCFunction)gen_next, METH_VARARGS, + "next() -- get the next value, or raise StopIteration"}, + {NULL, NULL} /* Sentinel */ + }; + + static PyObject * + gen_getattr(genobject *gen, char *name) + { + return Py_FindMethod(gen_methods, (PyObject *)gen, name); + } + + statichere PyTypeObject gentype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ + "generator", /* tp_name */ + sizeof(genobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)gen_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)gen_getattr, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)gen_getiter, /* tp_iter */ + (iternextfunc)gen_iternext, /* tp_iternext */ + }; + + #ifdef WITH_THREAD *************** *** 338,342 **** WHY_RETURN, /* 'return' statement */ WHY_BREAK, /* 'break' statement */ ! WHY_CONTINUE /* 'continue' statement */ }; --- 457,462 ---- WHY_RETURN, /* 'return' statement */ WHY_BREAK, /* 'break' statement */ ! WHY_CONTINUE, /* 'continue' statement */ ! WHY_YIELD, /* 'yield' operator */ }; *************** *** 359,366 **** /* Interpreter main loop */ ! static PyObject * ! eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ! PyObject **args, int argcount, PyObject **kws, int kwcount, ! PyObject **defs, int defcount, PyObject *closure) { #ifdef DXPAIRS --- 479,484 ---- /* Interpreter main loop */ ! PyObject * ! eval_frame(PyFrameObject *f) { #ifdef DXPAIRS *************** *** 379,386 **** register PyObject *t; register PyObject *stream = NULL; /* for PRINT opcodes */ - register PyFrameObject *f; /* Current frame */ register PyObject **fastlocals, **freevars; PyObject *retval = NULL; /* Return value */ PyThreadState *tstate = PyThreadState_GET(); unsigned char *first_instr; #ifdef LLTRACE --- 497,504 ---- register PyObject *t; register PyObject *stream = NULL; /* for PRINT opcodes */ register PyObject **fastlocals, **freevars; PyObject *retval = NULL; /* Return value */ PyThreadState *tstate = PyThreadState_GET(); + PyCodeObject *co; unsigned char *first_instr; #ifdef LLTRACE *************** *** 389,393 **** #if defined(Py_DEBUG) || defined(LLTRACE) /* Make it easier to find out where we are with a debugger */ ! char *filename = PyString_AsString(co->co_filename); #endif --- 507,511 ---- #if defined(Py_DEBUG) || defined(LLTRACE) /* Make it easier to find out where we are with a debugger */ ! char *filename; #endif *************** *** 427,430 **** --- 545,551 ---- /* Start of code */ + if (f == NULL) + return NULL; + #ifdef USE_STACKCHECK if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) { *************** *** 433,675 **** } #endif - - if (globals == NULL) { - PyErr_SetString(PyExc_SystemError, "eval_code2: NULL globals"); - return NULL; - } - - #ifdef LLTRACE - lltrace = PyDict_GetItemString(globals, "__lltrace__") != NULL; - #endif - - f = PyFrame_New(tstate, /*back*/ - co, /*code*/ - globals, locals); - if (f == NULL) - return NULL; - - tstate->frame = f; - fastlocals = f->f_localsplus; - freevars = f->f_localsplus + f->f_nlocals; - - if (co->co_argcount > 0 || - co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) { - int i; - int n = argcount; - PyObject *kwdict = NULL; - if (co->co_flags & CO_VARKEYWORDS) { - kwdict = PyDict_New(); - if (kwdict == NULL) - goto fail; - i = co->co_argcount; - if (co->co_flags & CO_VARARGS) - i++; - SETLOCAL(i, kwdict); - } - if (argcount > co->co_argcount) { - if (!(co->co_flags & CO_VARARGS)) { - PyErr_Format(PyExc_TypeError, - "%.200s() takes %s %d " - "%sargument%s (%d given)", - PyString_AsString(co->co_name), - defcount ? "at most" : "exactly", - co->co_argcount, - kwcount ? "non-keyword " : "", - co->co_argcount == 1 ? "" : "s", - argcount); - goto fail; - } - n = co->co_argcount; - } - for (i = 0; i < n; i++) { - x = args[i]; - Py_INCREF(x); - SETLOCAL(i, x); - } - if (co->co_flags & CO_VARARGS) { - u = PyTuple_New(argcount - n); - if (u == NULL) - goto fail; - SETLOCAL(co->co_argcount, u); - for (i = n; i < argcount; i++) { - x = args[i]; - Py_INCREF(x); - PyTuple_SET_ITEM(u, i-n, x); - } - } - for (i = 0; i < kwcount; i++) { - PyObject *keyword = kws[2*i]; - PyObject *value = kws[2*i + 1]; - int j; - if (keyword == NULL || !PyString_Check(keyword)) { - PyErr_Format(PyExc_TypeError, - "%.200s() keywords must be strings", - PyString_AsString(co->co_name)); - goto fail; - } - /* XXX slow -- speed up using dictionary? */ - for (j = 0; j < co->co_argcount; j++) { - PyObject *nm = PyTuple_GET_ITEM( - co->co_varnames, j); - int cmp = PyObject_RichCompareBool( - keyword, nm, Py_EQ); - if (cmp > 0) - break; - else if (cmp < 0) - goto fail; - } - /* Check errors from Compare */ - if (PyErr_Occurred()) - goto fail; - if (j >= co->co_argcount) { - if (kwdict == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s() got an unexpected " - "keyword argument '%.400s'", - PyString_AsString(co->co_name), - PyString_AsString(keyword)); - goto fail; - } - PyDict_SetItem(kwdict, keyword, value); - } - else { - if (GETLOCAL(j) != NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s() got multiple " - "values for keyword " - "argument '%.400s'", - PyString_AsString(co->co_name), - PyString_AsString(keyword)); - goto fail; - } - Py_INCREF(value); - SETLOCAL(j, value); - } - } - if (argcount < co->co_argcount) { - int m = co->co_argcount - defcount; - for (i = argcount; i < m; i++) { - if (GETLOCAL(i) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s() takes %s %d " - "%sargument%s (%d given)", - PyString_AsString(co->co_name), - ((co->co_flags & CO_VARARGS) || - defcount) ? "at least" - : "exactly", - m, kwcount ? "non-keyword " : "", - m == 1 ? "" : "s", i); - goto fail; - } - } - if (n > m) - i = n - m; - else - i = 0; - for (; i < defcount; i++) { - if (GETLOCAL(m+i) == NULL) { - PyObject *def = defs[i]; - Py_INCREF(def); - SETLOCAL(m+i, def); - } - } - } - } - else { - if (argcount > 0 || kwcount > 0) { - PyErr_Format(PyExc_TypeError, - "%.200s() takes no arguments (%d given)", - PyString_AsString(co->co_name), - argcount + kwcount); - goto fail; - } - } - /* Allocate and initialize storage for cell vars, and copy free - vars into frame. This isn't too efficient right now. */ - if (f->f_ncells) { - int i = 0, j = 0, nargs, found; - char *cellname, *argname; - PyObject *c; - - nargs = co->co_argcount; - if (co->co_flags & CO_VARARGS) - nargs++; - if (co->co_flags & CO_VARKEYWORDS) - nargs++; ! /* Check for cells that shadow args */ ! for (i = 0; i < f->f_ncells && j < nargs; ++i) { ! cellname = PyString_AS_STRING( ! PyTuple_GET_ITEM(co->co_cellvars, i)); ! found = 0; ! while (j < nargs) { ! argname = PyString_AS_STRING( ! PyTuple_GET_ITEM(co->co_varnames, j)); ! if (strcmp(cellname, argname) == 0) { ! c = PyCell_New(GETLOCAL(j)); ! if (c == NULL) ! goto fail; ! GETLOCAL(f->f_nlocals + i) = c; ! found = 1; ! break; ! } ! j++; ! } ! if (found == 0) { ! c = PyCell_New(NULL); ! if (c == NULL) ! goto fail; ! SETLOCAL(f->f_nlocals + i, c); ! } ! } ! /* Initialize any that are left */ ! while (i < f->f_ncells) { ! c = PyCell_New(NULL); ! if (c == NULL) ! goto fail; ! SETLOCAL(f->f_nlocals + i, c); ! i++; ! } ! } ! if (f->f_nfreevars) { ! int i; ! for (i = 0; i < f->f_nfreevars; ++i) { ! PyObject *o = PyTuple_GET_ITEM(closure, i); ! Py_INCREF(o); ! freevars[f->f_ncells + i] = o; ! } ! } ! ! if (tstate->sys_tracefunc != NULL) { ! /* tstate->sys_tracefunc, if defined, is a function that ! will be called on *every* entry to a code block. ! Its return value, if not None, is a function that ! will be called at the start of each executed line ! of code. (Actually, the function must return ! itself in order to continue tracing.) ! The trace functions are called with three arguments: ! a pointer to the current frame, a string indicating ! why the function is called, and an argument which ! depends on the situation. The global trace function ! (sys.trace) is also called whenever an exception ! is detected. */ ! if (call_trace(&tstate->sys_tracefunc, ! &f->f_trace, f, "call", &str_call, ! Py_None/*XXX how to compute arguments now?*/)) { ! /* Trace function raised an error */ ! goto fail; ! } ! } ! ! if (tstate->sys_profilefunc != NULL) { ! /* Similar for sys_profilefunc, except it needn't return ! itself and isn't called for "line" events */ ! if (call_trace(&tstate->sys_profilefunc, ! (PyObject**)0, f, "call", &str_call, ! Py_None/*XXX*/)) { ! goto fail; ! } ! } ! if (++tstate->recursion_depth > recursion_limit) { --tstate->recursion_depth; --- 554,559 ---- } #endif ! /* push frame */ if (++tstate->recursion_depth > recursion_limit) { --tstate->recursion_depth; *************** *** 677,687 **** "maximum recursion depth exceeded"); tstate->frame = f->f_back; - Py_DECREF(f); return NULL; } _PyCode_GETCODEPTR(co, &first_instr); ! next_instr = first_instr; ! stack_pointer = f->f_valuestack; why = WHY_NOT; --- 561,584 ---- "maximum recursion depth exceeded"); tstate->frame = f->f_back; return NULL; } + f->f_back = tstate->frame; + tstate->frame = f; + + co = f->f_code; + fastlocals = f->f_localsplus; + freevars = f->f_localsplus + f->f_nlocals; _PyCode_GETCODEPTR(co, &first_instr); ! next_instr = first_instr + f->f_lasti; ! stack_pointer = f->f_stackbottom; ! f->f_stackbottom = NULL; ! ! #ifdef LLTRACE ! lltrace = PyDict_GetItemString(f->f_globals,"__lltrace__") != NULL; ! #endif ! #if defined(Py_DEBUG) || defined(LLTRACE) ! filename = PyString_AsString(co->co_filename); ! #endif why = WHY_NOT; *************** *** 1460,1463 **** --- 1357,1368 ---- break; + case YIELD_VALUE: + retval = POP(); + f->f_stackbottom = stack_pointer; + f->f_lasti = INSTR_OFFSET(); + why = WHY_YIELD; + break; + + case EXEC_STMT: w = POP(); *************** *** 1485,1488 **** --- 1390,1394 ---- why = (enum why_code) PyInt_AsLong(v); if (why == WHY_RETURN || + why == WHY_YIELD || why == CONTINUE_LOOP) retval = POP(); *************** *** 2226,2230 **** /* Unwind stacks if a (pseudo) exception occurred */ ! while (why != WHY_NOT && f->f_iblock > 0) { PyTryBlock *b = PyFrame_BlockPop(f); --- 2132,2136 ---- /* Unwind stacks if a (pseudo) exception occurred */ ! while (why != WHY_NOT && why != WHY_YIELD && f->f_iblock > 0) { PyTryBlock *b = PyFrame_BlockPop(f); *************** *** 2296,2309 **** /* Pop remaining stack entries */ while (!EMPTY()) { v = POP(); Py_XDECREF(v); } ! if (why != WHY_RETURN) retval = NULL; if (f->f_trace) { ! if (why == WHY_RETURN) { if (call_trace(&f->f_trace, &f->f_trace, f, "return", &str_return, retval)) { --- 2202,2217 ---- /* Pop remaining stack entries */ + /* while (!EMPTY()) { v = POP(); Py_XDECREF(v); } + */ ! if (why != WHY_RETURN && why != WHY_YIELD) retval = NULL; if (f->f_trace) { ! if (why == WHY_RETURN || why == WHY_YIELD) { if (call_trace(&f->f_trace, &f->f_trace, f, "return", &str_return, retval)) { *************** *** 2315,2319 **** } ! if (tstate->sys_profilefunc && why == WHY_RETURN) { if (call_trace(&tstate->sys_profilefunc, (PyObject**)0, f, "return", &str_return, retval)) { --- 2223,2228 ---- } ! if (tstate->sys_profilefunc && ! (why == WHY_RETURN || why == WHY_YIELD)) { if (call_trace(&tstate->sys_profilefunc, (PyObject**)0, f, "return", &str_return, retval)) { *************** *** 2326,2340 **** reset_exc_info(tstate); --tstate->recursion_depth; ! fail: /* Jump here from prelude on failure */ ! /* Restore previous frame and release the current one */ ! tstate->frame = f->f_back; ! Py_DECREF(f); return retval; } static void --- 2235,2503 ---- reset_exc_info(tstate); + /* pop frame */ --tstate->recursion_depth; + tstate->frame = f->f_back; ! return retval; ! } ! ! static PyObject * ! eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ! PyObject **args, int argcount, PyObject **kws, int kwcount, ! PyObject **defs, int defcount, PyObject *closure) ! { ! register PyFrameObject *f; ! register PyObject *retval = NULL; ! register PyObject **fastlocals, **freevars; ! PyThreadState *tstate = PyThreadState_GET(); ! PyObject *x, *u; ! if (globals == NULL) { ! PyErr_SetString(PyExc_SystemError, "eval_code2: NULL globals"); ! return NULL; ! } ! f = PyFrame_New(tstate, /*back*/ ! co, /*code*/ ! globals, locals); ! if (f == NULL) ! return NULL; ! ! fastlocals = f->f_localsplus; ! freevars = f->f_localsplus + f->f_nlocals; ! ! if (co->co_argcount > 0 || ! co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) { ! int i; ! int n = argcount; ! PyObject *kwdict = NULL; ! if (co->co_flags & CO_VARKEYWORDS) { ! kwdict = PyDict_New(); ! if (kwdict == NULL) ! goto fail; ! i = co->co_argcount; ! if (co->co_flags & CO_VARARGS) ! i++; ! SETLOCAL(i, kwdict); ! } ! if (argcount > co->co_argcount) { ! if (!(co->co_flags & CO_VARARGS)) { ! PyErr_Format(PyExc_TypeError, ! "%.200s() takes %s %d " ! "%sargument%s (%d given)", ! PyString_AsString(co->co_name), ! defcount ? "at most" : "exactly", ! co->co_argcount, ! kwcount ? "non-keyword " : "", ! co->co_argcount == 1 ? "" : "s", ! argcount); ! goto fail; ! } ! n = co->co_argcount; ! } ! for (i = 0; i < n; i++) { ! x = args[i]; ! Py_INCREF(x); ! SETLOCAL(i, x); ! } ! if (co->co_flags & CO_VARARGS) { ! u = PyTuple_New(argcount - n); ! if (u == NULL) ! goto fail; ! SETLOCAL(co->co_argcount, u); ! for (i = n; i < argcount; i++) { ! x = args[i]; ! Py_INCREF(x); ! PyTuple_SET_ITEM(u, i-n, x); ! } ! } ! for (i = 0; i < kwcount; i++) { ! PyObject *keyword = kws[2*i]; ! PyObject *value = kws[2*i + 1]; ! int j; ! if (keyword == NULL || !PyString_Check(keyword)) { ! PyErr_Format(PyExc_TypeError, ! "%.200s() keywords must be strings", ! PyString_AsString(co->co_name)); ! goto fail; ! } ! /* XXX slow -- speed up using dictionary? */ ! for (j = 0; j < co->co_argcount; j++) { ! PyObject *nm = PyTuple_GET_ITEM( ! co->co_varnames, j); ! int cmp = PyObject_RichCompareBool( ! keyword, nm, Py_EQ); ! if (cmp > 0) ! break; ! else if (cmp < 0) ! goto fail; ! } ! /* Check errors from Compare */ ! if (PyErr_Occurred()) ! goto fail; ! if (j >= co->co_argcount) { ! if (kwdict == NULL) { ! PyErr_Format(PyExc_TypeError, ! "%.200s() got an unexpected " ! "keyword argument '%.400s'", ! PyString_AsString(co->co_name), ! PyString_AsString(keyword)); ! goto fail; ! } ! PyDict_SetItem(kwdict, keyword, value); ! } ! else { ! if (GETLOCAL(j) != NULL) { ! PyErr_Format(PyExc_TypeError, ! "%.200s() got multiple " ! "values for keyword " ! "argument '%.400s'", ! PyString_AsString(co->co_name), ! PyString_AsString(keyword)); ! goto fail; ! } ! Py_INCREF(value); ! SETLOCAL(j, value); ! } ! } ! if (argcount < co->co_argcount) { ! int m = co->co_argcount - defcount; ! for (i = argcount; i < m; i++) { ! if (GETLOCAL(i) == NULL) { ! PyErr_Format(PyExc_TypeError, ! "%.200s() takes %s %d " ! "%sargument%s (%d given)", ! PyString_AsString(co->co_name), ! ((co->co_flags & CO_VARARGS) || ! defcount) ? "at least" ! : "exactly", ! m, kwcount ? "non-keyword " : "", ! m == 1 ? "" : "s", i); ! goto fail; ! } ! } ! if (n > m) ! i = n - m; ! else ! i = 0; ! for (; i < defcount; i++) { ! if (GETLOCAL(m+i) == NULL) { ! PyObject *def = defs[i]; ! Py_INCREF(def); ! SETLOCAL(m+i, def); ! } ! } ! } ! } ! else { ! if (argcount > 0 || kwcount > 0) { ! PyErr_Format(PyExc_TypeError, ! "%.200s() takes no arguments (%d given)", ! PyString_AsString(co->co_name), ! argcount + kwcount); ! goto fail; ! } ! } ! /* Allocate and initialize storage for cell vars, and copy free ! vars into frame. This isn't too efficient right now. */ ! if (f->f_ncells) { ! int i = 0, j = 0, nargs, found; ! char *cellname, *argname; ! PyObject *c; ! ! nargs = co->co_argcount; ! if (co->co_flags & CO_VARARGS) ! nargs++; ! if (co->co_flags & CO_VARKEYWORDS) ! nargs++; ! ! /* Check for cells that shadow args */ ! for (i = 0; i < f->f_ncells && j < nargs; ++i) { ! cellname = PyString_AS_STRING( ! PyTuple_GET_ITEM(co->co_cellvars, i)); ! found = 0; ! while (j < nargs) { ! argname = PyString_AS_STRING( ! PyTuple_GET_ITEM(co->co_varnames, j)); ! if (strcmp(cellname, argname) == 0) { ! c = PyCell_New(GETLOCAL(j)); ! if (c == NULL) ! goto fail; ! GETLOCAL(f->f_nlocals + i) = c; ! found = 1; ! break; ! } ! j++; ! } ! if (found == 0) { ! c = PyCell_New(NULL); ! if (c == NULL) ! goto fail; ! SETLOCAL(f->f_nlocals + i, c); ! } ! } ! /* Initialize any that are left */ ! while (i < f->f_ncells) { ! c = PyCell_New(NULL); ! if (c == NULL) ! goto fail; ! SETLOCAL(f->f_nlocals + i, c); ! i++; ! } ! } ! if (f->f_nfreevars) { ! int i; ! for (i = 0; i < f->f_nfreevars; ++i) { ! PyObject *o = PyTuple_GET_ITEM(closure, i); ! Py_INCREF(o); ! freevars[f->f_ncells + i] = o; ! } ! } ! ! if (tstate->sys_tracefunc != NULL) { ! /* tstate->sys_tracefunc, if defined, is a function that ! will be called on *every* entry to a code block. ! Its return value, if not None, is a function that ! will be called at the start of each executed line ! of code. (Actually, the function must return ! itself in order to continue tracing.) ! The trace functions are called with three arguments: ! a pointer to the current frame, a string indicating ! why the function is called, and an argument which ! depends on the situation. The global trace function ! (sys.trace) is also called whenever an exception ! is detected. */ ! if (call_trace(&tstate->sys_tracefunc, ! &f->f_trace, f, "call", &str_call, ! Py_None/*XXX how to compute arguments now?*/)) { ! /* Trace function raised an error */ ! goto fail; ! } ! } + if (tstate->sys_profilefunc != NULL) { + /* Similar for sys_profilefunc, except it needn't return + itself and isn't called for "line" events */ + if (call_trace(&tstate->sys_profilefunc, + (PyObject**)0, f, "call", &str_call, + Py_None/*XXX*/)) { + goto fail; + } + } + + if (co->co_flags & CO_GENERATOR) { + /* create a new generator that owns the ready to run frame + * and return that as the value */ + return gen_new(f); + } + + retval = eval_frame(f); + + fail: /* Jump here from prelude on failure */ + + Py_DECREF(f); return retval; } + static void Index: compile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v retrieving revision 2.201 retrieving revision 2.201.2.1 diff -C2 -r2.201 -r2.201.2.1 *** compile.c 2001/06/09 09:26:21 2.201 --- compile.c 2001/06/15 18:56:44 2.201.2.1 *************** *** 2635,2649 **** com_error(c, PyExc_SyntaxError, "'return' outside function"); } ! if (NCH(n) < 2) { ! com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None)); com_push(c, 1); } ! else ! com_node(c, CHILD(n, 1)); ! com_addbyte(c, RETURN_VALUE); com_pop(c, 1); } static void com_raise_stmt(struct compiling *c, node *n) { --- 2635,2673 ---- com_error(c, PyExc_SyntaxError, "'return' outside function"); } ! if (c->c_flags & CO_GENERATOR) { ! if (NCH(n) > 1) { ! com_error(c, PyExc_SyntaxError, ! "'return' with argument inside generator"); ! } ! com_addoparg(c, LOAD_CONST, ! com_addconst(c, PyExc_StopIteration)); com_push(c, 1); + com_addoparg(c, RAISE_VARARGS, 1); } ! else { ! if (NCH(n) < 2) { ! com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None)); ! com_push(c, 1); ! } ! else ! com_node(c, CHILD(n, 1)); ! com_addbyte(c, RETURN_VALUE); ! } com_pop(c, 1); } static void + com_yield_stmt(struct compiling *c, node *n) + { + REQ(n, yield_stmt); /* 'yield' testlist */ + if (!c->c_infunction) { + com_error(c, PyExc_SyntaxError, "'yield' outside function"); + } + com_node(c, CHILD(n, 1)); + com_addbyte(c, YIELD_VALUE); + com_pop(c, 1); + } + + static void com_raise_stmt(struct compiling *c, node *n) { *************** *** 3456,3459 **** --- 3480,3486 ---- com_return_stmt(c, n); break; + case yield_stmt: + com_yield_stmt(c, n); + break; case raise_stmt: com_raise_stmt(c, n); *************** *** 3675,3682 **** com_node(c, CHILD(n, 4)); c->c_infunction = 0; ! com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None)); ! com_push(c, 1); ! com_addbyte(c, RETURN_VALUE); ! com_pop(c, 1); } --- 3702,3718 ---- com_node(c, CHILD(n, 4)); c->c_infunction = 0; ! if (c->c_flags & CO_GENERATOR) { ! com_addoparg(c, LOAD_CONST, ! com_addconst(c, PyExc_StopIteration)); ! com_push(c, 1); ! com_addoparg(c, RAISE_VARARGS, 1); ! com_pop(c, 1); ! } ! else { ! com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None)); ! com_push(c, 1); ! com_addbyte(c, RETURN_VALUE); ! com_pop(c, 1); ! } } *************** *** 4343,4346 **** --- 4379,4384 ---- if (c->c_future && c->c_future->ff_nested_scopes) c->c_flags |= CO_NESTED; + if (ste->ste_generator) + c->c_flags |= CO_GENERATOR; if (ste->ste_type != TYPE_MODULE) c->c_flags |= CO_NEWLOCALS; *************** *** 4901,4904 **** --- 4939,4946 ---- symtable_assign(st, CHILD(n, 1), 0); break; + case yield_stmt: + st->st_cur->ste_generator = 1; + n = CHILD(n, 1); + goto loop; case expr_stmt: if (NCH(n) == 1) Index: graminit.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/graminit.c,v retrieving revision 2.28 retrieving revision 2.28.10.1 diff -C2 -r2.28 -r2.28.10.1 *** graminit.c 2000/08/24 20:11:32 2.28 --- graminit.c 2001/06/15 18:56:44 2.28.10.1 *************** *** 342,350 **** {1, arcs_15_1}, }; ! static arc arcs_16_0[4] = { {54, 1}, {55, 1}, {56, 1}, {57, 1}, }; static arc arcs_16_1[1] = { --- 342,351 ---- [...2505 lines suppressed...] {25, 0}, {2, 0}, {3, 0}, ! {319, 0}, {1, "lambda"}, ! {316, 0}, {309, 0}, {310, 0}, + {311, 0}, {1, "class"}, {317, 0}, ! {318, 0}, ! {320, 0}, }; grammar _PyParser_Grammar = { ! 65, dfas, ! {144, labels}, 256 }; Index: marshal.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/marshal.c,v retrieving revision 1.63 retrieving revision 1.63.2.1 diff -C2 -r1.63 -r1.63.2.1 *** marshal.c 2001/05/08 15:19:57 1.63 --- marshal.c 2001/06/15 18:56:45 1.63.2.1 *************** *** 18,21 **** --- 18,22 ---- #define TYPE_NULL '0' #define TYPE_NONE 'N' + #define TYPE_STOPITER 'S' #define TYPE_ELLIPSIS '.' #define TYPE_INT 'i' *************** *** 121,124 **** --- 122,128 ---- w_byte(TYPE_NONE, p); } + else if (v == PyExc_StopIteration) { + w_byte(TYPE_STOPITER, p); + } else if (v == Py_Ellipsis) { w_byte(TYPE_ELLIPSIS, p); *************** *** 376,379 **** --- 380,387 ---- Py_INCREF(Py_None); return Py_None; + + case TYPE_STOPITER: + Py_INCREF(PyExc_StopIteration); + return PyExc_StopIteration; case TYPE_ELLIPSIS: Index: symtable.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/symtable.c,v retrieving revision 2.4 retrieving revision 2.4.8.1 diff -C2 -r2.4 -r2.4.8.1 *** symtable.c 2001/02/27 19:07:02 2.4 --- symtable.c 2001/06/15 18:56:45 2.4.8.1 *************** *** 70,73 **** --- 70,74 ---- ste->ste_nested = 0; ste->ste_child_free = 0; + ste->ste_generator = 0; if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0) From tim_one@users.sourceforge.net Fri Jun 15 21:50:44 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 15 Jun 2001 13:50:44 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0255.txt,1.3,1.4 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv29269/python/nondist/peps Modified Files: pep-0255.txt Log Message: Added pointer to the gen-branch of the CVS tree. Index: pep-0255.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0255.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -r1.3 -r1.4 *** pep-0255.txt 2001/06/14 16:06:02 1.3 --- pep-0255.txt 2001/06/15 20:50:42 1.4 *************** *** 250,256 **** Reference Implementation ! A preliminary patch against the CVS Python source is available[7]. Footnotes and References --- 250,260 ---- Reference Implementation ! A preliminary implementation is available as the gen-branch of the ! Python CVS tree on SourceForge[9]. Using this requires that you ! build Python from source. + This was derived from an earlier patch by Neil Schemenauer[7]. + Footnotes and References *************** *** 266,269 **** --- 270,275 ---- [7] http://python.ca/nas/python/generator.diff [8] http://python.sf.net/peps/pep-0236.html + [9] The reference implementation is on the gen-branch of Python CVS: + http://sf.net/cvs/?group_id=5470 From fdrake@users.sourceforge.net Fri Jun 15 22:32:00 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Fri, 15 Jun 2001 14:32:00 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/perl python.perl,1.101,1.102 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/perl In directory usw-pr-cvs1:/tmp/cvs-serv5388/perl Modified Files: python.perl Log Message: Implement the \verbatiminput LaTeX macro; this contains more magic than it should, but only enough that LaTeX2HTML doesn't bite us. Index: python.perl =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/perl/python.perl,v retrieving revision 1.101 retrieving revision 1.102 diff -C2 -r1.101 -r1.102 *** python.perl 2001/05/11 01:00:30 1.101 --- python.perl 2001/06/15 21:31:57 1.102 *************** *** 1661,1664 **** --- 1661,1710 ---- } + sub do_cmd_verbatiminput{ + local($_) = @_; + my $fname = next_argument(); + my $file; + my $found = 0; + my $texpath; + # Search TEXINPUTS for the input file, the way we're supposed to: + foreach $texpath (split /$envkey/, $TEXINPUTS) { + $file = "$texpath$dd$fname"; + last if ($found = (-f $file)); + } + my $text; + if ($found) { + open(MYFILE, "<$file") || die "\n$!\n"; + read(MYFILE, $text, 1024*1024); + close(MYFILE); + # + # These rewrites convert the raw text to something that will + # be properly visible as HTML and also will pass through the + # vagaries of conversion through LaTeX2HTML. The order in + # which the specific rewrites are performed is significant. + # + $text =~ s/\&/\&/g; + # These need to happen before the normal < and > re-writes, + # since we need to avoid LaTeX2HTML's attempt to perform + # ligature processing without regard to context (since it + # doesn't have font information). + $text =~ s/--/-&\#45;/g; + $text =~ s/<>/\>\&\#62;/g; + # Just normal re-writes... + $text =~ s//\>/g; + # These last isn't needed for the HTML, but is needed to get + # past LaTeX2HTML processing TeX macros. We use \ instead + # of / since many browsers don't support that. + $text =~ s/\\/\&\#92;/g; + } + else { + $text = 'Could not locate requested file $fname!\n'; + } + return ($alltt_start + . $text + . $alltt_end + . $_); + } 1; # This must be the last line From tim_one@users.sourceforge.net Fri Jun 15 22:37:17 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 15 Jun 2001 14:37:17 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0255.txt,1.4,1.5 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv6331/python/nondist/peps Modified Files: pep-0255.txt Log Message: Add branch-retrieval instructions, adapted from PEP 253. Index: pep-0255.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0255.txt,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -r1.4 -r1.5 *** pep-0255.txt 2001/06/15 20:50:42 1.4 --- pep-0255.txt 2001/06/15 21:37:15 1.5 *************** *** 270,275 **** [7] http://python.ca/nas/python/generator.diff [8] http://python.sf.net/peps/pep-0236.html ! [9] The reference implementation is on the gen-branch of Python CVS: ! http://sf.net/cvs/?group_id=5470 --- 270,279 ---- [7] http://python.ca/nas/python/generator.diff [8] http://python.sf.net/peps/pep-0236.html ! [9] To experiment with this implementation, proceed to check out ! Python from CVS according to the instructions at ! http://sf.net/cvs/?group_id=5470 ! but add the arguments "-r gen-branch" to the cvs checkout command. ! You can also start with an existing checkout and do ! cvs update -r gen-branch From tim_one@users.sourceforge.net Sat Jun 16 01:09:30 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 15 Jun 2001 17:09:30 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python ceval.c,2.246,2.247 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv32542/python/dist/src/Python Modified Files: ceval.c Log Message: SF bug 433228: repr(list) woes when len(list) big call_object: If the object isn't callable, display its type in the error msg rather than its repr. Bugfix candidate. Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.246 retrieving revision 2.247 diff -C2 -r2.246 -r2.247 *** ceval.c 2001/06/08 04:33:09 2.246 --- ceval.c 2001/06/16 00:09:28 2.247 *************** *** 2863,2868 **** result = (*call)(func, arg, kw); else { ! PyErr_Format(PyExc_TypeError, "object is not callable: %s", ! PyString_AS_STRING(PyObject_Repr(func))); return NULL; } --- 2863,2869 ---- result = (*call)(func, arg, kw); else { ! PyErr_Format(PyExc_TypeError, ! "object of type '%.100s' is not callable", ! func->ob_type->tp_name); return NULL; } From tim_one@users.sourceforge.net Sat Jun 16 06:11:19 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 15 Jun 2001 22:11:19 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include stringobject.h,2.27,2.28 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv12913/python/dist/src/Include Modified Files: stringobject.h Log Message: SF bug 433228: repr(list) woes when len(list) big. Gave Python linear-time repr() implementations for dicts, lists, strings. This means, e.g., that repr(range(50000)) is no longer 50x slower than pprint.pprint() in 2.2 . I don't consider this a bugfix candidate, as it's a performance boost. Added _PyString_Join() to the internal string API. If we want that in the public API, fine, but then it requires runtime error checks instead of asserts. Index: stringobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/stringobject.h,v retrieving revision 2.27 retrieving revision 2.28 diff -C2 -r2.27 -r2.28 *** stringobject.h 2001/05/24 16:56:35 2.27 --- stringobject.h 2001/06/16 05:11:17 2.28 *************** *** 78,81 **** --- 78,85 ---- #define PyString_GET_SIZE(op) (((PyStringObject *)(op))->ob_size) + /* _PyString_Join(sep, x) is like sep.join(x). sep must be PyStringObject*, + x must be an iterable object. */ + extern DL_IMPORT(PyObject *) _PyString_Join(PyObject *sep, PyObject *x); + /* --- Generic Codecs ----------------------------------------------------- */ From tim_one@users.sourceforge.net Sat Jun 16 06:11:20 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 15 Jun 2001 22:11:20 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.103,2.104 listobject.c,2.95,2.96 stringobject.c,2.118,2.119 tupleobject.c,2.52,2.53 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv12913/python/dist/src/Objects Modified Files: dictobject.c listobject.c stringobject.c tupleobject.c Log Message: SF bug 433228: repr(list) woes when len(list) big. Gave Python linear-time repr() implementations for dicts, lists, strings. This means, e.g., that repr(range(50000)) is no longer 50x slower than pprint.pprint() in 2.2 . I don't consider this a bugfix candidate, as it's a performance boost. Added _PyString_Join() to the internal string API. If we want that in the public API, fine, but then it requires runtime error checks instead of asserts. Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.103 retrieving revision 2.104 diff -C2 -r2.103 -r2.104 *** dictobject.c 2001/06/04 21:00:21 2.103 --- dictobject.c 2001/06/16 05:11:17 2.104 *************** *** 810,849 **** dict_repr(dictobject *mp) { ! auto PyObject *v; ! PyObject *sepa, *colon; ! register int i; ! register int any; ! i = Py_ReprEnter((PyObject*)mp); if (i != 0) { ! if (i > 0) ! return PyString_FromString("{...}"); ! return NULL; } ! v = PyString_FromString("{"); ! sepa = PyString_FromString(", "); colon = PyString_FromString(": "); ! any = 0; ! for (i = 0; i <= mp->ma_mask && v; i++) { ! dictentry *ep = mp->ma_table + i; ! PyObject *pvalue = ep->me_value; ! if (pvalue != NULL) { ! /* Prevent PyObject_Repr from deleting value during ! key format */ ! Py_INCREF(pvalue); ! if (any++) ! PyString_Concat(&v, sepa); ! PyString_ConcatAndDel(&v, PyObject_Repr(ep->me_key)); ! PyString_Concat(&v, colon); ! PyString_ConcatAndDel(&v, PyObject_Repr(pvalue)); ! Py_DECREF(pvalue); ! } } ! PyString_ConcatAndDel(&v, PyString_FromString("}")); ! Py_ReprLeave((PyObject*)mp); ! Py_XDECREF(sepa); Py_XDECREF(colon); ! return v; } --- 810,887 ---- dict_repr(dictobject *mp) { ! int i, pos; ! PyObject *s, *temp, *colon = NULL; ! PyObject *pieces = NULL, *result = NULL; ! PyObject *key, *value; ! i = Py_ReprEnter((PyObject *)mp); if (i != 0) { ! return i > 0 ? PyString_FromString("{...}") : NULL; } ! if (mp->ma_used == 0) { ! result = PyString_FromString("{}"); ! goto Done; ! } ! ! pieces = PyList_New(0); ! if (pieces == NULL) ! goto Done; ! colon = PyString_FromString(": "); ! if (colon == NULL) ! goto Done; ! ! /* Do repr() on each key+value pair, and insert ": " between them. ! Note that repr may mutate the dict. */ ! pos = 0; ! while (PyDict_Next((PyObject *)mp, &pos, &key, &value)) { ! int status; ! /* Prevent repr from deleting value during key format. */ ! Py_INCREF(value); ! s = PyObject_Repr(key); ! PyString_Concat(&s, colon); ! PyString_ConcatAndDel(&s, PyObject_Repr(value)); ! Py_DECREF(value); ! if (s == NULL) ! goto Done; ! status = PyList_Append(pieces, s); ! Py_DECREF(s); /* append created a new ref */ ! if (status < 0) ! goto Done; } ! ! /* Add "{}" decorations to the first and last items. */ ! assert(PyList_GET_SIZE(pieces) > 0); ! s = PyString_FromString("{"); ! if (s == NULL) ! goto Done; ! temp = PyList_GET_ITEM(pieces, 0); ! PyString_ConcatAndDel(&s, temp); ! PyList_SET_ITEM(pieces, 0, s); ! if (s == NULL) ! goto Done; ! ! s = PyString_FromString("}"); ! if (s == NULL) ! goto Done; ! temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1); ! PyString_ConcatAndDel(&temp, s); ! PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp); ! if (temp == NULL) ! goto Done; ! ! /* Paste them all together with ", " between. */ ! s = PyString_FromString(", "); ! if (s == NULL) ! goto Done; ! result = _PyString_Join(s, pieces); ! Py_DECREF(s); ! ! Done: ! Py_XDECREF(pieces); Py_XDECREF(colon); ! Py_ReprLeave((PyObject *)mp); ! return result; } Index: listobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v retrieving revision 2.95 retrieving revision 2.96 diff -C2 -r2.95 -r2.96 *** listobject.c 2001/05/26 19:37:54 2.95 --- listobject.c 2001/06/16 05:11:17 2.96 *************** *** 247,270 **** list_repr(PyListObject *v) { - PyObject *s, *comma; int i; i = Py_ReprEnter((PyObject*)v); if (i != 0) { ! if (i > 0) ! return PyString_FromString("[...]"); ! return NULL; } ! s = PyString_FromString("["); ! comma = PyString_FromString(", "); ! for (i = 0; i < v->ob_size && s != NULL; i++) { ! if (i > 0) ! PyString_Concat(&s, comma); ! PyString_ConcatAndDel(&s, PyObject_Repr(v->ob_item[i])); } ! Py_XDECREF(comma); ! PyString_ConcatAndDel(&s, PyString_FromString("]")); Py_ReprLeave((PyObject *)v); ! return s; } --- 247,312 ---- list_repr(PyListObject *v) { int i; + PyObject *s, *temp; + PyObject *pieces = NULL, *result = NULL; i = Py_ReprEnter((PyObject*)v); if (i != 0) { ! return i > 0 ? PyString_FromString("[...]") : NULL; } ! ! if (v->ob_size == 0) { ! result = PyString_FromString("[]"); ! goto Done; ! } ! ! pieces = PyList_New(0); ! if (pieces == NULL) ! goto Done; ! ! /* Do repr() on each element. Note that this may mutate the list, ! so must refetch the list size on each iteration. */ ! for (i = 0; i < v->ob_size; ++i) { ! int status; ! s = PyObject_Repr(v->ob_item[i]); ! if (s == NULL) ! goto Done; ! status = PyList_Append(pieces, s); ! Py_DECREF(s); /* append created a new ref */ ! if (status < 0) ! goto Done; } ! ! /* Add "[]" decorations to the first and last items. */ ! assert(PyList_GET_SIZE(pieces) > 0); ! s = PyString_FromString("["); ! if (s == NULL) ! goto Done; ! temp = PyList_GET_ITEM(pieces, 0); ! PyString_ConcatAndDel(&s, temp); ! PyList_SET_ITEM(pieces, 0, s); ! if (s == NULL) ! goto Done; ! ! s = PyString_FromString("]"); ! if (s == NULL) ! goto Done; ! temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1); ! PyString_ConcatAndDel(&temp, s); ! PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp); ! if (temp == NULL) ! goto Done; ! ! /* Paste them all together with ", " between. */ ! s = PyString_FromString(", "); ! if (s == NULL) ! goto Done; ! result = _PyString_Join(s, pieces); ! Py_DECREF(s); ! ! Done: ! Py_XDECREF(pieces); Py_ReprLeave((PyObject *)v); ! return result; } Index: stringobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v retrieving revision 2.118 retrieving revision 2.119 diff -C2 -r2.118 -r2.119 *** stringobject.c 2001/06/12 13:14:10 2.118 --- stringobject.c 2001/06/16 05:11:17 2.119 *************** *** 1032,1035 **** --- 1032,1052 ---- } + PyObject *_PyString_Join(PyObject *sep, PyObject *x) + { + PyObject* args; + PyObject* result = NULL; + + assert(sep != NULL && PyString_Check(sep)); + assert(x != NULL); + args = PyTuple_New(1); + if (args != NULL) { + Py_INCREF(x); + PyTuple_SET_ITEM(args, 0, x); + result = string_join((PyStringObject *)sep, args); + Py_DECREF(args); + } + return result; + } + static long string_find_internal(PyStringObject *self, PyObject *args, int dir) Index: tupleobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/tupleobject.c,v retrieving revision 2.52 retrieving revision 2.53 diff -C2 -r2.52 -r2.53 *** tupleobject.c 2001/05/29 07:58:45 2.52 --- tupleobject.c 2001/06/16 05:11:17 2.53 *************** *** 185,202 **** tuplerepr(PyTupleObject *v) { ! PyObject *s, *comma; ! int i; ! s = PyString_FromString("("); ! comma = PyString_FromString(", "); ! for (i = 0; i < v->ob_size && s != NULL; i++) { ! if (i > 0) ! PyString_Concat(&s, comma); ! PyString_ConcatAndDel(&s, PyObject_Repr(v->ob_item[i])); } ! Py_DECREF(comma); ! if (v->ob_size == 1) ! PyString_ConcatAndDel(&s, PyString_FromString(",")); ! PyString_ConcatAndDel(&s, PyString_FromString(")")); ! return s; } --- 185,238 ---- tuplerepr(PyTupleObject *v) { ! int i, n; ! PyObject *s, *temp; ! PyObject *pieces, *result = NULL; ! ! n = v->ob_size; ! if (n == 0) ! return PyString_FromString("()"); ! ! pieces = PyTuple_New(n); ! if (pieces == NULL) ! return NULL; ! ! /* Do repr() on each element. */ ! for (i = 0; i < n; ++i) { ! s = PyObject_Repr(v->ob_item[i]); ! if (s == NULL) ! goto Done; ! PyTuple_SET_ITEM(pieces, i, s); } ! ! /* Add "()" decorations to the first and last items. */ ! assert(n > 0); ! s = PyString_FromString("("); ! if (s == NULL) ! goto Done; ! temp = PyTuple_GET_ITEM(pieces, 0); ! PyString_ConcatAndDel(&s, temp); ! PyTuple_SET_ITEM(pieces, 0, s); ! if (s == NULL) ! goto Done; ! ! s = PyString_FromString(n == 1 ? ",)" : ")"); ! if (s == NULL) ! goto Done; ! temp = PyTuple_GET_ITEM(pieces, n-1); ! PyString_ConcatAndDel(&temp, s); ! PyTuple_SET_ITEM(pieces, n-1, temp); ! if (temp == NULL) ! goto Done; ! ! /* Paste them all together with ", " between. */ ! s = PyString_FromString(", "); ! if (s == NULL) ! goto Done; ! result = _PyString_Join(s, pieces); ! Py_DECREF(s); ! ! Done: ! Py_DECREF(pieces); ! return result; } From tim_one@users.sourceforge.net Sat Jun 16 06:42:59 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 15 Jun 2001 22:42:59 -0700 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.184,1.185 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv19395/python/dist/src/Misc Modified Files: NEWS Log Message: Reformat decl of new _PyString_Join. Add NEWS blurb about repr() speedup. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.184 retrieving revision 1.185 diff -C2 -r1.184 -r1.185 *** NEWS 2001/06/12 16:48:52 1.184 --- NEWS 2001/06/16 05:42:57 1.185 *************** *** 127,130 **** --- 127,133 ---- the nature of an effective cure (last December! better late than never). + - repr() is much faster for large containers (dict, list, tuple). + + Library From tim_one@users.sourceforge.net Sat Jun 16 06:42:59 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 15 Jun 2001 22:42:59 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects stringobject.c,2.119,2.120 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv19395/python/dist/src/Objects Modified Files: stringobject.c Log Message: Reformat decl of new _PyString_Join. Add NEWS blurb about repr() speedup. Index: stringobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v retrieving revision 2.119 retrieving revision 2.120 diff -C2 -r2.119 -r2.120 *** stringobject.c 2001/06/16 05:11:17 2.119 --- stringobject.c 2001/06/16 05:42:57 2.120 *************** *** 1032,1036 **** } ! PyObject *_PyString_Join(PyObject *sep, PyObject *x) { PyObject* args; --- 1032,1037 ---- } ! PyObject * ! _PyString_Join(PyObject *sep, PyObject *x) { PyObject* args; From tim_one@users.sourceforge.net Sat Jun 16 08:52:55 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 16 Jun 2001 00:52:55 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.104,2.105 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv9907/python/dist/src/Objects Modified Files: dictobject.c Log Message: dict_repr: Reuse one of the int vars (minor code simplification). Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.104 retrieving revision 2.105 diff -C2 -r2.104 -r2.105 *** dictobject.c 2001/06/16 05:11:17 2.104 --- dictobject.c 2001/06/16 07:52:53 2.105 *************** *** 810,814 **** dict_repr(dictobject *mp) { ! int i, pos; PyObject *s, *temp, *colon = NULL; PyObject *pieces = NULL, *result = NULL; --- 810,814 ---- dict_repr(dictobject *mp) { ! int i; PyObject *s, *temp, *colon = NULL; PyObject *pieces = NULL, *result = NULL; *************** *** 835,840 **** /* Do repr() on each key+value pair, and insert ": " between them. Note that repr may mutate the dict. */ ! pos = 0; ! while (PyDict_Next((PyObject *)mp, &pos, &key, &value)) { int status; /* Prevent repr from deleting value during key format. */ --- 835,840 ---- /* Do repr() on each key+value pair, and insert ": " between them. Note that repr may mutate the dict. */ ! i = 0; ! while (PyDict_Next((PyObject *)mp, &i, &key, &value)) { int status; /* Prevent repr from deleting value during key format. */ From tim_one@users.sourceforge.net Sat Jun 16 09:10:15 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 16 Jun 2001 01:10:15 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules _testcapimodule.c,1.7,1.8 testcapi_long.h,1.1,1.2 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv12541/python/dist/src/Modules Modified Files: _testcapimodule.c testcapi_long.h Log Message: Fix error in comment, and in test_long_api and test_longlong_api remove the need for the F_ERROR macro. Index: _testcapimodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_testcapimodule.c,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -r1.7 -r1.8 *** _testcapimodule.c 2001/06/14 01:11:03 1.7 --- _testcapimodule.c 2001/06/16 08:10:13 1.8 *************** *** 203,207 **** #define F_U_TO_PY PyLong_FromUnsignedLong #define F_PY_TO_U PyLong_AsUnsignedLong - #define F_ERROR raise_test_long_error #include "testcapi_long.h" --- 203,206 ---- *************** *** 213,217 **** return NULL; ! return TESTNAME(); } --- 212,216 ---- return NULL; ! return TESTNAME(raise_test_long_error); } *************** *** 222,226 **** #undef F_U_TO_PY #undef F_PY_TO_U - #undef F_ERROR #ifdef HAVE_LONG_LONG --- 221,224 ---- *************** *** 238,242 **** #define F_U_TO_PY PyLong_FromUnsignedLongLong #define F_PY_TO_U PyLong_AsUnsignedLongLong - #define F_ERROR raise_test_longlong_error #include "testcapi_long.h" --- 236,239 ---- *************** *** 248,252 **** return NULL; ! return TESTNAME(); } --- 245,249 ---- return NULL; ! return TESTNAME(raise_test_longlong_error); } *************** *** 257,261 **** #undef F_U_TO_PY #undef F_PY_TO_U - #undef F_ERROR #endif /* ifdef HAVE_LONG_LONG */ --- 254,257 ---- Index: testcapi_long.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/testcapi_long.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -r1.1 -r1.2 *** testcapi_long.h 2001/06/14 00:55:41 1.1 --- testcapi_long.h 2001/06/16 08:10:13 1.2 *************** *** 5,14 **** F_PY_TO_S convert pylong to signed; PyObject* -> TYPENAME F_U_TO_PY convert unsigned to pylong; unsigned TYPENAME -> PyObject* ! F_PY_TO_U convert pylong to unsigned; PyObject* -> TypeError ! F_ERROR error-report function; char* -> PyObject* (returns NULL) */ static PyObject * ! TESTNAME() { const int NBITS = sizeof(TYPENAME) * 8; --- 5,13 ---- F_PY_TO_S convert pylong to signed; PyObject* -> TYPENAME F_U_TO_PY convert unsigned to pylong; unsigned TYPENAME -> PyObject* ! F_PY_TO_U convert pylong to unsigned; PyObject* -> unsigned TYPENAME */ static PyObject * ! TESTNAME(PyObject *error(const char*)) { const int NBITS = sizeof(TYPENAME) * 8; *************** *** 46,58 **** pyresult = F_U_TO_PY(uin); if (pyresult == NULL) ! return F_ERROR( "unsigned unexpected null result"); uout = F_PY_TO_U(pyresult); if (uout == (unsigned TYPENAME)-1 && PyErr_Occurred()) ! return F_ERROR( "unsigned unexpected -1 result"); if (uout != uin) ! return F_ERROR( "unsigned output != input"); UNBIND(pyresult); --- 45,57 ---- pyresult = F_U_TO_PY(uin); if (pyresult == NULL) ! return error( "unsigned unexpected null result"); uout = F_PY_TO_U(pyresult); if (uout == (unsigned TYPENAME)-1 && PyErr_Occurred()) ! return error( "unsigned unexpected -1 result"); if (uout != uin) ! return error( "unsigned output != input"); UNBIND(pyresult); *************** *** 61,73 **** pyresult = F_S_TO_PY(in); if (pyresult == NULL) ! return F_ERROR( "signed unexpected null result"); out = F_PY_TO_S(pyresult); if (out == (TYPENAME)-1 && PyErr_Occurred()) ! return F_ERROR( "signed unexpected -1 result"); if (out != in) ! return F_ERROR( "signed output != input"); UNBIND(pyresult); --- 60,72 ---- pyresult = F_S_TO_PY(in); if (pyresult == NULL) ! return error( "signed unexpected null result"); out = F_PY_TO_S(pyresult); if (out == (TYPENAME)-1 && PyErr_Occurred()) ! return error( "signed unexpected -1 result"); if (out != in) ! return error( "signed output != input"); UNBIND(pyresult); *************** *** 86,90 **** one = PyLong_FromLong(1); if (one == NULL) ! return F_ERROR( "unexpected NULL from PyLong_FromLong"); --- 85,89 ---- one = PyLong_FromLong(1); if (one == NULL) ! return error( "unexpected NULL from PyLong_FromLong"); *************** *** 92,101 **** x = PyNumber_Negative(one); if (x == NULL) ! return F_ERROR( "unexpected NULL from PyNumber_Negative"); uout = F_PY_TO_U(x); if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) ! return F_ERROR( "PyLong_AsUnsignedXXX(-1) didn't complain"); PyErr_Clear(); --- 91,100 ---- x = PyNumber_Negative(one); if (x == NULL) ! return error( "unexpected NULL from PyNumber_Negative"); uout = F_PY_TO_U(x); if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) ! return error( "PyLong_AsUnsignedXXX(-1) didn't complain"); PyErr_Clear(); *************** *** 105,109 **** y = PyLong_FromLong((long)NBITS); if (y == NULL) ! return F_ERROR( "unexpected NULL from PyLong_FromLong"); --- 104,108 ---- y = PyLong_FromLong((long)NBITS); if (y == NULL) ! return error( "unexpected NULL from PyLong_FromLong"); *************** *** 111,120 **** UNBIND(y); if (x == NULL) ! return F_ERROR( "unexpected NULL from PyNumber_Lshift"); uout = F_PY_TO_U(x); if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) ! return F_ERROR( "PyLong_AsUnsignedXXX(2**NBITS) didn't " "complain"); --- 110,119 ---- UNBIND(y); if (x == NULL) ! return error( "unexpected NULL from PyNumber_Lshift"); uout = F_PY_TO_U(x); if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) ! return error( "PyLong_AsUnsignedXXX(2**NBITS) didn't " "complain"); *************** *** 126,135 **** UNBIND(x); if (y == NULL) ! return F_ERROR( "unexpected NULL from PyNumber_Rshift"); out = F_PY_TO_S(y); if (out != (TYPENAME)-1 || !PyErr_Occurred()) ! return F_ERROR( "PyLong_AsXXX(2**(NBITS-1)) didn't " "complain"); --- 125,134 ---- UNBIND(x); if (y == NULL) ! return error( "unexpected NULL from PyNumber_Rshift"); out = F_PY_TO_S(y); if (out != (TYPENAME)-1 || !PyErr_Occurred()) ! return error( "PyLong_AsXXX(2**(NBITS-1)) didn't " "complain"); *************** *** 141,145 **** UNBIND(y); if (x == NULL) ! return F_ERROR( "unexpected NULL from PyNumber_Negative"); --- 140,144 ---- UNBIND(y); if (x == NULL) ! return error( "unexpected NULL from PyNumber_Negative"); *************** *** 147,156 **** UNBIND(x); if (y == NULL) ! return F_ERROR( "unexpected NULL from PyNumber_Subtract"); out = F_PY_TO_S(y); if (out != (TYPENAME)-1 || !PyErr_Occurred()) ! return F_ERROR( "PyLong_AsXXX(-2**(NBITS-1)-1) didn't " "complain"); --- 146,155 ---- UNBIND(x); if (y == NULL) ! return error( "unexpected NULL from PyNumber_Subtract"); out = F_PY_TO_S(y); if (out != (TYPENAME)-1 || !PyErr_Occurred()) ! return error( "PyLong_AsXXX(-2**(NBITS-1)-1) didn't " "complain"); From loewis@users.sourceforge.net Sat Jun 16 09:14:06 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sat, 16 Jun 2001 01:14:06 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libfnmatch.tex,1.18,1.19 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv13074 Modified Files: libfnmatch.tex Log Message: Document that filter is added in 2.2. Index: libfnmatch.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libfnmatch.tex,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -r1.18 -r1.19 *** libfnmatch.tex 2001/06/07 19:01:24 1.18 --- libfnmatch.tex 2001/06/16 08:14:04 1.19 *************** *** 48,51 **** --- 48,52 ---- It is the same as \code{[n for n in names if fnmatch(n, pattern)]}, but implemented more efficiently. + \versionadded{2.2} \end{funcdesc} From tim_one@users.sourceforge.net Sat Jun 16 09:48:42 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 16 Jun 2001 01:48:42 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.82,1.83 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv17494/python/dist/src/Objects Modified Files: longobject.c Log Message: PyLong_{As, From}VoidPtr: cleanup, replacing assumptions in comments with #if/#error constructs. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.82 retrieving revision 1.83 diff -C2 -r1.82 -r1.83 *** longobject.c 2001/06/14 18:42:50 1.82 --- longobject.c 2001/06/16 08:48:40 1.83 *************** *** 509,524 **** PyLong_FromVoidPtr(void *p) { ! #if SIZEOF_VOID_P == SIZEOF_LONG return PyInt_FromLong((long)p); #else /* optimize null pointers */ ! if ( p == NULL ) return PyInt_FromLong(0); - - /* we can assume that HAVE_LONG_LONG is true. if not, then the - configuration process should have bailed (having big pointers - without long longs seems non-sensical) */ return PyLong_FromLongLong((LONG_LONG)p); ! #endif /* SIZEOF_VOID_P == SIZEOF_LONG */ } --- 509,528 ---- PyLong_FromVoidPtr(void *p) { ! #if SIZEOF_VOID_P <= SIZEOF_LONG return PyInt_FromLong((long)p); #else + + #ifndef HAVE_LONG_LONG + # error "PyLong_FromVoidPtr: sizeof(void*) > sizeof(long), but no long long" + #endif + #if SIZEOF_LONG_LONG < SIZEOF_VOID_P + # error "PyLong_FromVoidPtr: sizeof(LONG_LONG) < sizeof(void*)" + #endif /* optimize null pointers */ ! if (p == NULL) return PyInt_FromLong(0); return PyLong_FromLongLong((LONG_LONG)p); ! ! #endif /* SIZEOF_VOID_P <= SIZEOF_LONG */ } *************** *** 532,554 **** PyExc_SystemError, "bad argument to internal function" */ ! ! #if SIZEOF_VOID_P == SIZEOF_LONG long x; ! if ( PyInt_Check(vv) ) x = PyInt_AS_LONG(vv); else x = PyLong_AsLong(vv); #else ! /* we can assume that HAVE_LONG_LONG is true. if not, then the ! configuration process should have bailed (having big pointers ! without long longs seems non-sensical) */ LONG_LONG x; ! if ( PyInt_Check(vv) ) x = PyInt_AS_LONG(vv); else x = PyLong_AsLongLong(vv); ! #endif /* SIZEOF_VOID_P == SIZEOF_LONG */ if (x == -1 && PyErr_Occurred()) --- 536,562 ---- PyExc_SystemError, "bad argument to internal function" */ ! #if SIZEOF_VOID_P <= SIZEOF_LONG long x; ! if (PyInt_Check(vv)) x = PyInt_AS_LONG(vv); else x = PyLong_AsLong(vv); #else ! ! #ifndef HAVE_LONG_LONG ! # error "PyLong_AsVoidPtr: sizeof(void*) > sizeof(long), but no long long" ! #endif ! #if SIZEOF_LONG_LONG < SIZEOF_VOID_P ! # error "PyLong_AsVoidPtr: sizeof(LONG_LONG) < sizeof(void*)" ! #endif LONG_LONG x; ! if (PyInt_Check(vv)) x = PyInt_AS_LONG(vv); else x = PyLong_AsLongLong(vv); ! ! #endif /* SIZEOF_VOID_P <= SIZEOF_LONG */ if (x == -1 && PyErr_Occurred()) From gvanrossum@users.sourceforge.net Sat Jun 16 14:59:50 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 16 Jun 2001 06:59:50 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include object.h,2.79.2.13,2.79.2.14 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv30033/Include Modified Files: Tag: descr-branch object.h Log Message: Rename the *other* tp_alloc to tp_allocs. Index: object.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/object.h,v retrieving revision 2.79.2.13 retrieving revision 2.79.2.14 diff -C2 -r2.79.2.13 -r2.79.2.14 *** object.h 2001/06/07 18:31:55 2.79.2.13 --- object.h 2001/06/16 13:59:48 2.79.2.14 *************** *** 278,282 **** #ifdef COUNT_ALLOCS /* these must be last and never explicitly initialized */ ! int tp_alloc; int tp_free; int tp_maxalloc; --- 278,282 ---- #ifdef COUNT_ALLOCS /* these must be last and never explicitly initialized */ ! int tp_allocs; int tp_free; int tp_maxalloc; From gvanrossum@users.sourceforge.net Sat Jun 16 14:59:50 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 16 Jun 2001 06:59:50 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects classobject.c,2.127.2.4,2.127.2.5 object.c,2.124.4.13,2.124.4.14 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv30033/Objects Modified Files: Tag: descr-branch classobject.c object.c Log Message: Rename the *other* tp_alloc to tp_allocs. Index: classobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/classobject.c,v retrieving revision 2.127.2.4 retrieving revision 2.127.2.5 diff -C2 -r2.127.2.4 -r2.127.2.5 *** classobject.c 2001/06/05 12:45:46 2.127.2.4 --- classobject.c 2001/06/16 13:59:48 2.127.2.5 *************** *** 560,564 **** * _Py_RefTotal was also boosted; we'll knock that down later. */ ! inst->ob_type->tp_alloc--; #endif #else /* !Py_TRACE_REFS */ --- 560,564 ---- * _Py_RefTotal was also boosted; we'll knock that down later. */ ! inst->ob_type->tp_allocs--; #endif #else /* !Py_TRACE_REFS */ Index: object.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v retrieving revision 2.124.4.13 retrieving revision 2.124.4.14 diff -C2 -r2.124.4.13 -r2.124.4.14 *** object.c 2001/06/07 18:31:55 2.124.4.13 --- object.c 2001/06/16 13:59:48 2.124.4.14 *************** *** 33,37 **** for (tp = type_list; tp; tp = tp->tp_next) fprintf(stderr, "%s alloc'd: %d, freed: %d, max in use: %d\n", ! tp->tp_name, tp->tp_alloc, tp->tp_free, tp->tp_maxalloc); fprintf(stderr, "fast tuple allocs: %d, empty: %d\n", --- 33,37 ---- for (tp = type_list; tp; tp = tp->tp_next) fprintf(stderr, "%s alloc'd: %d, freed: %d, max in use: %d\n", ! tp->tp_name, tp->tp_allocs, tp->tp_free, tp->tp_maxalloc); fprintf(stderr, "fast tuple allocs: %d, empty: %d\n", *************** *** 54,58 **** return NULL; for (tp = type_list; tp; tp = tp->tp_next) { ! v = Py_BuildValue("(siii)", tp->tp_name, tp->tp_alloc, tp->tp_free, tp->tp_maxalloc); if (v == NULL) { --- 54,58 ---- return NULL; for (tp = type_list; tp; tp = tp->tp_next) { ! v = Py_BuildValue("(siii)", tp->tp_name, tp->tp_allocs, tp->tp_free, tp->tp_maxalloc); if (v == NULL) { *************** *** 73,77 **** inc_count(PyTypeObject *tp) { ! if (tp->tp_alloc == 0) { /* first time; insert in linked list */ if (tp->tp_next != NULL) /* sanity check */ --- 73,77 ---- inc_count(PyTypeObject *tp) { ! if (tp->tp_allocs == 0) { /* first time; insert in linked list */ if (tp->tp_next != NULL) /* sanity check */ *************** *** 80,86 **** type_list = tp; } ! tp->tp_alloc++; ! if (tp->tp_alloc - tp->tp_free > tp->tp_maxalloc) ! tp->tp_maxalloc = tp->tp_alloc - tp->tp_free; } #endif --- 80,86 ---- type_list = tp; } ! tp->tp_allocs++; ! if (tp->tp_allocs - tp->tp_free > tp->tp_maxalloc) ! tp->tp_maxalloc = tp->tp_allocs - tp->tp_free; } #endif From gvanrossum@users.sourceforge.net Sat Jun 16 15:34:15 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 16 Jun 2001 07:34:15 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules cPickle.c,2.59,2.59.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv8861 Modified Files: Tag: descr-branch cPickle.c Log Message: Make type objects picklable. They are pickled as globals. This isn't always right, but works for the important cases. Index: cPickle.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/cPickle.c,v retrieving revision 2.59 retrieving revision 2.59.4.1 diff -C2 -r2.59 -r2.59.4.1 *** cPickle.c 2001/04/10 04:35:28 2.59 --- cPickle.c 2001/06/16 14:34:13 2.59.4.1 *************** *** 1872,1875 **** --- 1872,1879 ---- goto finally; } + if (type == &PyType_Type) { + res = save_global(self, args, NULL); + goto finally; + } break; From gvanrossum@users.sourceforge.net Sat Jun 16 15:34:34 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 16 Jun 2001 07:34:34 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib pickle.py,1.48,1.48.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv9095 Modified Files: Tag: descr-branch pickle.py Log Message: Make type objects picklable. They are pickled as globals. This isn't always right, but works for the important cases. Index: pickle.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pickle.py,v retrieving revision 1.48 retrieving revision 1.48.4.1 diff -C2 -r1.48 -r1.48.4.1 *** pickle.py 2001/04/10 05:02:52 1.48 --- pickle.py 2001/06/16 14:34:32 1.48.4.1 *************** *** 505,508 **** --- 505,509 ---- dispatch[FunctionType] = save_global dispatch[BuiltinFunctionType] = save_global + dispatch[TypeType] = save_global From gvanrossum@users.sourceforge.net Sat Jun 16 15:38:39 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 16 Jun 2001 07:38:39 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects stringobject.c,2.103.2.5,2.103.2.6 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv10364 Modified Files: Tag: descr-branch stringobject.c Log Message: Change the name of the string type from string to str, so that it doesn't lie (since it's __builtin__.str now). This breaks my heart, and maybe I'll think of a better solution later, but for now, this is the best I can think of to make built-in types picklable. Types should be smarter about when to return __builtin__ as their module name, but that's a separate story. Index: stringobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v retrieving revision 2.103.2.5 retrieving revision 2.103.2.6 diff -C2 -r2.103.2.5 -r2.103.2.6 *** stringobject.c 2001/06/14 01:01:16 2.103.2.5 --- stringobject.c 2001/06/16 14:38:37 2.103.2.6 *************** *** 2381,2385 **** PyObject_HEAD_INIT(&PyType_Type) 0, ! "string", sizeof(PyStringObject), sizeof(char), --- 2381,2385 ---- PyObject_HEAD_INIT(&PyType_Type) 0, ! "str", sizeof(PyStringObject), sizeof(char), From gvanrossum@users.sourceforge.net Sat Jun 16 15:41:42 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 16 Jun 2001 07:41:42 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include object.h,2.79.2.14,2.79.2.15 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv11001/Include Modified Files: Tag: descr-branch object.h Log Message: I think I've got the right solution for tp_alloc: it's a lower-level function that really should only allocate the memory and initialize the type and refcount. The new signature gets the number of items (in case it's a VarObject). The smarts have to be put in tp_new(). Thies does away wih my fear that tp_alloc() and tp_new() would have to be merged -- they are both needed. Index: object.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/object.h,v retrieving revision 2.79.2.14 retrieving revision 2.79.2.15 diff -C2 -r2.79.2.14 -r2.79.2.15 *** object.h 2001/06/16 13:59:48 2.79.2.14 --- object.h 2001/06/16 14:41:40 2.79.2.15 *************** *** 206,210 **** typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *); typedef int (*initproc)(PyObject *, PyObject *, PyObject *); ! typedef PyObject *(*allocfunc)(struct _typeobject *, PyObject *, PyObject *); typedef struct _typeobject { --- 206,211 ---- typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *); typedef int (*initproc)(PyObject *, PyObject *, PyObject *); ! typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *); ! typedef PyObject *(*allocfunc)(struct _typeobject *, int); typedef struct _typeobject { *************** *** 271,275 **** initproc tp_init; allocfunc tp_alloc; ! allocfunc tp_new; PyObject *tp_bases; PyObject *tp_mro; /* method resolution order */ --- 272,276 ---- initproc tp_init; allocfunc tp_alloc; ! newfunc tp_new; PyObject *tp_bases; PyObject *tp_mro; /* method resolution order */ *************** *** 297,302 **** extern DL_IMPORT(int) PyType_InitDict(PyTypeObject *); ! extern DL_IMPORT(PyObject *) PyType_GenericAlloc(PyTypeObject *, ! PyObject *, PyObject *); extern DL_IMPORT(PyObject *) PyType_GenericNew(PyTypeObject *, PyObject *, PyObject *); --- 298,302 ---- extern DL_IMPORT(int) PyType_InitDict(PyTypeObject *); ! extern DL_IMPORT(PyObject *) PyType_GenericAlloc(PyTypeObject *, int); extern DL_IMPORT(PyObject *) PyType_GenericNew(PyTypeObject *, PyObject *, PyObject *); From gvanrossum@users.sourceforge.net Sat Jun 16 15:41:42 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 16 Jun 2001 07:41:42 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.40,2.16.8.41 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv11001/Objects Modified Files: Tag: descr-branch typeobject.c Log Message: I think I've got the right solution for tp_alloc: it's a lower-level function that really should only allocate the memory and initialize the type and refcount. The new signature gets the number of items (in case it's a VarObject). The smarts have to be put in tp_new(). Thies does away wih my fear that tp_alloc() and tp_new() would have to be merged -- they are both needed. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.40 retrieving revision 2.16.8.41 diff -C2 -r2.16.8.40 -r2.16.8.41 *** typeobject.c 2001/06/14 14:13:46 2.16.8.40 --- typeobject.c 2001/06/16 14:41:40 2.16.8.41 *************** *** 78,82 **** PyObject * ! PyType_GenericAlloc(PyTypeObject *type, PyObject *args, PyObject *kwds) { int size; --- 78,82 ---- PyObject * ! PyType_GenericAlloc(PyTypeObject *type, int nitems) { int size; *************** *** 85,89 **** /* Inline PyObject_New() so we can zero the memory */ ! size = _PyObject_SIZE(type); mem = PyObject_MALLOC(size); if (mem == NULL) --- 85,89 ---- /* Inline PyObject_New() so we can zero the memory */ ! size = _PyObject_VAR_SIZE(type, nitems); mem = PyObject_MALLOC(size); if (mem == NULL) *************** *** 96,100 **** if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) Py_INCREF(type); ! PyObject_INIT(obj, type); if (PyType_IS_GC(type)) PyObject_GC_Init(obj); --- 96,103 ---- if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) Py_INCREF(type); ! if (type->tp_itemsize == 0) ! PyObject_INIT(obj, type); ! else ! (void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems); if (PyType_IS_GC(type)) PyObject_GC_Init(obj); *************** *** 107,111 **** PyObject *self; ! self = type->tp_alloc(type, args, kwds); if (self == NULL) return NULL; --- 110,114 ---- PyObject *self; ! self = type->tp_alloc(type, 0); if (self == NULL) return NULL; *************** *** 527,541 **** static PyObject * ! type_alloc(PyTypeObject *metatype, PyObject *args, PyObject *kwds) { PyTypeObject *type; - PyObject *name, *bases, *dict; - static char *kwlist[] = {"name", "bases", "dict", 0}; ! /* Check arguments (again?!?! yes, alas -- we need the dict!) */ ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO:type", kwlist, ! &name, &bases, &dict)) ! return NULL; ! type = (PyTypeObject *)PyType_GenericAlloc(metatype, args, kwds); if (type != NULL) type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE; --- 530,538 ---- static PyObject * ! type_alloc(PyTypeObject *metatype, int nitems) { PyTypeObject *type; ! type = (PyTypeObject *)PyType_GenericAlloc(metatype, nitems); if (type != NULL) type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE; From fdrake@users.sourceforge.net Sat Jun 16 21:46:12 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Sat, 16 Jun 2001 13:46:12 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules termios.c,2.24.2.4,2.24.2.5 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv16654/Modules Modified Files: Tag: release21-maint termios.c Log Message: Spell "#ifdef" as "#ifdef", not "#endif". Index: termios.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/termios.c,v retrieving revision 2.24.2.4 retrieving revision 2.24.2.5 diff -C2 -r2.24.2.4 -r2.24.2.5 *** termios.c 2001/06/15 11:58:49 2.24.2.4 --- termios.c 2001/06/16 20:46:10 2.24.2.5 *************** *** 517,521 **** {"ECHOKE", ECHOKE}, #endif ! #endif FLUSHO {"FLUSHO", FLUSHO}, #endif --- 517,521 ---- {"ECHOKE", ECHOKE}, #endif ! #ifndef FLUSHO {"FLUSHO", FLUSHO}, #endif From fdrake@users.sourceforge.net Sat Jun 16 22:02:33 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Sat, 16 Jun 2001 14:02:33 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python ceval.c,2.247,2.248 sysmodule.c,2.85,2.86 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv19114 Modified Files: ceval.c sysmodule.c Log Message: Instead of initializing & interning the strings passed to the profile and trace functions lazily, which incurs extra argument pushing and checks in the C overhead for profiling/tracing, create the strings semi-lazily when the Python code first registers a profile or trace function. This simplifies the trampoline into the profile/trace functions. Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.247 retrieving revision 2.248 diff -C2 -r2.247 -r2.248 *** ceval.c 2001/06/16 00:09:28 2.247 --- ceval.c 2001/06/16 21:02:31 2.248 *************** *** 63,67 **** static void call_exc_trace(PyObject **, PyObject**, PyFrameObject *); static int call_trace(PyObject **, PyObject **, ! PyFrameObject *, char *, PyObject **, PyObject *); static PyObject *loop_subscript(PyObject *, PyObject *); static PyObject *apply_slice(PyObject *, PyObject *, PyObject *); --- 63,67 ---- static void call_exc_trace(PyObject **, PyObject**, PyFrameObject *); static int call_trace(PyObject **, PyObject **, ! PyFrameObject *, PyObject *, PyObject *); static PyObject *loop_subscript(PyObject *, PyObject *); static PyObject *apply_slice(PyObject *, PyObject *, PyObject *); *************** *** 655,659 **** is detected. */ if (call_trace(&tstate->sys_tracefunc, ! &f->f_trace, f, "call", &str_call, Py_None/*XXX how to compute arguments now?*/)) { /* Trace function raised an error */ --- 655,659 ---- is detected. */ if (call_trace(&tstate->sys_tracefunc, ! &f->f_trace, f, str_call, Py_None/*XXX how to compute arguments now?*/)) { /* Trace function raised an error */ *************** *** 666,670 **** itself and isn't called for "line" events */ if (call_trace(&tstate->sys_profilefunc, ! (PyObject**)0, f, "call", &str_call, Py_None/*XXX*/)) { goto fail; --- 666,670 ---- itself and isn't called for "line" events */ if (call_trace(&tstate->sys_profilefunc, ! (PyObject**)0, f, str_call, Py_None/*XXX*/)) { goto fail; *************** *** 1962,1966 **** f->f_lasti = INSTR_OFFSET(); err = call_trace(&f->f_trace, &f->f_trace, ! f, "line", &str_line, Py_None); break; --- 1962,1966 ---- f->f_lasti = INSTR_OFFSET(); err = call_trace(&f->f_trace, &f->f_trace, ! f, str_line, Py_None); break; *************** *** 2307,2311 **** if (why == WHY_RETURN) { if (call_trace(&f->f_trace, &f->f_trace, f, ! "return", &str_return, retval)) { Py_XDECREF(retval); retval = NULL; --- 2307,2311 ---- if (why == WHY_RETURN) { if (call_trace(&f->f_trace, &f->f_trace, f, ! str_return, retval)) { Py_XDECREF(retval); retval = NULL; *************** *** 2317,2321 **** if (tstate->sys_profilefunc && why == WHY_RETURN) { if (call_trace(&tstate->sys_profilefunc, (PyObject**)0, ! f, "return", &str_return, retval)) { Py_XDECREF(retval); retval = NULL; --- 2317,2321 ---- if (tstate->sys_profilefunc && why == WHY_RETURN) { if (call_trace(&tstate->sys_profilefunc, (PyObject**)0, ! f, str_return, retval)) { Py_XDECREF(retval); retval = NULL; *************** *** 2585,2590 **** return; } ! err = call_trace(p_trace, p_newtrace, f, ! "exception", &str_exception, arg); Py_DECREF(arg); if (err == 0) --- 2585,2589 ---- return; } ! err = call_trace(p_trace, p_newtrace, f, str_exception, arg); Py_DECREF(arg); if (err == 0) *************** *** 2602,2617 **** may point to NULL variable; may be same variable as p_newtrace ! PyObject **p_omsg: in/out; may not be NULL; ! if non-null & *p_omsg == NULL, will be ! initialized with an interned string ! corresponding to msg. */ static int call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, ! char *msg, PyObject **p_omsg, PyObject *arg) { PyThreadState *tstate = f->f_tstate; ! PyObject *args, *what; PyObject *res = NULL; --- 2601,2613 ---- may point to NULL variable; may be same variable as p_newtrace ! PyObject *msg: in; must not be NULL */ static int call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, ! PyObject *msg, PyObject *arg) { PyThreadState *tstate = f->f_tstate; ! PyObject *args; PyObject *res = NULL; *************** *** 2628,2645 **** if (args == NULL) goto cleanup; ! if (*p_omsg != NULL) { ! what = *p_omsg; ! Py_INCREF(what); ! } ! else { ! what = PyString_InternFromString(msg); ! if (what == NULL) ! goto cleanup; ! *p_omsg = what; ! Py_INCREF(what); ! } Py_INCREF(f); PyTuple_SET_ITEM(args, 0, (PyObject *)f); ! PyTuple_SET_ITEM(args, 1, what); if (arg == NULL) arg = Py_None; --- 2624,2631 ---- if (args == NULL) goto cleanup; ! Py_INCREF(msg); Py_INCREF(f); PyTuple_SET_ITEM(args, 0, (PyObject *)f); ! PyTuple_SET_ITEM(args, 1, msg); if (arg == NULL) arg = Py_None; *************** *** 2686,2689 **** --- 2672,2705 ---- } } + + /* Initialize the strings that get passed to the profile and trace functions; + * this avoids doing this while we're actually profiling/tracing. + */ + int + _PyTrace_Init(void) + { + if (str_call == NULL) { + str_call = PyString_InternFromString("call"); + if (str_call == NULL) + return -1; + } + if (str_exception == NULL) { + str_exception = PyString_InternFromString("exception"); + if (str_exception == NULL) + return -1; + } + if (str_line == NULL) { + str_line = PyString_InternFromString("line"); + if (str_line == NULL) + return -1; + } + if (str_return == NULL) { + str_return = PyString_InternFromString("return"); + if (str_return == NULL) + return -1; + } + return 0; + } + PyObject * Index: sysmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/sysmodule.c,v retrieving revision 2.85 retrieving revision 2.86 diff -C2 -r2.85 -r2.86 *** sysmodule.c 2001/04/10 22:07:43 2.85 --- sysmodule.c 2001/06/16 21:02:31 2.86 *************** *** 197,204 **** --- 197,208 ---- Set the current default string encoding used by the Unicode implementation."; + extern int _PyTrace_Init(void); + static PyObject * sys_settrace(PyObject *self, PyObject *args) { PyThreadState *tstate = PyThreadState_Get(); + if (_PyTrace_Init() == -1) + return NULL; if (args == Py_None) args = NULL; *************** *** 221,224 **** --- 225,230 ---- { PyThreadState *tstate = PyThreadState_Get(); + if (_PyTrace_Init() == -1) + return NULL; if (args == Py_None) args = NULL; From loewis@users.sourceforge.net Sun Jun 17 08:05:45 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 17 Jun 2001 00:05:45 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/xml/sax expatreader.py,1.22,1.23 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/xml/sax In directory usw-pr-cvs1:/tmp/cvs-serv27805 Modified Files: expatreader.py Log Message: Synchronize with 1.13 of PyXML: Allow application to set a new content handler and lex_prop handler during parsing. Closes bug #433761. Small hack to make expat be ignored in Jython. Index: expatreader.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/xml/sax/expatreader.py,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -r1.22 -r1.23 *** expatreader.py 2001/01/27 09:01:20 1.22 --- expatreader.py 2001/06/17 07:05:43 1.23 *************** *** 7,10 **** --- 7,17 ---- from xml.sax._exceptions import * + + # xml.parsers.expat does not raise ImportError in Jython + import sys + if sys.platform[ : 4] == "java": + raise SAXReaderNotAvailable("expat not available in Java", None) + del sys + try: from xml.parsers import expat *************** *** 47,50 **** --- 54,64 ---- self._parser.SetBase(source.getSystemId()) + # Redefined setContentHandle to allow changing handlers during parsing + + def setContentHandler(self, handler): + xmlreader.IncrementalParser.setContentHandler(self, handler) + if self._parsing: + self._reset_cont_handler() + def getFeature(self, name): if name == handler.feature_namespaces: *************** *** 69,72 **** --- 83,88 ---- if name == handler.property_lexical_handler: self._lex_handler_prop = value + if self._parsing: + self._reset_lex_handler_prop() else: raise SAXNotRecognizedException("Property '%s' not recognized" % name) *************** *** 102,105 **** --- 118,131 ---- self._parser = None + def _reset_cont_handler(self): + self._parser.ProcessingInstructionHandler = \ + self._cont_handler.processingInstruction + self._parser.CharacterDataHandler = self._cont_handler.characters + + def _reset_lex_handler_prop(self): + self._parser.CommentHandler = self._lex_handler_prop.comment + self._parser.StartCdataSectionHandler = self._lex_handler_prop.startCDATA + self._parser.EndCdataSectionHandler = self._lex_handler_prop.endCDATA + def reset(self): if self._namespaces: *************** *** 112,118 **** self._parser.EndElementHandler = self.end_element ! self._parser.ProcessingInstructionHandler = \ ! self._cont_handler.processingInstruction ! self._parser.CharacterDataHandler = self._cont_handler.characters self._parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl self._parser.NotationDeclHandler = self.notation_decl --- 138,142 ---- self._parser.EndElementHandler = self.end_element ! self._reset_cont_handler() self._parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl self._parser.NotationDeclHandler = self.notation_decl *************** *** 122,128 **** self._decl_handler_prop = None if self._lex_handler_prop: ! self._parser.CommentHandler = self._lex_handler_prop.comment ! self._parser.StartCdataSectionHandler = self._lex_handler_prop.startCDATA ! self._parser.EndCdataSectionHandler = self._lex_handler_prop.endCDATA # self._parser.DefaultHandler = # self._parser.DefaultHandlerExpand = --- 146,150 ---- self._decl_handler_prop = None if self._lex_handler_prop: ! self._reset_lex_handler_prop() # self._parser.DefaultHandler = # self._parser.DefaultHandlerExpand = From gvanrossum@users.sourceforge.net Sun Jun 17 14:31:28 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 17 Jun 2001 06:31:28 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib imaplib.py,1.27,1.28 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv31273 Modified Files: imaplib.py Log Message: SF patch #433619, by Michel Pelletier: Summary: NAMESPACE support in imaplib.py Initial Comment: Support for the IMAP NAMESPACE extension defined in rfc 2342. This is almost a necessity for working with modern IMAP servers. Index: imaplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/imaplib.py,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -r1.27 -r1.28 *** imaplib.py 2001/02/22 13:24:27 1.27 --- imaplib.py 2001/06/17 13:31:25 1.28 *************** *** 59,62 **** --- 59,63 ---- 'UID': ('SELECTED',), 'UNSUBSCRIBE': ('AUTH', 'SELECTED'), + 'NAMESPACE': ('AUTH', 'SELECTED'), } *************** *** 572,575 **** --- 573,582 ---- return apply(self._simple_command, (name,) + args) + def namespace(self): + """ Returns IMAP namespaces ala rfc2342 + """ + name = 'NAMESPACE' + typ, dat = self._simple_command(name) + return self._untagged_response(typ, dat, name) From lemburg@users.sourceforge.net Sun Jun 17 19:32:38 2001 From: lemburg@users.sourceforge.net (M.-A. Lemburg) Date: Sun, 17 Jun 2001 11:32:38 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules _codecsmodule.c,2.6,2.7 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv17705 Modified Files: _codecsmodule.c Log Message: Fix for bug [ #433047 ] missing args to PyArg_ParseTuple Index: _codecsmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_codecsmodule.c,v retrieving revision 2.6 retrieving revision 2.7 diff -C2 -r2.6 -r2.7 *** _codecsmodule.c 2000/09/21 21:09:45 2.6 --- _codecsmodule.c 2001/06/17 18:32:36 2.7 *************** *** 441,445 **** const char *errors = NULL; ! if (!PyArg_ParseTuple(args, "O|zi:utf_16_le_encode", &str, &errors)) return NULL; --- 441,445 ---- const char *errors = NULL; ! if (!PyArg_ParseTuple(args, "O|z:utf_16_le_encode", &str, &errors)) return NULL; *************** *** 464,468 **** const char *errors = NULL; ! if (!PyArg_ParseTuple(args, "O|zi:utf_16_be_encode", &str, &errors)) return NULL; --- 464,468 ---- const char *errors = NULL; ! if (!PyArg_ParseTuple(args, "O|z:utf_16_be_encode", &str, &errors)) return NULL; From tim_one@users.sourceforge.net Sun Jun 17 22:57:19 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 17 Jun 2001 14:57:19 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/tut tut.tex,1.139,1.140 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tut In directory usw-pr-cvs1:/tmp/cvs-serv17843/python/dist/src/Doc/tut Modified Files: tut.tex Log Message: Clarification in the fp appendix suggested on c.l.py by Michael Chermside. Also replaced a *star* style emphasis in the Representation Error section with an \emph{} thingie. Index: tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.139 retrieving revision 1.140 diff -C2 -r1.139 -r1.140 *** tut.tex 2001/06/08 17:09:01 1.139 --- tut.tex 2001/06/17 21:57:17 1.140 *************** *** 4181,4185 **** not a bug in Python, it is not a bug in your code either, and you'll see the same kind of thing in all languages that support your ! hardware's floating-point arithmetic. Python's builtin \function{str()} function produces only 12 --- 4181,4186 ---- not a bug in Python, it is not a bug in your code either, and you'll see the same kind of thing in all languages that support your ! hardware's floating-point arithmetic (although some languages may ! not \emph{display} the difference by default, or in all output modes). Python's builtin \function{str()} function produces only 12 *************** *** 4327,4331 **** Note that since we rounded up, this is actually a little bit larger than 1/10; if we had not rounded up, the quotient would have been a little ! bit smaller than 1/10. But in no case can it be *exactly* 1/10! So the computer never ``sees'' 1/10: what it sees is the exact --- 4328,4332 ---- Note that since we rounded up, this is actually a little bit larger than 1/10; if we had not rounded up, the quotient would have been a little ! bit smaller than 1/10. But in no case can it be \emph{exactly} 1/10! So the computer never ``sees'' 1/10: what it sees is the exact From tim_one@users.sourceforge.net Sun Jun 17 22:57:19 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 17 Jun 2001 14:57:19 -0700 Subject: [Python-checkins] CVS: python/dist/src/Misc ACKS,1.97,1.98 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv17843/python/dist/src/Misc Modified Files: ACKS Log Message: Clarification in the fp appendix suggested on c.l.py by Michael Chermside. Also replaced a *star* style emphasis in the Representation Error section with an \emph{} thingie. Index: ACKS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/ACKS,v retrieving revision 1.97 retrieving revision 1.98 diff -C2 -r1.97 -r1.98 *** ACKS 2001/06/09 09:26:21 1.97 --- ACKS 2001/06/17 21:57:17 1.98 *************** *** 72,75 **** --- 72,76 ---- David Chaum Nicolas Chauvat + Michael Chermside Albert Chin-A-Young Tom Christiansen From gvanrossum@users.sourceforge.net Mon Jun 18 00:13:42 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 17 Jun 2001 16:13:42 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include object.h,2.79.2.15,2.79.2.16 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv28752 Modified Files: Tag: descr-branch object.h Log Message: Add a new flag, Py_TPFLAGS_BASETYPE, that must be set in a type that supports subtyping. This makes more sense than requiring that tp_init is set. Index: object.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/object.h,v retrieving revision 2.79.2.15 retrieving revision 2.79.2.16 diff -C2 -r2.79.2.15 -r2.79.2.16 *** object.h 2001/06/16 14:41:40 2.79.2.15 --- object.h 2001/06/17 23:13:39 2.79.2.16 *************** *** 401,404 **** --- 401,407 ---- #define Py_TPFLAGS_HEAPTYPE (1L<<9) + /* Set if the type allows subclassing */ + #define Py_TPFLAGS_BASETYPE (1L<<10) + #define Py_TPFLAGS_DEFAULT ( \ Py_TPFLAGS_HAVE_GETCHARBUFFER | \ From gvanrossum@users.sourceforge.net Mon Jun 18 00:18:21 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 17 Jun 2001 16:18:21 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects listobject.c,2.92.6.8,2.92.6.9 dictobject.c,2.80.2.12,2.80.2.13 moduleobject.c,2.31.6.4,2.31.6.5 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv29363 Modified Files: Tag: descr-branch listobject.c dictobject.c moduleobject.c Log Message: Add Py_TPFLAGS_BASETYPE to tp_flags. Index: listobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v retrieving revision 2.92.6.8 retrieving revision 2.92.6.9 diff -C2 -r2.92.6.8 -r2.92.6.9 *** listobject.c 2001/06/11 19:06:44 2.92.6.8 --- listobject.c 2001/06/17 23:18:19 2.92.6.9 *************** *** 1661,1665 **** 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ list_doc, /* tp_doc */ (traverseproc)list_traverse, /* tp_traverse */ --- 1661,1666 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC | ! Py_TPFLAGS_BASETYPE, /* tp_flags */ list_doc, /* tp_doc */ (traverseproc)list_traverse, /* tp_traverse */ Index: dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.80.2.12 retrieving revision 2.80.2.13 diff -C2 -r2.80.2.12 -r2.80.2.13 *** dictobject.c 2001/06/14 14:10:16 2.80.2.12 --- dictobject.c 2001/06/17 23:18:19 2.80.2.13 *************** *** 1313,1317 **** 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ "dictionary type", /* tp_doc */ (traverseproc)dict_traverse, /* tp_traverse */ --- 1313,1318 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC | ! Py_TPFLAGS_BASETYPE, /* tp_flags */ "dictionary type", /* tp_doc */ (traverseproc)dict_traverse, /* tp_traverse */ Index: moduleobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/moduleobject.c,v retrieving revision 2.31.6.4 retrieving revision 2.31.6.5 diff -C2 -r2.31.6.4 -r2.31.6.5 *** moduleobject.c 2001/06/06 14:27:54 2.31.6.4 --- moduleobject.c 2001/06/17 23:18:19 2.31.6.5 *************** *** 209,213 **** PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)module_traverse, /* tp_traverse */ --- 209,214 ---- PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC | ! Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ (traverseproc)module_traverse, /* tp_traverse */ From gvanrossum@users.sourceforge.net Mon Jun 18 00:27:30 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 17 Jun 2001 16:27:30 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.1.2.13,1.1.2.14 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv30823 Modified Files: Tag: descr-branch test_descr.py Log Message: Add tests for some specific error conditions. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/Attic/test_descr.py,v retrieving revision 1.1.2.13 retrieving revision 1.1.2.14 diff -C2 -r1.1.2.13 -r1.1.2.14 *** test_descr.py 2001/06/07 19:17:39 1.1.2.13 --- test_descr.py 2001/06/17 23:27:27 1.1.2.14 *************** *** 413,416 **** --- 413,461 ---- verify(G.__mro__ == (G, E, D, C, B, A, object)) + def errors(): + if verbose: print "Testing errors..." + + try: + class C(list, dictionary): + pass + except TypeError: + pass + else: + print "Ouch: inheritance from both list and dict should be illegal!" + + try: + class C(object, None): + pass + except TypeError: + pass + else: + print "Ouch: inheritance from non-type should be illegal!" + class Classic: + pass + + try: + class C(object, Classic): + pass + except TypeError: + pass + else: + print "Ouch: inheritance from object and Classic should be illegal!" + + try: + class C(int): + pass + except TypeError: + pass + else: + print "Ouch: inheritance from int should be illegal!" + + try: + class C(object): + __slots__ = {} + except TypeError: + pass + else: + print "Ouch: __slots__ = {} should be illegal!" + def all(): lists() *************** *** 426,429 **** --- 471,475 ---- multi() diamond() + errors() all() From gvanrossum@users.sourceforge.net Mon Jun 18 00:28:33 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 17 Jun 2001 16:28:33 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.41,2.16.8.42 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv30954 Modified Files: Tag: descr-branch typeobject.c Log Message: Test for the Py_TPFLAGS_BASETYPE flag. Fold type_init() into type_new(). You can now instantiate object() again. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.41 retrieving revision 2.16.8.42 diff -C2 -r2.16.8.41 -r2.16.8.42 *** typeobject.c 2001/06/16 14:41:40 2.16.8.41 --- typeobject.c 2001/06/17 23:28:31 2.16.8.42 *************** *** 321,347 **** } ! /* TypeType's initializer; called when a type is subclassed */ staticforward void object_dealloc(PyObject *); staticforward int object_init(PyObject *, PyObject *, PyObject *); ! static int ! type_init(PyObject *self, PyObject *args, PyObject *kwds) { ! PyObject *name, *bases, *dict, *slots; ! PyTypeObject *type, *base; static char *kwlist[] = {"name", "bases", "dict", 0}; etype *et; struct memberlist *mp; ! int i, nbases, nslots, slotoffset, allocsize; ! ! assert(PyType_Check(self)); ! type = (PyTypeObject *)self; ! /* Check this is a virginal type object */ ! if (type->tp_dict != NULL) { ! PyErr_SetString(PyExc_TypeError, ! "can't re-initialize type objects"); ! return -1; } --- 321,386 ---- } ! static int ! extra_ivars(PyTypeObject *type, PyTypeObject *base) ! { ! int t_size = type->tp_basicsize; ! int b_size = base->tp_basicsize; ! ! assert((type->tp_flags & Py_TPFLAGS_GC) >= ! (base->tp_flags & Py_TPFLAGS_GC)); /* base has GC, type not! */ ! if (type->tp_flags & Py_TPFLAGS_GC) ! t_size -= PyGC_HEAD_SIZE; ! if (base->tp_flags & Py_TPFLAGS_GC) ! b_size -= PyGC_HEAD_SIZE; ! assert(t_size >= b_size); /* type smaller than base! */ ! if (type->tp_itemsize || base->tp_itemsize) { ! /* If itemsize is involved, stricter rules */ ! return t_size != b_size || ! type->tp_itemsize != base->tp_itemsize; ! } ! if (t_size == b_size) ! return 0; ! if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 && ! type->tp_dictoffset == b_size && ! t_size == b_size + sizeof(PyObject *)) ! return 0; /* "Forgive" adding a __dict__ only */ ! return 1; ! } ! ! static PyTypeObject * ! solid_base(PyTypeObject *type) ! { ! PyTypeObject *base; + if (type->tp_base) + base = solid_base(type->tp_base); + else + base = &PyBaseObject_Type; + if (extra_ivars(type, base)) + return type; + else + return base; + } + staticforward void object_dealloc(PyObject *); staticforward int object_init(PyObject *, PyObject *, PyObject *); ! static PyObject * ! type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) { ! PyObject *name, *bases, *dict; static char *kwlist[] = {"name", "bases", "dict", 0}; + PyObject *slots; + PyTypeObject *type, *base; etype *et; struct memberlist *mp; ! int i, nbases, nslots, slotoffset; ! if (PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 && ! (kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) { ! /* type(x) -> x.__class__ */ ! PyObject *x = PyTuple_GET_ITEM(args, 0); ! Py_INCREF(x->ob_type); ! return (PyObject *) x->ob_type; } *************** *** 349,357 **** if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO:type", kwlist, &name, &bases, &dict)) ! return -1; ! if (!PyTuple_Check(bases) || !PyDict_Check(dict)) { ! PyErr_SetString(PyExc_TypeError, ! "usage: type(name, bases, dict) "); ! return -1; } --- 388,410 ---- if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO:type", kwlist, &name, &bases, &dict)) ! return NULL; ! if (PyTuple_Check(bases)) { ! int i, n; ! n = PyTuple_GET_SIZE(bases); ! for (i = 0; i < n; i++) { ! PyObject *base_i = PyTuple_GET_ITEM(bases, i); ! PyTypeObject *type_i = base_i->ob_type; ! if (issubtype(metatype, type_i)) ! continue; ! if (issubtype(type_i, metatype)) { ! metatype = type_i; ! continue; ! } ! PyErr_SetString(PyExc_TypeError, ! "metaclass conflict among bases"); ! return NULL; ! } ! if (metatype->tp_new != type_new) ! return metatype->tp_new(metatype, args, kwds); } *************** *** 361,365 **** bases = Py_BuildValue("(O)", &PyBaseObject_Type); if (bases == NULL) ! return -1; nbases = 1; } --- 414,418 ---- bases = Py_BuildValue("(O)", &PyBaseObject_Type); if (bases == NULL) ! return NULL; nbases = 1; } *************** *** 370,387 **** base = best_base(bases); if (base == NULL) ! return -1; ! if (base->tp_init == NULL && base != &PyBaseObject_Type) { ! PyErr_SetString(PyExc_TypeError, ! "base type must have a constructor slot"); ! return -1; } - /* Set tp_base and tp_bases */ - type->tp_bases = bases; - Py_INCREF(base); - type->tp_base = base; - /* Check for a __slots__ sequence variable in dict, and count it */ - /* XXX This should move to type_alloc() */ slots = PyDict_GetItemString(dict, "__slots__"); nslots = 0; --- 423,435 ---- base = best_base(bases); if (base == NULL) ! return NULL; ! if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) { ! PyErr_Format(PyExc_TypeError, ! "type '%.100s' is not an acceptable base type", ! base->tp_name); ! return NULL; } /* Check for a __slots__ sequence variable in dict, and count it */ slots = PyDict_GetItemString(dict, "__slots__"); nslots = 0; *************** *** 393,397 **** slots = PySequence_Tuple(slots); if (slots == NULL) ! return -1; nslots = PyTuple_GET_SIZE(slots); for (i = 0; i < nslots; i++) { --- 441,445 ---- slots = PySequence_Tuple(slots); if (slots == NULL) ! return NULL; nslots = PyTuple_GET_SIZE(slots); for (i = 0; i < nslots; i++) { *************** *** 400,404 **** "__slots__ must be a sequence of strings"); Py_DECREF(slots); ! return -1; } } --- 448,452 ---- "__slots__ must be a sequence of strings"); Py_DECREF(slots); ! return NULL; } } *************** *** 409,427 **** nslots = 1; ! /* Check allocation size and initialize the type object */ ! allocsize = sizeof(etype) + nslots*sizeof(struct memberlist); ! if (type->ob_type->tp_basicsize < allocsize) { ! PyErr_Format( ! PyExc_SystemError, ! "insufficient allocated memory for subtype: " ! "allocated %d, needed %d", ! type->ob_type->tp_basicsize, ! allocsize); ! return -1; ! } et = (etype *)type; Py_INCREF(name); et->name = name; et->slots = slots; type->tp_as_number = &et->as_number; type->tp_as_sequence = &et->as_sequence; --- 457,474 ---- nslots = 1; ! /* Allocate the type object */ ! type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots); ! if (type == NULL) ! return NULL; ! ! /* Keep name and slots alive in the extended type object */ et = (etype *)type; Py_INCREF(name); et->name = name; et->slots = slots; + + /* Initialize essential fields */ + type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | + Py_TPFLAGS_BASETYPE; type->tp_as_number = &et->as_number; type->tp_as_sequence = &et->as_sequence; *************** *** 430,437 **** type->tp_name = PyString_AS_STRING(name); /* Initialize tp_introduced from passed-in dict */ type->tp_introduced = dict = PyDict_Copy(dict); if (dict == NULL) ! return -1; /* Add descriptors for custom slots from __slots__, or for __dict__ */ --- 477,489 ---- type->tp_name = PyString_AS_STRING(name); + /* Set tp_base and tp_bases */ + type->tp_bases = bases; + Py_INCREF(base); + type->tp_base = base; + /* Initialize tp_introduced from passed-in dict */ type->tp_introduced = dict = PyDict_Copy(dict); if (dict == NULL) ! return NULL; /* Add descriptors for custom slots from __slots__, or for __dict__ */ *************** *** 467,584 **** type->tp_setattro = PyObject_GenericSetAttr; } - if (base->tp_dealloc == NULL) - type->tp_dealloc = object_dealloc; - else - type->tp_dealloc = subtype_dealloc; if (base->tp_new == NULL) type->tp_new = PyType_GenericNew; if (base->tp_alloc == NULL) type->tp_alloc = PyType_GenericAlloc; - if (base->tp_init == NULL) - type->tp_init = object_init; /* Initialize the rest */ if (PyType_InitDict(type) < 0) ! return -1; /* Override slots that deserve it */ override_slots(type, type->tp_dict); - return 0; - } - - static int - extra_ivars(PyTypeObject *type, PyTypeObject *base) - { - int t_size = type->tp_basicsize; - int b_size = base->tp_basicsize; - - assert((type->tp_flags & Py_TPFLAGS_GC) >= - (base->tp_flags & Py_TPFLAGS_GC)); /* base has GC, type not! */ - if (type->tp_flags & Py_TPFLAGS_GC) - t_size -= PyGC_HEAD_SIZE; - if (base->tp_flags & Py_TPFLAGS_GC) - b_size -= PyGC_HEAD_SIZE; - assert(t_size >= b_size); /* type smaller than base! */ - if (type->tp_itemsize || base->tp_itemsize) { - /* If itemsize is involved, stricter rules */ - return t_size != b_size || - type->tp_itemsize != base->tp_itemsize; - } - if (t_size == b_size) - return 0; - if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 && - type->tp_dictoffset == b_size && - t_size == b_size + sizeof(PyObject *)) - return 0; /* "Forgive" adding a __dict__ only */ - return 1; - } - - static PyTypeObject * - solid_base(PyTypeObject *type) - { - PyTypeObject *base; - - if (type->tp_base) - base = solid_base(type->tp_base); - else - base = &PyBaseObject_Type; - if (extra_ivars(type, base)) - return type; - else - return base; - } - - static PyObject * - type_alloc(PyTypeObject *metatype, int nitems) - { - PyTypeObject *type; - - type = (PyTypeObject *)PyType_GenericAlloc(metatype, nitems); - if (type != NULL) - type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE; return (PyObject *)type; } static PyObject * - type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) - { - PyObject *name, *bases, *dict; - static char *kwlist[] = {"name", "bases", "dict", 0}; - - if (PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 && - (kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) { - /* type(x) -> x.__class__ */ - PyObject *x = PyTuple_GET_ITEM(args, 0); - Py_INCREF(x->ob_type); - return (PyObject *) x->ob_type; - } - - /* Check arguments (again?!?! yes, alas -- we need the bases!) */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO:type", kwlist, - &name, &bases, &dict)) - return NULL; - if (PyTuple_Check(bases)) { - int i, n; - n = PyTuple_GET_SIZE(bases); - for (i = 0; i < n; i++) { - PyObject *base_i = PyTuple_GET_ITEM(bases, i); - PyTypeObject *type_i = base_i->ob_type; - if (issubtype(metatype, type_i)) - continue; - if (issubtype(type_i, metatype)) { - metatype = type_i; - continue; - } - PyErr_SetString(PyExc_TypeError, - "metaclass conflict among bases"); - return NULL; - } - if (metatype->tp_new != type_new) - return metatype->tp_new(metatype, args, kwds); - } - return PyType_GenericNew(metatype, args, kwds); - } - - static PyObject * type_getattro(PyTypeObject *type, PyObject *name) { --- 519,537 ---- type->tp_setattro = PyObject_GenericSetAttr; } if (base->tp_new == NULL) type->tp_new = PyType_GenericNew; if (base->tp_alloc == NULL) type->tp_alloc = PyType_GenericAlloc; /* Initialize the rest */ if (PyType_InitDict(type) < 0) ! return NULL; /* Override slots that deserve it */ override_slots(type, type->tp_dict); return (PyObject *)type; } static PyObject * type_getattro(PyTypeObject *type, PyObject *name) { *************** *** 614,619 **** 0, /* ob_size */ "type", /* tp_name */ ! sizeof(etype) + sizeof(struct memberlist), /* tp_basicsize */ ! 0, /* tp_itemsize */ (destructor)type_dealloc, /* tp_dealloc */ 0, /* tp_print */ --- 567,572 ---- 0, /* ob_size */ "type", /* tp_name */ ! sizeof(etype), /* tp_basicsize */ ! sizeof(struct memberlist), /* tp_itemsize */ (destructor)type_dealloc, /* tp_dealloc */ 0, /* tp_print */ *************** *** 631,635 **** 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT, /* tp_flags */ type_doc, /* tp_doc */ 0, /* tp_traverse */ --- 584,588 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ type_doc, /* tp_doc */ 0, /* tp_traverse */ *************** *** 647,652 **** 0, /* tp_descr_set */ offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ ! type_init, /* tp_init */ ! type_alloc, /* tp_alloc */ type_new, /* tp_new */ }; --- 600,605 ---- 0, /* tp_descr_set */ offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ ! 0, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ type_new, /* tp_new */ }; *************** *** 678,682 **** sizeof(PyObject), /* tp_basicsize */ 0, /* tp_itemsize */ ! 0/*(destructor)object_dealloc*/, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ --- 631,635 ---- sizeof(PyObject), /* tp_basicsize */ 0, /* tp_itemsize */ ! (destructor)object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ *************** *** 693,697 **** 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT, /* tp_flags */ "The most base type", /* tp_doc */ 0, /* tp_traverse */ --- 646,650 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ "The most base type", /* tp_doc */ 0, /* tp_traverse */ *************** *** 709,715 **** 0, /* tp_descr_set */ 0, /* tp_dictoffset */ ! 0, /* tp_init */ ! 0, /* tp_alloc */ ! 0, /* tp_new */ }; --- 662,668 ---- 0, /* tp_descr_set */ 0, /* tp_dictoffset */ ! object_init, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ ! PyType_GenericNew, /* tp_new */ }; From loewis@users.sourceforge.net Mon Jun 18 02:09:43 2001 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 17 Jun 2001 18:09:43 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib UserDict.py,1.13,1.14 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv12119 Modified Files: UserDict.py Log Message: Patch #413171: Implement get, setdefault, update in terms of has_key, __getitem__, and __setitem__. Index: UserDict.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/UserDict.py,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -r1.13 -r1.14 *** UserDict.py 2001/05/03 04:54:41 1.13 --- UserDict.py 2001/06/18 01:09:41 1.14 *************** *** 35,45 **** else: for k, v in dict.items(): ! self.data[k] = v def get(self, key, failobj=None): ! return self.data.get(key, failobj) def setdefault(self, key, failobj=None): ! if not self.data.has_key(key): ! self.data[key] = failobj ! return self.data[key] def popitem(self): return self.data.popitem() --- 35,47 ---- else: for k, v in dict.items(): ! self[k] = v def get(self, key, failobj=None): ! if not self.has_key(key): ! return failobj ! return self[key] def setdefault(self, key, failobj=None): ! if not self.has_key(key): ! self[key] = failobj ! return self[key] def popitem(self): return self.data.popitem() From gvanrossum@users.sourceforge.net Mon Jun 18 13:33:38 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 05:33:38 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib rexec.py,1.28,1.29 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv27537 Modified Files: rexec.py Log Message: Fix SF bug #433904 (Alex Martelli) - all s_* methods return None only. Index: rexec.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/rexec.py,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -r1.28 -r1.29 *** rexec.py 2001/02/15 22:15:13 1.28 --- rexec.py 2001/06/18 12:33:36 1.29 *************** *** 333,354 **** finally: self.restore_files() def s_exec(self, *args): ! self.s_apply(self.r_exec, args) def s_eval(self, *args): ! self.s_apply(self.r_eval, args) def s_execfile(self, *args): ! self.s_apply(self.r_execfile, args) def s_import(self, *args): ! self.s_apply(self.r_import, args) def s_reload(self, *args): ! self.s_apply(self.r_reload, args) def s_unload(self, *args): ! self.s_apply(self.r_unload, args) # Restricted open(...) --- 333,355 ---- finally: self.restore_files() + return r def s_exec(self, *args): ! return self.s_apply(self.r_exec, args) def s_eval(self, *args): ! return self.s_apply(self.r_eval, args) def s_execfile(self, *args): ! return self.s_apply(self.r_execfile, args) def s_import(self, *args): ! return self.s_apply(self.r_import, args) def s_reload(self, *args): ! return self.s_apply(self.r_reload, args) def s_unload(self, *args): ! return self.s_apply(self.r_unload, args) # Restricted open(...) From gvanrossum@users.sourceforge.net Mon Jun 18 13:34:34 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 05:34:34 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib rexec.py,1.28,1.28.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv27875 Modified Files: Tag: release21-maint rexec.py Log Message: Applying this to the 2.1.1 branch: Fix SF bug #433904 (Alex Martelli) - all s_* methods return None only. Index: rexec.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/rexec.py,v retrieving revision 1.28 retrieving revision 1.28.4.1 diff -C2 -r1.28 -r1.28.4.1 *** rexec.py 2001/02/15 22:15:13 1.28 --- rexec.py 2001/06/18 12:34:31 1.28.4.1 *************** *** 333,354 **** finally: self.restore_files() def s_exec(self, *args): ! self.s_apply(self.r_exec, args) def s_eval(self, *args): ! self.s_apply(self.r_eval, args) def s_execfile(self, *args): ! self.s_apply(self.r_execfile, args) def s_import(self, *args): ! self.s_apply(self.r_import, args) def s_reload(self, *args): ! self.s_apply(self.r_reload, args) def s_unload(self, *args): ! self.s_apply(self.r_unload, args) # Restricted open(...) --- 333,355 ---- finally: self.restore_files() + return r def s_exec(self, *args): ! return self.s_apply(self.r_exec, args) def s_eval(self, *args): ! return self.s_apply(self.r_eval, args) def s_execfile(self, *args): ! return self.s_apply(self.r_execfile, args) def s_import(self, *args): ! return self.s_apply(self.r_import, args) def s_reload(self, *args): ! return self.s_apply(self.r_reload, args) def s_unload(self, *args): ! return self.s_apply(self.r_unload, args) # Restricted open(...) From gvanrossum@users.sourceforge.net Mon Jun 18 14:38:56 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 06:38:56 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.42,2.16.8.43 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv9596 Modified Files: Tag: descr-branch typeobject.c Log Message: Add generic getattr to base object type, so object().__class__ works. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.42 retrieving revision 2.16.8.43 diff -C2 -r2.16.8.42 -r2.16.8.43 *** typeobject.c 2001/06/17 23:28:31 2.16.8.42 --- typeobject.c 2001/06/18 13:38:54 2.16.8.43 *************** *** 643,647 **** 0, /* tp_call */ 0, /* tp_str */ ! 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ --- 643,647 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ From gvanrossum@users.sourceforge.net Mon Jun 18 14:40:17 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 06:40:17 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.1.2.14,1.1.2.15 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv9860 Modified Files: Tag: descr-branch test_descr.py Log Message: Add tests for behavior of object(). Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/Attic/test_descr.py,v retrieving revision 1.1.2.14 retrieving revision 1.1.2.15 diff -C2 -r1.1.2.14 -r1.1.2.15 *** test_descr.py 2001/06/17 23:27:27 1.1.2.14 --- test_descr.py 2001/06/18 13:40:15 1.1.2.15 *************** *** 413,416 **** --- 413,438 ---- verify(G.__mro__ == (G, E, D, C, B, A, object)) + def objects(): + if verbose: print "Testing 'object' class..." + # Not much to test here :-) + a = object() + verify(a.__class__ == object == type(a)) + b = object() + verify(a is not b) + + try: + object().foo + except AttributeError: + pass + else: + print "Ouch: object() should not have a foo attribute!" + + try: + object().foo = 12 + except AttributeError: + pass + else: + print "Ouch: object() should not allow setting a foo attribute!" + def errors(): if verbose: print "Testing errors..." *************** *** 471,474 **** --- 493,497 ---- multi() diamond() + objects() errors() From fdrake@users.sourceforge.net Mon Jun 18 16:00:00 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 18 Jun 2001 08:00:00 -0700 Subject: [Python-checkins] CVS: python/dist/src/Doc/doc doc.tex,1.41,1.42 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/doc In directory usw-pr-cvs1:/tmp/cvs-serv28487/doc Modified Files: doc.tex Log Message: Add some information on the use of \verbatiminput to display sources from an external file. Index: doc.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/doc/doc.tex,v retrieving revision 1.41 retrieving revision 1.42 diff -C2 -r1.41 -r1.42 *** doc.tex 2001/05/11 01:01:12 1.41 --- doc.tex 2001/06/18 14:59:58 1.42 *************** *** 612,615 **** --- 612,630 ---- lines at the top or bottom of any \env{verbatim} display. + Longer displays of verbatim text may be included by storing the + example text in an external file containing only plain text. The + file may be included using the standard \macro{verbatiminput} + macro; this macro takes a single argument naming the file + containing the text. For example, to include the Python source + file \file{example.py}, use: + + \begin{verbatim} + \verbatiminput{example.py} + \end{verbatim} + + Use of \macro{verbatiminput} allows easier use of special editing + modes for the included file. The file should be placed in the + same directory as the \LaTeX{} files for the document. + The Python Documentation Special Interest Group has discussed a number of approaches to creating pretty-printed code displays and From gvanrossum@users.sourceforge.net Mon Jun 18 18:38:43 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 10:38:43 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.43,2.16.8.44 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv736 Modified Files: Tag: descr-branch typeobject.c Log Message: Fix an older bug: while tp_dictoffset was calculated correctly, the offset in the descriptor for the __dict__ was wrong. (I've a suspicion there's still a bug in the calculation of __slots__ offsets -- will investiage these later.) Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.43 retrieving revision 2.16.8.44 diff -C2 -r2.16.8.43 -r2.16.8.44 *** typeobject.c 2001/06/18 13:38:54 2.16.8.43 --- typeobject.c 2001/06/18 17:38:41 2.16.8.44 *************** *** 503,511 **** else if (nslots) { type->tp_dictoffset = slotoffset; - slotoffset += sizeof(PyObject *); mp->name = "__dict__"; mp->type = T_OBJECT; mp->offset = slotoffset; mp->readonly = 1; } type->tp_basicsize = slotoffset; --- 503,511 ---- else if (nslots) { type->tp_dictoffset = slotoffset; mp->name = "__dict__"; mp->type = T_OBJECT; mp->offset = slotoffset; mp->readonly = 1; + slotoffset += sizeof(PyObject *); } type->tp_basicsize = slotoffset; From gvanrossum@users.sourceforge.net Mon Jun 18 19:13:09 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 11:13:09 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0254.txt,NONE,1.1 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv8945 Added Files: pep-0254.txt Log Message: Make a dummy PEP so that PEP 0 doesn't have a broken link. --- NEW FILE: pep-0254.txt --- PEP: 254 Title: Making Classes Look More Like Types Version: $Revision: 1.1 $ Author: guido@python.org (Guido van Rossum) Status: Draft Type: Standards Track Python-Version: 2.2 Created: 18-June-2001 Post-History: Abstract This PEP has not been written yet. Watch this space! Copyright This document has been placed in the public domain. Local Variables: mode: indented-text indent-tabs-mode: nil End: From akuchling@users.sourceforge.net Mon Jun 18 20:04:06 2001 From: akuchling@users.sourceforge.net (A.M. Kuchling) Date: Mon, 18 Jun 2001 12:04:06 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules pcremodule.c,2.25,2.26 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv20746 Modified Files: pcremodule.c Log Message: [Bug #433047, reported by Armin Rigo] Remove extra 'i' character in PyArg_ParseTuple() call. (2.1.1 bugfix candidate.) Index: pcremodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/pcremodule.c,v retrieving revision 2.25 retrieving revision 2.26 diff -C2 -r2.25 -r2.26 *** pcremodule.c 2000/09/01 23:29:27 2.25 --- pcremodule.c 2001/06/18 19:04:04 2.26 *************** *** 75,79 **** PyObject *list; ! if (!PyArg_ParseTuple(args, "t#|iiii:match", &string, &stringlen, &pos, &endpos, &options)) return NULL; if (endpos == -1) {endpos = stringlen;} --- 75,80 ---- PyObject *list; ! if (!PyArg_ParseTuple(args, "t#|iii:match", &string, &stringlen, ! &pos, &endpos, &options)) return NULL; if (endpos == -1) {endpos = stringlen;} From gvanrossum@users.sourceforge.net Mon Jun 18 20:19:00 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 12:19:00 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0257.txt,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv26597 Modified Files: pep-0257.txt Log Message: New version from David Goodger, where he makes me co-author (since it's mostly lifted from my style guide). I don't plan to actively contribute much -- David is the primary author. There are many miscellaneous updates here. Index: pep-0257.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0257.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -r1.1 -r1.2 *** pep-0257.txt 2001/06/06 05:55:20 1.1 --- pep-0257.txt 2001/06/18 19:18:58 1.2 *************** *** 3,12 **** Version: $Revision$ Last-Modified: $Date$ ! Author: dgoodger@bigfoot.com (David Goodger) Discussions-To: doc-sig@python.org Status: Draft Type: Informational Created: 29-May-2001 ! Post-History: --- 3,13 ---- Version: $Revision$ Last-Modified: $Date$ ! Author: dgoodger@bigfoot.com (David Goodger), ! guido@digicool.com (Guido van Rossum) Discussions-To: doc-sig@python.org Status: Draft Type: Informational Created: 29-May-2001 ! Post-History: 13-Jun-2001 *************** *** 17,45 **** Specification All modules should normally have docstrings, and all functions and classes exported by a module should also have docstrings. Public methods (including the __init__ constructor) should also have ! docstrings. ! [+] A package may be documented in the module docstring of the ! [+] __init__.py file in the package directory. ! The docstring of a script (a stand-alone program) should be usable ! as its "usage" message, printed when the script is invoked with ! incorrect or missing arguments (or perhaps with a "-h" option, for ! "help"). Such a docstring should document the script's function ! and command line syntax, environment variables, and files. Usage ! messages can be fairly elaborate (several screens full) and should ! be sufficient for a new user to use the command properly, as well ! as a complete quick reference to all options and arguments for the ! sophisticated user. ! For consistency, always use """triple double quotes""" around ! docstrings. ! [+] Use r"""raw triple double quotes""" if you use any ! [+] backslashes in your docstrings. There are two forms of docstrings: one-liners and multi-line --- 18,75 ---- + Rationale + + The aim of this PEP is to standardize the high-level structure of + docstrings: what they should contain, and how to say it (without + touching on any markup syntax within docstrings). The PEP + contains conventions, not laws or syntax. + + "A universal convention supplies all of maintainability, + clarity, consistency, and a foundation for good programming + habits too. What it doesn't do is insist that you follow it + against your will. That's Python!" + + --Tim Peters on comp.lang.python, 2001-06-16 + + If you violate the conventions, the worst you'll get is some dirty + looks. But some software (such as the Docstring Processing System + [1]) will be aware of the conventions, so following them will get + you the best results. + + Specification + What is a Docstring? + -------------------- + + A docstring is a string literal that occurs as the first statement + in a module, function, class, or method definition. Such a + docstring becomes the __doc__ special attribute of that object. + All modules should normally have docstrings, and all functions and classes exported by a module should also have docstrings. Public methods (including the __init__ constructor) should also have ! docstrings. A package may be documented in the module docstring ! of the __init__.py file in the package directory. ! String literals occuring elsewhere in Python code may also act as ! documentation. They are not recognized by the Python bytecode ! compiler and are not accessible as runtime object attributes ! (i.e. not assigned to __doc__), but two types of extra docstrings ! are recognized by software tools: ! ! 1. String literals occuring immediately after a simple assignment ! at the top level of a module, class, or __init__ method ! are called "attribute docstrings". ! 2. String literals occuring immediately after another docstring ! are called "additional docstrings". ! Please see PEP 258 "DPS Generic Implementation Details" [2] for a ! detailed description of attribute and additional docstrings. ! For consistency, always use """triple double quotes""" around ! docstrings. Use r"""raw triple double quotes""" if you use any ! backslashes in your docstrings. There are two forms of docstrings: one-liners and multi-line *************** *** 50,54 **** One-liners are for really obvious cases. They should really fit ! on one line. For example: def kos_root(): --- 80,84 ---- One-liners are for really obvious cases. They should really fit ! on one line. For example:: def kos_root(): *************** *** 66,84 **** This looks better for one-liners. ! - There's no blank line either before or after the docstring. - The docstring is a phrase ending in a period. It prescribes the function's effect as a command ("Do this", "Return that"), not as a description: e.g. don't write "Returns the pathname ..." - - [+] - The one-line docstring should NOT be a "signature" reiterating - [+] the function parameters (which can be obtained by introspection). - [+] Don't do: - - [+] def function(a, b): - [+] """function(a, b) -> list""" ! [+] This type of docstring is only appropriate for C functions (such ! [+] as built-ins), where introspection is not possible. Multi-line Docstrings --- 96,114 ---- This looks better for one-liners. ! - There's no blank line either before or after the docstring. - The docstring is a phrase ending in a period. It prescribes the function's effect as a command ("Do this", "Return that"), not as a description: e.g. don't write "Returns the pathname ..." ! - The one-line docstring should NOT be a "signature" reiterating ! the function parameters (which can be obtained by ! introspection). Don't do:: ! ! def function(a, b): ! """function(a, b) -> list""" ! ! This type of docstring is only appropriate for C functions (such ! as built-ins), where introspection is not possible. Multi-line Docstrings *************** *** 109,117 **** a blank line. The docstring for a module should generally list the classes, exceptions and functions (and any other objects) that are exported by the module, with a one-line summary of each. (These summaries generally give less detail than the summary line in the object's ! docstring.) The docstring for a function or method should summarize its --- 139,159 ---- a blank line. + The docstring of a script (a stand-alone program) should be usable + as its "usage" message, printed when the script is invoked with + incorrect or missing arguments (or perhaps with a "-h" option, for + "help"). Such a docstring should document the script's function + and command line syntax, environment variables, and files. Usage + messages can be fairly elaborate (several screens full) and should + be sufficient for a new user to use the command properly, as well + as a complete quick reference to all options and arguments for the + sophisticated user. + The docstring for a module should generally list the classes, exceptions and functions (and any other objects) that are exported by the module, with a one-line summary of each. (These summaries generally give less detail than the summary line in the object's ! docstring.) The docstring for a package (i.e., the docstring of ! the package's __init__.py module) should also list the modules and ! subpackages exported by the package. The docstring for a function or method should summarize its *************** *** 142,150 **** case sensitive and the argument names can be used for keyword arguments, so the docstring should document the correct argument ! names. It is best to list each argument on a separate line, - [-] with two dashes separating the name from the description, - [-] like this: - def complex(real=0.0, imag=0.0): """Form a complex number. --- 184,190 ---- case sensitive and the argument names can be used for keyword arguments, so the docstring should document the correct argument ! names. It is best to list each argument on a separate line. For ! example:: def complex(real=0.0, imag=0.0): """Form a complex number. *************** *** 157,182 **** if imag == 0.0 and real == 0.0: return complex_zero ... - - [-] The BDFL [3] recommends inserting a blank line between the - [-] last paragraph in a multi-line docstring and its closing quotes, - [-] placing the closing quotes on a line by themselves. This way, - [-] Emacs' fill-paragraph command can be used on it. ! [+] Attribute Docstrings: see PEP 258, "DPS Generic Implementation ! [+] Details" [4] - [+] Additional Docstrings: see PEP 258, "DPS Generic Implementation - [+] Details" [4] - References and Footnotes ! [1] http://www.python.org/doc/essays/styleguide.html ! [2] http://www.python.org/sigs/doc-sig/ ! [3] Guido van Rossum, Python's Benevolent Dictator For Life. ! [4] http://python.sf.net/peps/pep-0258.html --- 197,219 ---- if imag == 0.0 and real == 0.0: return complex_zero ... ! The BDFL [3] recommends inserting a blank line between the last ! paragraph in a multi-line docstring and its closing quotes, ! placing the closing quotes on a line by themselves. This way, ! Emacs' fill-paragraph command can be used on it. References and Footnotes + + [1] http://python.sf.net/peps/pep-0256.html ! [2] http://python.sf.net/peps/pep-0258.html ! [3] Guido van Rossum, Python's creator and Benevolent Dictator For ! Life. ! [4] http://www.python.org/doc/essays/styleguide.html ! [5] http://www.python.org/sigs/doc-sig/ *************** *** 189,209 **** The "Specification" text comes mostly verbatim from the Python ! Style Guide by Guido van Rossum [1]. ! (If it's OK with him, I will add GvR as an author of this PEP. I ! am quite confident that the BDFL doesn't want to own this PEP :-). ! Apart from minor editing, proposed additions to the Style Guide ! text are marked with '[+]' to the left of each line, and proposed ! omissions are marked with '[-]'. If it is deemed that this PEP is ! unnecessary, then it can be taken as suggestions for Style Guide ! modification.) ! ! This document borrows ideas from the archives of the Python Doc-SIG ! [2]. Thanks to all members past and present. ! ! ! ! Local Variables: ! mode: indented-text ! indent-tabs-mode: nil ! End: --- 226,231 ---- The "Specification" text comes mostly verbatim from the Python ! Style Guide by Guido van Rossum [4]. ! This document borrows ideas from the archives of the Python ! Doc-SIG [5]. Thanks to all members past and present. From gvanrossum@users.sourceforge.net Mon Jun 18 20:19:53 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 12:19:53 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.97,1.98 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv26990 Modified Files: pep-0000.txt Log Message: Add van Rossum as co-author of PEP 257. Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.97 retrieving revision 1.98 diff -C2 -r1.97 -r1.98 *** pep-0000.txt 2001/06/13 16:22:05 1.97 --- pep-0000.txt 2001/06/18 19:19:51 1.98 *************** *** 59,63 **** S 255 pep-0255.txt Simple Generators Schemenauer, et al S 256 pep-0256.txt Docstring Processing System Framework Goodger ! S 257 pep-0257.txt Docstring Conventions Goodger S 258 pep-0258.txt DPS Generic Implementation Details Goodger --- 59,63 ---- S 255 pep-0255.txt Simple Generators Schemenauer, et al S 256 pep-0256.txt Docstring Processing System Framework Goodger ! S 257 pep-0257.txt Docstring Conventions Goodger, van Rossum S 258 pep-0258.txt DPS Generic Implementation Details Goodger *************** *** 184,188 **** S 255 pep-0255.txt Simple Generators Schemenauer, et al S 256 pep-0256.txt Docstring Processing System Framework Goodger ! S 257 pep-0257.txt Docstring Conventions Goodger S 258 pep-0258.txt DPS Generic Implementation Details Goodger SR 259 pep-0259.txt Omit printing newline after newline van Rossum --- 184,188 ---- S 255 pep-0255.txt Simple Generators Schemenauer, et al S 256 pep-0256.txt Docstring Processing System Framework Goodger ! S 257 pep-0257.txt Docstring Conventions Goodger, van Rossum S 258 pep-0258.txt DPS Generic Implementation Details Goodger SR 259 pep-0259.txt Omit printing newline after newline van Rossum From tim_one@users.sourceforge.net Mon Jun 18 20:21:13 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 18 Jun 2001 12:21:13 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_b1.py,1.34,1.35 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv27024/python/dist/src/Lib/test Modified Files: test_b1.py Log Message: SF bug 434186: 0x80000000/2 != 0x80000000>>1 i_divmod: New and simpler algorithm. Old one returned gibberish on most boxes when the numerator was -sys.maxint-1. Oddly enough, it worked in the release (not debug) build on Windows, because the compiler optimized away some tricky sign manipulations that were incorrect in this case. Makes you wonder ... Bugfix candidate. Index: test_b1.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_b1.py,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -r1.34 -r1.35 *** test_b1.py 2001/01/22 19:30:07 1.34 --- test_b1.py 2001/06/18 19:21:11 1.35 *************** *** 368,371 **** --- 368,378 ---- raise TestFailed, "int(%s)" % `s[1:]` + " should raise ValueError" + # SF bug 434186: 0x80000000/2 != 0x80000000>>1. + # Worked by accident in Windows release build, but failed in debug build. + # Failed in all Linux builds. + x = -1-sys.maxint + if x >> 1 != x/2: + raise TestFailed("x >> 1 != x/2 when x == -1-sys.maxint") + print 'isinstance' class C: From tim_one@users.sourceforge.net Mon Jun 18 20:21:13 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 18 Jun 2001 12:21:13 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects intobject.c,2.56,2.57 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv27024/python/dist/src/Objects Modified Files: intobject.c Log Message: SF bug 434186: 0x80000000/2 != 0x80000000>>1 i_divmod: New and simpler algorithm. Old one returned gibberish on most boxes when the numerator was -sys.maxint-1. Oddly enough, it worked in the release (not debug) build on Windows, because the compiler optimized away some tricky sign manipulations that were incorrect in this case. Makes you wonder ... Bugfix candidate. Index: intobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/intobject.c,v retrieving revision 2.56 retrieving revision 2.57 diff -C2 -r2.56 -r2.57 *** intobject.c 2001/03/06 12:12:02 2.56 --- intobject.c 2001/06/18 19:21:11 2.57 *************** *** 435,470 **** static int ! i_divmod(register long xi, register long yi, long *p_xdivy, long *p_xmody) { long xdivy, xmody; ! if (yi == 0) { PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero"); return -1; } ! if (yi < 0) { ! if (xi < 0) { ! if (yi == -1 && -xi < 0) { ! /* most negative / -1 */ ! err_ovf("integer division"); ! return -1; ! } ! xdivy = -xi / -yi; ! } ! else ! xdivy = - (xi / -yi); ! } ! else { ! if (xi < 0) ! xdivy = - (-xi / yi); ! else ! xdivy = xi / yi; } ! xmody = xi - xdivy*yi; ! if ((xmody < 0 && yi > 0) || (xmody > 0 && yi < 0)) { ! xmody += yi; ! xdivy -= 1; } *p_xdivy = xdivy; --- 435,464 ---- static int ! i_divmod(register long x, register long y, long *p_xdivy, long *p_xmody) { long xdivy, xmody; ! if (y == 0) { PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero"); return -1; } ! /* (-sys.maxint-1)/-1 is the only overflow case. */ ! if (y == -1 && x < 0 && x == -x) { ! err_ovf("integer division"); ! return -1; } ! xdivy = x / y; ! xmody = x - xdivy * y; ! /* If the signs of x and y differ, and the remainder is non-0, ! * C89 doesn't define whether xdivy is now the floor or the ! * ceiling of the infinitely precise quotient. We want the floor, ! * and we have it iff the remainder's sign matches y's. ! */ ! if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) { ! xmody += y; ! --xdivy; ! assert(xmody && ((y ^ xmody) >= 0)); } *p_xdivy = xdivy; From gvanrossum@users.sourceforge.net Mon Jun 18 21:17:38 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 13:17:38 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.44,2.16.8.45 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv13926 Modified Files: Tag: descr-branch typeobject.c Log Message: - type_new(): fix a bogus increment in the slotoffset calculation. - type_new(): DECREF(type) when raising an error. - PyBaseObject_Type: add a default setattr implementation. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.16.8.44 retrieving revision 2.16.8.45 diff -C2 -r2.16.8.44 -r2.16.8.45 *** typeobject.c 2001/06/18 17:38:41 2.16.8.44 --- typeobject.c 2001/06/18 20:17:36 2.16.8.45 *************** *** 484,489 **** /* Initialize tp_introduced from passed-in dict */ type->tp_introduced = dict = PyDict_Copy(dict); ! if (dict == NULL) return NULL; /* Add descriptors for custom slots from __slots__, or for __dict__ */ --- 484,491 ---- /* Initialize tp_introduced from passed-in dict */ type->tp_introduced = dict = PyDict_Copy(dict); ! if (dict == NULL) { ! Py_DECREF(type); return NULL; + } /* Add descriptors for custom slots from __slots__, or for __dict__ */ *************** *** 498,502 **** mp->type = T_OBJECT; mp->offset = slotoffset; ! slotoffset += i*sizeof(PyObject *); } } --- 500,504 ---- mp->type = T_OBJECT; mp->offset = slotoffset; ! slotoffset += sizeof(PyObject *); } } *************** *** 525,530 **** /* Initialize the rest */ ! if (PyType_InitDict(type) < 0) return NULL; /* Override slots that deserve it */ --- 527,534 ---- /* Initialize the rest */ ! if (PyType_InitDict(type) < 0) { ! Py_DECREF(type); return NULL; + } /* Override slots that deserve it */ *************** *** 644,648 **** 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ ! 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ --- 648,652 ---- 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ ! PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ From gvanrossum@users.sourceforge.net Mon Jun 18 21:46:15 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 13:46:15 -0700 Subject: [Python-checkins] CVS: python/nondist/peps pep-0252.txt,1.8,1.9 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv19320 Modified Files: pep-0252.txt Log Message: Fix typo reported by Andrew MacKeith. Index: pep-0252.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0252.txt,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -r1.8 -r1.9 *** pep-0252.txt 2001/06/08 20:50:31 1.8 --- pep-0252.txt 2001/06/18 20:46:13 1.9 *************** *** 328,332 **** - readonly: Boolean indicating whether assignment to this attribute is disallowed. This is usually true for methods. ! Example: C.meth.readonly == 1; C.ivar.kind == 0. - get(): a function of one argument that retrieves the attribute --- 328,332 ---- - readonly: Boolean indicating whether assignment to this attribute is disallowed. This is usually true for methods. ! Example: C.meth.readonly == 1; C.ivar.readonly == 0. - get(): a function of one argument that retrieves the attribute From gvanrossum@users.sourceforge.net Mon Jun 18 21:50:29 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 13:50:29 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.1.2.15,1.1.2.16 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv20299 Modified Files: Tag: descr-branch test_descr.py Log Message: Test slots. Write tests for non-existant attributes using hasattr(). Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/Attic/test_descr.py,v retrieving revision 1.1.2.15 retrieving revision 1.1.2.16 diff -C2 -r1.1.2.15 -r1.1.2.16 *** test_descr.py 2001/06/18 13:40:15 1.1.2.15 --- test_descr.py 2001/06/18 20:50:27 1.1.2.16 *************** *** 414,437 **** def objects(): ! if verbose: print "Testing 'object' class..." ! # Not much to test here :-) a = object() verify(a.__class__ == object == type(a)) b = object() verify(a is not b) ! try: ! object().foo except AttributeError: pass else: ! print "Ouch: object() should not have a foo attribute!" ! try: ! object().foo = 12 ! except AttributeError: pass ! else: ! print "Ouch: object() should not allow setting a foo attribute!" def errors(): --- 414,470 ---- def objects(): ! if verbose: print "Testing object class..." a = object() verify(a.__class__ == object == type(a)) b = object() verify(a is not b) ! verify(not hasattr(a, "foo")) try: ! a.foo = 12 except AttributeError: pass else: ! print "Ouch: object() should not allow setting a foo attribute!" ! verify(not hasattr(object(), "__dict__")) ! class Cdict(object): pass ! x = Cdict() ! verify(x.__dict__ is None) ! x.foo = 1 ! verify(x.foo == 1) ! verify(x.__dict__ == {'foo': 1}) ! ! def slots(): ! if verbose: print "Testing __slots__..." ! class C0(object): ! __slots__ = [] ! x = C0() ! verify(not hasattr(x, "__dict__")) ! verify(not hasattr(x, "foo")) ! ! class C1(object): ! __slots__ = ['a'] ! x = C1() ! verify(not hasattr(x, "__dict__")) ! verify(x.a == None) ! x.a = 1 ! verify(x.a == 1) ! del x.a ! verify(x.a == None) ! ! class C3(object): ! __slots__ = ['a', 'b', 'c'] ! x = C3() ! verify(not hasattr(x, "__dict__")) ! verify(x.a is None) ! verify(x.b is None) ! verify(x.c is None) ! x.a = 1 ! x.b = 2 ! x.c = 3 ! verify(x.a == 1) ! verify(x.b == 2) ! verify(x.c == 3) def errors(): *************** *** 480,483 **** --- 513,524 ---- print "Ouch: __slots__ = {} should be illegal!" + try: + class C(object): + __slots__ = [1] + except TypeError: + pass + else: + print "Ouch: __slots__ = [1] should be illegal!" + def all(): lists() *************** *** 494,497 **** --- 535,539 ---- diamond() objects() + slots() errors() From fdrake@users.sourceforge.net Mon Jun 18 22:05:07 2001 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 18 Jun 2001 14:05:07 -0700 Subject: [Python-checkins] CVS: python/dist/src/Modules termios.c,2.24.2.5,2.24.2.6 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv23740/Modules Modified Files: Tag: release21-maint termios.c Log Message: Fix my own typo: protect the FLUSHO usage with "#ifdef FLUSHO", not "#ifndef FLUSHO". Index: termios.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/termios.c,v retrieving revision 2.24.2.5 retrieving revision 2.24.2.6 diff -C2 -r2.24.2.5 -r2.24.2.6 *** termios.c 2001/06/16 20:46:10 2.24.2.5 --- termios.c 2001/06/18 21:05:04 2.24.2.6 *************** *** 517,521 **** {"ECHOKE", ECHOKE}, #endif ! #ifndef FLUSHO {"FLUSHO", FLUSHO}, #endif --- 517,521 ---- {"ECHOKE", ECHOKE}, #endif ! #ifdef FLUSHO {"FLUSHO", FLUSHO}, #endif From gvanrossum@users.sourceforge.net Mon Jun 18 22:33:19 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 14:33:19 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects complexobject.c,2.35.4.4,2.35.4.5 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv29437 Modified Files: Tag: descr-branch complexobject.c Log Message: Make complex usable as a base type. Wasn't so hard. :-) Index: complexobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/complexobject.c,v retrieving revision 2.35.4.4 retrieving revision 2.35.4.5 diff -C2 -r2.35.4.4 -r2.35.4.5 *** complexobject.c 2001/06/14 18:12:02 2.35.4.4 --- complexobject.c 2001/06/18 21:33:17 2.35.4.5 *************** *** 184,187 **** --- 184,198 ---- } + static PyObject * + complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval) + { + PyObject *op; + + op = PyType_GenericAlloc(type, 0); + if (op != NULL) + ((PyComplexObject *)op)->cval = cval; + return op; + } + PyObject * PyComplex_FromCComplex(Py_complex cval) *************** *** 198,201 **** --- 209,221 ---- } + static PyObject * + complex_subtype_from_doubles(PyTypeObject *type, double real, double imag) + { + Py_complex c; + c.real = real; + c.imag = imag; + return complex_subtype_from_c_complex(type, c); + } + PyObject * PyComplex_FromDoubles(double real, double imag) *************** *** 568,572 **** static PyObject * ! complex_from_string(PyObject *v) { extern double strtod(const char *, char **); --- 588,592 ---- static PyObject * ! complex_subtype_from_string(PyTypeObject *type, PyObject *v) { extern double strtod(const char *, char **); *************** *** 716,720 **** } ! return PyComplex_FromDoubles(x,y); } --- 736,740 ---- } ! return complex_subtype_from_doubles(type, x, y); } *************** *** 728,732 **** static char *kwlist[] = {"real", "imag", 0}; - assert(type == &PyComplex_Type); r = Py_False; i = NULL; --- 748,751 ---- *************** *** 735,739 **** return NULL; if (PyString_Check(r) || PyUnicode_Check(r)) ! return complex_from_string(r); if ((nbr = r->ob_type->tp_as_number) == NULL || nbr->nb_float == NULL || --- 754,758 ---- return NULL; if (PyString_Check(r) || PyUnicode_Check(r)) ! return complex_subtype_from_string(type, r); if ((nbr = r->ob_type->tp_as_number) == NULL || nbr->nb_float == NULL || *************** *** 808,812 **** cr.real -= ci.imag; cr.imag += ci.real; ! return PyComplex_FromCComplex(cr); } --- 827,831 ---- cr.real -= ci.imag; cr.imag += ci.real; ! return complex_subtype_from_c_complex(type, cr); } *************** *** 864,868 **** 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT, /* tp_flags */ complex_doc, /* tp_doc */ 0, /* tp_traverse */ --- 883,887 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ complex_doc, /* tp_doc */ 0, /* tp_traverse */ From gvanrossum@users.sourceforge.net Mon Jun 18 23:02:32 2001 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 18 Jun 2001 15:02:32 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.1.2.16,1.1.2.17 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv3702 Modified Files: Tag: descr-branch test_descr.py Log Message: numops(): add optional skip argument, a list of binary op names to skip. complexes(): new function, tests complex numerical operators and tests subtyping from complex. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/Attic/test_descr.py,v retrieving revision 1.1.2.16 retrieving revision 1.1.2.17 diff -C2 -r1.1.2.16 -r1.1.2.17 *** test_descr.py 2001/06/18 20:50:27 1.1.2.16 --- test_descr.py 2001/06/18 22:02:29 1.1.2.17 *************** *** 171,181 **** unops[name] = expr ! def numops(a, b): dict = {'a': a, 'b': b} for name, expr in binops.items(): ! name = "__%s__" % name ! if hasattr(a, name): ! res = eval(expr, dict) ! testbinop(a, b, res, expr, name) for name, expr in unops.items(): name = "__%s__" % name --- 171,182 ---- unops[name] = expr ! def numops(a, b, skip=[]): dict = {'a': a, 'b': b} for name, expr in binops.items(): ! if name not in skip: ! name = "__%s__" % name ! if hasattr(a, name): ! res = eval(expr, dict) ! testbinop(a, b, res, expr, name) for name, expr in unops.items(): name = "__%s__" % name *************** *** 196,199 **** --- 197,217 ---- numops(100.0, 3.0) + def complexes(): + if verbose: print "Testing complex operations..." + numops(100.0j, 3.0j, skip=['lt', 'le', 'gt', 'ge']) + class Number(complex): + __slots__ = ['prec'] + def __repr__(self): + prec = self.prec or 12 + if self.imag == 0.0: + return "%.*g" % (prec, self.real) + if self.real == 0.0: + return "%.*gj" % (prec, self.imag) + return "(%.*g+%.*gj)" % (prec, self.real, prec, self.imag) + __str__ = __repr__ + a = Number(3.14) + a.prec = 12 + verify(`a` == "3.14") + def spamlists(): if verbose: print "Testing spamlist operations..." *************** *** 527,530 **** --- 545,549 ---- longs() floats() + complexes() spamlists() spamdicts() From tim_one@users.sourceforge.net Mon Jun 18 23:08:15 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 18 Jun 2001 15:08:15 -0700 Subject: [Python-checkins] CVS: python/dist/src/Grammar Grammar,1.42,1.43 Message-ID: Update of /cvsroot/python/python/dist/src/Grammar In directory usw-pr-cvs1:/tmp/cvs-serv4630/python/dist/src/Grammar Modified Files: Grammar Log Message: Merging the gen-branch into the main line, at Guido's direction. Yay! Bugfix candidate in inspect.py: it was referencing "self" outside of a method. Index: Grammar =================================================================== RCS file: /cvsroot/python/python/dist/src/Grammar/Grammar,v retrieving revision 1.42 retrieving revision 1.43 diff -C2 -r1.42 -r1.43 *** Grammar 2001/02/27 18:36:14 1.42 --- Grammar 2001/06/18 22:08:13 1.43 *************** *** 44,51 **** del_stmt: 'del' exprlist pass_stmt: 'pass' ! flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] raise_stmt: 'raise' [test [',' test [',' test]]] import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*) --- 44,52 ---- del_stmt: 'del' exprlist pass_stmt: 'pass' ! flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] + yield_stmt: 'yield' testlist raise_stmt: 'raise' [test [',' test [',' test]]] import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*) From tim_one@users.sourceforge.net Mon Jun 18 23:08:15 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 18 Jun 2001 15:08:15 -0700 Subject: [Python-checkins] CVS: python/dist/src/Objects frameobject.c,2.50,2.51 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv4630/python/dist/src/Objects Modified Files: frameobject.c Log Message: Merging the gen-branch into the main line, at Guido's direction. Yay! Bugfix candidate in inspect.py: it was referencing "self" outside of a method. Index: frameobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/frameobject.c,v retrieving revision 2.50 retrieving revision 2.51 diff -C2 -r2.50 -r2.51 *** frameobject.c 2001/05/08 04:08:20 2.50 --- frameobject.c 2001/06/18 22:08:13 2.51 *************** *** 68,71 **** --- 68,72 ---- int i, slots; PyObject **fastlocals; + PyObject **p; Py_TRASHCAN_SAFE_BEGIN(f) *************** *** 77,80 **** --- 78,85 ---- } + /* Free stack */ + for (p = f->f_valuestack; p < f->f_stackbottom; p++) { + Py_XDECREF(*p); + } Py_XDECREF(f->f_back); Py_XDECREF(f->f_code); *************** *** 222,225 **** --- 227,231 ---- f->f_valuestack = f->f_localsplus + (f->f_nlocals + ncells + nfrees); + f->f_stackbottom = f->f_valuestack; return f; From tim_one@users.sourceforge.net Mon Jun 18 23:08:15 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 18 Jun 2001 15:08:15 -0700 Subject: [Python-checkins] CVS: python/dist/src/Include compile.h,2.29,2.30 frameobject.h,2.31,2.32 graminit.h,2.16,2.17 opcode.h,2.35,2.36 symtable.h,2.7,2.8 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv4630/python/dist/src/Include Modified Files: compile.h frameobject.h graminit.h opcode.h symtable.h Log Message: Merging the gen-branch into the main line, at Guido's direction. Yay! Bugfix candidate in inspect.py: it was referencing "self" outside of a method. Index: compile.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/compile.h,v retrieving revision 2.29 retrieving revision 2.30 diff -C2 -r2.29 -r2.30 *** compile.h 2001/03/22 02:32:48 2.29 --- compile.h 2001/06/18 22:08:13 2.30 *************** *** 34,37 **** --- 34,38 ---- #define CO_VARKEYWORDS 0x0008 #define CO_NESTED 0x0010 + #define CO_GENERATOR 0x0020 extern DL_IMPORT(PyTypeObject) PyCode_Type; Index: frameobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/frameobject.h,v retrieving revision 2.31 retrieving revision 2.32 diff -C2 -r2.31 -r2.32 *** frameobject.h 2001/03/13 01:58:21 2.31 --- frameobject.h 2001/06/18 22:08:13 2.32 *************** *** 22,25 **** --- 22,27 ---- PyObject *f_locals; /* local symbol table (PyDictObject) */ PyObject **f_valuestack; /* points after the last local */ + PyObject **f_stackbottom; /* points to the last item on the stack if + frame has yielded. */ PyObject *f_trace; /* Trace function */ PyObject *f_exc_type, *f_exc_value, *f_exc_traceback; Index: graminit.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/graminit.h,v retrieving revision 2.16 retrieving revision 2.17 diff -C2 -r2.16 -r2.17 *** graminit.h 2000/08/24 20:09:45 2.16 --- graminit.h 2001/06/18 22:08:13 2.17 *************** *** 19,64 **** #define continue_stmt 274 #define return_stmt 275 ! #define raise_stmt 276 ! #define import_stmt 277 ! #define import_as_name 278 ! #define dotted_as_name 279 ! #define dotted_name 280 ! #define global_stmt 281 ! #define exec_stmt 282 ! #define assert_stmt 283 ! #define compound_stmt 284 ! #define if_stmt 285 ! #define while_stmt 286 ! #define for_stmt 287 ! #define try_stmt 288 ! #define except_clause 289 ! #define suite 290 ! #define test 291 ! #define and_test 292 ! #define not_test 293 ! #define comparison 294 ! #define comp_op 295 ! #define expr 296 ! #define xor_expr 297 ! #define and_expr 298 ! #define shift_expr 299 ! #define arith_expr 300 ! #define term 301 ! #define factor 302 ! #define power 303 ! #define atom 304 ! #define listmaker 305 ! #define lambdef 306 ! #define trailer 307 ! #define subscriptlist 308 ! #define subscript 309 ! #define sliceop 310 ! #define exprlist 311 ! #define testlist 312 ! #define dictmaker 313 ! #define classdef 314 ! #define arglist 315 ! #define argument 316 ! #define list_iter 317 ! #define list_for 318 ! #define list_if 319 --- 19,65 ---- #define continue_stmt 274 #define return_stmt 275 ! #define yield_stmt 276 ! #define raise_stmt 277 ! #define import_stmt 278 ! #define import_as_name 279 ! #define dotted_as_name 280 ! #define dotted_name 281 ! #define global_stmt 282 ! #define exec_stmt 283 ! #define assert_stmt 284 ! #define compound_stmt 285 ! #define if_stmt 286 ! #define while_stmt 287 ! #define for_stmt 288 ! #define try_stmt 289 ! #define except_clause 290 ! #define suite 291 ! #define test 292 ! #define and_test 293 ! #define not_test 294 ! #define comparison 295 ! #define comp_op 296 ! #define expr 297 ! #define xor_expr 298 ! #define and_expr 299 ! #define shift_expr 300 ! #define arith_expr 301 ! #define term 302 ! #define factor 303 ! #define power 304 ! #define atom 305 ! #define listmaker 306 ! #define lambdef 307 ! #define trailer 308 ! #define subscriptlist 309 ! #define subscript 310 ! #define sliceop 311 ! #define exprlist 312 ! #define testlist 313 ! #define dictmaker 314 ! #define classdef 315 ! #define arglist 316 ! #define argument 317 ! #define list_iter 318 ! #define list_for 319 ! #define list_if 320 Index: opcode.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/opcode.h,v retrieving revision 2.35 retrieving revision 2.36 diff -C2 -r2.35 -r2.36 *** opcode.h 2001/04/20 19:13:01 2.35 --- opcode.h 2001/06/18 22:08:13 2.36 *************** *** 72,75 **** --- 72,76 ---- #define IMPORT_STAR 84 #define EXEC_STMT 85 + #define YIELD_VALUE 86 #define POP_BLOCK 87 Index: symtable.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/symtable.h,v retrieving revision 2.7 retrieving revision 2.8 diff -C2 -r2.7 -r2.8 *** symtable.h 2001/03/22 03:57:58 2.7 --- symtable.h 2001/06/18 22:08:13 2.8 *************** *** 47,50 **** --- 47,51 ---- int ste_child_free; /* true if a child scope has free variables, including free refs to globals */ + int ste_generator; /* true if namespace is a generator */ int ste_opt_lineno; /* lineno of last exec or import * */ struct symtable *ste_table; From tim_one@users.sourceforge.net Mon Jun 18 23:08:15 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 18 Jun 2001 15:08:15 -0700 Subject: [Python-checkins] CVS: python/dist/src/Lib dis.py,1.34,1.35 inspect.py,1.16,1.17 tabnanny.py,1.13,1.14 tokenize.py,1.22,1.23 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv4630/python/dist/src/Lib Modified Files: dis.py inspect.py tabnanny.py tokenize.py Log Message: Merging the gen-branch into the main line, at Guido's direction. Yay! Bugfix candidate in inspect.py: it was referencing "self" outside of a method. Index: dis.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/dis.py,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -r1.34 -r1.35 *** dis.py 2001/04/20 19:13:01 1.34 --- dis.py 2001/06/18 22:08:13 1.35 *************** *** 224,227 **** --- 224,228 ---- def_op('IMPORT_STAR', 84) def_op('EXEC_STMT', 85) + def_op('YIELD_STMT', 86) def_op('POP_BLOCK', 87) Index: inspect.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/inspect.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -r1.16 -r1.17 *** inspect.py 2001/04/13 14:04:02 1.16 --- inspect.py 2001/06/18 22:08:13 1.17 *************** *** 350,379 **** else: return '' ! class EndOfBlock(Exception): pass ! class BlockFinder: ! """Provide a tokeneater() method to detect the end of a code block.""" ! def __init__(self): ! self.indent = 0 ! self.started = 0 ! self.last = 0 ! def tokeneater(self, type, token, (srow, scol), (erow, ecol), line): ! if not self.started: ! if type == tokenize.NAME: self.started = 1 elif type == tokenize.NEWLINE: ! self.last = srow elif type == tokenize.INDENT: ! self.indent = self.indent + 1 elif type == tokenize.DEDENT: ! self.indent = self.indent - 1 ! if self.indent == 0: raise EndOfBlock, self.last ! ! def getblock(lines): ! """Extract the block of code at the top of the given list of lines.""" ! try: ! tokenize.tokenize(ListReader(lines).readline, BlockFinder().tokeneater) ! except EndOfBlock, eob: ! return lines[:eob.args[0]] def getsourcelines(object): --- 350,375 ---- else: return '' ! def getblock(lines): ! """Extract the block of code at the top of the given list of lines.""" ! indent = 0 ! started = 0 ! last = 0 ! tokens = tokenize.generate_tokens(ListReader(lines).readline) ! for (type, token, (srow, scol), (erow, ecol), line) in tokens: ! if not started: ! if type == tokenize.NAME: ! started = 1 elif type == tokenize.NEWLINE: ! last = srow elif type == tokenize.INDENT: ! indent = indent + 1 elif type == tokenize.DEDENT: ! indent = indent - 1 ! if indent == 0: ! return lines[:last] ! else: ! raise ValueError, "unable to find block" def getsourcelines(object): Index: tabnanny.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/tabnanny.py,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -r1.13 -r1.14 *** tabnanny.py 2001/04/08 00:38:42 1.13 --- tabnanny.py 2001/06/18 22:08:13 1.14 *************** *** 78,84 **** print "checking", `file`, "..." - reset_globals() try: ! tokenize.tokenize(f.readline, tokeneater) except tokenize.TokenError, msg: --- 78,83 ---- print "checking", `file`, "..." try: ! process_tokens(tokenize.generate_tokens(f.readline)) except tokenize.TokenError, msg: *************** *** 245,270 **** return prefix + " " + string.join(firsts, ', ') ! # The collection of globals, the reset_globals() function, and the ! # tokeneater() function, depend on which version of tokenize is ! # in use. ! if hasattr(tokenize, 'NL'): ! # take advantage of Guido's patch! ! ! indents = [] ! check_equal = 0 ! ! def reset_globals(): ! global indents, check_equal ! check_equal = 0 ! indents = [Whitespace("")] ! ! def tokeneater(type, token, start, end, line, INDENT=tokenize.INDENT, DEDENT=tokenize.DEDENT, NEWLINE=tokenize.NEWLINE, ! JUNK=(tokenize.COMMENT, tokenize.NL) ): ! global indents, check_equal if type == NEWLINE: # a program statement, or ENDMARKER, will eventually follow, --- 244,260 ---- return prefix + " " + string.join(firsts, ', ') ! # Need Guido's enhancement ! assert hasattr(tokenize, 'NL'), "tokenize module too old" ! def process_tokens(tokens, INDENT=tokenize.INDENT, DEDENT=tokenize.DEDENT, NEWLINE=tokenize.NEWLINE, ! JUNK=(tokenize.COMMENT, tokenize.NL)): + indents = [Whitespace("")] + check_equal = 0 + + for (type, token, start, end, line) in tokens: if type == NEWLINE: # a program statement, or ENDMARKER, will eventually follow, *************** *** 312,371 **** raise NannyNag(start[0], msg, line) - else: - # unpatched version of tokenize - - nesting_level = 0 - indents = [] - check_equal = 0 - - def reset_globals(): - global nesting_level, indents, check_equal - nesting_level = check_equal = 0 - indents = [Whitespace("")] - - def tokeneater(type, token, start, end, line, - INDENT=tokenize.INDENT, - DEDENT=tokenize.DEDENT, - NEWLINE=tokenize.NEWLINE, - COMMENT=tokenize.COMMENT, - OP=tokenize.OP): - global nesting_level, indents, check_equal - - if type == INDENT: - check_equal = 0 - thisguy = Whitespace(token) - if not indents[-1].less(thisguy): - witness = indents[-1].not_less_witness(thisguy) - msg = "indent not greater e.g. " + format_witnesses(witness) - raise NannyNag(start[0], msg, line) - indents.append(thisguy) - - elif type == DEDENT: - del indents[-1] - - elif type == NEWLINE: - if nesting_level == 0: - check_equal = 1 - - elif type == COMMENT: - pass - - elif check_equal: - check_equal = 0 - thisguy = Whitespace(line) - if not indents[-1].equal(thisguy): - witness = indents[-1].not_equal_witness(thisguy) - msg = "indent not equal e.g. " + format_witnesses(witness) - raise NannyNag(start[0], msg, line) - - if type == OP and token in ('{', '[', '('): - nesting_level = nesting_level + 1 - - elif type == OP and token in ('}', ']', ')'): - if nesting_level == 0: - raise NannyNag(start[0], - "unbalanced bracket '" + token + "'", - line) - nesting_level = nesting_level - 1 if __name__ == '__main__': --- 302,305 ---- Index: tokenize.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/tokenize.py,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -r1.22 -r1.23 *** tokenize.py 2001/03/23 05:22:49 1.22 --- tokenize.py 2001/06/18 22:08:13 1.23 *************** *** 112,116 **** --- 112,121 ---- pass + # backwards compatible interface, probably not used def tokenize_loop(readline, tokeneater): + for token_info in generate_tokens(readline): + apply(tokeneater, token_info) + + def generate_tokens(readline): lnum = parenlev = continued = 0 namechars, numchars = string.letters + '_', string.digits *************** *** 130,139 **** if endmatch: pos = end = endmatch.end(0) ! tokeneater(STRING, contstr + line[:end], strstart, (lnum, end), contline + line) contstr, needcont = '', 0 contline = None elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': ! tokeneater(ERRORTOKEN, contstr + line, strstart, (lnum, len(line)), contline) contstr = '' --- 135,144 ---- if endmatch: pos = end = endmatch.end(0) ! yield (STRING, contstr + line[:end], strstart, (lnum, end), contline + line) contstr, needcont = '', 0 contline = None elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': ! yield (ERRORTOKEN, contstr + line, strstart, (lnum, len(line)), contline) contstr = '' *************** *** 157,161 **** if line[pos] in '#\r\n': # skip comments or blank lines ! tokeneater((NL, COMMENT)[line[pos] == '#'], line[pos:], (lnum, pos), (lnum, len(line)), line) continue --- 162,166 ---- if line[pos] in '#\r\n': # skip comments or blank lines ! yield ((NL, COMMENT)[line[pos] == '#'], line[pos:], (lnum, pos), (lnum, len(line)), line) continue *************** *** 163,170 **** if column > indents[-1]: # count indents or dedents indents.append(column) ! tokeneater(INDENT, line[:pos], (lnum, 0), (lnum, pos), line) while column < indents[-1]: indents = indents[:-1] ! tokeneater(DEDENT, '', (lnum, pos), (lnum, pos), line) else: # continued statement --- 168,175 ---- if column > indents[-1]: # count indents or dedents indents.append(column) ! yield (INDENT, line[:pos], (lnum, 0), (lnum, pos), line) while column < indents[-1]: indents = indents[:-1] ! yield (DEDENT, '', (lnum, pos), (lnum, pos), line) else: # continued statement *************** *** 182,191 **** if initial in numchars or \ (initial == '.' and token != '.'): # ordinary number ! tokeneater(NUMBER, token, spos, epos, line) elif initial in '\r\n': ! tokeneater(parenlev > 0 and NL or NEWLINE, token, spos, epos, line) elif initial == '#': ! tokeneater(COMMENT, token, spos, epos, line) elif token in ("'''", '"""', # triple-quoted "r'''", 'r"""', "R'''", 'R"""', --- 187,196 ---- if initial in numchars or \ (initial == '.' and token != '.'): # ordinary number ! yield (NUMBER, token, spos, epos, line) elif initial in '\r\n': ! yield (parenlev > 0 and NL or NEWLINE, token, spos, epos, line) elif initial == '#': ! yield (COMMENT, token, spos, epos, line) elif token in ("'''", '"""', # triple-quoted "r'''", 'r"""', "R'''", 'R"""', *************** *** 198,202 **** pos = endmatch.end(0) token = line[start:pos] ! tokeneater(STRING, token, spos, (lnum, pos), line) else: strstart = (lnum, start) # multiple lines --- 203,207 ---- pos = endmatch.end(0) token = line[start:pos] ! yield (STRING, token, spos, (lnum, pos), line) else: strstart = (lnum, start) # multiple lines *************** *** 217,223 **** break else: # ordinary string ! tokeneater(STRING, token, spos, epos, line) elif initial in namechars: # ordinary name ! tokeneater(NAME, token, spos, epos, line) elif initial == '\\': # continued stmt continued = 1 --- 222,228 ---- break else: # ordinary string ! yield (STRING, token, spos, epos, line) elif initial in namechars: # ordinary name ! yield (NAME, token, spos, epos, line) elif initial == '\\': # continued stmt continued = 1 *************** *** 225,237 **** if initial in '([{': parenlev = parenlev + 1 elif initial in ')]}': parenlev = parenlev - 1 ! tokeneater(OP, token, spos, epos, line) else: ! tokeneater(ERRORTOKEN, line[pos], (lnum, pos), (lnum, pos+1), line) pos = pos + 1 for indent in indents[1:]: # pop remaining indent levels ! tokeneater(DEDENT, '', (lnum, 0), (lnum, 0), '') ! tokeneater(ENDMARKER, '', (lnum, 0), (lnum, 0), '') if __name__ == '__main__': # testing --- 230,242 ---- if initial in '([{': parenlev = parenlev + 1 elif initial in ')]}': parenlev = parenlev - 1 ! yield (OP, token, spos, epos, line) else: ! yield (ERRORTOKEN, line[pos], (lnum, pos), (lnum, pos+1), line) pos = pos + 1 for indent in indents[1:]: # pop remaining indent levels ! yield (DEDENT, '', (lnum, 0), (lnum, 0), '') ! yield (ENDMARKER, '', (lnum, 0), (lnum, 0), '') if __name__ == '__main__': # testing From tim_one@users.sourceforge.net Mon Jun 18 23:08:15 2001 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 18 Jun 2001 15:08:15 -0700 Subject: [Python-checkins] CVS: python/dist/src/Python ceval.c,2.248,2.249 compile.c,2.201,2.202 graminit.c,2.28,2.29 marshal.c,1.63,1.64 symtable.c,2.4,2.5 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv4630/python/dist/src/Python Modified Files: ceval.c compile.c graminit.c marshal.c symtable.c Log Message: Merging the gen-branch into the main line, at Guido's direction. Yay! Bugfix candidate in inspect.py: it was referencing "self" outside of a method. Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.248 retrieving revision 2.249 diff -C2 -r2.248 -r2.249 *** ceval.c 2001/06/16 21:02:31 2.248 --- ceval.c 2001/06/18 22:08:13 2.249 *************** *** 41,44 **** --- 41,45 ---- PyObject *); + static PyObject *eval_frame(PyFrameObject *); static char *get_func_name(PyObject *); static char *get_func_desc(PyObject *); *************** *** 107,110 **** --- 108,229 ---- + staticforward PyTypeObject gentype; + + typedef struct { + PyObject_HEAD + PyFrameObject *frame; + int running; /* true if generator is being executed */ + } genobject; + + static PyObject * + gen_new(PyFrameObject *f) + { + genobject *gen = PyObject_New(genobject, &gentype); + if (gen == NULL) { + Py_DECREF(f); + return NULL; + } + gen->frame = f; + gen->running = 0; + return (PyObject *)gen; + } + + static void + gen_dealloc(genobject *gen) + { + Py_DECREF(gen->frame); + PyObject_DEL(gen); + } + + static PyObject * + gen_iternext(genobject *gen) + { + PyFrameObject *f = gen->frame; + PyObject *result; + + if (gen->running) { + PyErr_SetString(PyExc_ValueError, + "generator already executing"); + return NULL; + } + if (f->f_stackbottom == NULL) { + return NULL; + } + gen->running = 1; + result = eval_frame(f); + gen->running = 0; + return result; + } + + static PyObject * + gen_next(genobject *gen, PyObject *args) + { + PyObject *result; + + if (!PyArg_ParseTuple(args, ":next")) + return NULL; + + result = gen_iternext(gen); + + if (result == NULL && !PyErr_Occurred()) { + PyErr_SetObject(PyExc_StopIteration, Py_None); + return NULL; + } + + return result; + } + + static PyObject * + gen_getiter(PyObject *gen) + { + Py_INCREF(gen); + return gen; + } + + static struct PyMethodDef gen_methods[] = { + {"next", (PyCFunction)gen_next, METH_VARARGS, + "next() -- get the next value, or raise StopIteration"}, + {NULL, NULL} /* Sentinel */ + }; + + static PyObject * + gen_getattr(genobject *gen, char *name) + { + return Py_FindMethod(gen_methods, (PyObject *)gen, name); + } + + statichere PyTypeObject gentype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ + "generator", /* tp_name */ + sizeof(genobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)gen_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)gen_getattr, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)gen_getiter, /* tp_iter */ + (iternextfunc)gen_iternext, /* tp_iternext */ + }; + + #ifdef WITH_THREAD *************** *** 338,342 **** WHY_RETURN, /* 'return' statement */ WHY_BREAK, /* 'break' statement */ ! WHY_CONTINUE /* 'continue' statement */ }; --- 457,462 ---- WHY_RETURN, /* 'return' statement */ WHY_BREAK, /* 'break' statement */ ! WHY_CONTINUE, /* 'continue' statement */ ! WHY_YIELD, /* 'yield' operator */ }; *************** *** 359,366 **** /* Interpreter main loop */ ! static PyObject * ! eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ! PyObject **args, int argcount, PyObject **kws, int kwcount, ! PyObject **defs, int defcount, PyObject *closure) { #ifdef DXPAIRS --- 479,484 ---- /* Interpreter main loop */ ! PyObject * ! eval_frame(PyFrameObject *f) { #ifdef DXPAIRS *************** *** 379,386 **** register PyObject *t; register PyObject *stream = NULL; /* for PRINT opcodes */ - register PyFrameObject *f; /* Current frame */ register PyObject **fastlocals, **freevars; PyObject *retval = NULL; /* Return value */ PyThreadState *tstate = PyThreadState_GET(); unsigned char *first_instr; #ifdef LLTRACE --- 497,504 ---- register PyObject *t; register PyObject *stream = NULL; /* for PRINT opcodes */ register PyObject **fastlocals, **freevars; PyObject *retval = NULL; /* Return value */ PyThreadState *tstate = PyThreadState_GET(); + PyCodeObject *co; unsigned char *first_instr; #ifdef LLTRACE *************** *** 389,393 **** #if defined(Py_DEBUG) || defined(LLTRACE) /* Make it easier to find out where we are with a debugger */ ! char *filename = PyString_AsString(co->co_filename); #endif --- 507,511 ---- #if defined(Py_DEBUG) || defined(LLTRACE) /* Make it easier to find out where we are with a debugger */ ! char *filename; #endif *************** *** 427,430 **** --- 545,551 ---- /* Start of code */ + if (f == NULL) + return NULL; + #ifdef USE_STACKCHECK if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) { *************** *** 433,675 **** } #endif - - if (globals == NULL) { - PyErr_SetString(PyExc_SystemError, "eval_code2: NULL globals"); - return NULL; - } - - #ifdef LLTRACE - lltrac