[Python-checkins] python/dist/src/Objects dictnotes.txt, NONE, 1.5.6.1 genobject.c, NONE, 1.4.4.1 setobject.c, NONE, 1.31.4.1 abstract.c, 2.103.2.1, 2.103.2.2 bufferobject.c, 2.19.2.1, 2.19.2.2 classobject.c, 2.158.2.1, 2.158.2.2 cobject.c, 2.14, 2.14.2.1 complexobject.c, 2.62.2.1, 2.62.2.2 descrobject.c, 2.27.2.1, 2.27.2.2 dictobject.c, 2.126.2.1, 2.126.2.2 enumobject.c, 1.2.2.1, 1.2.2.2 fileobject.c, 2.164.2.1, 2.164.2.2 floatobject.c, 2.113.2.1, 2.113.2.2 frameobject.c, 2.62.2.2, 2.62.2.3 funcobject.c, 2.55.2.2, 2.55.2.3 intobject.c, 2.84.2.1, 2.84.2.2 iterobject.c, 1.10.2.1, 1.10.2.2 listobject.c, 2.114.2.1, 2.114.2.2 longobject.c, 1.118.2.1, 1.118.2.2 methodobject.c, 2.42.2.1, 2.42.2.2 moduleobject.c, 2.45, 2.45.2.1 object.c, 2.179.2.2, 2.179.2.3 obmalloc.c, 2.45.2.1, 2.45.2.2 rangeobject.c, 2.41.2.1, 2.41.2.2 sliceobject.c, 2.15.2.1, 2.15.2.2 stringobject.c, 2.168.2.1, 2.168.2.2 tupleobject.c, 2.68.2.1, 2.68.2.2 typeobject.c, 2.157.2.2, 2.157.2.3 unicodectype.c, 2.11.18.1, 2.11.18.2 unicodeobject.c, 2.155.2.1, 2.155.2.2 unicodetype_db.h, 1.4.26.1, 1.4.26.2 weakrefobject.c, 1.9.2.1, 1.9.2.2 xxobject.c, 2.20.2.1, NONE

kbk at users.sourceforge.net kbk at users.sourceforge.net
Fri Jan 7 08:08:16 CET 2005


Update of /cvsroot/python/python/dist/src/Objects
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12896/Objects

Modified Files:
      Tag: ast-branch
	abstract.c bufferobject.c classobject.c cobject.c 
	complexobject.c descrobject.c dictobject.c enumobject.c 
	fileobject.c floatobject.c frameobject.c funcobject.c 
	intobject.c iterobject.c listobject.c longobject.c 
	methodobject.c moduleobject.c object.c obmalloc.c 
	rangeobject.c sliceobject.c stringobject.c tupleobject.c 
	typeobject.c unicodectype.c unicodeobject.c unicodetype_db.h 
	weakrefobject.c 
Added Files:
      Tag: ast-branch
	dictnotes.txt genobject.c setobject.c 
Removed Files:
      Tag: ast-branch
	xxobject.c 
Log Message:
Merge MAIN into ast-branch
cvs  up -kk -j mrg_to_ast-branch_24APR03  -j mrg_to_ast-branch_05JAN05
  (date of earlier merge estimated 24Apr03 17:30 UTC, repository tagged)

Not merged:
Lib/test/test_compile.py,  Python/compile.c

Refer to Tracker Patch # 1097671 for the merge output and list of
conflicts resolved.


--- NEW FILE: dictnotes.txt ---
NOTES ON OPTIMIZING DICTIONARIES
================================


Principal Use Cases for Dictionaries
------------------------------------

Passing keyword arguments
    Typically, one read and one write for 1 to 3 elements.
    Occurs frequently in normal python code.

Class method lookup
    Dictionaries vary in size with 8 to 16 elements being common.
    Usually written once with many lookups.
    When base classes are used, there are many failed lookups
        followed by a lookup in a base class.

Instance attribute lookup and Global variables
    Dictionaries vary in size.  4 to 10 elements are common.
    Both reads and writes are common.

Builtins
    Frequent reads.  Almost never written.
    Size 126 interned strings (as of Py2.3b1).
    A few keys are accessed much more frequently than others.

Uniquification
    Dictionaries of any size.  Bulk of work is in creation.
    Repeated writes to a smaller set of keys.
    Single read of each key.
    Some use cases have two consecutive accesses to the same key.

    * Removing duplicates from a sequence.
        dict.fromkeys(seqn).keys()

    * Counting elements in a sequence.
        for e in seqn:
          d[e] = d.get(e,0) + 1

    * Accumulating references in a dictionary of lists:

        for pagenumber, page in enumerate(pages):
          for word in page:
            d.setdefault(word, []).append(pagenumber)

    Note, the second example is a use case characterized by a get and set
    to the same key.  There are similar used cases with a __contains__
    followed by a get, set, or del to the same key.  Part of the
    justification for d.setdefault is combining the two lookups into one.

Membership Testing
    Dictionaries of any size.  Created once and then rarely changes.
    Single write to each key.
    Many calls to __contains__() or has_key().
    Similar access patterns occur with replacement dictionaries
        such as with the % formatting operator.

Dynamic Mappings
    Characterized by deletions interspersed with adds and replacements.
    Performance benefits greatly from the re-use of dummy entries.


Data Layout (assuming a 32-bit box with 64 bytes per cache line)
----------------------------------------------------------------

Smalldicts (8 entries) are attached to the dictobject structure
and the whole group nearly fills two consecutive cache lines.

Larger dicts use the first half of the dictobject structure (one cache
line) and a separate, continuous block of entries (at 12 bytes each
for a total of 5.333 entries per cache line).


Tunable Dictionary Parameters
-----------------------------

* PyDict_MINSIZE.  Currently set to 8.
    Must be a power of two.  New dicts have to zero-out every cell.
    Each additional 8 consumes 1.5 cache lines.  Increasing improves
    the sparseness of small dictionaries but costs time to read in
    the additional cache lines if they are not already in cache.
    That case is common when keyword arguments are passed.

* Maximum dictionary load in PyDict_SetItem.  Currently set to 2/3.
    Increasing this ratio makes dictionaries more dense resulting
    in more collisions.  Decreasing it improves sparseness at the
    expense of spreading entries over more cache lines and at the
    cost of total memory consumed.

    The load test occurs in highly time sensitive code.  Efforts
    to make the test more complex (for example, varying the load
    for different sizes) have degraded performance.

* Growth rate upon hitting maximum load.  Currently set to *2.
    Raising this to *4 results in half the number of resizes,
    less effort to resize, better sparseness for some (but not
    all dict sizes), and potentially doubles memory consumption
    depending on the size of the dictionary.  Setting to *4
    eliminates every other resize step.

Tune-ups should be measured across a broad range of applications and
use cases.  A change to any parameter will help in some situations and
hurt in others.  The key is to find settings that help the most common
cases and do the least damage to the less common cases.  Results will
vary dramatically depending on the exact number of keys, whether the
keys are all strings, whether reads or writes dominate, the exact
hash values of the keys (some sets of values have fewer collisions than
others).  Any one test or benchmark is likely to prove misleading.

While making a dictionary more sparse reduces collisions, it impairs
iteration and key listing.  Those methods loop over every potential
entry.  Doubling the size of dictionary results in twice as many
non-overlapping memory accesses for keys(), items(), values(),
__iter__(), iterkeys(), iteritems(), itervalues(), and update().
Also, every dictionary iterates at least twice, once for the memset()
when it is created and once by dealloc().


Results of Cache Locality Experiments
-------------------------------------

When an entry is retrieved from memory, 4.333 adjacent entries are also
retrieved into a cache line.  Since accessing items in cache is *much*
cheaper than a cache miss, an enticing idea is to probe the adjacent
entries as a first step in collision resolution.  Unfortunately, the
introduction of any regularity into collision searches results in more
collisions than the current random chaining approach.

Exploiting cache locality at the expense of additional collisions fails
to payoff when the entries are already loaded in cache (the expense
is paid with no compensating benefit).  This occurs in small dictionaries
where the whole dictionary fits into a pair of cache lines.  It also
occurs frequently in large dictionaries which have a common access pattern
where some keys are accessed much more frequently than others.  The
more popular entries *and* their collision chains tend to remain in cache.

To exploit cache locality, change the collision resolution section
in lookdict() and lookdict_string().  Set i^=1 at the top of the
loop and move the  i = (i << 2) + i + perturb + 1 to an unrolled
version of the loop.

This optimization strategy can be leveraged in several ways:

* If the dictionary is kept sparse (through the tunable parameters),
then the occurrence of additional collisions is lessened.

* If lookdict() and lookdict_string() are specialized for small dicts
and for largedicts, then the versions for large_dicts can be given
an alternate search strategy without increasing collisions in small dicts
which already have the maximum benefit of cache locality.

* If the use case for a dictionary is known to have a random key
access pattern (as opposed to a more common pattern with a Zipf's law
distribution), then there will be more benefit for large dictionaries
because any given key is no more likely than another to already be
in cache.

* In use cases with paired accesses to the same key, the second access
is always in cache and gets no benefit from efforts to further improve
cache locality.

Optimizing the Search of Small Dictionaries
-------------------------------------------

If lookdict() and lookdict_string() are specialized for smaller dictionaries,
then a custom search approach can be implemented that exploits the small
search space and cache locality.

* The simplest example is a linear search of contiguous entries.  This is
  simple to implement, guaranteed to terminate rapidly, never searches
  the same entry twice, and precludes the need to check for dummy entries.

* A more advanced example is a self-organizing search so that the most
  frequently accessed entries get probed first.  The organization
  adapts if the access pattern changes over time.  Treaps are ideally
  suited for self-organization with the most common entries at the
  top of the heap and a rapid binary search pattern.  Most probes and
  results are all located at the top of the tree allowing them all to
  be located in one or two cache lines.

* Also, small dictionaries may be made more dense, perhaps filling all
  eight cells to take the maximum advantage of two cache lines.


Strategy Pattern
----------------

Consider allowing the user to set the tunable parameters or to select a
particular search method.  Since some dictionary use cases have known
sizes and access patterns, the user may be able to provide useful hints.

1) For example, if membership testing or lookups dominate runtime and memory
   is not at a premium, the user may benefit from setting the maximum load
   ratio at 5% or 10% instead of the usual 66.7%.  This will sharply
   curtail the number of collisions but will increase iteration time.
   The builtin namespace is a prime example of a dictionary that can
   benefit from being highly sparse.

2) Dictionary creation time can be shortened in cases where the ultimate
   size of the dictionary is known in advance.  The dictionary can be
   pre-sized so that no resize operations are required during creation.
   Not only does this save resizes, but the key insertion will go
   more quickly because the first half of the keys will be inserted into
   a more sparse environment than before.  The preconditions for this
   strategy arise whenever a dictionary is created from a key or item
   sequence and the number of *unique* keys is known.

3) If the key space is large and the access pattern is known to be random,
   then search strategies exploiting cache locality can be fruitful.
   The preconditions for this strategy arise in simulations and
   numerical analysis.

4) If the keys are fixed and the access pattern strongly favors some of
   the keys, then the entries can be stored contiguously and accessed
   with a linear search or treap.  This exploits knowledge of the data,
   cache locality, and a simplified search routine.  It also eliminates
   the need to test for dummy entries on each probe.  The preconditions
   for this strategy arise in symbol tables and in the builtin dictionary.


Readonly Dictionaries
---------------------
Some dictionary use cases pass through a build stage and then move to a
more heavily exercised lookup stage with no further changes to the
dictionary.

An idea that emerged on python-dev is to be able to convert a dictionary
to a read-only state.  This can help prevent programming errors and also
provide knowledge that can be exploited for lookup optimization.

The dictionary can be immediately rebuilt (eliminating dummy entries),
resized (to an appropriate level of sparseness), and the keys can be
jostled (to minimize collisions).  The lookdict() routine can then
eliminate the test for dummy entries (saving about 1/4 of the time
spent in the collision resolution loop).

An additional possibility is to insert links into the empty spaces
so that dictionary iteration can proceed in len(d) steps instead of
(mp->mask + 1) steps.  Alternatively, a separate tuple of keys can be
kept just for iteration.


Caching Lookups
---------------
The idea is to exploit key access patterns by anticipating future lookups
based of previous lookups.

The simplest incarnation is to save the most recently accessed entry.
This gives optimal performance for use cases where every get is followed
by a set or del to the same key.

--- NEW FILE: genobject.c ---
/* Generator object implementation */

#include "Python.h"
#include "frameobject.h"
#include "genobject.h"
#include "ceval.h"
#include "structmember.h"

static int
gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
{
	return visit((PyObject *)gen->gi_frame, arg);
}

static void
gen_dealloc(PyGenObject *gen)
{
	_PyObject_GC_UNTRACK(gen);
	if (gen->gi_weakreflist != NULL)
		PyObject_ClearWeakRefs((PyObject *) gen);
	Py_DECREF(gen->gi_frame);
	PyObject_GC_Del(gen);
}

static PyObject *
gen_iternext(PyGenObject *gen)
{
	PyThreadState *tstate = PyThreadState_GET();
	PyFrameObject *f = gen->gi_frame;
	PyObject *result;

	if (gen->gi_running) {
		PyErr_SetString(PyExc_ValueError,
				"generator already executing");
		return NULL;
	}
	if (f->f_stacktop == NULL)
		return NULL;

	/* Generators always return to their most recent caller, not
	 * necessarily their creator. */
	Py_XINCREF(tstate->frame);
	assert(f->f_back == NULL);
	f->f_back = tstate->frame;

	gen->gi_running = 1;
	result = PyEval_EvalFrame(f);
	gen->gi_running = 0;

	/* Don't keep the reference to f_back any longer than necessary.  It
	 * may keep a chain of frames alive or it could create a reference
	 * cycle. */
	assert(f->f_back != NULL);
	Py_CLEAR(f->f_back);

	/* If the generator just returned (as opposed to yielding), signal
	 * that the generator is exhausted. */
	if (result == Py_None && f->f_stacktop == NULL) {
		Py_DECREF(result);
		result = NULL;
	}

	return result;
}

static PyMemberDef gen_memberlist[] = {
	{"gi_frame",	T_OBJECT, offsetof(PyGenObject, gi_frame),	RO},
	{"gi_running",	T_INT,    offsetof(PyGenObject, gi_running),	RO},
	{NULL}	/* Sentinel */
};

PyTypeObject PyGen_Type = {
	PyObject_HEAD_INIT(&PyType_Type)
	0,					/* ob_size */
	"generator",				/* tp_name */
	sizeof(PyGenObject),			/* tp_basicsize */
	0,					/* tp_itemsize */
	/* methods */
	(destructor)gen_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 */
	PyObject_GenericGetAttr,		/* tp_getattro */
	0,					/* tp_setattro */
	0,					/* tp_as_buffer */
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
 	0,					/* tp_doc */
 	(traverseproc)gen_traverse,		/* tp_traverse */
 	0,					/* tp_clear */
	0,					/* tp_richcompare */
	offsetof(PyGenObject, gi_weakreflist),	/* tp_weaklistoffset */
	PyObject_SelfIter,			/* tp_iter */
	(iternextfunc)gen_iternext,		/* tp_iternext */
	0,					/* tp_methods */
	gen_memberlist,				/* tp_members */
	0,					/* tp_getset */
	0,					/* tp_base */
	0,					/* tp_dict */
};

PyObject *
PyGen_New(PyFrameObject *f)
{
	PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type);
	if (gen == NULL) {
		Py_DECREF(f);
		return NULL;
	}
	gen->gi_frame = f;
	gen->gi_running = 0;
	gen->gi_weakreflist = NULL;
	_PyObject_GC_TRACK(gen);
	return (PyObject *)gen;
}

--- NEW FILE: setobject.c ---
#include "Python.h"
#include "structmember.h"

/* set object implementation 
   written and maintained by Raymond D. Hettinger <python at rcn.com>
   derived from sets.py written by Greg V. Wilson, Alex Martelli, 
   Guido van Rossum, Raymond Hettinger, and Tim Peters.

   Copyright (c) 2003 Python Software Foundation.
   All rights reserved.
*/

static PyObject *
set_update(PySetObject *so, PyObject *other)
{
	PyObject *item, *data, *it;

	if (PyAnySet_Check(other)) {
		if (PyDict_Merge(so->data, ((PySetObject *)other)->data, 1) == -1) 
[...1087 lines suppressed...]
	frozenset_doc,			/* tp_doc */
	0,				/* tp_traverse */
	0,				/* tp_clear */
	(richcmpfunc)set_richcompare,	/* tp_richcompare */
	offsetof(PySetObject, weakreflist),	/* tp_weaklistoffset */
	(getiterfunc)set_iter,		/* tp_iter */
	0,				/* tp_iternext */
	frozenset_methods,		/* 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 */
	frozenset_new,			/* tp_new */
	PyObject_Del,			/* tp_free */
};

Index: abstract.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v
retrieving revision 2.103.2.1
retrieving revision 2.103.2.2
diff -u -d -r2.103.2.1 -r2.103.2.2
--- abstract.c	28 Apr 2003 17:18:21 -0000	2.103.2.1
+++ abstract.c	7 Jan 2005 07:03:43 -0000	2.103.2.2
@@ -636,7 +636,7 @@
 	}
 	else {
 		return type_error(
-			"can't multiply sequence to non-int");
+			"can't multiply sequence by non-int");
 	}
 #if LONG_MAX != INT_MAX
 	if (count > INT_MAX) {
@@ -965,8 +965,17 @@
 					 10);
 #endif
 	m = o->ob_type->tp_as_number;
-	if (m && m->nb_int)
-		return m->nb_int(o);
+	if (m && m->nb_int) {
+		PyObject *res = m->nb_int(o);
+		if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
+			PyErr_Format(PyExc_TypeError,
+				     "__int__ returned non-int (type %.200s)",
+				     res->ob_type->tp_name);
+			Py_DECREF(res);
+			return NULL;
+		}
+		return res;
+	}
 	if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
 		return int_from_string((char*)buffer, buffer_len);
 
@@ -1022,8 +1031,17 @@
 					  10);
 #endif
 	m = o->ob_type->tp_as_number;
-	if (m && m->nb_long)
-		return m->nb_long(o);
+	if (m && m->nb_long) {
+		PyObject *res = m->nb_long(o);
+		if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
+			PyErr_Format(PyExc_TypeError,
+				     "__long__ returned non-long (type %.200s)",
+				     res->ob_type->tp_name);
+			Py_DECREF(res);
+			return NULL;
+		}
+		return res;
+	}
 	if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
 		return long_from_string(buffer, buffer_len);
 
@@ -1047,8 +1065,17 @@
 	}
 	if (!PyString_Check(o)) {
 		m = o->ob_type->tp_as_number;
-		if (m && m->nb_float)
-			return m->nb_float(o);
+		if (m && m->nb_float) {
+			PyObject *res = m->nb_float(o);
+			if (res && !PyFloat_Check(res)) {
+				PyErr_Format(PyExc_TypeError,
+			          "__float__ returned non-float (type %.200s)",
+			          res->ob_type->tp_name);
+				Py_DECREF(res);
+				return NULL;
+			}
+			return res;
+		}
 	}
 	return PyFloat_FromString(o, NULL);
 }
@@ -1058,6 +1085,8 @@
 int
 PySequence_Check(PyObject *s)
 {
+	if (s && PyInstance_Check(s))
+		return PyObject_HasAttrString(s, "__getitem__");
 	return s != NULL && s->ob_type->tp_as_sequence &&
 		s->ob_type->tp_as_sequence->sq_item != NULL;
 }
@@ -1252,7 +1281,7 @@
 		return m->sq_ass_item(s, i, o);
 	}
 
-	type_error("object doesn't support item assignment");
+	type_error("object does not support item assignment");
 	return -1;
 }
 
@@ -1380,7 +1409,7 @@
 		return NULL;
 
 	/* Guess result size and allocate space. */
-	n = PySequence_Size(v);
+	n = PyObject_Size(v);
 	if (n < 0) {
 		PyErr_Clear();
 		n = 10;  /* arbitrary */
@@ -1398,10 +1427,21 @@
 			break;
 		}
 		if (j >= n) {
-			if (n < 500)
-				n += 10;
-			else
-				n += 100;
+			int oldn = n;
+			/* The over-allocation strategy can grow a bit faster
+			   than for lists because unlike lists the 
+			   over-allocation isn't permanent -- we reclaim
+			   the excess before the end of this routine.
+			   So, grow by ten and then add 25%.
+			*/
+			n += 10;
+			n += n >> 2;
+			if (n < oldn) {
+				/* Check for overflow */
+				PyErr_NoMemory();
+				Py_DECREF(item);
+				goto Fail; 
+			}
 			if (_PyTuple_Resize(&result, n) != 0) {
 				Py_DECREF(item);
 				goto Fail;
@@ -1427,79 +1467,30 @@
 PyObject *
 PySequence_List(PyObject *v)
 {
-	PyObject *it;      /* iter(v) */
 	PyObject *result;  /* result list */
-	int n;		   /* guess for result list size */
-	int i;
+	PyObject *rv;      /* return value from PyList_Extend */
 
 	if (v == NULL)
 		return null_error();
 
-	/* Special-case list(a_list), for speed. */
-	if (PyList_Check(v))
-		return PyList_GetSlice(v, 0, PyList_GET_SIZE(v));
-
-	/* 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)
+	result = PyList_New(0);
+	if (result == NULL)
 		return NULL;
 
-	/* 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 */
-	result = PyList_New(n);
-	if (result == NULL) {
-		Py_DECREF(it);
+	rv = _PyList_Extend((PyListObject *)result, v);
+	if (rv == NULL) {
+		Py_DECREF(result);
 		return NULL;
 	}
-
-	/* Run iterator to exhaustion. */
-	for (i = 0; ; i++) {
-		PyObject *item = PyIter_Next(it);
-		if (item == NULL) {
-			if (PyErr_Occurred()) {
-				Py_DECREF(result);
-				result = NULL;
-			}
-			break;
-		}
-		if (i < n)
-			PyList_SET_ITEM(result, i, item); /* steals ref */
-		else {
-			int status = PyList_Append(result, item);
-			Py_DECREF(item);  /* append creates a new ref */
-			if (status < 0) {
-				Py_DECREF(result);
-				result = NULL;
-				break;
-			}
-		}
-	}
-
-	/* Cut back result list if initial guess was too large. */
-	if (i < n && result != NULL) {
-		if (PyList_SetSlice(result, i, n, (PyObject *)NULL) != 0) {
-			Py_DECREF(result);
-			result = NULL;
-		}
-	}
-	Py_DECREF(it);
+	Py_DECREF(rv);
 	return result;
 }
 
 PyObject *
 PySequence_Fast(PyObject *v, const char *m)
 {
+	PyObject *it;
+
 	if (v == NULL)
 		return null_error();
 
@@ -1508,9 +1499,15 @@
 		return v;
 	}
 
-	v = PySequence_Tuple(v);
-	if (v == NULL && PyErr_ExceptionMatches(PyExc_TypeError))
-		return type_error(m);
+ 	it = PyObject_GetIter(v);
+	if (it == NULL) {
+		if (PyErr_ExceptionMatches(PyExc_TypeError))
+			return type_error(m);
+		return NULL;
+	}
+
+	v = PySequence_List(it);
+	Py_DECREF(it);
 
 	return v;
 }
@@ -1643,8 +1640,13 @@
 int
 PyMapping_Check(PyObject *o)
 {
-	return o && o->ob_type->tp_as_mapping &&
-		o->ob_type->tp_as_mapping->mp_subscript;
+	if (o && PyInstance_Check(o))
+		return PyObject_HasAttrString(o, "__getitem__");
+
+	return  o && o->ob_type->tp_as_mapping &&
+		o->ob_type->tp_as_mapping->mp_subscript &&
+		!(o->ob_type->tp_as_sequence && 
+		  o->ob_type->tp_as_sequence->sq_slice);
 }
 
 int
@@ -2035,8 +2037,8 @@
 	return -1;
 }
 
-int
-PyObject_IsInstance(PyObject *inst, PyObject *cls)
+static int
+recursive_isinstance(PyObject *inst, PyObject *cls, int recursion_depth)
 {
 	PyObject *icls;
 	static PyObject *__class__ = NULL;
@@ -2071,14 +2073,20 @@
 		}
 	}
 	else if (PyTuple_Check(cls)) {
-		/* Not a general sequence -- that opens up the road to
-		   recursion and stack overflow. */
 		int i, n;
 
+                if (!recursion_depth) {
+                    PyErr_SetString(PyExc_RuntimeError,
+                                    "nest level of tuple too deep");
+                    return -1;
+                }
+
 		n = PyTuple_GET_SIZE(cls);
 		for (i = 0; i < n; i++) {
-			retval = PyObject_IsInstance(
-				inst, PyTuple_GET_ITEM(cls, i));
+			retval = recursive_isinstance(
+                                    inst,
+                                    PyTuple_GET_ITEM(cls, i),
+                                    recursion_depth-1);
 			if (retval != 0)
 				break;
 		}
@@ -2103,7 +2111,13 @@
 }
 
 int
-PyObject_IsSubclass(PyObject *derived, PyObject *cls)
+PyObject_IsInstance(PyObject *inst, PyObject *cls)
+{
+    return recursive_isinstance(inst, cls, Py_GetRecursionLimit());
+}
+
+static  int
+recursive_issubclass(PyObject *derived, PyObject *cls, int recursion_depth)
 {
 	int retval;
 
@@ -2115,9 +2129,17 @@
 		if (PyTuple_Check(cls)) {
 			int i;
 			int n = PyTuple_GET_SIZE(cls);
+
+                        if (!recursion_depth) {
+                            PyErr_SetString(PyExc_RuntimeError,
+                                            "nest level of tuple too deep");
+                            return -1;
+                        }
 			for (i = 0; i < n; ++i) {
-				retval = PyObject_IsSubclass(
-					derived, PyTuple_GET_ITEM(cls, i));
+				retval = recursive_issubclass(
+                                            derived,
+                                            PyTuple_GET_ITEM(cls, i),
+                                            recursion_depth-1);
 				if (retval != 0) {
 					/* either found it, or got an error */
 					return retval;
@@ -2143,6 +2165,13 @@
 	return retval;
 }
 
+int
+PyObject_IsSubclass(PyObject *derived, PyObject *cls)
+{
+    return recursive_issubclass(derived, cls, Py_GetRecursionLimit());
+}
+
+
 PyObject *
 PyObject_GetIter(PyObject *o)
 {

Index: bufferobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/bufferobject.c,v
retrieving revision 2.19.2.1
retrieving revision 2.19.2.2
diff -u -d -r2.19.2.1 -r2.19.2.2
--- bufferobject.c	28 Apr 2003 17:18:21 -0000	2.19.2.1
+++ bufferobject.c	7 Jan 2005 07:03:44 -0000	2.19.2.2
@@ -9,21 +9,68 @@
 	PyObject *b_base;
 	void *b_ptr;
 	int b_size;
+	int b_offset;
 	int b_readonly;
 	long b_hash;
 } PyBufferObject;
 
 
+static int
+get_buf(PyBufferObject *self, void **ptr, int *size)
+{
+	if (self->b_base == NULL) {
+		assert (ptr != NULL);
+		*ptr = self->b_ptr;
+		*size = self->b_size;
+	}
+	else {
+		int count, offset;
+		getreadbufferproc proc;
+		PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
+		if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
+			PyErr_SetString(PyExc_TypeError,
+				"single-segment buffer object expected");
+			return 0;
+		}
+		if (self->b_readonly)
+			proc = bp->bf_getreadbuffer;
+		else
+			proc = (getreadbufferproc)bp->bf_getwritebuffer;
+		if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
+			return 0;
+		/* apply constraints to the start/end */
+		if (self->b_offset > count)
+			offset = count;
+		else
+			offset = self->b_offset;
+		*(char **)ptr = *(char **)ptr + offset;
+		if (self->b_size == Py_END_OF_BUFFER)
+			*size = count;
+		else
+			*size = self->b_size;
+		if (offset + *size > count)
+			*size = count - offset;
+	}
+	return 1;
+}
+
+
 static PyObject *
-_PyBuffer_FromMemory(PyObject *base, void *ptr, int size, int readonly)
+buffer_from_memory(PyObject *base, int size, int offset, void *ptr,
+		   int readonly)
 {
 	PyBufferObject * b;
 
-	if ( size < 0 ) {
+	if (size < 0 && size != Py_END_OF_BUFFER) {
 		PyErr_SetString(PyExc_ValueError,
 				"size must be zero or positive");
 		return NULL;
 	}
+	if (offset < 0) {
+		PyErr_SetString(PyExc_ValueError,
+				"offset must be zero or positive");
+		return NULL;
+	}
 
 	b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
 	if ( b == NULL )
@@ -33,6 +80,7 @@
 	b->b_base = base;
 	b->b_ptr = ptr;
 	b->b_size = size;
+	b->b_offset = offset;
 	b->b_readonly = readonly;
 	b->b_hash = -1;
 
@@ -40,43 +88,27 @@
 }
 
 static PyObject *
-_PyBuffer_FromObject(PyObject *base, int offset, int size,
-                     getreadbufferproc proc, int readonly)
+buffer_from_object(PyObject *base, int size, int offset, int readonly)
 {
-	PyBufferProcs *pb = base->ob_type->tp_as_buffer;
-	void *p;
-	int count;
-
-	if ( offset < 0 ) {
+	if (offset < 0) {
 		PyErr_SetString(PyExc_ValueError,
 				"offset must be zero or positive");
 		return NULL;
 	}
-
-	if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
-	{
-		PyErr_SetString(PyExc_TypeError,
-				"single-segment buffer object expected");
-		return NULL;
+	if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
+		/* another buffer, refer to the base object */
+		PyBufferObject *b = (PyBufferObject *)base;
+		if (b->b_size != Py_END_OF_BUFFER) {
+			int base_size = b->b_size - offset;
+			if (base_size < 0)
+				base_size = 0;
+			if (size == Py_END_OF_BUFFER || size > base_size)
+				size = base_size;
+		}
+		offset += b->b_offset;
+		base = b->b_base;
 	}
-	if ( (count = (*proc)(base, 0, &p)) < 0 )
-		return NULL;
-
-	/* apply constraints to the start/end */
-	if ( size == Py_END_OF_BUFFER || size < 0 )
-		size = count;
-	if ( offset > count )
-		offset = count;
-	if ( offset + size > count )
-		size = count - offset;
-	
-	/* if the base object is another buffer, then "deref" it,
-	 * except if the base of the other buffer is NULL
-	 */
-	if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) )
-		base = ((PyBufferObject *)base)->b_base;
-	
-	return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
+	return buffer_from_memory(base, size, offset, NULL, readonly);
 }
 
 
@@ -93,8 +125,7 @@
 		return NULL;
 	}
 
-	return _PyBuffer_FromObject(base, offset, size,
-				    pb->bf_getreadbuffer, 1);
+	return buffer_from_object(base, size, offset, 1);
 }
 
 PyObject *
@@ -110,21 +141,19 @@
 		return NULL;
 	}
 
-	return _PyBuffer_FromObject(base, offset, size,
-				    (getreadbufferproc)pb->bf_getwritebuffer,
-				    0);
+	return buffer_from_object(base, size,  offset, 0);
 }
 
 PyObject *
 PyBuffer_FromMemory(void *ptr, int size)
 {
-	return _PyBuffer_FromMemory(NULL, ptr, size, 1);
+	return buffer_from_memory(NULL, size, 0, ptr, 1);
 }
 
 PyObject *
 PyBuffer_FromReadWriteMemory(void *ptr, int size)
 {
-	return _PyBuffer_FromMemory(NULL, ptr, size, 0);
+	return buffer_from_memory(NULL, size, 0, ptr, 0);
 }
 
 PyObject *
@@ -147,6 +176,7 @@
 	b->b_base = NULL;
 	b->b_ptr = (void *)(b + 1);
 	b->b_size = size;
+	b->b_offset = 0;
 	b->b_readonly = 0;
 	b->b_hash = -1;
 
@@ -186,12 +216,16 @@
 static int
 buffer_compare(PyBufferObject *self, PyBufferObject *other)
 {
-	int len_self = self->b_size;
-	int len_other = other->b_size;
-	int min_len = (len_self < len_other) ? len_self : len_other;
-	int cmp;
+	void *p1, *p2;
+	int len_self, len_other, min_len, cmp;
+
+	if (!get_buf(self, &p1, &len_self))
+		return -1;
+	if (!get_buf(other, &p2, &len_other))
+		return -1;
+	min_len = (len_self < len_other) ? len_self : len_other;
 	if (min_len > 0) {
-		cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
+		cmp = memcmp(p1, p2, min_len);
 		if (cmp != 0)
 			return cmp;
 	}
@@ -211,17 +245,19 @@
 					   self);
 	else
 		return PyString_FromFormat(
-			"<%s buffer for %p, ptr %p, size %d at %p>",
+			"<%s buffer for %p, size %d, offset %d at %p>",
 			status,
 			self->b_base,
-			self->b_ptr,
 			self->b_size,
+			self->b_offset,
 			self);
 }
 
 static long
 buffer_hash(PyBufferObject *self)
 {
+	void *ptr;
+	int size;
 	register int len;
 	register unsigned char *p;
 	register long x;
@@ -229,19 +265,28 @@
 	if ( self->b_hash != -1 )
 		return self->b_hash;
 
+	/* XXX potential bugs here, a readonly buffer does not imply that the
+	 * underlying memory is immutable.  b_readonly is a necessary but not
+	 * sufficient condition for a buffer to be hashable.  Perhaps it would
+	 * be better to only allow hashing if the underlying object is known to
+	 * be immutable (e.g. PyString_Check() is true).  Another idea would
+	 * be to call tp_hash on the underlying object and see if it raises
+	 * an error. */
 	if ( !self->b_readonly )
 	{
-		/* ### use different wording, since this is conditional? */
-		PyErr_SetString(PyExc_TypeError, "unhashable type");
+		PyErr_SetString(PyExc_TypeError,
+				"writable buffers are not hashable");
 		return -1;
 	}
 
-	len = self->b_size;
-	p = (unsigned char *) self->b_ptr;
+	if (!get_buf(self, &ptr, &size))
+		return -1;
+	p = (unsigned char *) ptr;
+	len = size;
 	x = *p << 7;
 	while (--len >= 0)
 		x = (1000003*x) ^ *p++;
-	x ^= self->b_size;
+	x ^= size;
 	if (x == -1)
 		x = -2;
 	self->b_hash = x;
@@ -251,7 +296,11 @@
 static PyObject *
 buffer_str(PyBufferObject *self)
 {
-	return PyString_FromStringAndSize(self->b_ptr, self->b_size);
+	void *ptr;
+	int size;
+	if (!get_buf(self, &ptr, &size))
+		return NULL;
+	return PyString_FromStringAndSize(ptr, size);
 }
 
 /* Sequence methods */
@@ -259,17 +308,21 @@
 static int
 buffer_length(PyBufferObject *self)
 {
-	return self->b_size;
+	void *ptr;
+	int size;
+	if (!get_buf(self, &ptr, &size))
+		return -1;
+	return size;
 }
 
 static PyObject *
 buffer_concat(PyBufferObject *self, PyObject *other)
 {
 	PyBufferProcs *pb = other->ob_type->tp_as_buffer;
-	char *p1;
-	void *p2;
+	void *ptr1, *ptr2;
+	char *p;
 	PyObject *ob;
-	int count;
+	int size, count;
 
 	if ( pb == NULL ||
 	     pb->bf_getreadbuffer == NULL ||
@@ -286,23 +339,26 @@
 		return NULL;
 	}
 
+ 	if (!get_buf(self, &ptr1, &size))
+ 		return NULL;
+ 
 	/* optimize special case */
-	if ( self->b_size == 0 )
+	if ( size == 0 )
 	{
 	    Py_INCREF(other);
 	    return other;
 	}
 
-	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
+	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
 		return NULL;
 
-	ob = PyString_FromStringAndSize(NULL, self->b_size + count);
-	p1 = PyString_AS_STRING(ob);
-	memcpy(p1, self->b_ptr, self->b_size);
-	memcpy(p1 + self->b_size, p2, count);
+ 	ob = PyString_FromStringAndSize(NULL, size + count);
+ 	p = PyString_AS_STRING(ob);
+ 	memcpy(p, ptr1, size);
+ 	memcpy(p + size, ptr2, count);
 
 	/* there is an extra byte in the string object, so this is safe */
-	p1[self->b_size + count] = '\0';
+	p[size + count] = '\0';
 
 	return ob;
 }
@@ -312,11 +368,13 @@
 {
 	PyObject *ob;
 	register char *p;
-	void *ptr = self->b_ptr;
-	int size = self->b_size;
+	void *ptr;
+	int size;
 
 	if ( count < 0 )
 		count = 0;
+	if (!get_buf(self, &ptr, &size))
+		return NULL;
 	ob = PyString_FromStringAndSize(NULL, size * count);
 	if ( ob == NULL )
 		return NULL;
@@ -337,26 +395,33 @@
 static PyObject *
 buffer_item(PyBufferObject *self, int idx)
 {
-	if ( idx < 0 || idx >= self->b_size )
-	{
+	void *ptr;
+	int size;
+	if (!get_buf(self, &ptr, &size))
+		return NULL;
+	if ( idx < 0 || idx >= size ) {
 		PyErr_SetString(PyExc_IndexError, "buffer index out of range");
 		return NULL;
 	}
-	return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
+	return PyString_FromStringAndSize((char *)ptr + idx, 1);
 }
 
 static PyObject *
 buffer_slice(PyBufferObject *self, int left, int right)
 {
+	void *ptr;
+	int size;
+	if (!get_buf(self, &ptr, &size))
+		return NULL;
 	if ( left < 0 )
 		left = 0;
 	if ( right < 0 )
 		right = 0;
-	if ( right > self->b_size )
-		right = self->b_size;
+	if ( right > size )
+		right = size;
 	if ( right < left )
 		right = left;
-	return PyString_FromStringAndSize((char *)self->b_ptr + left,
+	return PyString_FromStringAndSize((char *)ptr + left,
 					  right - left);
 }
 
@@ -364,7 +429,8 @@
 buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
 {
 	PyBufferProcs *pb;
-	void *p;
+	void *ptr1, *ptr2;
+	int size;
 	int count;
 
 	if ( self->b_readonly ) {
@@ -373,7 +439,10 @@
 		return -1;
 	}
 
-	if (idx < 0 || idx >= self->b_size) {
+	if (!get_buf(self, &ptr1, &size))
+		return -1;
+
+	if (idx < 0 || idx >= size) {
 		PyErr_SetString(PyExc_IndexError,
 				"buffer assignment index out of range");
 		return -1;
@@ -395,7 +464,7 @@
 		return -1;
 	}
 
-	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
+	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
 		return -1;
 	if ( count != 1 ) {
 		PyErr_SetString(PyExc_TypeError,
@@ -403,7 +472,7 @@
 		return -1;
 	}
 
-	((char *)self->b_ptr)[idx] = *(char *)p;
+	((char *)ptr1)[idx] = *(char *)ptr2;
 	return 0;
 }
 
@@ -411,7 +480,8 @@
 buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
 {
 	PyBufferProcs *pb;
-	void *p;
+	void *ptr1, *ptr2;
+	int size;
 	int slice_len;
 	int count;
 
@@ -436,17 +506,19 @@
 				"single-segment buffer object expected");
 		return -1;
 	}
-	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
+	if (!get_buf(self, &ptr1, &size))
+		return -1;
+	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
 		return -1;
 
 	if ( left < 0 )
 		left = 0;
-	else if ( left > self->b_size )
-		left = self->b_size;
+	else if ( left > size )
+		left = size;
 	if ( right < left )
 		right = left;
-	else if ( right > self->b_size )
-		right = self->b_size;
+	else if ( right > size )
+		right = size;
 	slice_len = right - left;
 
 	if ( count != slice_len ) {
@@ -457,7 +529,7 @@
 	}
 
 	if ( slice_len )
-	    memcpy((char *)self->b_ptr + left, p, slice_len);
+	    memcpy((char *)ptr1 + left, ptr2, slice_len);
 
 	return 0;
 }
@@ -467,13 +539,15 @@
 static int
 buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
 {
+	int size;
 	if ( idx != 0 ) {
 		PyErr_SetString(PyExc_SystemError,
 				"accessing non-existent buffer segment");
 		return -1;
 	}
-	*pp = self->b_ptr;
-	return self->b_size;
+	if (!get_buf(self, pp, &size))
+		return -1;
+	return size;
 }
 
 static int
@@ -490,21 +564,29 @@
 static int
 buffer_getsegcount(PyBufferObject *self, int *lenp)
 {
-	if ( lenp )
-		*lenp = self->b_size;
+	void *ptr;
+	int size;
+	if (!get_buf(self, &ptr, &size))
+		return -1;
+	if (lenp)
+		*lenp = size;
 	return 1;
 }
 
 static int
 buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
 {
+	void *ptr;
+	int size;
 	if ( idx != 0 ) {
 		PyErr_SetString(PyExc_SystemError,
 				"accessing non-existent buffer segment");
 		return -1;
 	}
-	*pp = (const char *)self->b_ptr;
-	return self->b_size;
+	if (!get_buf(self, &ptr, &size))
+		return -1;
+	*pp = (const char *)ptr;
+	return size;
 }
 
 

Index: classobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/classobject.c,v
retrieving revision 2.158.2.1
retrieving revision 2.158.2.2
diff -u -d -r2.158.2.1 -r2.158.2.2
--- classobject.c	28 Apr 2003 17:18:20 -0000	2.158.2.1
+++ classobject.c	7 Jan 2005 07:03:44 -0000	2.158.2.2
@@ -670,13 +670,14 @@
 		_Py_NewReference((PyObject *)inst);
 		inst->ob_refcnt = refcnt;
 		_PyObject_GC_TRACK(inst);
-		/* If Py_REF_DEBUG, the original decref dropped _Py_RefTotal,
-		 * but _Py_NewReference bumped it again, so that's a wash.
-		 * If Py_TRACE_REFS, _Py_NewReference re-added self to the
-		 * object chain, so no more to do there either.
+		/* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
+		 * we need to undo that. */
+		_Py_DEC_REFTOTAL;
+		/* If Py_TRACE_REFS, _Py_NewReference re-added self to the
+		 * object chain, so no more to do there.
 		 * If COUNT_ALLOCS, the original decref bumped tp_frees, and
-		 * _Py_NewReference bumped tp_allocs:  both of those need to
-		 * be undone.
+		 * _Py_NewReference bumped tp_allocs: both of those need to be
+		 * undone.
 		 */
 #ifdef COUNT_ALLOCS
 		--inst->ob_type->tp_frees;
@@ -750,7 +751,7 @@
 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
 			return NULL;
 		PyErr_Clear();
-		args = Py_BuildValue("(OO)", inst, name);
+		args = PyTuple_Pack(2, inst, name);
 		if (args == NULL)
 			return NULL;
 		res = PyEval_CallObject(func, args);
@@ -847,9 +848,9 @@
 	if (func == NULL)
 		return instance_setattr1(inst, name, v);
 	if (v == NULL)
-		args = Py_BuildValue("(OO)", inst, name);
+		args = PyTuple_Pack(2, inst, name);
 	else
-		args = Py_BuildValue("(OOO)", inst, name, v);
+		args = PyTuple_Pack(3, inst, name, v);
 	if (args == NULL)
 		return -1;
 	res = PyEval_CallObject(func, args);
@@ -953,6 +954,7 @@
 				return _Py_HashPointer(inst);
 			}
 		}
+		Py_XDECREF(func);
 		PyErr_SetString(PyExc_TypeError, "unhashable instance");
 		return -1;
 	}
@@ -1037,7 +1039,7 @@
 	func = instance_getattr(inst, getitemstr);
 	if (func == NULL)
 		return NULL;
-	arg = Py_BuildValue("(O)", key);
+	arg = PyTuple_Pack(1, key);
 	if (arg == NULL) {
 		Py_DECREF(func);
 		return NULL;
@@ -1068,9 +1070,9 @@
 	if (func == NULL)
 		return -1;
 	if (value == NULL)
-		arg = Py_BuildValue("(O)", key);
+		arg = PyTuple_Pack(1, key);
 	else
-		arg = Py_BuildValue("(OO)", key, value);
+		arg = PyTuple_Pack(2, key, value);
 	if (arg == NULL) {
 		Py_DECREF(func);
 		return -1;
@@ -1280,7 +1282,7 @@
 	if (func) {
 		PyObject *res;
 		int ret;
-		PyObject *arg = Py_BuildValue("(O)", member);
+		PyObject *arg = PyTuple_Pack(1, member);
 		if(arg == NULL) {
 			Py_DECREF(func);
 			return -1;
@@ -1345,7 +1347,7 @@
 		Py_INCREF(Py_NotImplemented);
 		return Py_NotImplemented;
 	}
-	args = Py_BuildValue("(O)", w);
+	args = PyTuple_Pack(1, w);
 	if (args == NULL) {
 		Py_DECREF(func);
 		return NULL;
@@ -1388,7 +1390,7 @@
 		return generic_binary_op(v, w, opname);
 	}
 
-	args = Py_BuildValue("(O)", w);
+	args = PyTuple_Pack(1, w);
 	if (args == NULL) {
 		Py_DECREF(coercefunc);
 		return NULL;
@@ -1473,7 +1475,7 @@
 		return 1;
 	}
 	/* Has __coerce__ method: call it */
-	args = Py_BuildValue("(O)", w);
+	args = PyTuple_Pack(1, w);
 	if (args == NULL) {
 		return -1;
 	}
@@ -1586,7 +1588,7 @@
 		return 2;
 	}
 
-	args = Py_BuildValue("(O)", w);
+	args = PyTuple_Pack(1, w);
 	if (args == NULL) {
 		Py_DECREF(cmp_func);
 		return -2;
@@ -1746,7 +1748,7 @@
 		func = PyObject_GetAttrString(v, "__pow__");
 		if (func == NULL)
 			return NULL;
-		args = Py_BuildValue("(OO)", w, z);
+		args = PyTuple_Pack(2, w, z);
 		if (args == NULL) {
 			Py_DECREF(func);
 			return NULL;
@@ -1785,7 +1787,7 @@
 			PyErr_Clear();
 			return instance_pow(v, w, z);
 		}
-		args = Py_BuildValue("(OO)", w, z);
+		args = PyTuple_Pack(2, w, z);
 		if (args == NULL) {
 			Py_DECREF(func);
 			return NULL;
@@ -1858,7 +1860,7 @@
 		return res;
 	}
 
-	args = Py_BuildValue("(O)", w);
+	args = PyTuple_Pack(1, w);
 	if (args == NULL) {
 		Py_DECREF(method);
 		return NULL;
@@ -1871,9 +1873,6 @@
 	return res;
 }
 
-/* Map rich comparison operators to their swapped version, e.g. LT --> GT */
-static int swapped_op[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE};
-
 static PyObject *
 instance_richcompare(PyObject *v, PyObject *w, int op)
 {
@@ -1887,7 +1886,7 @@
 	}
 
 	if (PyInstance_Check(w)) {
-		res = half_richcompare(w, v, swapped_op[op]);
+		res = half_richcompare(w, v, _Py_SwappedOp[op]);
 		if (res != Py_NotImplemented)
 			return res;
 		Py_DECREF(res);
@@ -1969,7 +1968,6 @@
 static PyObject *
 instance_call(PyObject *func, PyObject *arg, PyObject *kw)
 {
-	PyThreadState *tstate = PyThreadState_GET();
 	PyObject *res, *call = PyObject_GetAttrString(func, "__call__");
 	if (call == NULL) {
 		PyInstanceObject *inst = (PyInstanceObject*) func;
@@ -1989,14 +1987,13 @@
 	       a() # infinite recursion
 	   This bounces between instance_call() and PyObject_Call() without
 	   ever hitting eval_frame() (which has the main recursion check). */
-	if (tstate->recursion_depth++ > Py_GetRecursionLimit()) {
-		PyErr_SetString(PyExc_RuntimeError,
-				"maximum __call__ recursion depth exceeded");
+	if (Py_EnterRecursiveCall(" in __call__")) {
 		res = NULL;
 	}
-	else
+	else {
 		res = PyObject_Call(call, arg, kw);
-	tstate->recursion_depth--;
+		Py_LeaveRecursiveCall();
+	}
 	Py_DECREF(call);
 	return res;
 }
@@ -2139,19 +2136,34 @@
 	{NULL}	/* Sentinel */
 };
 
-/* The getattr() implementation for PyMethod objects is similar to
-   PyObject_GenericGetAttr(), but instead of looking in __dict__ it
-   asks im_self for the attribute.  Then the error handling is a bit
-   different because we want to preserve the exception raised by the
-   delegate, unless we have an alternative from our class. */
+/* Christian Tismer argued convincingly that method attributes should
+   (nearly) always override function attributes.
+   The one exception is __doc__; there's a default __doc__ which
+   should only be used for the class, not for instances */
+
+static PyObject *
+instancemethod_get_doc(PyMethodObject *im, void *context)
+{
+	static PyObject *docstr;
+	if (docstr == NULL) {
+		docstr= PyString_InternFromString("__doc__");
+		if (docstr == NULL)
+			return NULL;
+	}
+	return PyObject_GetAttr(im->im_func, docstr);
+}
+
+static PyGetSetDef instancemethod_getset[] = {
+	{"__doc__", (getter)instancemethod_get_doc, NULL, NULL},
+	{0}
+};
 
 static PyObject *
 instancemethod_getattro(PyObject *obj, PyObject *name)
 {
 	PyMethodObject *im = (PyMethodObject *)obj;
 	PyTypeObject *tp = obj->ob_type;
-	PyObject *descr = NULL, *res;
-	descrgetfunc f = NULL;
+	PyObject *descr = NULL;
 
 	if (PyType_HasFeature(tp, Py_TPFLAGS_HAVE_CLASS)) {
 		if (tp->tp_dict == NULL) {
@@ -2161,30 +2173,17 @@
 		descr = _PyType_Lookup(tp, name);
 	}
 
-	f = NULL;
 	if (descr != NULL) {
-		f = TP_DESCR_GET(descr->ob_type);
-		if (f != NULL && PyDescr_IsData(descr))
+		descrgetfunc f = TP_DESCR_GET(descr->ob_type);
+		if (f != NULL)
 			return f(descr, obj, (PyObject *)obj->ob_type);
+		else {
+			Py_INCREF(descr);
+			return descr;
+		}
 	}
 
-	res = PyObject_GetAttr(im->im_func, name);
-	if (res != NULL || !PyErr_ExceptionMatches(PyExc_AttributeError))
-		return res;
-
-	if (f != NULL) {
-		PyErr_Clear();
-		return f(descr, obj, (PyObject *)obj->ob_type);
-	}
-
-	if (descr != NULL) {
-		PyErr_Clear();
-		Py_INCREF(descr);
-		return descr;
-	}
-
-	assert(PyErr_Occurred());
-	return NULL;
+	return PyObject_GetAttr(im->im_func, name);
 }
 
 PyDoc_STRVAR(instancemethod_doc,
@@ -2491,7 +2490,7 @@
 	0,					/* tp_iternext */
 	0,					/* tp_methods */
 	instancemethod_memberlist,		/* tp_members */
-	0,					/* tp_getset */
+	instancemethod_getset,			/* tp_getset */
 	0,					/* tp_base */
 	0,					/* tp_dict */
 	instancemethod_descr_get,		/* tp_descr_get */

Index: cobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/cobject.c,v
retrieving revision 2.14
retrieving revision 2.14.2.1
diff -u -d -r2.14 -r2.14.2.1
--- cobject.c	13 Jun 2002 20:32:56 -0000	2.14
+++ cobject.c	7 Jan 2005 07:03:44 -0000	2.14.2.1
@@ -46,9 +46,9 @@
     self = PyObject_NEW(PyCObject, &PyCObject_Type);
     if (self == NULL)
         return NULL;
-    self->cobject=cobj;
-    self->destructor=(destructor1)destr;
-    self->desc=desc;
+    self->cobject = cobj;
+    self->destructor = (destructor1)destr;
+    self->desc = desc;
 
     return (PyObject *)self;
 }
@@ -99,6 +99,20 @@
     return r;
 }
 
+int
+PyCObject_SetVoidPtr(PyObject *_self, void *cobj)
+{
+    PyCObject* self = (PyCObject*)_self;
+    if (self == NULL || !PyCObject_Check(self) ||
+	self->destructor != NULL) {
+	PyErr_SetString(PyExc_TypeError, 
+			"Invalid call to PyCObject_SetVoidPtr");
+	return 0;
+    }
+    self->cobject = cobj;
+    return 1;
+}
+
 static void
 PyCObject_dealloc(PyCObject *self)
 {

Index: complexobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/complexobject.c,v
retrieving revision 2.62.2.1
retrieving revision 2.62.2.2
diff -u -d -r2.62.2.1 -r2.62.2.2
--- complexobject.c	28 Apr 2003 17:18:20 -0000	2.62.2.1
+++ complexobject.c	7 Jan 2005 07:03:44 -0000	2.62.2.2
@@ -272,13 +272,23 @@
 static void
 complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision)
 {
-	if (v->cval.real == 0.)
-		PyOS_snprintf(buf, bufsz, "%.*gj",
-			      precision, v->cval.imag);
-	else
-		PyOS_snprintf(buf, bufsz, "(%.*g%+.*gj)",
-			      precision, v->cval.real,
-			      precision, v->cval.imag);
+	char format[32];
+	if (v->cval.real == 0.) {
+		PyOS_snprintf(format, 32, "%%.%ig", precision);
+		PyOS_ascii_formatd(buf, bufsz, format, v->cval.imag);
+		strncat(buf, "j", bufsz);
+	} else {
+		char re[64], im[64];
+		char *fmt;
+		PyOS_snprintf(format, 32, "%%.%ig", precision);
+		PyOS_ascii_formatd(re, 64, format, v->cval.real);
+		PyOS_ascii_formatd(im, 64, format, v->cval.imag);
+		if (v->cval.imag < 0.)
+			fmt = "(%s%sj)";
+		else
+			fmt = "(%s+%sj)";
+		PyOS_snprintf(buf, bufsz, fmt, re, im);
+	}
 }
 
 static int
@@ -439,7 +449,7 @@
 	mod = c_diff(v->cval, c_prod(w->cval, div));
 	d = PyComplex_FromCComplex(div);
 	m = PyComplex_FromCComplex(mod);
-	z = Py_BuildValue("(OO)", d, m);
+	z = PyTuple_Pack(2, d, m);
 	Py_XDECREF(d);
 	Py_XDECREF(m);
 	return z;
@@ -593,7 +603,7 @@
 
 	if (op != Py_EQ && op != Py_NE) {
 		PyErr_SetString(PyExc_TypeError,
-			"cannot compare complex numbers using <, <=, >, >=");
+			"no ordering relation is defined for complex numbers");
 		return NULL;
 	}
 
@@ -610,7 +620,7 @@
 complex_int(PyObject *v)
 {
 	PyErr_SetString(PyExc_TypeError,
-		   "can't convert complex to int; use e.g. int(abs(z))");
+		   "can't convert complex to int; use int(abs(z))");
 	return NULL;
 }
 
@@ -618,7 +628,7 @@
 complex_long(PyObject *v)
 {
 	PyErr_SetString(PyExc_TypeError,
-		   "can't convert complex to long; use e.g. long(abs(z))");
+		   "can't convert complex to long; use long(abs(z))");
 	return NULL;
 }
 
@@ -626,7 +636,7 @@
 complex_float(PyObject *v)
 {
 	PyErr_SetString(PyExc_TypeError,
-		   "can't convert complex to float; use e.g. abs(z)");
+		   "can't convert complex to float; use abs(z)");
 	return NULL;
 }
 
@@ -662,7 +672,6 @@
 static PyObject *
 complex_subtype_from_string(PyTypeObject *type, PyObject *v)
 {
-	extern double strtod(const char *, char **);
 	const char *s, *start;
 	char *end;
 	double x=0.0, y=0.0, z;
@@ -774,7 +783,7 @@
 			}
 			errno = 0;
 			PyFPE_START_PROTECT("strtod", return 0)
-				z = strtod(s, &end) ;
+				z = PyOS_ascii_strtod(s, &end) ;
 			PyFPE_END_PROTECT(z)
 				if (errno != 0) {
 					PyOS_snprintf(buffer, sizeof(buffer),
@@ -831,7 +840,7 @@
 					 &r, &i))
 		return NULL;
 
-	/* Special-case for single argumet that is already complex */
+	/* Special-case for single argument that is already complex */
 	if (PyComplex_CheckExact(r) && i == NULL &&
 	    type == &PyComplex_Type) {
 		/* Note that we can't know whether it's safe to return
@@ -865,7 +874,7 @@
 	if (f == NULL)
 		PyErr_Clear();
 	else {
-		PyObject *args = Py_BuildValue("()");
+		PyObject *args = PyTuple_New(0);
 		if (args == NULL)
 			return NULL;
 		r = PyEval_CallObject(f, args);
@@ -882,6 +891,9 @@
 	    ((i != NULL) && (nbi == NULL || nbi->nb_float == NULL))) {
 		PyErr_SetString(PyExc_TypeError,
 			   "complex() argument must be a string or a number");
+		if (own_r) {
+			Py_DECREF(r);
+		}
 		return NULL;
 	}
 	if (PyComplex_Check(r)) {

Index: descrobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/descrobject.c,v
retrieving revision 2.27.2.1
retrieving revision 2.27.2.2
diff -u -d -r2.27.2.1 -r2.27.2.2
--- descrobject.c	28 Apr 2003 17:18:19 -0000	2.27.2.1
+++ descrobject.c	7 Jan 2005 07:03:45 -0000	2.27.2.2
@@ -690,7 +690,7 @@
 static int
 proxy_contains(proxyobject *pp, PyObject *key)
 {
-	return PySequence_Contains(pp->dict, key);
+	return PyDict_Contains(pp->dict, key);
 }
 
 static PySequenceMethods proxy_as_sequence = {
@@ -709,7 +709,10 @@
 static PyObject *
 proxy_has_key(proxyobject *pp, PyObject *key)
 {
-	return PyInt_FromLong(PySequence_Contains(pp->dict, key));
+	int res = PyDict_Contains(pp->dict, key);
+	if (res < 0)
+		return NULL;
+	return PyBool_FromLong(res);
 }
 
 static PyObject *
@@ -765,7 +768,7 @@
 
 static PyMethodDef proxy_methods[] = {
 	{"has_key",   (PyCFunction)proxy_has_key,    METH_O,
-	 PyDoc_STR("D.has_key(k) -> 1 if D has a key k, else 0")},
+	 PyDoc_STR("D.has_key(k) -> True if D has a key k, else False")},
 	{"get",       (PyCFunction)proxy_get,        METH_VARARGS,
 	 PyDoc_STR("D.get(k[,d]) -> D[k] if D.has_key(k), else d."
 	 				"  d defaults to None.")},

Index: dictobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v
retrieving revision 2.126.2.1
retrieving revision 2.126.2.2
diff -u -d -r2.126.2.1 -r2.126.2.2
--- dictobject.c	28 Apr 2003 17:18:19 -0000	2.126.2.1
+++ dictobject.c	7 Jan 2005 07:03:45 -0000	2.126.2.2
@@ -1,6 +1,12 @@
 
 /* Dictionary object implementation using a hash table */
 
+/* The distribution includes a separate file, Objects/dictnotes.txt,
+   describing explorations into dictionary design and optimization.  
+   It covers typical dictionary use patterns, the parameters for
+   tuning dictionaries, and several ideas for possible optimizations.
+*/
+
 #include "Python.h"
 
 typedef PyDictEntry dictentry;
@@ -146,6 +152,11 @@
 	INIT_NONZERO_DICT_SLOTS(mp);					\
     } while(0)
 
+/* Dictionary reuse scheme to save calls to malloc, free, and memset */
+#define MAXFREEDICTS 80
+static PyDictObject *free_dicts[MAXFREEDICTS];
+static int num_free_dicts = 0;
+
 PyObject *
 PyDict_New(void)
 {
@@ -158,10 +169,23 @@
 		Py_AtExit(show_counts);
 #endif
 	}
-	mp = PyObject_GC_New(dictobject, &PyDict_Type);
-	if (mp == NULL)
-		return NULL;
-	EMPTY_TO_MINSIZE(mp);
+	if (num_free_dicts) {
+		mp = free_dicts[--num_free_dicts];
+		assert (mp != NULL);
+		assert (mp->ob_type == &PyDict_Type);
+		_Py_NewReference((PyObject *)mp);
+		if (mp->ma_fill) {
+			EMPTY_TO_MINSIZE(mp);
+		}
+		assert (mp->ma_used == 0);
+		assert (mp->ma_table == mp->ma_smalltable);
+		assert (mp->ma_mask == PyDict_MINSIZE - 1);
+	} else {
+		mp = PyObject_GC_New(dictobject, &PyDict_Type);
+		if (mp == NULL)
+			return NULL;
+		EMPTY_TO_MINSIZE(mp);
+	}
 	mp->ma_lookup = lookdict_string;
 #ifdef SHOW_CONVERSION_COUNTS
 	++created;
@@ -525,17 +549,23 @@
 	Py_INCREF(value);
 	Py_INCREF(key);
 	insertdict(mp, key, hash, value);
-	/* If we added a key, we can safely resize.  Otherwise skip this!
-	 * If fill >= 2/3 size, adjust size.  Normally, this doubles the
-	 * size, but it's also possible for the dict to shrink (if ma_fill is
-	 * much larger than ma_used, meaning a lot of dict keys have been
-	 * deleted).
+	/* If we added a key, we can safely resize.  Otherwise just return!
+	 * If fill >= 2/3 size, adjust size.  Normally, this doubles or
+	 * quaduples the size, but it's also possible for the dict to shrink
+	 * (if ma_fill is much larger than ma_used, meaning a lot of dict 
+	 * keys have been * deleted).
+	 * 
+	 * Quadrupling the size improves average dictionary sparseness
+	 * (reducing collisions) at the cost of some memory and iteration
+	 * speed (which loops over every possible entry).  It also halves
+	 * the number of expensive resize operations in a growing dictionary.
+	 * 
+	 * Very large dictionaries (over 50K items) use doubling instead.  
+	 * This may help applications with severe memory constraints.
 	 */
-	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;
-	}
-	return 0;
+	if (!(mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2))
+		return 0;
+	return dictresize(mp, mp->ma_used*(mp->ma_used>50000 ? 2 : 4));
 }
 
 int
@@ -660,23 +690,25 @@
 int
 PyDict_Next(PyObject *op, int *ppos, PyObject **pkey, PyObject **pvalue)
 {
-	int i;
-	register dictobject *mp;
+	register int i, mask;
+	register dictentry *ep;
+
 	if (!PyDict_Check(op))
 		return 0;
-	mp = (dictobject *)op;
 	i = *ppos;
 	if (i < 0)
 		return 0;
-	while (i <= mp->ma_mask && mp->ma_table[i].me_value == NULL)
+	ep = ((dictobject *)op)->ma_table;
+	mask = ((dictobject *)op)->ma_mask;
+	while (i <= mask && ep[i].me_value == NULL)
 		i++;
 	*ppos = i+1;
-	if (i > mp->ma_mask)
+	if (i > mask)
 		return 0;
 	if (pkey)
-		*pkey = mp->ma_table[i].me_key;
+		*pkey = ep[i].me_key;
 	if (pvalue)
-		*pvalue = mp->ma_table[i].me_value;
+		*pvalue = ep[i].me_value;
 	return 1;
 }
 
@@ -698,7 +730,10 @@
 	}
 	if (mp->ma_table != mp->ma_smalltable)
 		PyMem_DEL(mp->ma_table);
-	mp->ob_type->tp_free((PyObject *)mp);
+	if (num_free_dicts < MAXFREEDICTS && mp->ob_type == &PyDict_Type)
+		free_dicts[num_free_dicts++] = mp;
+	else 
+		mp->ob_type->tp_free((PyObject *)mp);
 	Py_TRASHCAN_SAFE_END(mp)
 }
 
@@ -870,7 +905,9 @@
 dict_keys(register dictobject *mp)
 {
 	register PyObject *v;
-	register int i, j, n;
+	register int i, j;
+	dictentry *ep;
+	int mask, n;
 
   again:
 	n = mp->ma_used;
@@ -884,14 +921,17 @@
 		Py_DECREF(v);
 		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;
+	ep = mp->ma_table;
+	mask = mp->ma_mask;
+	for (i = 0, j = 0; i <= mask; i++) {
+		if (ep[i].me_value != NULL) {
+			PyObject *key = ep[i].me_key;
 			Py_INCREF(key);
 			PyList_SET_ITEM(v, j, key);
 			j++;
 		}
 	}
+	assert(j == n);
 	return v;
 }
 
@@ -899,7 +939,9 @@
 dict_values(register dictobject *mp)
 {
 	register PyObject *v;
-	register int i, j, n;
+	register int i, j;
+	dictentry *ep;
+	int mask, n;
 
   again:
 	n = mp->ma_used;
@@ -913,14 +955,17 @@
 		Py_DECREF(v);
 		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;
+	ep = mp->ma_table;
+	mask = mp->ma_mask;
+	for (i = 0, j = 0; i <= mask; i++) {
+		if (ep[i].me_value != NULL) {
+			PyObject *value = ep[i].me_value;
 			Py_INCREF(value);
 			PyList_SET_ITEM(v, j, value);
 			j++;
 		}
 	}
+	assert(j == n);
 	return v;
 }
 
@@ -929,7 +974,9 @@
 {
 	register PyObject *v;
 	register int i, j, n;
+	int mask;
 	PyObject *item, *key, *value;
+	dictentry *ep;
 
 	/* Preallocate the list of tuples, to avoid allocations during
 	 * the loop over the items, which could trigger GC, which
@@ -956,10 +1003,11 @@
 		goto again;
 	}
 	/* 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;
-			value = mp->ma_table[i].me_value;
+	ep = mp->ma_table;
+	mask = mp->ma_mask;
+	for (i = 0, j = 0; i <= mask; i++) {
+		if ((value=ep[i].me_value) != NULL) {
+			key = ep[i].me_key;
 			item = PyList_GET_ITEM(v, j);
 			Py_INCREF(key);
 			PyTuple_SET_ITEM(item, 0, key);
@@ -1017,13 +1065,32 @@
 	return NULL;
 }
 
+static int
+dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, char *methname)
+{
+	PyObject *arg = NULL;
+	int result = 0;
+
+	if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg))
+		result = -1;
+
+	else if (arg != NULL) {
+		if (PyObject_HasAttrString(arg, "keys"))
+			result = PyDict_Merge(self, arg, 1);
+		else
+			result = PyDict_MergeFromSeq2(self, arg, 1);
+	}
+	if (result == 0 && kwds != NULL)
+		result = PyDict_Merge(self, kwds, 1);
+	return result;
+}
+
 static PyObject *
-dict_update(PyObject *mp, PyObject *other)
+dict_update(PyObject *self, PyObject *args, PyObject *kwds)
 {
-	if (PyDict_Update(mp, other) < 0)
-		return NULL;
-	Py_INCREF(Py_None);
-	return Py_None;
+	if (dict_update_common(self, args, kwds, "update") != -1)
+		Py_RETURN_NONE;
+	return NULL;
 }
 
 /* Update unconditionally replaces existing items.
@@ -1139,7 +1206,7 @@
 		 * 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)
+		   if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0)
 			   return -1;
 		}
 		for (i = 0; i <= other->ma_mask; i++) {
@@ -1210,33 +1277,19 @@
 PyObject *
 PyDict_Copy(PyObject *o)
 {
-	register dictobject *mp;
-	register int i;
-	dictobject *copy;
-	dictentry *entry;
+	PyObject *copy;
 
 	if (o == NULL || !PyDict_Check(o)) {
 		PyErr_BadInternalCall();
 		return NULL;
 	}
-	mp = (dictobject *)o;
-	copy = (dictobject *)PyDict_New();
+	copy = PyDict_New();
 	if (copy == NULL)
 		return NULL;
-	if (mp->ma_used > 0) {
-		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) {
-				Py_INCREF(entry->me_key);
-				Py_INCREF(entry->me_value);
-				insertdict(copy, entry->me_key, entry->me_hash,
-					   entry->me_value);
-			}
-		}
-	}
-	return (PyObject *)copy;
+	if (PyDict_Merge(copy, o, 1) == 0)
+		return copy;
+	Py_DECREF(copy);
+	return copy;
 }
 
 int
@@ -1244,7 +1297,7 @@
 {
 	if (mp == NULL || !PyDict_Check(mp)) {
 		PyErr_BadInternalCall();
-		return 0;
+		return -1;
 	}
 	return ((dictobject *)mp)->ma_used;
 }
@@ -1539,8 +1592,7 @@
 dict_clear(register dictobject *mp)
 {
 	PyDict_Clear((PyObject *)mp);
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1671,57 +1723,37 @@
 }
 
 
-static PyObject *dictiter_new(dictobject *, binaryfunc);
-
-static PyObject *
-select_key(PyObject *key, PyObject *value)
-{
-	Py_INCREF(key);
-	return key;
-}
-
-static PyObject *
-select_value(PyObject *key, PyObject *value)
-{
-	Py_INCREF(value);
-	return value;
-}
-
-static PyObject *
-select_item(PyObject *key, PyObject *value)
-{
-	PyObject *res = PyTuple_New(2);
-
-	if (res != NULL) {
-		Py_INCREF(key);
-		Py_INCREF(value);
-		PyTuple_SET_ITEM(res, 0, key);
-		PyTuple_SET_ITEM(res, 1, value);
-	}
-	return res;
-}
+extern PyTypeObject PyDictIterKey_Type; /* Forward */
+extern PyTypeObject PyDictIterValue_Type; /* Forward */
+extern PyTypeObject PyDictIterItem_Type; /* Forward */
+static PyObject *dictiter_new(dictobject *, PyTypeObject *);
 
 static PyObject *
 dict_iterkeys(dictobject *dict)
 {
-	return dictiter_new(dict, select_key);
+	return dictiter_new(dict, &PyDictIterKey_Type);
 }
 
 static PyObject *
 dict_itervalues(dictobject *dict)
 {
-	return dictiter_new(dict, select_value);
+	return dictiter_new(dict, &PyDictIterValue_Type);
 }
 
 static PyObject *
 dict_iteritems(dictobject *dict)
 {
-	return dictiter_new(dict, select_item);
+	return dictiter_new(dict, &PyDictIterItem_Type);
 }
 
 
 PyDoc_STRVAR(has_key__doc__,
-"D.has_key(k) -> 1 if D has a key k, else 0");
+"D.has_key(k) -> True if D has a key k, else False");
+
+PyDoc_STRVAR(contains__doc__,
+"D.__contains__(k) -> True if D has a key k, else False");
+
+PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
 
 PyDoc_STRVAR(get__doc__,
 "D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.");
@@ -1747,7 +1779,8 @@
 "D.values() -> list of D's values");
 
 PyDoc_STRVAR(update__doc__,
-"D.update(E) -> None.  Update D from E: for k in E.keys(): D[k] = E[k]");
+"D.update(E, **F) -> None.  Update D from E and F: for k in E: D[k] = E[k]\n\
+(if E has keys else: for (k, v) in E: D[k] = v) then: for k in F: D[k] = F[k]");
 
 PyDoc_STRVAR(fromkeys__doc__,
 "dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v.\n\
@@ -1769,6 +1802,10 @@
 "D.iteritems() -> an iterator over the (key, value) items of D");
 
 static PyMethodDef mapp_methods[] = {
+	{"__contains__",(PyCFunction)dict_has_key,      METH_O | METH_COEXIST,
+	 contains__doc__},
+	{"__getitem__", (PyCFunction)dict_subscript,	METH_O | METH_COEXIST,
+	 getitem__doc__},
 	{"has_key",	(PyCFunction)dict_has_key,      METH_O,
 	 has_key__doc__},
 	{"get",         (PyCFunction)dict_get,          METH_VARARGS,
@@ -1785,7 +1822,7 @@
 	 items__doc__},
 	{"values",	(PyCFunction)dict_values,	METH_NOARGS,
 	 values__doc__},
-	{"update",	(PyCFunction)dict_update,	METH_O,
+	{"update",	(PyCFunction)dict_update,	METH_VARARGS | METH_KEYWORDS,
 	 update__doc__},
 	{"fromkeys",	(PyCFunction)dict_fromkeys,	METH_VARARGS | METH_CLASS,
 	 fromkeys__doc__},
@@ -1802,10 +1839,11 @@
 	{NULL,		NULL}	/* sentinel */
 };
 
-static int
-dict_contains(dictobject *mp, PyObject *key)
+int
+PyDict_Contains(PyObject *op, PyObject *key)
 {
 	long hash;
+	dictobject *mp = (dictobject *)op;
 
 	if (!PyString_CheckExact(key) ||
 	    (hash = ((PyStringObject *) key)->ob_shash) == -1) {
@@ -1825,7 +1863,7 @@
 	0,					/* sq_slice */
 	0,					/* sq_ass_item */
 	0,					/* sq_ass_slice */
-	(objobjproc)dict_contains,		/* sq_contains */
+	(objobjproc)PyDict_Contains,		/* sq_contains */
 	0,					/* sq_inplace_concat */
 	0,					/* sq_inplace_repeat */
 };
@@ -1853,21 +1891,7 @@
 static int
 dict_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
-	PyObject *arg = NULL;
-	int result = 0;
-
-	if (!PyArg_UnpackTuple(args, "dict", 0, 1, &arg))
-		result = -1;
-
-	else if (arg != NULL) {
-		if (PyObject_HasAttrString(arg, "keys"))
-			result = PyDict_Merge(self, arg, 1);
-		else
-			result = PyDict_MergeFromSeq2(self, arg, 1);
-	}
-	if (result == 0 && kwds != NULL)
-		result = PyDict_Merge(self, kwds, 1);
-	return result;
+	return dict_update_common(self, args, kwds, "dict");
 }
 
 static long
@@ -1880,7 +1904,7 @@
 static PyObject *
 dict_iter(dictobject *dict)
 {
-	return dictiter_new(dict, select_key);
+	return dictiter_new(dict, &PyDictIterKey_Type);
 }
 
 PyDoc_STRVAR(dictionary_doc,
@@ -1979,30 +2003,38 @@
 	return err;
 }
 
-/* Dictionary iterator type */
-
-extern PyTypeObject PyDictIter_Type; /* Forward */
+/* Dictionary iterator types */
 
 typedef struct {
 	PyObject_HEAD
 	dictobject *di_dict; /* Set to NULL when iterator is exhausted */
 	int di_used;
 	int di_pos;
-	binaryfunc di_select;
+	PyObject* di_result; /* reusable result tuple for iteritems */
+	long len;
 } dictiterobject;
 
 static PyObject *
-dictiter_new(dictobject *dict, binaryfunc select)
+dictiter_new(dictobject *dict, PyTypeObject *itertype)
 {
 	dictiterobject *di;
-	di = PyObject_New(dictiterobject, &PyDictIter_Type);
+	di = PyObject_New(dictiterobject, itertype);
 	if (di == NULL)
 		return NULL;
 	Py_INCREF(dict);
 	di->di_dict = dict;
 	di->di_used = dict->ma_used;
 	di->di_pos = 0;
-	di->di_select = select;
+	di->len = dict->ma_used;
+	if (itertype == &PyDictIterItem_Type) {
+		di->di_result = PyTuple_Pack(2, Py_None, Py_None);
+		if (di->di_result == NULL) {
+			Py_DECREF(di);
+			return NULL;
+		}
+	}
+	else
+		di->di_result = NULL;
 	return (PyObject *)di;
 }
 
@@ -2010,34 +2042,66 @@
 dictiter_dealloc(dictiterobject *di)
 {
 	Py_XDECREF(di->di_dict);
+	Py_XDECREF(di->di_result);
 	PyObject_Del(di);
 }
 
-static PyObject *dictiter_iternext(dictiterobject *di)
+static int
+dictiter_len(dictiterobject *di)
 {
-	PyObject *key, *value;
+	if (di->di_dict != NULL && di->di_used == di->di_dict->ma_used)
+		return di->len;
+	return 0;
+}
 
-	if (di->di_dict == NULL)
+static PySequenceMethods dictiter_as_sequence = {
+	(inquiry)dictiter_len,		/* sq_length */
+	0,				/* sq_concat */
+};
+
+static PyObject *dictiter_iternextkey(dictiterobject *di)
+{
+	PyObject *key;
+	register int i, mask;
+	register dictentry *ep;
+	dictobject *d = di->di_dict;
+
+	if (d == NULL)
 		return NULL;
+	assert (PyDict_Check(d));
 
-	if (di->di_used != di->di_dict->ma_used) {
+	if (di->di_used != d->ma_used) {
 		PyErr_SetString(PyExc_RuntimeError,
 				"dictionary changed size during iteration");
 		di->di_used = -1; /* Make this state sticky */
 		return NULL;
 	}
-	if (PyDict_Next((PyObject *)(di->di_dict), &di->di_pos, &key, &value))
-		return (*di->di_select)(key, value);
 
-	Py_DECREF(di->di_dict);
+	i = di->di_pos;
+	if (i < 0)
+		goto fail;
+	ep = d->ma_table;
+	mask = d->ma_mask;
+	while (i <= mask && ep[i].me_value == NULL)
+		i++;
+	di->di_pos = i+1;
+	if (i > mask)
+		goto fail;
+	di->len--;
+	key = ep[i].me_key;
+	Py_INCREF(key);
+	return key;
+
+fail:
+	Py_DECREF(d);
 	di->di_dict = NULL;
 	return NULL;
 }
 
-PyTypeObject PyDictIter_Type = {
+PyTypeObject PyDictIterKey_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,					/* ob_size */
-	"dictionary-iterator",			/* tp_name */
+	"dictionary-keyiterator",		/* tp_name */
 	sizeof(dictiterobject),			/* tp_basicsize */
 	0,					/* tp_itemsize */
 	/* methods */
@@ -2048,7 +2112,7 @@
 	0,					/* tp_compare */
 	0,					/* tp_repr */
 	0,					/* tp_as_number */
-	0,					/* tp_as_sequence */
+	&dictiter_as_sequence,			/* tp_as_sequence */
 	0,					/* tp_as_mapping */
 	0,					/* tp_hash */
 	0,					/* tp_call */
@@ -2063,12 +2127,161 @@
 	0,					/* tp_richcompare */
 	0,					/* tp_weaklistoffset */
 	PyObject_SelfIter,			/* tp_iter */
-	(iternextfunc)dictiter_iternext,	/* 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 */
+	(iternextfunc)dictiter_iternextkey,	/* tp_iternext */
+};
+
+static PyObject *dictiter_iternextvalue(dictiterobject *di)
+{
+	PyObject *value;
+	register int i, mask;
+	register dictentry *ep;
+	dictobject *d = di->di_dict;
+
+	if (d == NULL)
+		return NULL;
+	assert (PyDict_Check(d));
+
+	if (di->di_used != d->ma_used) {
+		PyErr_SetString(PyExc_RuntimeError,
+				"dictionary changed size during iteration");
+		di->di_used = -1; /* Make this state sticky */
+		return NULL;
+	}
+
+	i = di->di_pos;
+	mask = d->ma_mask;
+	if (i < 0 || i > mask)
+		goto fail;
+	ep = d->ma_table;
+	while ((value=ep[i].me_value) == NULL) {
+		i++;
+		if (i > mask)
+			goto fail;
+	}
+	di->di_pos = i+1;
+	di->len--;
+	Py_INCREF(value);
+	return value;
+
+fail:
+	Py_DECREF(d);
+	di->di_dict = NULL;
+	return NULL;
+}
+
+PyTypeObject PyDictIterValue_Type = {
+	PyObject_HEAD_INIT(&PyType_Type)
+	0,					/* ob_size */
+	"dictionary-valueiterator",		/* tp_name */
+	sizeof(dictiterobject),			/* tp_basicsize */
+	0,					/* tp_itemsize */
+	/* methods */
+	(destructor)dictiter_dealloc, 		/* tp_dealloc */
+	0,					/* tp_print */
+	0,					/* tp_getattr */
+	0,					/* tp_setattr */
+	0,					/* tp_compare */
+	0,					/* tp_repr */
+	0,					/* tp_as_number */
+	&dictiter_as_sequence,			/* tp_as_sequence */
+	0,					/* tp_as_mapping */
+	0,					/* tp_hash */
+	0,					/* tp_call */
+	0,					/* tp_str */
+	PyObject_GenericGetAttr,		/* 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 */
+	PyObject_SelfIter,			/* tp_iter */
+	(iternextfunc)dictiter_iternextvalue,	/* tp_iternext */
+};
+
+static PyObject *dictiter_iternextitem(dictiterobject *di)
+{
+	PyObject *key, *value, *result = di->di_result;
+	register int i, mask;
+	register dictentry *ep;
+	dictobject *d = di->di_dict;
+
+	if (d == NULL)
+		return NULL;
+	assert (PyDict_Check(d));
+
+	if (di->di_used != d->ma_used) {
+		PyErr_SetString(PyExc_RuntimeError,
+				"dictionary changed size during iteration");
+		di->di_used = -1; /* Make this state sticky */
+		return NULL;
+	}
+
+	i = di->di_pos;
+	if (i < 0)
+		goto fail;
+	ep = d->ma_table;
+	mask = d->ma_mask;
+	while (i <= mask && ep[i].me_value == NULL)
+		i++;
+	di->di_pos = i+1;
+	if (i > mask)
+		goto fail;
+
+	if (result->ob_refcnt == 1) {
+		Py_INCREF(result);
+		Py_DECREF(PyTuple_GET_ITEM(result, 0));
+		Py_DECREF(PyTuple_GET_ITEM(result, 1));
+	} else {
+		result = PyTuple_New(2);
+		if (result == NULL) 
+			return NULL;
+	}
+	di->len--;
+	key = ep[i].me_key;
+	value = ep[i].me_value;
+	Py_INCREF(key);
+	Py_INCREF(value);
+	PyTuple_SET_ITEM(result, 0, key);
+	PyTuple_SET_ITEM(result, 1, value);
+	return result;
+
+fail:
+	Py_DECREF(d);
+	di->di_dict = NULL;
+	return NULL;
+}
+
+PyTypeObject PyDictIterItem_Type = {
+	PyObject_HEAD_INIT(&PyType_Type)
+	0,					/* ob_size */
+	"dictionary-itemiterator",		/* tp_name */
+	sizeof(dictiterobject),			/* tp_basicsize */
+	0,					/* tp_itemsize */
+	/* methods */
+	(destructor)dictiter_dealloc, 		/* tp_dealloc */
+	0,					/* tp_print */
+	0,					/* tp_getattr */
+	0,					/* tp_setattr */
+	0,					/* tp_compare */
+	0,					/* tp_repr */
+	0,					/* tp_as_number */
+	&dictiter_as_sequence,			/* tp_as_sequence */
+	0,					/* tp_as_mapping */
+	0,					/* tp_hash */
+	0,					/* tp_call */
+	0,					/* tp_str */
+	PyObject_GenericGetAttr,		/* 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 */
+	PyObject_SelfIter,			/* tp_iter */
+	(iternextfunc)dictiter_iternextitem,	/* tp_iternext */
 };

Index: enumobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/enumobject.c,v
retrieving revision 1.2.2.1
retrieving revision 1.2.2.2
diff -u -d -r1.2.2.1 -r1.2.2.2
--- enumobject.c	28 Apr 2003 17:18:19 -0000	1.2.2.1
+++ enumobject.c	7 Jan 2005 07:04:00 -0000	1.2.2.2
@@ -6,6 +6,7 @@
 	PyObject_HEAD
 	long      en_index;        /* current index of enumeration */
 	PyObject* en_sit;          /* secondary iterator of enumeration */
+	PyObject* en_result;	   /* result tuple  */
 } enumobject;
 
 PyTypeObject PyEnum_Type;
@@ -30,6 +31,12 @@
 		Py_DECREF(en);
 		return NULL;
 	}
+	en->en_result = PyTuple_Pack(2, Py_None, Py_None);
+	if (en->en_result == NULL) {
+		Py_DECREF(en->en_sit);
+		Py_DECREF(en);
+		return NULL;
+	}
 	return (PyObject *)en;
 }
 
@@ -38,42 +45,60 @@
 {
 	PyObject_GC_UnTrack(en);
 	Py_XDECREF(en->en_sit);
+	Py_XDECREF(en->en_result);
 	en->ob_type->tp_free(en);
 }
 
 static int
 enum_traverse(enumobject *en, visitproc visit, void *arg)
 {
-	if (en->en_sit)
-		return visit(en->en_sit, arg);
+	int err;
+
+	if (en->en_sit) {
+		err = visit(en->en_sit, arg);
+		if (err)
+			return err;
+	}
+	if (en->en_result) {
+		err = visit(en->en_result, arg);
+		if (err)
+			return err;
+	}
 	return 0;
 }
 
 static PyObject *
 enum_next(enumobject *en)
 {
-	PyObject *result;
 	PyObject *next_index;
 	PyObject *next_item;
+	PyObject *result = en->en_result;
+	PyObject *it = en->en_sit;
 
-	result = PyTuple_New(2);
-	if (result == NULL)
+	next_item = (*it->ob_type->tp_iternext)(it);
+	if (next_item == NULL)
 		return NULL;
 
 	next_index = PyInt_FromLong(en->en_index);
 	if (next_index == NULL) {
-		Py_DECREF(result);
+		Py_DECREF(next_item);
 		return NULL;
 	}
-	PyTuple_SET_ITEM(result, 0, next_index);
+	en->en_index++;
 
-	next_item = PyIter_Next(en->en_sit);
-	if (next_item == NULL) {
-		Py_DECREF(result);
-		return NULL;
+	if (result->ob_refcnt == 1) {
+		Py_INCREF(result);
+		Py_DECREF(PyTuple_GET_ITEM(result, 0));
+		Py_DECREF(PyTuple_GET_ITEM(result, 1));
+	} else {
+		result = PyTuple_New(2);
+		if (result == NULL) {
+			Py_DECREF(next_index);
+			Py_DECREF(next_item);
+			return NULL;
+		}
 	}
-
-	en->en_index++;
+	PyTuple_SET_ITEM(result, 0, next_index);
 	PyTuple_SET_ITEM(result, 1, next_item);
 	return result;
 }
@@ -130,3 +155,150 @@
 	enum_new,                       /* tp_new */
 	PyObject_GC_Del,                /* tp_free */
 };
+
+/* Reversed Object ***************************************************************/
+
+typedef struct {
+	PyObject_HEAD
+	long      index;
+	PyObject* seq;
+} reversedobject;
+
+static PyObject *
+reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	long n;
+	PyObject *seq;
+	reversedobject *ro;
+
+	if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq))
+		return NULL;
+
+	if (PyObject_HasAttrString(seq, "__reversed__"))
+		return PyObject_CallMethod(seq, "__reversed__", NULL);
+
+	if (!PySequence_Check(seq)) {
+		PyErr_SetString(PyExc_TypeError,
+				"argument to reversed() must be a sequence");
+		return NULL;
+	}
+
+	n = PySequence_Size(seq);
+	if (n == -1)
+		return NULL;
+
+	ro = (reversedobject *)type->tp_alloc(type, 0);
+	if (ro == NULL)
+		return NULL;
+
+	ro->index = n-1;
+	Py_INCREF(seq);
+	ro->seq = seq;
+	return (PyObject *)ro;
+}
+
+static void
+reversed_dealloc(reversedobject *ro)
+{
+	PyObject_GC_UnTrack(ro);
+	Py_XDECREF(ro->seq);
+	ro->ob_type->tp_free(ro);
+}
+
+static int
+reversed_traverse(reversedobject *ro, visitproc visit, void *arg)
+{
+	if (ro->seq)
+		return visit((PyObject *)(ro->seq), arg);
+	return 0;
+}
+
+static PyObject *
+reversed_next(reversedobject *ro)
+{
+	PyObject *item;
+	long index = ro->index;
+
+	if (index >= 0) {
+		item = PySequence_GetItem(ro->seq, index);
+		if (item != NULL) {
+			ro->index--;
+			return item;
+		}
+		if (PyErr_ExceptionMatches(PyExc_IndexError) ||
+		    PyErr_ExceptionMatches(PyExc_StopIteration))
+			PyErr_Clear();
+	}
+	ro->index = -1;
+	Py_CLEAR(ro->seq);
+	return NULL;
+}
+
+PyDoc_STRVAR(reversed_doc,
+"reversed(sequence) -> reverse iterator over values of the sequence\n"
+"\n"
+"Return a reverse iterator");
+
+static int
+reversed_len(reversedobject *ro)
+{
+	int position, seqsize;
+
+	if (ro->seq == NULL)
+		return 0;
+	seqsize = PySequence_Size(ro->seq);
+	if (seqsize == -1)
+		return -1;
+	position = ro->index + 1;
+	return (seqsize < position)  ?  0  :  position;
+}
+
+static PySequenceMethods reversed_as_sequence = {
+	(inquiry)reversed_len,		/* sq_length */
+	0,				/* sq_concat */
+};
+
+PyTypeObject PyReversed_Type = {
+	PyObject_HEAD_INIT(&PyType_Type)
+	0,                              /* ob_size */
+	"reversed",                     /* tp_name */
+	sizeof(reversedobject),         /* tp_basicsize */
+	0,                              /* tp_itemsize */
+	/* methods */
+	(destructor)reversed_dealloc,   /* tp_dealloc */
+	0,                              /* tp_print */
+	0,                              /* tp_getattr */
+	0,                              /* tp_setattr */
+	0,                              /* tp_compare */
+	0,                              /* tp_repr */
+	0,                              /* tp_as_number */
+	&reversed_as_sequence,          /* tp_as_sequence */
+	0,                              /* tp_as_mapping */
+	0,                              /* tp_hash */
+	0,                              /* tp_call */
+	0,                              /* tp_str */
+	PyObject_GenericGetAttr,        /* tp_getattro */
+	0,                              /* tp_setattro */
+	0,                              /* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+		Py_TPFLAGS_BASETYPE,    /* tp_flags */
+	reversed_doc,                   /* tp_doc */
+	(traverseproc)reversed_traverse,/* tp_traverse */
+	0,                              /* tp_clear */
+	0,                              /* tp_richcompare */
+	0,                              /* tp_weaklistoffset */
+	PyObject_SelfIter,		/* tp_iter */
+	(iternextfunc)reversed_next,    /* 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 */
+	reversed_new,                   /* tp_new */
+	PyObject_GC_Del,                /* tp_free */
+};

Index: fileobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v
retrieving revision 2.164.2.1
retrieving revision 2.164.2.2
diff -u -d -r2.164.2.1 -r2.164.2.2
--- fileobject.c	28 Apr 2003 17:18:18 -0000	2.164.2.1
+++ fileobject.c	7 Jan 2005 07:04:01 -0000	2.164.2.2
@@ -21,17 +21,6 @@
 #include <windows.h>
 #endif /* _MSC_VER */
 
-#ifdef macintosh
-#ifdef USE_GUSI
-#define HAVE_FTRUNCATE
-#endif
-#endif
-
-#ifdef __MWERKS__
-/* Mwerks fopen() doesn't always set errno */
-#define NO_FOPEN_ERRNO
-#endif
-
 #if defined(PYOS_OS2) && defined(PYCC_GCC)
 #include <io.h>
 #endif
@@ -52,13 +41,11 @@
 #define FUNLOCKFILE(f)
 #endif
 
-#ifdef WITH_UNIVERSAL_NEWLINES
 /* Bits in f_newlinetypes */
 #define NEWLINE_UNKNOWN	0	/* No newline seen, yet */
 #define NEWLINE_CR 1		/* \r newline seen */
 #define NEWLINE_LF 2		/* \n newline seen */
 #define NEWLINE_CRLF 4		/* \r\n newline seen */
-#endif
 
 FILE *
 PyFile_AsFile(PyObject *f)
@@ -96,9 +83,10 @@
 #else
 		char *msg = "Is a directory";
 #endif
-		PyObject *exc = PyObject_CallFunction(PyExc_IOError, "(is)", 
+		PyObject *exc = PyObject_CallFunction(PyExc_IOError, "(is)",
 						      EISDIR, msg);
 		PyErr_SetObject(PyExc_IOError, exc);
+		Py_XDECREF(exc);
 		return NULL;
 	}
 #endif
@@ -107,8 +95,8 @@
 
 
 static PyObject *
-fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode,
-		 int (*close)(FILE *), PyObject *wname)
+fill_file_fields(PyFileObject *f, FILE *fp, PyObject *name, char *mode,
+		 int (*close)(FILE *))
 {
 	assert(f != NULL);
 	assert(PyFile_Check(f));
@@ -116,23 +104,22 @@
 
 	Py_DECREF(f->f_name);
 	Py_DECREF(f->f_mode);
-#ifdef Py_USING_UNICODE
-	if (wname)
-		f->f_name = PyUnicode_FromObject(wname);
-	else
-#endif
-		f->f_name = PyString_FromString(name);
+	Py_DECREF(f->f_encoding);
+
+        Py_INCREF (name);
+        f->f_name = name;
+
 	f->f_mode = PyString_FromString(mode);
 
 	f->f_close = close;
 	f->f_softspace = 0;
 	f->f_binary = strchr(mode,'b') != NULL;
 	f->f_buf = NULL;
-#ifdef WITH_UNIVERSAL_NEWLINES
 	f->f_univ_newline = (strchr(mode, 'U') != NULL);
 	f->f_newlinetypes = NEWLINE_UNKNOWN;
 	f->f_skipnextlf = 0;
-#endif
+	Py_INCREF(Py_None);
+	f->f_encoding = Py_None;
 
 	if (f->f_name == NULL || f->f_mode == NULL)
 		return NULL;
@@ -164,59 +151,31 @@
 		return NULL;
 	}
 	errno = 0;
-#ifdef HAVE_FOPENRF
-	if (*mode == '*') {
-		FILE *fopenRF();
-		f->f_fp = fopenRF(name, mode+1);
-	}
-	else
-#endif
-	{
-#ifdef WITH_UNIVERSAL_NEWLINES
-		if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0)
-			mode = "rb";
-#else
-		/* Compatibility: specifying U in a Python without universal
-		** newlines is allowed, and the file is opened as a normal text
-		** file.
-		*/
-		if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0)
-			mode = "r";
-#endif
+
+	if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0)
+		mode = "rb";
 #ifdef MS_WINDOWS
-		if (PyUnicode_Check(f->f_name)) {
-			PyObject *wmode; 
-			wmode = PyUnicode_DecodeASCII(mode, strlen(mode), NULL); 
-			if (f->f_name && wmode) {
-				Py_BEGIN_ALLOW_THREADS
-				/* PyUnicode_AS_UNICODE OK without thread
-				   lock as it is a simple dereference. */
-				f->f_fp = _wfopen(PyUnicode_AS_UNICODE(f->f_name),
-						  PyUnicode_AS_UNICODE(wmode));
-				Py_END_ALLOW_THREADS
-			}
-			Py_XDECREF(wmode);
-		}
-#endif
-		if (NULL == f->f_fp && NULL != name) {
+	if (PyUnicode_Check(f->f_name)) {
+		PyObject *wmode;
+		wmode = PyUnicode_DecodeASCII(mode, strlen(mode), NULL);
+		if (f->f_name && wmode) {
 			Py_BEGIN_ALLOW_THREADS
-			f->f_fp = fopen(name, mode);
+			/* PyUnicode_AS_UNICODE OK without thread
+			   lock as it is a simple dereference. */
+			f->f_fp = _wfopen(PyUnicode_AS_UNICODE(f->f_name),
+					  PyUnicode_AS_UNICODE(wmode));
 			Py_END_ALLOW_THREADS
 		}
+		Py_XDECREF(wmode);
 	}
-	if (f->f_fp == NULL) {
-#ifdef NO_FOPEN_ERRNO
-		/* Metroworks only, wich does not always sets errno */
-		if (errno == 0) {
-			PyObject *v;
-			v = Py_BuildValue("(is)", 0, "Cannot open file");
-			if (v != NULL) {
-				PyErr_SetObject(PyExc_IOError, v);
-				Py_DECREF(v);
-			}
-			return NULL;
-		}
 #endif
+	if (NULL == f->f_fp && NULL != name) {
+		Py_BEGIN_ALLOW_THREADS
+		f->f_fp = fopen(name, mode);
+		Py_END_ALLOW_THREADS
+	}
+
+	if (f->f_fp == NULL) {
 #ifdef _MSC_VER
 		/* MSVC 6 (Microsoft) leaves errno at 0 for bad mode strings,
 		 * across all Windows flavors.  When it sets EINVAL varies
@@ -234,11 +193,7 @@
 			PyErr_Format(PyExc_IOError, "invalid mode: %s",
 				     mode);
 		else
-#ifdef MS_WINDOWS
 			PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, f->f_name);
-#else
-			PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
-#endif /* MS_WINDOWS */
 		f = NULL;
 	}
 	if (f != NULL)
@@ -252,10 +207,12 @@
 	PyFileObject *f = (PyFileObject *)PyFile_Type.tp_new(&PyFile_Type,
 							     NULL, NULL);
 	if (f != NULL) {
-		if (fill_file_fields(f, fp, name, mode, close, NULL) == NULL) {
+                PyObject *o_name = PyString_FromString(name);
+		if (fill_file_fields(f, fp, o_name, mode, close) == NULL) {
 			Py_DECREF(f);
 			f = NULL;
 		}
+                Py_DECREF(o_name);
 	}
 	return (PyObject *) f;
 }
@@ -279,29 +236,56 @@
 void
 PyFile_SetBufSize(PyObject *f, int bufsize)
 {
+	PyFileObject *file = (PyFileObject *)f;
 	if (bufsize >= 0) {
-#ifdef HAVE_SETVBUF
 		int type;
 		switch (bufsize) {
 		case 0:
 			type = _IONBF;
 			break;
+#ifdef HAVE_SETVBUF
 		case 1:
 			type = _IOLBF;
 			bufsize = BUFSIZ;
 			break;
+#endif
 		default:
 			type = _IOFBF;
+#ifndef HAVE_SETVBUF
+			bufsize = BUFSIZ;
+#endif
+			break;
 		}
-		setvbuf(((PyFileObject *)f)->f_fp, (char *)NULL,
-			type, bufsize);
+		fflush(file->f_fp);
+		if (type == _IONBF) {
+			PyMem_Free(file->f_setbuf);
+			file->f_setbuf = NULL;
+		} else {
+			file->f_setbuf = PyMem_Realloc(file->f_setbuf, bufsize);
+		}
+#ifdef HAVE_SETVBUF
+		setvbuf(file->f_fp, file->f_setbuf, type, bufsize);
 #else /* !HAVE_SETVBUF */
-		if (bufsize <= 1)
-			setbuf(((PyFileObject *)f)->f_fp, (char *)NULL);
+		setbuf(file->f_fp, file->f_setbuf);
 #endif /* !HAVE_SETVBUF */
 	}
 }
 
+/* Set the encoding used to output Unicode strings.
+   Returh 1 on success, 0 on failure. */
+
+int
+PyFile_SetEncoding(PyObject *f, const char *enc)
+{
+	PyFileObject *file = (PyFileObject*)f;
+	PyObject *str = PyString_FromString(enc);
+	if (!str)
+		return 0;
+	Py_DECREF(file->f_encoding);
+	file->f_encoding = str;
+	return 1;
+}
+
 static PyObject *
 err_closed(void)
 {
@@ -316,13 +300,24 @@
 static void
 file_dealloc(PyFileObject *f)
 {
+	int sts = 0;
+	if (f->weakreflist != NULL)
+		PyObject_ClearWeakRefs((PyObject *) f);
 	if (f->f_fp != NULL && f->f_close != NULL) {
 		Py_BEGIN_ALLOW_THREADS
-		(*f->f_close)(f->f_fp);
+		sts = (*f->f_close)(f->f_fp);
 		Py_END_ALLOW_THREADS
+		if (sts == EOF) 
+#ifdef HAVE_STRERROR
+			PySys_WriteStderr("close failed: [Errno %d] %s\n", errno, strerror(errno)); 
+#else
+			PySys_WriteStderr("close failed: [Errno %d]\n", errno); 
+#endif
 	}
+	PyMem_Free(f->f_setbuf);
 	Py_XDECREF(f->f_name);
 	Py_XDECREF(f->f_mode);
+	Py_XDECREF(f->f_encoding);
 	drop_readahead(f);
 	f->ob_type->tp_free((PyObject *)f);
 }
@@ -365,6 +360,8 @@
 		}
 		f->f_fp = NULL;
 	}
+	PyMem_Free(f->f_setbuf);
+	f->f_setbuf = NULL;
 	if (sts == EOF)
 		return PyErr_SetFromErrno(PyExc_IOError);
 	if (sts != 0)
@@ -484,9 +481,7 @@
 		clearerr(f->f_fp);
 		return NULL;
 	}
-#ifdef WITH_UNIVERSAL_NEWLINES
 	f->f_skipnextlf = 0;
-#endif
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -496,18 +491,33 @@
 static PyObject *
 file_truncate(PyFileObject *f, PyObject *args)
 {
-	int ret;
 	Py_off_t newsize;
-	PyObject *newsizeobj;
+	PyObject *newsizeobj = NULL;
+	Py_off_t initialpos;
+	int ret;
 
 	if (f->f_fp == NULL)
 		return err_closed();
-	newsizeobj = NULL;
 	if (!PyArg_UnpackTuple(args, "truncate", 0, 1, &newsizeobj))
 		return NULL;
 
+	/* Get current file position.  If the file happens to be open for
+	 * update and the last operation was an input operation, C doesn't
+	 * define what the later fflush() will do, but we promise truncate()
+	 * won't change the current position (and fflush() *does* change it
+	 * then at least on Windows).  The easiest thing is to capture
+	 * current pos now and seek back to it at the end.
+	 */
+	Py_BEGIN_ALLOW_THREADS
+	errno = 0;
+	initialpos = _portable_ftell(f->f_fp);
+	Py_END_ALLOW_THREADS
+	if (initialpos == -1)
+		goto onioerror;
+
 	/* Set newsize to current postion if newsizeobj NULL, else to the
-	   specified value. */
+	 * specified value.
+	 */
 	if (newsizeobj != NULL) {
 #if !defined(HAVE_LARGEFILE_SUPPORT)
 		newsize = PyInt_AsLong(newsizeobj);
@@ -519,17 +529,13 @@
 		if (PyErr_Occurred())
 			return NULL;
 	}
-	else {
-		/* Default to current position. */
-		Py_BEGIN_ALLOW_THREADS
-		errno = 0;
-		newsize = _portable_ftell(f->f_fp);
-		Py_END_ALLOW_THREADS
-		if (newsize == -1)
-			goto onioerror;
-	}
+	else /* default to current position */
+		newsize = initialpos;
 
-	/* Flush the file. */
+	/* Flush the stream.  We're mixing stream-level I/O with lower-level
+	 * I/O, and a flush may be necessary to synch both platform views
+	 * of the current file state.
+	 */
 	Py_BEGIN_ALLOW_THREADS
 	errno = 0;
 	ret = fflush(f->f_fp);
@@ -541,66 +547,47 @@
 	/* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
 	   so don't even try using it. */
 	{
-		Py_off_t current;	/* current file position */
 		HANDLE hFile;
-		int error;
 
-		/* current <- current file postion. */
-		if (newsizeobj == NULL)
-			current = newsize;
-		else {
-			Py_BEGIN_ALLOW_THREADS
-			errno = 0;
-			current = _portable_ftell(f->f_fp);
-			Py_END_ALLOW_THREADS
-			if (current == -1)
-				goto onioerror;
-		}
-
-		/* Move to newsize. */
-		if (current != newsize) {
-			Py_BEGIN_ALLOW_THREADS
-			errno = 0;
-			error = _portable_fseek(f->f_fp, newsize, SEEK_SET)
-				!= 0;
-			Py_END_ALLOW_THREADS
-			if (error)
-				goto onioerror;
-		}
+		/* Have to move current pos to desired endpoint on Windows. */
+		Py_BEGIN_ALLOW_THREADS
+		errno = 0;
+		ret = _portable_fseek(f->f_fp, newsize, SEEK_SET) != 0;
+		Py_END_ALLOW_THREADS
+		if (ret)
+			goto onioerror;
 
 		/* Truncate.  Note that this may grow the file! */
 		Py_BEGIN_ALLOW_THREADS
 		errno = 0;
 		hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp));
-		error = hFile == (HANDLE)-1;
-		if (!error) {
-			error = SetEndOfFile(hFile) == 0;
-			if (error)
+		ret = hFile == (HANDLE)-1;
+		if (ret == 0) {
+			ret = SetEndOfFile(hFile) == 0;
+			if (ret)
 				errno = EACCES;
 		}
 		Py_END_ALLOW_THREADS
-		if (error)
+		if (ret)
 			goto onioerror;
-
-		/* Restore original file position. */
-		if (current != newsize) {
-			Py_BEGIN_ALLOW_THREADS
-			errno = 0;
-			error = _portable_fseek(f->f_fp, current, SEEK_SET)
-				!= 0;
-			Py_END_ALLOW_THREADS
-			if (error)
-				goto onioerror;
-		}
 	}
 #else
 	Py_BEGIN_ALLOW_THREADS
 	errno = 0;
 	ret = ftruncate(fileno(f->f_fp), newsize);
 	Py_END_ALLOW_THREADS
-	if (ret != 0) goto onioerror;
+	if (ret != 0)
+		goto onioerror;
 #endif /* !MS_WINDOWS */
 
+	/* Restore original file position. */
+	Py_BEGIN_ALLOW_THREADS
+	errno = 0;
+	ret = _portable_fseek(f->f_fp, initialpos, SEEK_SET) != 0;
+	Py_END_ALLOW_THREADS
+	if (ret)
+		goto onioerror;
+
 	Py_INCREF(Py_None);
 	return Py_None;
 
@@ -627,7 +614,6 @@
 		clearerr(f->f_fp);
 		return NULL;
 	}
-#ifdef WITH_UNIVERSAL_NEWLINES
 	if (f->f_skipnextlf) {
 		int c;
 		c = GETC(f->f_fp);
@@ -636,7 +622,6 @@
 			f->f_skipnextlf = 0;
 		} else if (c != EOF) ungetc(c, f->f_fp);
 	}
-#endif
 #if !defined(HAVE_LARGEFILE_SUPPORT)
 	return PyInt_FromLong(pos);
 #else
@@ -714,12 +699,7 @@
 		   works.  We can't use the lseek() value either, because we
 		   need to take the amount of buffered data into account.
 		   (Yet another reason why stdio stinks. :-) */
-#ifdef USE_GUSI2
-		pos = lseek(fileno(f->f_fp), 1L, SEEK_CUR);
-		pos = lseek(fileno(f->f_fp), -1L, SEEK_CUR);
-#else
 		pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR);
-#endif
 		if (pos >= 0) {
 			pos = ftell(f->f_fp);
 		}
@@ -833,7 +813,7 @@
 	while (ntodo > 0) {
 		Py_BEGIN_ALLOW_THREADS
 		errno = 0;
-		nnow = Py_UniversalNewlineFread(ptr+ndone, ntodo, f->f_fp, 
+		nnow = Py_UniversalNewlineFread(ptr+ndone, ntodo, f->f_fp,
 						(PyObject *)f);
 		Py_END_ALLOW_THREADS
 		if (nnow == 0) {
@@ -1073,18 +1053,12 @@
 	size_t used_v_size;	/* # used slots in buffer */
 	size_t increment;       /* amount to increment the buffer */
 	PyObject *v;
-#ifdef WITH_UNIVERSAL_NEWLINES
 	int newlinetypes = f->f_newlinetypes;
 	int skipnextlf = f->f_skipnextlf;
 	int univ_newline = f->f_univ_newline;
-#endif
 
 #if defined(USE_FGETS_IN_GETLINE)
-#ifdef WITH_UNIVERSAL_NEWLINES
 	if (n <= 0 && !univ_newline )
-#else
-	if (n <= 0)
-#endif
 		return getline_via_fgets(fp);
 #endif
 	total_v_size = n > 0 ? n : 100;
@@ -1097,15 +1071,14 @@
 	for (;;) {
 		Py_BEGIN_ALLOW_THREADS
 		FLOCKFILE(fp);
-#ifdef WITH_UNIVERSAL_NEWLINES
 		if (univ_newline) {
 			c = 'x'; /* Shut up gcc warning */
 			while ( buf != end && (c = GETC(fp)) != EOF ) {
 				if (skipnextlf ) {
 					skipnextlf = 0;
 					if (c == '\n') {
-						/* Seeing a \n here with 
-						 * skipnextlf true means we 
+						/* Seeing a \n here with
+						 * skipnextlf true means we
 						 * saw a \r before.
 						 */
 						newlinetypes |= NEWLINE_CRLF;
@@ -1126,17 +1099,14 @@
 			if ( c == EOF && skipnextlf )
 				newlinetypes |= NEWLINE_CR;
 		} else /* If not universal newlines use the normal loop */
-#endif
 		while ((c = GETC(fp)) != EOF &&
 		       (*buf++ = c) != '\n' &&
 			buf != end)
 			;
 		FUNLOCKFILE(fp);
 		Py_END_ALLOW_THREADS
-#ifdef WITH_UNIVERSAL_NEWLINES
 		f->f_newlinetypes = newlinetypes;
 		f->f_skipnextlf = skipnextlf;
-#endif
 		if (c == '\n')
 			break;
 		if (c == EOF) {
@@ -1202,7 +1172,7 @@
 		if (reader == NULL)
 			return NULL;
 		if (n <= 0)
-			args = Py_BuildValue("()");
+			args = PyTuple_New(0);
 		else
 			args = Py_BuildValue("(i)", n);
 		if (args == NULL) {
@@ -1588,7 +1558,9 @@
 "0 (offset from start of file, offset should be >= 0); other values are 1\n"
 "(move relative to current position, positive or negative), and 2 (move\n"
 "relative to end of file, usually negative, although many platforms allow\n"
-"seeking beyond the end of a file).\n"
+"seeking beyond the end of a file).  If the file is opened in text mode,\n"
+"only offsets returned by tell() are legal.  Use of other offsets causes\n"
+"undefined behavior."
 "\n"
 "Note that not all file objects are seekable.");
 
@@ -1667,6 +1639,8 @@
 	 "file mode ('r', 'U', 'w', 'a', possibly with 'b' or '+' added)"},
 	{"name",	T_OBJECT,	OFF(f_name),	RO,
 	 "file name"},
+	{"encoding",	T_OBJECT,	OFF(f_encoding),	RO,
+	 "file encoding"},
 	/* getattr(f, "closed") is implemented without this table */
 	{NULL}	/* Sentinel */
 };
@@ -1676,7 +1650,6 @@
 {
 	return PyBool_FromLong((long)(f->f_fp == 0));
 }
-#ifdef WITH_UNIVERSAL_NEWLINES
 static PyObject *
 get_newlines(PyFileObject *f, void *closure)
 {
@@ -1699,20 +1672,17 @@
 	case NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF:
 		return Py_BuildValue("(sss)", "\r", "\n", "\r\n");
 	default:
-		PyErr_Format(PyExc_SystemError, 
-			     "Unknown newlines value 0x%x\n", 
+		PyErr_Format(PyExc_SystemError,
+			     "Unknown newlines value 0x%x\n",
 			     f->f_newlinetypes);
 		return NULL;
 	}
 }
-#endif
 
 static PyGetSetDef file_getsetlist[] = {
 	{"closed", (getter)get_closed, NULL, "True if the file is closed"},
-#ifdef WITH_UNIVERSAL_NEWLINES
-	{"newlines", (getter)get_newlines, NULL, 
+	{"newlines", (getter)get_newlines, NULL,
 	 "end-of-line convention used in this file"},
-#endif
 	{0},
 };
 
@@ -1725,8 +1695,8 @@
 	}
 }
 
-/* Make sure that file has a readahead buffer with at least one byte 
-   (unless at EOF) and no more than bufsize.  Returns negative value on 
+/* Make sure that file has a readahead buffer with at least one byte
+   (unless at EOF) and no more than bufsize.  Returns negative value on
    error */
 static int
 readahead(PyFileObject *f, int bufsize)
@@ -1734,7 +1704,7 @@
 	int chunksize;
 
 	if (f->f_buf != NULL) {
-		if( (f->f_bufend - f->f_bufptr) >= 1) 
+		if( (f->f_bufend - f->f_bufptr) >= 1)
 			return 0;
 		else
 			drop_readahead(f);
@@ -1761,8 +1731,8 @@
 }
 
 /* Used by file_iternext.  The returned string will start with 'skip'
-   uninitialized bytes followed by the remainder of the line. Don't be 
-   horrified by the recursive call: maximum recursion depth is limited by 
+   uninitialized bytes followed by the remainder of the line. Don't be
+   horrified by the recursive call: maximum recursion depth is limited by
    logarithmic buffer growth to about 50 even when reading a 1gb line. */
 
 static PyStringObject *
@@ -1774,11 +1744,11 @@
 	int len;
 
 	if (f->f_buf == NULL)
-		if (readahead(f, bufsize) < 0) 
+		if (readahead(f, bufsize) < 0)
 			return NULL;
 
 	len = f->f_bufend - f->f_bufptr;
-	if (len == 0) 
+	if (len == 0)
 		return (PyStringObject *)
 			PyString_FromStringAndSize(NULL, skip);
 	bufptr = memchr(f->f_bufptr, '\n', len);
@@ -1787,7 +1757,7 @@
 		len = bufptr - f->f_bufptr;
 		s = (PyStringObject *)
 			PyString_FromStringAndSize(NULL, skip+len);
-		if (s == NULL) 
+		if (s == NULL)
 			return NULL;
 		memcpy(PyString_AS_STRING(s)+skip, f->f_bufptr, len);
 		f->f_bufptr = bufptr;
@@ -1851,6 +1821,9 @@
 		((PyFileObject *)self)->f_name = not_yet_string;
 		Py_INCREF(not_yet_string);
 		((PyFileObject *)self)->f_mode = not_yet_string;
+		Py_INCREF(Py_None);
+		((PyFileObject *)self)->f_encoding = Py_None;
+		((PyFileObject *)self)->weakreflist = NULL;
 	}
 	return self;
 }
@@ -1881,8 +1854,8 @@
 		if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:file",
 						kwlist, &po, &mode, &bufsize)) {
 			wideargument = 1;
-			if (fill_file_fields(foself, NULL, name, mode,
-					     fclose, po) == NULL)
+			if (fill_file_fields(foself, NULL, po, mode,
+					     fclose) == NULL)
 				goto Error;
 		} else {
 			/* Drop the argument parsing error as narrow
@@ -1893,17 +1866,26 @@
 #endif
 
 	if (!wideargument) {
+                PyObject *o_name;
+
 		if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist,
 						 Py_FileSystemDefaultEncoding,
 						 &name,
 						 &mode, &bufsize))
 			return -1;
-		if (fill_file_fields(foself, NULL, name, mode,
-				     fclose, NULL) == NULL)
+
+                /* We parse again to get the name as a PyObject */
+                if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|si:file", kwlist,
+                    &o_name, &mode, &bufsize))
+                        return -1;
+
+		if (fill_file_fields(foself, NULL, o_name, mode,
+				     fclose) == NULL)
 			goto Error;
 	}
 	if (open_the_file(foself, name, mode) == NULL)
 		goto Error;
+	foself->f_setbuf = NULL;
 	PyFile_SetBufSize(self, bufsize);
 	goto Done;
 
@@ -1927,7 +1909,6 @@
 "If the buffering argument is given, 0 means unbuffered, 1 means line\n"
 "buffered, and larger numbers specify the buffer size.\n"
 )
-#ifdef WITH_UNIVERSAL_NEWLINES
 PyDoc_STR(
 "Add a 'U' to mode to open the file for input with universal newline\n"
 "support.  Any line ending in the input file will be seen as a '\\n'\n"
@@ -1937,7 +1918,6 @@
 "\n"
 "'U' cannot be combined with 'w' or '+' mode.\n"
 )
-#endif /* WITH_UNIVERSAL_NEWLINES */
 PyDoc_STR(
 "\n"
 "Note:  open() is an alias for file()."
@@ -1962,14 +1942,15 @@
 	0,					/* tp_call */
 	0,					/* tp_str */
 	PyObject_GenericGetAttr,		/* tp_getattro */
-	0,					/* tp_setattro */
+	/* softspace is writable:  we must supply tp_setattro */
+	PyObject_GenericSetAttr,		/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
 	file_doc,				/* tp_doc */
 	0,					/* tp_traverse */
 	0,					/* tp_clear */
 	0,					/* tp_richcompare */
-	0,					/* tp_weaklistoffset */
+	offsetof(PyFileObject, weakreflist),	/* tp_weaklistoffset */
 	(getiterfunc)file_getiter,		/* tp_iter */
 	(iternextfunc)file_iternext,		/* tp_iternext */
 	file_methods,				/* tp_methods */
@@ -2033,11 +2014,31 @@
 	}
 	else if (PyFile_Check(f)) {
 		FILE *fp = PyFile_AsFile(f);
+#ifdef Py_USING_UNICODE
+		PyObject *enc = ((PyFileObject*)f)->f_encoding;
+		int result;
+#endif
 		if (fp == NULL) {
 			err_closed();
 			return -1;
 		}
+#ifdef Py_USING_UNICODE
+                if ((flags & Py_PRINT_RAW) &&
+		    PyUnicode_Check(v) && enc != Py_None) {
+			char *cenc = PyString_AS_STRING(enc);
+			value = PyUnicode_AsEncodedString(v, cenc, "strict");
+			if (value == NULL)
+				return -1;
+		} else {
+			value = v;
+			Py_INCREF(value);
+		}
+		result = PyObject_Print(value, fp, flags);
+		Py_DECREF(value);
+		return result;
+#else
 		return PyObject_Print(v, fp, flags);
+#endif
 	}
 	writer = PyObject_GetAttrString(f, "write");
 	if (writer == NULL)
@@ -2055,7 +2056,7 @@
 		Py_DECREF(writer);
 		return -1;
 	}
-	args = Py_BuildValue("(O)", value);
+	args = PyTuple_Pack(1, value);
 	if (args == NULL) {
 		Py_DECREF(value);
 		Py_DECREF(writer);
@@ -2158,7 +2159,6 @@
 	return fd;
 }
 
-#ifdef WITH_UNIVERSAL_NEWLINES
 /* From here on we need access to the real fgets and fread */
 #undef fgets
 #undef fread
@@ -2336,4 +2336,3 @@
 	f->f_skipnextlf = skipnextlf;
 	return dst - buf;
 }
-#endif

Index: floatobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/floatobject.c,v
retrieving revision 2.113.2.1
retrieving revision 2.113.2.2
diff -u -d -r2.113.2.1 -r2.113.2.2
--- floatobject.c	28 Apr 2003 17:18:18 -0000	2.113.2.1
+++ floatobject.c	7 Jan 2005 07:04:01 -0000	2.113.2.2
@@ -8,21 +8,11 @@
 
 #include <ctype.h>
 
-#if !defined(__STDC__) && !defined(macintosh)
+#if !defined(__STDC__)
 extern double fmod(double, double);
 extern double pow(double, double);
 #endif
 
-#if defined(sun) && !defined(__SVR4)
-/* On SunOS4.1 only libm.a exists. Make sure that references to all
-   needed math functions exist in the executable, so that dynamic
-   loading of mathmodule does not fail. */
-double (*_Py_math_funcs_hack[])() = {
-	acos, asin, atan, atan2, ceil, cos, cosh, exp, fabs, floor,
-	fmod, log, log10, pow, sin, sinh, sqrt, tan, tanh
-};
-#endif
-
 /* Special free list -- see comments for same code in intobject.c. */
 #define BLOCK_SIZE	1000	/* 1K less typical malloc overhead */
 #define BHEAD_SIZE	8	/* Enough for a 64-bit pointer */
@@ -142,7 +132,7 @@
 	 * key off errno.
          */
 	PyFPE_START_PROTECT("strtod", return NULL)
-	x = strtod(s, (char **)&end);
+	x = PyOS_ascii_strtod(s, (char **)&end);
 	PyFPE_END_PROTECT(x)
 	errno = 0;
 	/* Believe it or not, Solaris 2.6 can move end *beyond* the null
@@ -174,7 +164,7 @@
 		/* See above -- may have been strtod being anal
 		   about denorms. */
 		PyFPE_START_PROTECT("atof", return NULL)
-		x = atof(s);
+		x = PyOS_ascii_atof(s);
 		PyFPE_END_PROTECT(x)
 		errno = 0;    /* whether atof ever set errno is undefined */
 	}
@@ -233,6 +223,7 @@
 format_float(char *buf, size_t buflen, PyFloatObject *v, int precision)
 {
 	register char *cp;
+	char format[32];
 	/* Subroutine for float_repr and float_print.
 	   We want float numbers to be recognizable as such,
 	   i.e., they should contain a decimal point or an exponent.
@@ -240,7 +231,8 @@
 	   in such cases, we append ".0" to the string. */
 
 	assert(PyFloat_Check(v));
-	PyOS_snprintf(buf, buflen, "%.*g", precision, v->ob_fval);
+	PyOS_snprintf(format, 32, "%%.%ig", precision);
+	PyOS_ascii_formatd(buf, buflen, format, v->ob_fval);
 	cp = buf;
 	if (*cp == '-')
 		cp++;
@@ -362,12 +354,234 @@
 	return PyString_FromString(buf);
 }
 
-static int
-float_compare(PyFloatObject *v, PyFloatObject *w)
+/* Comparison is pretty much a nightmare.  When comparing float to float,
+ * we do it as straightforwardly (and long-windedly) as conceivable, so
+ * that, e.g., Python x == y delivers the same result as the platform
+ * C x == y when x and/or y is a NaN.
+ * When mixing float with an integer type, there's no good *uniform* approach.
+ * Converting the double to an integer obviously doesn't work, since we
+ * may lose info from fractional bits.  Converting the integer to a double
+ * also has two failure modes:  (1) a long int may trigger overflow (too
+ * large to fit in the dynamic range of a C double); (2) even a C long may have
+ * more bits than fit in a C double (e.g., on a a 64-bit box long may have
+ * 63 bits of precision, but a C double probably has only 53), and then
+ * we can falsely claim equality when low-order integer bits are lost by
+ * coercion to double.  So this part is painful too.
+ */
+
+static PyObject*
+float_richcompare(PyObject *v, PyObject *w, int op)
 {
-	double i = v->ob_fval;
-	double j = w->ob_fval;
-	return (i < j) ? -1 : (i > j) ? 1 : 0;
+	double i, j;
+	int r = 0;
+
+	assert(PyFloat_Check(v));
+	i = PyFloat_AS_DOUBLE(v);
+
+	/* Switch on the type of w.  Set i and j to doubles to be compared,
+	 * and op to the richcomp to use.
+	 */
+	if (PyFloat_Check(w))
+		j = PyFloat_AS_DOUBLE(w);
+
+	else if (Py_IS_INFINITY(i) || Py_IS_NAN(i)) {
+		if (PyInt_Check(w) || PyLong_Check(w))
+			/* If i is an infinity, its magnitude exceeds any
+			 * finite integer, so it doesn't matter which int we
+			 * compare i with.  If i is a NaN, similarly.
+			 */
+			j = 0.0;
+		else
+			goto Unimplemented;
+	}
+
+	else if (PyInt_Check(w)) {
+		long jj = PyInt_AS_LONG(w);
+		/* In the worst realistic case I can imagine, C double is a
+		 * Cray single with 48 bits of precision, and long has 64
+		 * bits.
+		 */
+#if SIZEOF_LONG > 6
+		unsigned long abs = (unsigned long)(jj < 0 ? -jj : jj);
+		if (abs >> 48) {
+			/* Needs more than 48 bits.  Make it take the
+			 * PyLong path.
+			 */
+			PyObject *result;
+			PyObject *ww = PyLong_FromLong(jj);
+
+			if (ww == NULL)
+				return NULL;
+			result = float_richcompare(v, ww, op);
+			Py_DECREF(ww);
+			return result;
+		}
+#endif
+		j = (double)jj;
+		assert((long)j == jj);
+	}
+
+	else if (PyLong_Check(w)) {
+		int vsign = i == 0.0 ? 0 : i < 0.0 ? -1 : 1;
+		int wsign = _PyLong_Sign(w);
+		size_t nbits;
+		double mant;
+		int exponent;
+
+		if (vsign != wsign) {
+			/* Magnitudes are irrelevant -- the signs alone
+			 * determine the outcome.
+			 */
+			i = (double)vsign;
+			j = (double)wsign;
+			goto Compare;
+		}
+		/* The signs are the same. */
+		/* Convert w to a double if it fits.  In particular, 0 fits. */
+		nbits = _PyLong_NumBits(w);
+		if (nbits == (size_t)-1 && PyErr_Occurred()) {
+			/* This long is so large that size_t isn't big enough
+			 * to hold the # of bits.  Replace with little doubles
+			 * that give the same outcome -- w is so large that
+			 * its magnitude must exceed the magnitude of any
+			 * finite float.
+			 */
+			PyErr_Clear();
+			i = (double)vsign;
+			assert(wsign != 0);
+			j = wsign * 2.0;
+			goto Compare;
+		}
+		if (nbits <= 48) {
+			j = PyLong_AsDouble(w);
+			/* It's impossible that <= 48 bits overflowed. */
+			assert(j != -1.0 || ! PyErr_Occurred());
+			goto Compare;
+		}
+		assert(wsign != 0); /* else nbits was 0 */
+		assert(vsign != 0); /* if vsign were 0, then since wsign is
+		                     * not 0, we would have taken the
+		                     * vsign != wsign branch at the start */
+		/* We want to work with non-negative numbers. */
+		if (vsign < 0) {
+			/* "Multiply both sides" by -1; this also swaps the
+			 * comparator.
+			 */
+			i = -i;
+			op = _Py_SwappedOp[op];
+		}
+		assert(i > 0.0);
+		mant = frexp(i, &exponent);
+		/* exponent is the # of bits in v before the radix point;
+		 * we know that nbits (the # of bits in w) > 48 at this point
+		 */
+		if (exponent < 0 || (size_t)exponent < nbits) {
+			i = 1.0;
+			j = 2.0;
+			goto Compare;
+		}
+		if ((size_t)exponent > nbits) {
+			i = 2.0;
+			j = 1.0;
+			goto Compare;
+		}
+		/* v and w have the same number of bits before the radix
+		 * point.  Construct two longs that have the same comparison
+		 * outcome.
+		 */
+		{
+			double fracpart;
+			double intpart;
+			PyObject *result = NULL;
+			PyObject *one = NULL;
+			PyObject *vv = NULL;
+			PyObject *ww = w;
+
+			if (wsign < 0) {
+				ww = PyNumber_Negative(w);
+				if (ww == NULL)
+					goto Error;
+			}
+			else
+				Py_INCREF(ww);
+
+			fracpart = modf(i, &intpart);
+			vv = PyLong_FromDouble(intpart);
+			if (vv == NULL)
+				goto Error;
+
+			if (fracpart != 0.0) {
+				/* Shift left, and or a 1 bit into vv
+				 * to represent the lost fraction.
+				 */
+				PyObject *temp;
+
+				one = PyInt_FromLong(1);
+				if (one == NULL)
+					goto Error;
+
+				temp = PyNumber_Lshift(ww, one);
+				if (temp == NULL)
+					goto Error;
+				Py_DECREF(ww);
+				ww = temp;
+
+				temp = PyNumber_Lshift(vv, one);
+				if (temp == NULL)
+					goto Error;
+				Py_DECREF(vv);
+				vv = temp;
+
+				temp = PyNumber_Or(vv, one);
+				if (temp == NULL)
+					goto Error;
+				Py_DECREF(vv);
+				vv = temp;
+			}
+
+			r = PyObject_RichCompareBool(vv, ww, op);
+			if (r < 0)
+				goto Error;
+			result = PyBool_FromLong(r);
+ 		 Error:
+ 		 	Py_XDECREF(vv);
+ 		 	Py_XDECREF(ww);
+ 		 	Py_XDECREF(one);
+ 		 	return result;
+		}
+	} /* else if (PyLong_Check(w)) */
+
+	else	/* w isn't float, int, or long */
+		goto Unimplemented;
+
+ Compare:
+	PyFPE_START_PROTECT("richcompare", return NULL)
+	switch (op) {
+	case Py_EQ:
+		r = i == j;
+		break;
+	case Py_NE:
+		r = i != j;
+		break;
+	case Py_LE:
+		r = i <= j;
+		break;
+	case Py_GE:
+		r = i >= j;
+		break;
+	case Py_LT:
+		r = i < j;
+		break;
+	case Py_GT:
+		r = i > j;
+		break;
+	}
+	PyFPE_END_PROTECT(r)
+	return PyBool_FromLong(r);
+
+ Unimplemented:
+	Py_INCREF(Py_NotImplemented);
+	return Py_NotImplemented;
 }
 
 static long
@@ -572,10 +786,39 @@
 		}
 		return PyFloat_FromDouble(0.0);
 	}
-	if (iv < 0.0 && iw != floor(iw)) {
-		PyErr_SetString(PyExc_ValueError,
-				"negative number cannot be raised to a fractional power");
-		return NULL;
+	if (iv < 0.0) {
+		/* Whether this is an error is a mess, and bumps into libm
+		 * bugs so we have to figure it out ourselves.
+		 */
+		if (iw != floor(iw)) {
+			PyErr_SetString(PyExc_ValueError, "negative number "
+				"cannot be raised to a fractional power");
+			return NULL;
+		}
+		/* iw is an exact integer, albeit perhaps a very large one.
+		 * -1 raised to an exact integer should never be exceptional.
+		 * Alas, some libms (chiefly glibc as of early 2003) return
+		 * NaN and set EDOM on pow(-1, large_int) if the int doesn't
+		 * happen to be representable in a *C* integer.  That's a
+		 * bug; we let that slide in math.pow() (which currently
+		 * reflects all platform accidents), but not for Python's **.
+		 */
+		 if (iv == -1.0 && !Py_IS_INFINITY(iw) && iw == iw) {
+		 	/* XXX the "iw == iw" was to weed out NaNs.  This
+		 	 * XXX doesn't actually work on all platforms.
+		 	 */
+		 	/* Return 1 if iw is even, -1 if iw is odd; there's
+		 	 * no guarantee that any C integral type is big
+		 	 * enough to hold iw, so we have to check this
+		 	 * indirectly.
+		 	 */
+		 	ix = floor(iw * 0.5) * 2.0;
+			return PyFloat_FromDouble(ix == iw ? 1.0 : -1.0);
+		}
+		/* Else iv != -1.0, and overflow or underflow are possible.
+		 * Unless we're to write pow() ourselves, we have to trust
+		 * the platform to do this correctly.
+		 */
 	}
 	errno = 0;
 	PyFPE_START_PROTECT("pow", return NULL)
@@ -583,8 +826,11 @@
 	PyFPE_END_PROTECT(ix)
 	Py_ADJUST_ERANGE1(ix);
 	if (errno != 0) {
-		assert(errno == ERANGE);
-		PyErr_SetFromErrno(PyExc_OverflowError);
+		/* We don't expect any errno value other than ERANGE, but
+		 * the range of libm bugs appears unbounded.
+		 */
+		PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError :
+						     PyExc_ValueError);
 		return NULL;
 	}
 	return PyFloat_FromDouble(ix);
@@ -719,8 +965,10 @@
 		return NULL;
 	assert(PyFloat_CheckExact(tmp));
 	new = type->tp_alloc(type, 0);
-	if (new == NULL)
+	if (new == NULL) {
+		Py_DECREF(tmp);
 		return NULL;
+	}
 	((PyFloatObject *)new)->ob_fval = ((PyFloatObject *)tmp)->ob_fval;
 	Py_DECREF(tmp);
 	return new;
@@ -794,7 +1042,7 @@
 	(printfunc)float_print, 		/* tp_print */
 	0,					/* tp_getattr */
 	0,					/* tp_setattr */
-	(cmpfunc)float_compare, 		/* tp_compare */
+	0,			 		/* tp_compare */
 	(reprfunc)float_repr,			/* tp_repr */
 	&float_as_number,			/* tp_as_number */
 	0,					/* tp_as_sequence */
@@ -810,7 +1058,7 @@
 	float_doc,				/* tp_doc */
  	0,					/* tp_traverse */
 	0,					/* tp_clear */
-	0,					/* tp_richcompare */
+	(richcmpfunc)float_richcompare,		/* tp_richcompare */
 	0,					/* tp_weaklistoffset */
 	0,					/* tp_iter */
 	0,					/* tp_iternext */
@@ -832,7 +1080,7 @@
 {
 	PyFloatObject *p;
 	PyFloatBlock *list, *next;
-	int i;
+	unsigned i;
 	int bc, bf;	/* block count, number of freed blocks */
 	int frem, fsum;	/* remaining unfreed floats per block, total */
 

Index: frameobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/frameobject.c,v
retrieving revision 2.62.2.2
retrieving revision 2.62.2.3
diff -u -d -r2.62.2.2 -r2.62.2.3
--- frameobject.c	28 Apr 2003 17:18:18 -0000	2.62.2.2
+++ frameobject.c	7 Jan 2005 07:04:01 -0000	2.62.2.3
@@ -541,11 +541,11 @@
 	PyFrameObject *back = tstate->frame;
 	PyFrameObject *f;
 	PyObject *builtins;
-	int extras, ncells, nfrees;
+	int extras, ncells, nfrees, i;
 
 #ifdef Py_DEBUG
 	if (code == NULL || globals == NULL || !PyDict_Check(globals) ||
-	    (locals != NULL && !PyDict_Check(locals))) {
+	    (locals != NULL && !PyMapping_Check(locals))) {
 		PyErr_BadInternalCall();
 		return NULL;
 	}
@@ -585,8 +585,10 @@
 	}
 	if (free_list == NULL) {
 		f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, extras);
-		if (f == NULL)
+		if (f == NULL) {
+			Py_DECREF(builtins);
 			return NULL;
+		}
 	}
 	else {
 		assert(numfree > 0);
@@ -595,8 +597,10 @@
 		free_list = free_list->f_back;
 		if (f->ob_size < extras) {
 			f = PyObject_GC_Resize(PyFrameObject, f, extras);
-			if (f == NULL)
+			if (f == NULL) {
+				Py_DECREF(builtins);
 				return NULL;
+			}
 		}
 		_Py_NewReference((PyObject *)f);
 	}
@@ -610,7 +614,7 @@
 	/* Most functions have CO_NEWLOCALS and CO_OPTIMIZED set. */
 	if ((code->co_flags & (CO_NEWLOCALS | CO_OPTIMIZED)) == 
 		(CO_NEWLOCALS | CO_OPTIMIZED))
-		locals = NULL; /* PyFrame_Fast2Locals() will set. */
+		locals = NULL; /* PyFrame_FastToLocals() will set. */
 	else if (code->co_flags & CO_NEWLOCALS) {
 		locals = PyDict_New();
 		if (locals == NULL) {
@@ -638,7 +642,9 @@
 	f->f_nfreevars = nfrees;
 
 	extras = f->f_nlocals + ncells + nfrees;
-	memset(f->f_localsplus, 0, extras * sizeof(f->f_localsplus[0]));
+	/* Tim said it's ok to replace memset */
+	for (i=0; i<extras; i++)
+		f->f_localsplus[i] = NULL;
 
 	f->f_valuestack = f->f_localsplus + extras;
 	f->f_stacktop = f->f_valuestack;
@@ -683,11 +689,11 @@
 		if (deref)
 			value = PyCell_GET(value);
 		if (value == NULL) {
-			if (PyDict_DelItem(dict, key) != 0)
+			if (PyObject_DelItem(dict, key) != 0)
 				PyErr_Clear();
 		}
 		else {
-			if (PyDict_SetItem(dict, key, value) != 0)
+			if (PyObject_SetItem(dict, key, value) != 0)
 				PyErr_Clear();
 		}
 	}
@@ -700,7 +706,9 @@
 	int j;
 	for (j = nmap; --j >= 0; ) {
 		PyObject *key = PyTuple_GET_ITEM(map, j);
-		PyObject *value = PyDict_GetItem(dict, key);
+		PyObject *value = PyObject_GetItem(dict, key);
+		if (value == NULL)
+			PyErr_Clear();
 		if (deref) {
 			if (value || clear) {
 				if (PyCell_GET(values[j]) != value) {
@@ -715,6 +723,7 @@
 				values[j] = value;
 			}
 		}
+		Py_XDECREF(value);
 	}
 }
 
@@ -737,7 +746,7 @@
 		}
 	}
 	map = f->f_code->co_varnames;
-	if (!PyDict_Check(locals) || !PyTuple_Check(map))
+	if (!PyTuple_Check(map))
 		return;
 	PyErr_Fetch(&error_type, &error_value, &error_traceback);
 	fast = f->f_localsplus;
@@ -745,11 +754,10 @@
 	if (j > f->f_nlocals)
 		j = f->f_nlocals;
 	if (f->f_nlocals)
-	    map_to_dict(map, j, locals, fast, 0);
+		map_to_dict(map, j, locals, fast, 0);
 	if (f->f_ncells || f->f_nfreevars) {
 		if (!(PyTuple_Check(f->f_code->co_cellvars)
 		      && PyTuple_Check(f->f_code->co_freevars))) {
-			Py_DECREF(locals);
 			return;
 		}
 		map_to_dict(f->f_code->co_cellvars, 
@@ -776,7 +784,7 @@
 	map = f->f_code->co_varnames;
 	if (locals == NULL)
 		return;
-	if (!PyDict_Check(locals) || !PyTuple_Check(map))
+	if (!PyTuple_Check(map))
 		return;
 	PyErr_Fetch(&error_type, &error_value, &error_traceback);
 	fast = f->f_localsplus;

Index: funcobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/funcobject.c,v
retrieving revision 2.55.2.2
retrieving revision 2.55.2.3
diff -u -d -r2.55.2.2 -r2.55.2.3
--- funcobject.c	28 Apr 2003 17:18:17 -0000	2.55.2.2
+++ funcobject.c	7 Jan 2005 07:04:01 -0000	2.55.2.3
@@ -11,6 +11,7 @@
 {
 	PyFunctionObject *op = PyObject_GC_New(PyFunctionObject,
 					    &PyFunction_Type);
+	static PyObject *__name__ = 0;
 	if (op != NULL) {
 		PyObject *doc;
 		PyObject *consts;
@@ -40,7 +41,14 @@
 		/* __module__: If module name is in globals, use it.
 		   Otherwise, use None.
 		*/
-		module = PyDict_GetItemString(globals, "__name__");
+		if (!__name__) {
+			__name__ = PyString_InternFromString("__name__");
+			if (!__name__) {
+				Py_DECREF(op);
+				return NULL;
+			}
+		}
+		module = PyDict_GetItem(globals, __name__);
 		if (module) {
 		    Py_INCREF(module);
 		    op->func_module = module;
@@ -148,8 +156,6 @@
 
 #define OFF(x) offsetof(PyFunctionObject, x)
 
-#define RR ()
-
 static PyMemberDef func_memberlist[] = {
         {"func_closure",  T_OBJECT,     OFF(func_closure),
 	 RESTRICTED|READONLY},
@@ -157,8 +163,6 @@
         {"__doc__",       T_OBJECT,     OFF(func_doc), WRITE_RESTRICTED},
         {"func_globals",  T_OBJECT,     OFF(func_globals),
 	 RESTRICTED|READONLY},
-        {"func_name",     T_OBJECT,     OFF(func_name),         READONLY},
-        {"__name__",      T_OBJECT,     OFF(func_name),         READONLY},
         {"__module__",    T_OBJECT,     OFF(func_module), WRITE_RESTRICTED},
         {NULL}  /* Sentinel */
 };
@@ -226,6 +230,7 @@
 func_set_code(PyFunctionObject *op, PyObject *value)
 {
 	PyObject *tmp;
+	int nfree, nclosure;
 
 	if (restricted())
 		return -1;
@@ -236,6 +241,17 @@
 				"func_code must be set to a code object");
 		return -1;
 	}
+	nfree = PyCode_GetNumFree((PyCodeObject *)value);
+	nclosure = (op->func_closure == NULL ? 0 :
+		    PyTuple_GET_SIZE(op->func_closure));
+	if (nclosure != nfree) {
+		PyErr_Format(PyExc_ValueError,
+			     "%s() requires a code object with %d free vars,"
+			     " not %d",
+			     PyString_AsString(op->func_name),
+			     nclosure, nfree);
+		return -1;
+	}
 	tmp = op->func_code;
 	Py_INCREF(value);
 	op->func_code = value;
@@ -244,6 +260,36 @@
 }
 
 static PyObject *
+func_get_name(PyFunctionObject *op)
+{
+	if (restricted())
+		return NULL;
+	Py_INCREF(op->func_name);
+	return op->func_name;
+}
+
+static int
+func_set_name(PyFunctionObject *op, PyObject *value)
+{
+	PyObject *tmp;
+
+	if (restricted())
+		return -1;
+	/* Not legal to del f.func_name or to set it to anything
+	 * other than a string object. */
+	if (value == NULL || !PyString_Check(value)) {
+		PyErr_SetString(PyExc_TypeError,
+				"func_name must be set to a string object");
+		return -1;
+	}
+	tmp = op->func_name;
+	Py_INCREF(value);
+	op->func_name = value;
+	Py_DECREF(tmp);
+	return 0;
+}
+
+static PyObject *
 func_get_defaults(PyFunctionObject *op)
 {
 	if (restricted())
@@ -285,6 +331,8 @@
 	 (setter)func_set_defaults},
 	{"func_dict", (getter)func_get_dict, (setter)func_set_dict},
 	{"__dict__", (getter)func_get_dict, (setter)func_set_dict},
+	{"func_name", (getter)func_get_name, (setter)func_set_name},
+	{"__name__", (getter)func_get_name, (setter)func_set_name},
 	{NULL} /* Sentinel */
 };
 
@@ -316,8 +364,11 @@
 	PyObject *closure = Py_None;
 	PyFunctionObject *newfunc;
 	int nfree, nclosure;
+	static char *kwlist[] = {"code", "globals", "name",
+				 "argdefs", "closure", 0};
 
-	if (!PyArg_ParseTuple(args, "O!O!|OOO:function",
+	if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!|OOO:function",
+			      kwlist,
 			      &PyCode_Type, &code,
 			      &PyDict_Type, &globals,
 			      &name, &defaults, &closure))
@@ -407,8 +458,6 @@
 static PyObject*
 func_repr(PyFunctionObject *op)
 {
-	if (op->func_name == Py_None)
-		return PyString_FromFormat("<anonymous function at %p>", op);
 	return PyString_FromFormat("<function %s at %p>",
 				   PyString_AsString(op->func_name),
 				   op);
@@ -637,6 +686,12 @@
 
 	if (!PyArg_UnpackTuple(args, "classmethod", 1, 1, &callable))
 		return -1;
+	if (!PyCallable_Check(callable)) {
+		PyErr_Format(PyExc_TypeError, "'%s' object is not callable",
+		     callable->ob_type->tp_name);
+		return -1;
+	}
+	
 	Py_INCREF(callable);
 	cm->cm_callable = callable;
 	return 0;

Index: intobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/intobject.c,v
retrieving revision 2.84.2.1
retrieving revision 2.84.2.2
diff -u -d -r2.84.2.1 -r2.84.2.2
--- intobject.c	28 Apr 2003 17:18:17 -0000	2.84.2.1
+++ intobject.c	7 Jan 2005 07:04:02 -0000	2.84.2.2
@@ -10,19 +10,6 @@
 	return LONG_MAX;	/* To initialize sys.maxint */
 }
 
-/* Return 1 if exception raised, 0 if caller should retry using longs */
-static int
-err_ovf(char *msg)
-{
-	if (PyErr_Warn(PyExc_OverflowWarning, msg) < 0) {
-		if (PyErr_ExceptionMatches(PyExc_OverflowWarning))
-			PyErr_SetString(PyExc_OverflowError, msg);
-		return 1;
-	}
-	else
-		return 0;
-}
-
 /* Integers are quite normal objects, to make object handling uniform.
    (Using odd pointers to represent integers would save much space
    but require extra checks for this special case throughout the code.)
@@ -278,7 +265,6 @@
 	char *end;
 	long x;
 	char buffer[256]; /* For errors */
-	int warn = 0;
 
 	if ((base != 0 && base < 2) || base > 36) {
 		PyErr_SetString(PyExc_ValueError,
@@ -292,7 +278,7 @@
 	if (base == 0 && s[0] == '0') {
 		x = (long) PyOS_strtoul(s, &end, base);
 		if (x < 0)
-			warn = 1;
+			return PyLong_FromString(s, pend, base);
 	}
 	else
 		x = PyOS_strtol(s, &end, base);
@@ -307,16 +293,8 @@
 		PyErr_SetString(PyExc_ValueError, buffer);
 		return NULL;
 	}
-	else if (errno != 0) {
-		if (err_ovf("string/unicode conversion"))
-			return NULL;
+	else if (errno != 0)
 		return PyLong_FromString(s, pend, base);
-	}
-	if (warn) {
-		if (PyErr_Warn(PyExc_FutureWarning,
-			"int('0...', 0): sign will change in Python 2.4") < 0)
-			return NULL;
-	}
 	if (pend)
 		*pend = end;
 	return PyInt_FromLong(x);
@@ -402,8 +380,6 @@
 	x = a + b;
 	if ((x^a) >= 0 || (x^b) >= 0)
 		return PyInt_FromLong(x);
-	if (err_ovf("integer addition"))
-		return NULL;
 	return PyLong_Type.tp_as_number->nb_add((PyObject *)v, (PyObject *)w);
 }
 
@@ -416,8 +392,6 @@
 	x = a - b;
 	if ((x^a) >= 0 || (x^~b) >= 0)
 		return PyInt_FromLong(x);
-	if (err_ovf("integer subtraction"))
-		return NULL;
 	return PyLong_Type.tp_as_number->nb_subtract((PyObject *)v,
 						     (PyObject *)w);
 }
@@ -481,8 +455,6 @@
 		   32 * absdiff <= absprod -- 5 good bits is "close enough" */
 		if (32.0 * absdiff <= absprod)
 			return PyInt_FromLong(longprod);
-		else if (err_ovf("integer multiplication"))
-			return NULL;
 		else
 			return PyLong_Type.tp_as_number->nb_multiply(v, w);
 	}
@@ -507,11 +479,8 @@
 		return DIVMOD_ERROR;
 	}
 	/* (-sys.maxint-1)/-1 is the only overflow case. */
-	if (y == -1 && x < 0 && x == -x) {
-		if (err_ovf("integer division"))
-			return DIVMOD_ERROR;
+	if (y == -1 && x < 0 && x == -x)
 		return DIVMOD_OVERFLOW;
-	}
 	xdivy = x / y;
 	xmody = x - xdivy * y;
 	/* If the signs of x and y differ, and the remainder is non-0,
@@ -660,8 +629,6 @@
 			if (temp == 0)
 				break; /* Avoid ix / 0 */
 			if (ix / temp != prev) {
-				if (err_ovf("integer exponentiation"))
-					return NULL;
 				return PyLong_Type.tp_as_number->nb_power(
 					(PyObject *)v,
 					(PyObject *)w,
@@ -672,9 +639,7 @@
 	        if (iw==0) break;
 	 	prev = temp;
 	 	temp *= temp;	/* Square the value of temp */
-	 	if (prev!=0 && temp/prev!=prev) {
-			if (err_ovf("integer exponentiation"))
-				return NULL;
+	 	if (prev != 0 && temp / prev != prev) {
 			return PyLong_Type.tp_as_number->nb_power(
 				(PyObject *)v, (PyObject *)w, (PyObject *)z);
 		}
@@ -707,10 +672,7 @@
 	a = v->ob_ival;
 	x = -a;
 	if (a < 0 && x < 0) {
-		PyObject *o;
-		if (err_ovf("integer negation"))
-			return NULL;
-		o = PyLong_FromLong(a);
+		PyObject *o = PyLong_FromLong(a);
 		if (o != NULL) {
 			PyObject *result = PyNumber_Negative(o);
 			Py_DECREF(o);
@@ -757,6 +719,8 @@
 int_lshift(PyIntObject *v, PyIntObject *w)
 {
 	long a, b, c;
+	PyObject *vv, *ww, *result;
+
 	CONVERT_TO_LONG(v, a);
 	CONVERT_TO_LONG(w, b);
 	if (b < 0) {
@@ -766,18 +730,33 @@
 	if (a == 0 || b == 0)
 		return int_pos(v);
 	if (b >= LONG_BIT) {
-		if (PyErr_Warn(PyExc_FutureWarning,
-			       "x<<y losing bits or changing sign "
-			       "will return a long in Python 2.4 and up") < 0)
+		vv = PyLong_FromLong(PyInt_AS_LONG(v));
+		if (vv == NULL)
 			return NULL;
-		return PyInt_FromLong(0L);
+		ww = PyLong_FromLong(PyInt_AS_LONG(w));
+		if (ww == NULL) {
+			Py_DECREF(vv);
+			return NULL;
+		}
+		result = PyNumber_Lshift(vv, ww);
+		Py_DECREF(vv);
+		Py_DECREF(ww);
+		return result;
 	}
 	c = a << b;
 	if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) {
-		if (PyErr_Warn(PyExc_FutureWarning,
-			       "x<<y losing bits or changing sign "
-			       "will return a long in Python 2.4 and up") < 0)
+		vv = PyLong_FromLong(PyInt_AS_LONG(v));
+		if (vv == NULL)
 			return NULL;
+		ww = PyLong_FromLong(PyInt_AS_LONG(w));
+		if (ww == NULL) {
+			Py_DECREF(vv);
+			return NULL;
+		}
+		result = PyNumber_Lshift(vv, ww);
+		Py_DECREF(vv);
+		Py_DECREF(ww);
+		return result;
 	}
 	return PyInt_FromLong(c);
 }
@@ -868,13 +847,9 @@
 {
 	char buf[100];
 	long x = v -> ob_ival;
-	if (x < 0) {
-		if (PyErr_Warn(PyExc_FutureWarning,
-			       "hex()/oct() of negative int will return "
-			       "a signed string in Python 2.4 and up") < 0)
-			return NULL;
-	}
-	if (x == 0)
+	if (x < 0)
+		PyOS_snprintf(buf, sizeof(buf), "-0%lo", -x);
+	else if (x == 0)
 		strcpy(buf, "0");
 	else
 		PyOS_snprintf(buf, sizeof(buf), "0%lo", x);
@@ -886,13 +861,10 @@
 {
 	char buf[100];
 	long x = v -> ob_ival;
-	if (x < 0) {
-		if (PyErr_Warn(PyExc_FutureWarning,
-			       "hex()/oct() of negative int will return "
-			       "a signed string in Python 2.4 and up") < 0)
-			return NULL;
-	}
-	PyOS_snprintf(buf, sizeof(buf), "0x%lx", x);
+	if (x < 0)
+		PyOS_snprintf(buf, sizeof(buf), "-0x%lx", -x);
+	else
+		PyOS_snprintf(buf, sizeof(buf), "0x%lx", x);
 	return PyString_FromString(buf);
 }
 
@@ -944,22 +916,20 @@
 	if (tmp == NULL)
 		return NULL;
 	if (!PyInt_Check(tmp)) {
-		if (!PyLong_Check(tmp)) {
-			PyErr_SetString(PyExc_ValueError,
-					"value must convertable to an int");
-			return NULL;
-		}
 		ival = PyLong_AsLong(tmp);
-		if (ival == -1 && PyErr_Occurred())
+		if (ival == -1 && PyErr_Occurred()) {
+			Py_DECREF(tmp);
 			return NULL;
-
+		}
 	} else {
 		ival = ((PyIntObject *)tmp)->ob_ival;
 	}
 
 	new = type->tp_alloc(type, 0);
-	if (new == NULL)
+	if (new == NULL) {
+		Py_DECREF(tmp);
 		return NULL;
+	}
 	((PyIntObject *)new)->ob_ival = ival;
 	Py_DECREF(tmp);
 	return new;
@@ -1078,7 +1048,7 @@
 	int ival;
 #if NSMALLNEGINTS + NSMALLPOSINTS > 0
 	for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++) {
-		if ((free_list = fill_free_list()) == NULL)
+              if (!free_list && (free_list = fill_free_list()) == NULL)
 			return 0;
 		/* PyObject_New is inlined */
 		v = free_list;

Index: iterobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/iterobject.c,v
retrieving revision 1.10.2.1
retrieving revision 1.10.2.2
diff -u -d -r1.10.2.1 -r1.10.2.2
--- iterobject.c	28 Apr 2003 17:18:17 -0000	1.10.2.1
+++ iterobject.c	7 Jan 2005 07:04:02 -0000	1.10.2.2
@@ -71,6 +71,27 @@
 	return NULL;
 }
 
+static int
+iter_len(seqiterobject *it)
+{
+	int seqsize, len;
+
+	if (it->it_seq) {
+		seqsize = PySequence_Size(it->it_seq);
+		if (seqsize == -1)
+			return -1;
+		len = seqsize - it->it_index;
+		if (len >= 0)
+			return len;
+	}
+	return 0;
+}
+
+static PySequenceMethods iter_as_sequence = {
+	(inquiry)iter_len,		/* sq_length */
+	0,				/* sq_concat */
+};
+
 PyTypeObject PySeqIter_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,					/* ob_size */
@@ -85,7 +106,7 @@
 	0,					/* tp_compare */
 	0,					/* tp_repr */
 	0,					/* tp_as_number */
-	0,					/* tp_as_sequence */
+	&iter_as_sequence,			/* tp_as_sequence */
 	0,					/* tp_as_mapping */
 	0,					/* tp_hash */
 	0,					/* tp_call */
@@ -171,18 +192,14 @@
 				return result; /* Common case, fast path */
 			Py_DECREF(result);
 			if (ok > 0) {
-				Py_DECREF(it->it_callable);
-				it->it_callable = NULL;
-				Py_DECREF(it->it_sentinel);
-				it->it_sentinel = NULL;
+				Py_CLEAR(it->it_callable);
+				Py_CLEAR(it->it_sentinel);
 			}
 		}
 		else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
 			PyErr_Clear();
-			Py_DECREF(it->it_callable);
-			it->it_callable = NULL;
-			Py_DECREF(it->it_sentinel);
-			it->it_sentinel = NULL;
+			Py_CLEAR(it->it_callable);
+			Py_CLEAR(it->it_sentinel);
 		}
 	}
 	return NULL;
@@ -211,9 +228,9 @@
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- 	0,					/* tp_doc */
- 	(traverseproc)calliter_traverse,	/* tp_traverse */
- 	0,					/* tp_clear */
+	0,					/* tp_doc */
+	(traverseproc)calliter_traverse,	/* tp_traverse */
+	0,					/* tp_clear */
 	0,					/* tp_richcompare */
 	0,					/* tp_weaklistoffset */
 	PyObject_SelfIter,			/* tp_iter */

Index: listobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v
retrieving revision 2.114.2.1
retrieving revision 2.114.2.2
diff -u -d -r2.114.2.1 -r2.114.2.2
--- listobject.c	28 Apr 2003 17:18:16 -0000	2.114.2.1
+++ listobject.c	7 Jan 2005 07:04:02 -0000	2.114.2.2
@@ -8,79 +8,112 @@
 #include <sys/types.h>		/* For size_t */
 #endif
 
+/* Ensure ob_item has room for at least newsize elements, and set
+ * ob_size to newsize.  If newsize > ob_size on entry, the content
+ * of the new slots at exit is undefined heap trash; it's the caller's
+ * responsiblity to overwrite them with sane values.
+ * The number of allocated elements may grow, shrink, or stay the same.
+ * Failure is impossible if newsize <= self.allocated on entry, although
+ * that partly relies on an assumption that the system realloc() never
+ * fails when passed a number of bytes <= the number of bytes last
[...1688 lines suppressed...]
+	0,					/* tp_repr */
+	0,					/* tp_as_number */
+	&listreviter_as_sequence,		/* tp_as_sequence */
+	0,					/* tp_as_mapping */
+	0,					/* tp_hash */
+	0,					/* tp_call */
+	0,					/* tp_str */
+	PyObject_GenericGetAttr,		/* tp_getattro */
+	0,					/* tp_setattro */
+	0,					/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+	0,					/* tp_doc */
+	(traverseproc)listreviter_traverse,	/* tp_traverse */
+	0,					/* tp_clear */
+	0,					/* tp_richcompare */
+	0,					/* tp_weaklistoffset */
+	PyObject_SelfIter,			/* tp_iter */
+	(iternextfunc)listreviter_next,		/* tp_iternext */
+	0,
+};

Index: longobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v
retrieving revision 1.118.2.1
retrieving revision 1.118.2.2
diff -u -d -r1.118.2.1 -r1.118.2.2
--- longobject.c	28 Apr 2003 17:18:13 -0000	1.118.2.1
+++ longobject.c	7 Jan 2005 07:04:03 -0000	1.118.2.2
@@ -12,7 +12,15 @@
  * both operands contain more than KARATSUBA_CUTOFF digits (this
  * being an internal Python long digit, in base BASE).
  */
-#define KARATSUBA_CUTOFF 35
+#define KARATSUBA_CUTOFF 70
+#define KARATSUBA_SQUARE_CUTOFF (2 * KARATSUBA_CUTOFF)
+
+/* For exponentiation, use the binary left-to-right algorithm
+ * unless the exponent contains more than FIVEARY_CUTOFF digits.
+ * In that case, do 5 bits at a time.  The potential drawback is that
+ * a table of 2**5 intermediate results is computed.
+ */
+#define FIVEARY_CUTOFF 8
 
 #define ABS(x) ((x) < 0 ? -(x) : (x))
 
@@ -237,6 +245,15 @@
 	int i;
 
 	if (vv == NULL || !PyLong_Check(vv)) {
+		if (vv != NULL && PyInt_Check(vv)) {
+			long val = PyInt_AsLong(vv);
+			if (val < 0) {
+				PyErr_SetString(PyExc_OverflowError,
+				"can't convert negative value to unsigned long");
+				return (unsigned long) -1;
+			}
+			return val;
+		}
 		PyErr_BadInternalCall();
 		return (unsigned long) -1;
 	}
@@ -271,6 +288,8 @@
 	int i, sign;
 
 	if (vv == NULL || !PyLong_Check(vv)) {
+		if (vv != NULL && PyInt_Check(vv))
+			return PyInt_AsUnsignedLongMask(vv);
 		PyErr_BadInternalCall();
 		return (unsigned long) -1;
 	}
@@ -1201,8 +1220,8 @@
 	bits_in_accum = 0;
 	pdigit = z->ob_digit;
 	while (--p >= start) {
-		unsigned char ch = (unsigned char)*p;
-		digit k;
+		int k;
+		char ch = *p;
 
 		if (ch <= '9')
 			k = ch - '0';
@@ -1212,8 +1231,8 @@
 			assert(ch >= 'A');
 			k = ch - 'A' + 10;
 		}
-		assert(k < base);
-		accum |= k << bits_in_accum;
+		assert(k >= 0 && k < base);
+		accum |= (twodigits)(k << bits_in_accum);
 		bits_in_accum += bits_per_char;
 		if (bits_in_accum >= SHIFT) {
 			*pdigit++ = (digit)(accum & MASK);
@@ -1440,7 +1459,7 @@
 			digit zz = (digit) (z >> SHIFT);
 			carry += v->ob_digit[i+k] - z
 				+ ((twodigits)zz << SHIFT);
-			v->ob_digit[i+k] = carry & MASK;
+			v->ob_digit[i+k] = (digit)(carry & MASK);
 			carry = Py_ARITHMETIC_RIGHT_SHIFT(BASE_TWODIGITS_TYPE,
 							  carry, SHIFT);
 			carry -= zz;
@@ -1459,7 +1478,7 @@
 			carry = 0;
 			for (i = 0; i < size_w && i+k < size_v; ++i) {
 				carry += v->ob_digit[i+k] + w->ob_digit[i];
-				v->ob_digit[i+k] = carry & MASK;
+				v->ob_digit[i+k] = (digit)(carry & MASK);
 				carry = Py_ARITHMETIC_RIGHT_SHIFT(
 						BASE_TWODIGITS_TYPE,
 						carry, SHIFT);
@@ -1717,26 +1736,72 @@
 		return NULL;
 
 	memset(z->ob_digit, 0, z->ob_size * sizeof(digit));
-	for (i = 0; i < size_a; ++i) {
-		twodigits carry = 0;
-		twodigits f = a->ob_digit[i];
-		int j;
-		digit *pz = z->ob_digit + i;
+	if (a == b) {
+		/* Efficient squaring per HAC, Algorithm 14.16:
+		 * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
+		 * Gives slightly less than a 2x speedup when a == b,
+		 * via exploiting that each entry in the multiplication
+		 * pyramid appears twice (except for the size_a squares).
+		 */
+		for (i = 0; i < size_a; ++i) {
+			twodigits carry;
+			twodigits f = a->ob_digit[i];
+			digit *pz = z->ob_digit + (i << 1);
+			digit *pa = a->ob_digit + i + 1;
+			digit *paend = a->ob_digit + size_a;
 
-		SIGCHECK({
-			Py_DECREF(z);
-			return NULL;
-		})
-		for (j = 0; j < size_b; ++j) {
-			carry += *pz + b->ob_digit[j] * f;
-			*pz++ = (digit) (carry & MASK);
+			SIGCHECK({
+				Py_DECREF(z);
+				return NULL;
+			})
+
+			carry = *pz + f * f;
+			*pz++ = (digit)(carry & MASK);
 			carry >>= SHIFT;
+			assert(carry <= MASK);
+
+			/* Now f is added in twice in each column of the
+			 * pyramid it appears.  Same as adding f<<1 once.
+			 */
+			f <<= 1;
+			while (pa < paend) {
+				carry += *pz + *pa++ * f;
+				*pz++ = (digit)(carry & MASK);
+				carry >>= SHIFT;
+				assert(carry <= (MASK << 1));
+			}
+			if (carry) {
+				carry += *pz;
+				*pz++ = (digit)(carry & MASK);
+				carry >>= SHIFT;
+			}
+			if (carry)
+				*pz += (digit)(carry & MASK);
+			assert((carry >> SHIFT) == 0);
 		}
-		for (; carry != 0; ++j) {
-			assert(i+j < z->ob_size);
-			carry += *pz;
-			*pz++ = (digit) (carry & MASK);
-			carry >>= SHIFT;
+	}
+	else {	/* a is not the same as b -- gradeschool long mult */
+		for (i = 0; i < size_a; ++i) {
+			twodigits carry = 0;
+			twodigits f = a->ob_digit[i];
+			digit *pz = z->ob_digit + i;
+			digit *pb = b->ob_digit;
+			digit *pbend = b->ob_digit + size_b;
+
+			SIGCHECK({
+				Py_DECREF(z);
+				return NULL;
+			})
+
+			while (pb < pbend) {
+				carry += *pz + *pb++ * f;
+				*pz++ = (digit)(carry & MASK);
+				carry >>= SHIFT;
+				assert(carry <= MASK);
+			}
+			if (carry)
+				*pz += (digit)(carry & MASK);
+			assert((carry >> SHIFT) == 0);
 		}
 	}
 	return long_normalize(z);
@@ -1816,7 +1881,8 @@
 	}
 
 	/* Use gradeschool math when either number is too small. */
-	if (asize <= KARATSUBA_CUTOFF) {
+	i = a == b ? KARATSUBA_SQUARE_CUTOFF : KARATSUBA_CUTOFF;
+	if (asize <= i) {
 		if (asize == 0)
 			return _PyLong_New(0);
 		else
@@ -1837,7 +1903,13 @@
 	if (kmul_split(a, shift, &ah, &al) < 0) goto fail;
 	assert(ah->ob_size > 0);	/* the split isn't degenerate */
 
-	if (kmul_split(b, shift, &bh, &bl) < 0) goto fail;
+	if (a == b) {
+		bh = ah;
+		bl = al;
+		Py_INCREF(bh);
+		Py_INCREF(bl);
+	}
+	else if (kmul_split(b, shift, &bh, &bl) < 0) goto fail;
 
 	/* The plan:
 	 * 1. Allocate result space (asize + bsize digits:  that's always
@@ -1906,7 +1978,11 @@
 	Py_DECREF(al);
 	ah = al = NULL;
 
-	if ((t2 = x_add(bh, bl)) == NULL) {
+	if (a == b) {
+		t2 = t1;
+		Py_INCREF(t2);
+	}
+	else if ((t2 = x_add(bh, bl)) == NULL) {
 		Py_DECREF(t1);
 		goto fail;
 	}
@@ -2078,6 +2154,12 @@
    have different signs.  We then subtract one from the 'div'
    part of the outcome to keep the invariant intact. */
 
+/* Compute
+ *     *pdiv, *pmod = divmod(v, w)
+ * NULL can be passed for pdiv or pmod, in which case that part of
+ * the result is simply thrown away.  The caller owns a reference to
+ * each of these it requests (does not pass NULL for).
+ */
 static int
 l_divmod(PyLongObject *v, PyLongObject *w,
 	 PyLongObject **pdiv, PyLongObject **pmod)
@@ -2109,44 +2191,43 @@
 		Py_DECREF(div);
 		div = temp;
 	}
-	*pdiv = div;
-	*pmod = mod;
+	if (pdiv != NULL)
+		*pdiv = div;
+	else
+		Py_DECREF(div);
+
+	if (pmod != NULL)
+		*pmod = mod;
+	else
+		Py_DECREF(mod);
+
 	return 0;
 }
 
 static PyObject *
 long_div(PyObject *v, PyObject *w)
 {
-	PyLongObject *a, *b, *div, *mod;
+	PyLongObject *a, *b, *div;
 
 	CONVERT_BINOP(v, w, &a, &b);
-
-	if (l_divmod(a, b, &div, &mod) < 0) {
-		Py_DECREF(a);
-		Py_DECREF(b);
-		return NULL;
-	}
+	if (l_divmod(a, b, &div, NULL) < 0)
+		div = NULL;
 	Py_DECREF(a);
 	Py_DECREF(b);
-	Py_DECREF(mod);
 	return (PyObject *)div;
 }
 
 static PyObject *
 long_classic_div(PyObject *v, PyObject *w)
 {
-	PyLongObject *a, *b, *div, *mod;
+	PyLongObject *a, *b, *div;
 
 	CONVERT_BINOP(v, w, &a, &b);
-
 	if (Py_DivisionWarningFlag &&
 	    PyErr_Warn(PyExc_DeprecationWarning, "classic long division") < 0)
 		div = NULL;
-	else if (l_divmod(a, b, &div, &mod) < 0)
+	else if (l_divmod(a, b, &div, NULL) < 0)
 		div = NULL;
-	else
-		Py_DECREF(mod);
-
 	Py_DECREF(a);
 	Py_DECREF(b);
 	return (PyObject *)div;
@@ -2197,18 +2278,14 @@
 static PyObject *
 long_mod(PyObject *v, PyObject *w)
 {
-	PyLongObject *a, *b, *div, *mod;
+	PyLongObject *a, *b, *mod;
 
 	CONVERT_BINOP(v, w, &a, &b);
 
-	if (l_divmod(a, b, &div, &mod) < 0) {
-		Py_DECREF(a);
-		Py_DECREF(b);
-		return NULL;
-	}
+	if (l_divmod(a, b, NULL, &mod) < 0)
+		mod = NULL;
 	Py_DECREF(a);
 	Py_DECREF(b);
-	Py_DECREF(div);
 	return (PyObject *)mod;
 }
 
@@ -2239,22 +2316,33 @@
 	return z;
 }
 
+/* pow(v, w, x) */
 static PyObject *
 long_pow(PyObject *v, PyObject *w, PyObject *x)
 {
-	PyLongObject *a, *b;
-	PyObject *c;
-	PyLongObject *z, *div, *mod;
-	int size_b, i;
+	PyLongObject *a, *b, *c; /* a,b,c = v,w,x */
+	int negativeOutput = 0;  /* if x<0 return negative output */
+
+	PyLongObject *z = NULL;  /* accumulated result */
+	int i, j, k;             /* counters */
+	PyLongObject *temp = NULL;
 
+	/* 5-ary values.  If the exponent is large enough, table is
+	 * precomputed so that table[i] == a**i % c for i in range(32).
+	 */
+	PyLongObject *table[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+				   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+	/* a, b, c = v, w, x */
 	CONVERT_BINOP(v, w, &a, &b);
-	if (PyLong_Check(x) || Py_None == x) {
-		c = x;
+	if (PyLong_Check(x)) {
+		c = (PyLongObject *)x;
 		Py_INCREF(x);
 	}
-	else if (PyInt_Check(x)) {
-		c = PyLong_FromLong(PyInt_AS_LONG(x));
-	}
+	else if (PyInt_Check(x))
+		c = (PyLongObject *)PyLong_FromLong(PyInt_AS_LONG(x));
+	else if (x == Py_None)
+		c = NULL;
 	else {
 		Py_DECREF(a);
 		Py_DECREF(b);
@@ -2262,95 +2350,154 @@
 		return Py_NotImplemented;
 	}
 
-	if (c != Py_None && ((PyLongObject *)c)->ob_size == 0) {
-		PyErr_SetString(PyExc_ValueError,
-				"pow() 3rd argument cannot be 0");
-		z = NULL;
-		goto error;
-	}
-
-	size_b = b->ob_size;
-	if (size_b < 0) {
-		Py_DECREF(a);
-		Py_DECREF(b);
-		Py_DECREF(c);
-		if (x != Py_None) {
+	if (b->ob_size < 0) {  /* if exponent is negative */
+		if (c) {
 			PyErr_SetString(PyExc_TypeError, "pow() 2nd argument "
-			     "cannot be negative when 3rd argument specified");
-			return NULL;
+			    "cannot be negative when 3rd argument specified");
+			goto Error;
+		}
+		else {
+			/* else return a float.  This works because we know
+			   that this calls float_pow() which converts its
+			   arguments to double. */
+			Py_DECREF(a);
+			Py_DECREF(b);
+			return PyFloat_Type.tp_as_number->nb_power(v, w, x);
 		}
-		/* Return a float.  This works because we know that
-		   this calls float_pow() which converts its
-		   arguments to double. */
-		return PyFloat_Type.tp_as_number->nb_power(v, w, x);
 	}
-	z = (PyLongObject *)PyLong_FromLong(1L);
-	for (i = 0; i < size_b; ++i) {
-		digit bi = b->ob_digit[i];
-		int j;
 
-		for (j = 0; j < SHIFT; ++j) {
-			PyLongObject *temp;
+	if (c) {
+		/* if modulus == 0:
+		       raise ValueError() */
+		if (c->ob_size == 0) {
+			PyErr_SetString(PyExc_ValueError,
+					"pow() 3rd argument cannot be 0");
+			goto Error;
+		}
 
-			if (bi & 1) {
-				temp = (PyLongObject *)long_mul(z, a);
-				Py_DECREF(z);
-			 	if (c!=Py_None && temp!=NULL) {
-			 		if (l_divmod(temp,(PyLongObject *)c,
-							&div,&mod) < 0) {
-						Py_DECREF(temp);
-						z = NULL;
-						goto error;
-					}
-				 	Py_XDECREF(div);
-				 	Py_DECREF(temp);
-				 	temp = mod;
-				}
-			 	z = temp;
-				if (z == NULL)
-					break;
-			}
-			bi >>= 1;
-			if (bi == 0 && i+1 == size_b)
-				break;
-			temp = (PyLongObject *)long_mul(a, a);
+		/* if modulus < 0:
+		       negativeOutput = True
+		       modulus = -modulus */
+		if (c->ob_size < 0) {
+			negativeOutput = 1;
+			temp = (PyLongObject *)_PyLong_Copy(c);
+			if (temp == NULL)
+				goto Error;
+			Py_DECREF(c);
+			c = temp;
+			temp = NULL;
+			c->ob_size = - c->ob_size;
+		}
+
+		/* if modulus == 1:
+		       return 0 */
+		if ((c->ob_size == 1) && (c->ob_digit[0] == 1)) {
+			z = (PyLongObject *)PyLong_FromLong(0L);
+			goto Done;
+		}
+
+		/* if base < 0:
+		       base = base % modulus
+		   Having the base positive just makes things easier. */
+		if (a->ob_size < 0) {
+			if (l_divmod(a, c, NULL, &temp) < 0)
+				goto Error;
 			Py_DECREF(a);
-		 	if (c!=Py_None && temp!=NULL) {
-			 	if (l_divmod(temp, (PyLongObject *)c, &div,
-							&mod) < 0) {
-					Py_DECREF(temp);
-					z = NULL;
-					goto error;
-				}
-			 	Py_XDECREF(div);
-			 	Py_DECREF(temp);
-			 	temp = mod;
-			}
 			a = temp;
-			if (a == NULL) {
-				Py_DECREF(z);
-				z = NULL;
-				break;
-			}
+			temp = NULL;
 		}
-		if (a == NULL || z == NULL)
-			break;
 	}
-	if (c!=Py_None && z!=NULL) {
-		if (l_divmod(z, (PyLongObject *)c, &div, &mod) < 0) {
-			Py_DECREF(z);
-			z = NULL;
+
+	/* At this point a, b, and c are guaranteed non-negative UNLESS
+	   c is NULL, in which case a may be negative. */
+
+	z = (PyLongObject *)PyLong_FromLong(1L);
+	if (z == NULL)
+		goto Error;
+
+	/* Perform a modular reduction, X = X % c, but leave X alone if c
+	 * is NULL.
+	 */
+#define REDUCE(X)					\
+	if (c != NULL) {				\
+		if (l_divmod(X, c, NULL, &temp) < 0)	\
+			goto Error;			\
+		Py_XDECREF(X);				\
+		X = temp;				\
+		temp = NULL;				\
+	}
+
+	/* Multiply two values, then reduce the result:
+	   result = X*Y % c.  If c is NULL, skip the mod. */
+#define MULT(X, Y, result)				\
+{							\
+	temp = (PyLongObject *)long_mul(X, Y);		\
+	if (temp == NULL)				\
+		goto Error;				\
+	Py_XDECREF(result);				\
+	result = temp;					\
+	temp = NULL;					\
+	REDUCE(result)					\
+}
+
+	if (b->ob_size <= FIVEARY_CUTOFF) {
+		/* Left-to-right binary exponentiation (HAC Algorithm 14.79) */
+		/* http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf    */
+		for (i = b->ob_size - 1; i >= 0; --i) {
+			digit bi = b->ob_digit[i];
+
+			for (j = 1 << (SHIFT-1); j != 0; j >>= 1) {
+				MULT(z, z, z)
+				if (bi & j)
+					MULT(z, a, z)
+			}
 		}
-		else {
-			Py_XDECREF(div);
-			Py_DECREF(z);
-			z = mod;
+	}
+	else {
+		/* Left-to-right 5-ary exponentiation (HAC Algorithm 14.82) */
+		Py_INCREF(z);	/* still holds 1L */
+		table[0] = z;
+		for (i = 1; i < 32; ++i)
+			MULT(table[i-1], a, table[i])
+
+		for (i = b->ob_size - 1; i >= 0; --i) {
+			const digit bi = b->ob_digit[i];
+
+			for (j = SHIFT - 5; j >= 0; j -= 5) {
+				const int index = (bi >> j) & 0x1f;
+				for (k = 0; k < 5; ++k)
+					MULT(z, z, z)
+				if (index)
+					MULT(z, table[index], z)
+			}
 		}
 	}
-  error:
+
+	if (negativeOutput && (z->ob_size != 0)) {
+		temp = (PyLongObject *)long_sub(z, c);
+		if (temp == NULL)
+			goto Error;
+		Py_DECREF(z);
+		z = temp;
+		temp = NULL;
+	}
+	goto Done;
+
+ Error:
+ 	if (z != NULL) {
+ 		Py_DECREF(z);
+ 		z = NULL;
+ 	}
+	/* fall through */
+ Done:
 	Py_XDECREF(a);
-	Py_DECREF(b);
-	Py_DECREF(c);
+	Py_XDECREF(b);
+	Py_XDECREF(c);
+	Py_XDECREF(temp);
+	if (b->ob_size > FIVEARY_CUTOFF) {
+		for (i = 0; i < 32; ++i)
+			Py_XDECREF(table[i]);
+	}
 	return (PyObject *)z;
 }
 
@@ -2794,8 +2941,10 @@
 	if (n < 0)
 		n = -n;
 	new = (PyLongObject *)type->tp_alloc(type, n);
-	if (new == NULL)
+	if (new == NULL) {
+		Py_DECREF(tmp);
 		return NULL;
+	}
 	assert(PyLong_Check(new));
 	new->ob_size = tmp->ob_size;
 	for (i = 0; i < n; i++)

Index: methodobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/methodobject.c,v
retrieving revision 2.42.2.1
retrieving revision 2.42.2.2
diff -u -d -r2.42.2.1 -r2.42.2.2
--- methodobject.c	28 Apr 2003 17:18:12 -0000	2.42.2.1
+++ methodobject.c	7 Jan 2005 07:04:03 -0000	2.42.2.2
@@ -67,7 +67,7 @@
 	PyObject *self = PyCFunction_GET_SELF(func);
 	int size;
 
-	switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC)) {
+	switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
 	case METH_VARARGS:
 		if (kw == NULL || PyDict_Size(kw) == 0)
 			return (*meth)(self, arg);

Index: moduleobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/moduleobject.c,v
retrieving revision 2.45
retrieving revision 2.45.2.1
diff -u -d -r2.45 -r2.45.2.1
--- moduleobject.c	13 Jun 2002 20:33:01 -0000	2.45
+++ moduleobject.c	7 Jan 2005 07:04:04 -0000	2.45.2.1
@@ -151,7 +151,7 @@
 {
 	static char *kwlist[] = {"name", "doc", NULL};
 	PyObject *dict, *name = Py_None, *doc = Py_None;
-	if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|O", kwlist,
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|O:module.__init__", kwlist,
 					 &name, &doc))
 		return -1;
 	dict = m->md_dict;

Index: object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.179.2.2
retrieving revision 2.179.2.3
diff -u -d -r2.179.2.2 -r2.179.2.3
--- object.c	28 Apr 2003 17:18:10 -0000	2.179.2.2
+++ object.c	7 Jan 2005 07:04:04 -0000	2.179.2.3
@@ -3,10 +3,6 @@
 
 #include "Python.h"
 
-#ifdef macintosh
-#include "macglue.h"
-#endif
-
 #ifdef Py_REF_DEBUG
 long _Py_RefTotal;
 #endif
@@ -150,6 +146,18 @@
 
 #endif /* Py_REF_DEBUG */
 
+void
+Py_IncRef(PyObject *o)
+{
+    Py_XINCREF(o);
+}
+
+void
+Py_DecRef(PyObject *o)
+{
+    Py_XDECREF(o);
+}
+
 PyObject *
 PyObject_Init(PyObject *op, PyTypeObject *tp)
 {
@@ -468,7 +476,7 @@
                          ? (t)->tp_richcompare : NULL)
 
 /* Map rich comparison operators to their swapped version, e.g. LT --> GT */
-static int swapped_op[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE};
+int _Py_SwappedOp[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE};
 
 /* Try a genuine rich comparison, returning an object.  Return:
    NULL for exception;
@@ -486,7 +494,7 @@
 	if (v->ob_type != w->ob_type &&
 	    PyType_IsSubtype(w->ob_type, v->ob_type) &&
 	    (f = RICHCOMPARE(w->ob_type)) != NULL) {
-		res = (*f)(w, v, swapped_op[op]);
+		res = (*f)(w, v, _Py_SwappedOp[op]);
 		if (res != Py_NotImplemented)
 			return res;
 		Py_DECREF(res);
@@ -498,7 +506,7 @@
 		Py_DECREF(res);
 	}
 	if ((f = RICHCOMPARE(w->ob_type)) != NULL) {
-		return (*f)(w, v, swapped_op[op]);
+		return (*f)(w, v, _Py_SwappedOp[op]);
 	}
 	res = Py_NotImplemented;
 	Py_INCREF(res);
@@ -598,33 +606,28 @@
 	    w->ob_type->tp_compare == _PyObject_SlotCompare)
 		return _PyObject_SlotCompare(v, w);
 
-	/* Try coercion; if it fails, give up */
+	/* If we're here, v and w,
+	    a) are not instances;
+	    b) have different types or a type without tp_compare; and
+	    c) don't have a user-defined tp_compare.
+	   tp_compare implementations in C assume that both arguments
+	   have their type, so we give up if the coercion fails or if
+	   it yields types which are still incompatible (which can
+	   happen with a user-defined nb_coerce).
+	*/
 	c = PyNumber_CoerceEx(&v, &w);
 	if (c < 0)
 		return -2;
 	if (c > 0)
 		return 2;
-
-	/* Try v's comparison, if defined */
-	if ((f = v->ob_type->tp_compare) != NULL) {
+	f = v->ob_type->tp_compare;
+	if (f != NULL && f == w->ob_type->tp_compare) {
 		c = (*f)(v, w);
 		Py_DECREF(v);
 		Py_DECREF(w);
 		return adjust_tp_compare(c);
 	}
 
-	/* Try w's comparison, if defined */
-	if ((f = w->ob_type->tp_compare) != NULL) {
-		c = (*f)(w, v); /* swapped! */
-		Py_DECREF(v);
-		Py_DECREF(w);
-		c = adjust_tp_compare(c);
-		if (c >= -1)
-			return -c; /* Swapped! */
-		else
-			return c;
-	}
-
 	/* No comparison defined */
 	Py_DECREF(v);
 	Py_DECREF(w);
@@ -696,8 +699,6 @@
 		Py_uintptr_t)(w->ob_type)) ? -1 : 1;
 }
 
-#define CHECK_TYPES(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_CHECKTYPES)
-
 /* Do a 3-way comparison, by hook or by crook.  Return:
    -2 for an exception (but see below);
    -1 if v <  w;
@@ -740,120 +741,6 @@
 	return default_3way_compare(v, w);
 }
 
-/* compare_nesting is incremented before calling compare (for
-   some types) and decremented on exit.  If the count exceeds the
-   nesting limit, enable code to detect circular data structures.
-
-   This is a tunable parameter that should only affect the performance
-   of comparisons, nothing else.  Setting it high makes comparing deeply
-   nested non-cyclical data structures faster, but makes comparing cyclical
-   data structures slower.
-*/
-#define NESTING_LIMIT 20
-
-static int compare_nesting = 0;
-
-static PyObject*
-get_inprogress_dict(void)
-{
-	static PyObject *key;
-	PyObject *tstate_dict, *inprogress;
-
-	if (key == NULL) {
-		key = PyString_InternFromString("cmp_state");
-		if (key == NULL)
-			return NULL;
-	}
-
-	tstate_dict = PyThreadState_GetDict();
-	if (tstate_dict == NULL) {
-		PyErr_BadInternalCall();
-		return NULL;
-	}
-
-	inprogress = PyDict_GetItem(tstate_dict, key);
-	if (inprogress == NULL) {
-		inprogress = PyDict_New();
-		if (inprogress == NULL)
-			return NULL;
-		if (PyDict_SetItem(tstate_dict, key, inprogress) == -1) {
-		    Py_DECREF(inprogress);
-		    return NULL;
-		}
-		Py_DECREF(inprogress);
-	}
-
-	return inprogress;
-}
-
-/* If the comparison "v op w" is already in progress in this thread, returns
- * a borrowed reference to Py_None (the caller must not decref).
- * If it's not already in progress, returns "a token" which must eventually
- * be passed to delete_token().  The caller must not decref this either
- * (delete_token decrefs it).  The token must not survive beyond any point
- * where v or w may die.
- * If an error occurs (out-of-memory), returns NULL.
- */
-static PyObject *
-check_recursion(PyObject *v, PyObject *w, int op)
-{
-	PyObject *inprogress;
-	PyObject *token;
-	Py_uintptr_t iv = (Py_uintptr_t)v;
-	Py_uintptr_t iw = (Py_uintptr_t)w;
-	PyObject *x, *y, *z;
-
-	inprogress = get_inprogress_dict();
-	if (inprogress == NULL)
-		return NULL;
-
-	token = PyTuple_New(3);
-	if (token == NULL)
-		return NULL;
-
-	if (iv <= iw) {
-		PyTuple_SET_ITEM(token, 0, x = PyLong_FromVoidPtr((void *)v));
-		PyTuple_SET_ITEM(token, 1, y = PyLong_FromVoidPtr((void *)w));
-		if (op >= 0)
-			op = swapped_op[op];
-	} else {
-		PyTuple_SET_ITEM(token, 0, x = PyLong_FromVoidPtr((void *)w));
-		PyTuple_SET_ITEM(token, 1, y = PyLong_FromVoidPtr((void *)v));
-	}
-	PyTuple_SET_ITEM(token, 2, z = PyInt_FromLong((long)op));
-	if (x == NULL || y == NULL || z == NULL) {
-		Py_DECREF(token);
-		return NULL;
-	}
-
-	if (PyDict_GetItem(inprogress, token) != NULL) {
-		Py_DECREF(token);
-		return Py_None; /* Without INCREF! */
-	}
-
-	if (PyDict_SetItem(inprogress, token, token) < 0) {
-		Py_DECREF(token);
-		return NULL;
-	}
-
-	return token;
-}
-
-static void
-delete_token(PyObject *token)
-{
-	PyObject *inprogress;
-
-	if (token == NULL || token == Py_None)
-		return;
-	inprogress = get_inprogress_dict();
-	if (inprogress == NULL)
-		PyErr_Clear();
-	else
-		PyDict_DelItem(inprogress, token);
-	Py_DECREF(token);
-}
-
 /* Compare v to w.  Return
    -1 if v <  w or exception (PyErr_Occurred() true in latter case).
     0 if v == w.
@@ -864,47 +751,18 @@
 int
 PyObject_Compare(PyObject *v, PyObject *w)
 {
-	PyTypeObject *vtp;
 	int result;
 
-#if defined(USE_STACKCHECK)
-	if (PyOS_CheckStack()) {
-		PyErr_SetString(PyExc_MemoryError, "Stack overflow");
-		return -1;
-	}
-#endif
 	if (v == NULL || w == NULL) {
 		PyErr_BadInternalCall();
 		return -1;
 	}
 	if (v == w)
 		return 0;
-	vtp = v->ob_type;
-	compare_nesting++;
-	if (compare_nesting > NESTING_LIMIT &&
-	    (vtp->tp_as_mapping || vtp->tp_as_sequence) &&
-	    !PyString_CheckExact(v) &&
-	    !PyTuple_CheckExact(v)) {
-		/* try to detect circular data structures */
-		PyObject *token = check_recursion(v, w, -1);
-
-		if (token == NULL) {
-			result = -1;
-		}
-		else if (token == Py_None) {
-			/* already comparing these objects.  assume
-			   they're equal until shown otherwise */
-                        result = 0;
-		}
-		else {
-			result = do_cmp(v, w);
-			delete_token(token);
-		}
-	}
-	else {
-		result = do_cmp(v, w);
-	}
-	compare_nesting--;
+	if (Py_EnterRecursiveCall(" in cmp"))
+		return -1;
+	result = do_cmp(v, w);
+	Py_LeaveRecursiveCall();
 	return result < 0 ? -1 : result;
 }
 
@@ -975,41 +833,10 @@
 	PyObject *res;
 
 	assert(Py_LT <= op && op <= Py_GE);
+	if (Py_EnterRecursiveCall(" in cmp"))
+		return NULL;
 
-	compare_nesting++;
-	if (compare_nesting > NESTING_LIMIT &&
-	    (v->ob_type->tp_as_mapping || v->ob_type->tp_as_sequence) &&
-	    !PyString_CheckExact(v) &&
-	    !PyTuple_CheckExact(v)) {
-		/* try to detect circular data structures */
-		PyObject *token = check_recursion(v, w, op);
-		if (token == NULL) {
-			res = NULL;
-			goto Done;
-		}
-		else if (token == Py_None) {
-			/* already comparing these objects with this operator.
-			   assume they're equal until shown otherwise */
-			if (op == Py_EQ)
-				res = Py_True;
-			else if (op == Py_NE)
-				res = Py_False;
-			else {
-				PyErr_SetString(PyExc_ValueError,
-					"can't order recursive values");
-				res = NULL;
-			}
-			Py_XINCREF(res);
-		}
-		else {
-			res = do_richcmp(v, w, op);
-			delete_token(token);
-		}
-		goto Done;
-	}
-
-	/* No nesting extremism.
-	   If the types are equal, and not old-style instances, try to
+	/* If the types are equal, and not old-style instances, try to
 	   get out cheap (don't bother with coercions etc.). */
 	if (v->ob_type == w->ob_type && !PyInstance_Check(v)) {
 		cmpfunc fcmp;
@@ -1041,7 +868,7 @@
 	/* Fast path not taken, or couldn't deliver a useful result. */
 	res = do_richcmp(v, w, op);
 Done:
-	compare_nesting--;
+	Py_LeaveRecursiveCall();
 	return res;
 }
 
@@ -1049,9 +876,19 @@
 int
 PyObject_RichCompareBool(PyObject *v, PyObject *w, int op)
 {
-	PyObject *res = PyObject_RichCompare(v, w, op);
+	PyObject *res;
 	int ok;
 
+	/* Quick result when objects are the same.
+	   Guarantees that identity implies equality. */
+	if (v == w) {
+		if (op == Py_EQ)
+			return 1;
+		else if (op == Py_NE)
+			return 0;
+	}
+
+	res = PyObject_RichCompare(v, w, op);
 	if (res == NULL)
 		return -1;
 	if (PyBool_Check(res))
@@ -1063,7 +900,7 @@
 }
 
 /* Set of hash utility functions to help maintaining the invariant that
-	iff a==b then hash(a)==hash(b)
+	if a==b then hash(a)==hash(b)
 
    All the utility functions (_Py_Hash*()) return "-1" to signify an error.
 */
@@ -1080,15 +917,7 @@
 	 * of mapping keys will turn out weird.
 	 */
 
-#ifdef MPW /* MPW C modf expects pointer to extended as second argument */
-{
-	extended e;
-	fractpart = modf(v, &e);
-	intpart = e;
-}
-#else
 	fractpart = modf(v, &intpart);
-#endif
 	if (fractpart == 0.0) {
 		/* This must return the same hash as an equal int or long. */
 		if (intpart > LONG_MAX || -intpart > LONG_MAX) {
@@ -1342,8 +1171,6 @@
 	return (PyObject **) ((char *)obj + dictoffset);
 }
 
-/* Generic GetAttr functions - put these in your tp_[gs]etattro slot */
-
 PyObject *
 PyObject_SelfIter(PyObject *obj)
 {
@@ -1351,6 +1178,8 @@
 	return obj;
 }
 
+/* Generic GetAttr functions - put these in your tp_[gs]etattro slot */
+
 PyObject *
 PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
 {
@@ -1412,12 +1241,15 @@
 		}
 	}
 
+	Py_XINCREF(descr);
+
 	f = NULL;
 	if (descr != NULL &&
 	    PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS)) {
 		f = descr->ob_type->tp_descr_get;
 		if (f != NULL && PyDescr_IsData(descr)) {
 			res = f(descr, obj, (PyObject *)obj->ob_type);
+			Py_DECREF(descr);
 			goto done;
 		}
 	}
@@ -1445,6 +1277,7 @@
 			res = PyDict_GetItem(dict, name);
 			if (res != NULL) {
 				Py_INCREF(res);
+				Py_XDECREF(descr);
 				goto done;
 			}
 		}
@@ -1452,12 +1285,13 @@
 
 	if (f != NULL) {
 		res = f(descr, obj, (PyObject *)obj->ob_type);
+		Py_DECREF(descr);
 		goto done;
 	}
 
 	if (descr != NULL) {
-		Py_INCREF(descr);
 		res = descr;
+		/* descr was already increfed above */
 		goto done;
 	}
 
@@ -1780,7 +1614,7 @@
 		PyObject *locals = PyEval_GetLocals();
 		if (locals == NULL)
 			goto error;
-		result = PyDict_Keys(locals);
+		result = PyMapping_Keys(locals);
 		if (result == NULL)
 			goto error;
 	}
@@ -1863,6 +1697,11 @@
 	}
 
 	assert(result);
+	if (!PyList_Check(result)) {
+		PyErr_SetString(PyExc_TypeError,
+			"Expected keys() to be a list.");
+		goto error;
+	}
 	if (PyList_Sort(result) != 0)
 		goto error;
 	else
@@ -1961,6 +1800,9 @@
 	if (PyType_Ready(&PyType_Type) < 0)
 		Py_FatalError("Can't initialize 'type'");
 
+	if (PyType_Ready(&_PyWeakref_RefType) < 0)
+		Py_FatalError("Can't initialize 'weakref'");
+
 	if (PyType_Ready(&PyBool_Type) < 0)
 		Py_FatalError("Can't initialize 'bool'");
 

Index: obmalloc.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/obmalloc.c,v
retrieving revision 2.45.2.1
retrieving revision 2.45.2.2
diff -u -d -r2.45.2.1 -r2.45.2.2
--- obmalloc.c	28 Apr 2003 17:18:10 -0000	2.45.2.1
+++ obmalloc.c	7 Jan 2005 07:04:04 -0000	2.45.2.2
@@ -534,8 +534,32 @@
  * so the (I) < narenas must be false, saving us from trying to index into
  * a NULL arenas.
  */
-#define ADDRESS_IN_RANGE(P, I) \
-	((I) < narenas && (uptr)(P) - arenas[I] < (uptr)ARENA_SIZE)
+#define Py_ADDRESS_IN_RANGE(P, POOL)	\
+	((POOL)->arenaindex < narenas &&		\
+	 (uptr)(P) - arenas[(POOL)->arenaindex] < (uptr)ARENA_SIZE)
+
+/* This is only useful when running memory debuggers such as
+ * Purify or Valgrind.  Uncomment to use.
+ *
+#define Py_USING_MEMORY_DEBUGGER
+ */
+
+#ifdef Py_USING_MEMORY_DEBUGGER
+
+/* Py_ADDRESS_IN_RANGE may access uninitialized memory by design
+ * This leads to thousands of spurious warnings when using
+ * Purify or Valgrind.  By making a function, we can easily
+ * suppress the uninitialized memory reads in this one function.
+ * So we won't ignore real errors elsewhere.
+ *
+ * Disable the macro and use a function.
+ */
+
+#undef Py_ADDRESS_IN_RANGE
+
+/* Don't make static, to ensure this isn't inlined. */
+int Py_ADDRESS_IN_RANGE(void *P, poolp pool);
+#endif
 
 /*==========================================================================*/
 
@@ -651,9 +675,9 @@
 			UNLOCK();
 			return (void *)bp;
 		}
-                /*
-                 * Allocate new pool
-                 */
+		/*
+		 * Allocate new pool
+		 */
 		if (nfreepools) {
 		commit_pool:
 			--nfreepools;
@@ -663,9 +687,9 @@
 			pool->szidx = DUMMY_SIZE_IDX;
 			goto init_pool;
 		}
-                /*
-                 * Allocate new arena
-                 */
+		/*
+		 * Allocate new arena
+		 */
 #ifdef WITH_MEMORY_LIMITS
 		if (!(narenas < MAX_ARENAS)) {
 			UNLOCK();
@@ -708,7 +732,7 @@
 		return;
 
 	pool = POOL_ADDR(p);
-	if (ADDRESS_IN_RANGE(p, pool->arenaindex)) {
+	if (Py_ADDRESS_IN_RANGE(p, pool)) {
 		/* We allocated this address. */
 		LOCK();
 		/*
@@ -791,7 +815,7 @@
 		return PyObject_Malloc(nbytes);
 
 	pool = POOL_ADDR(p);
-	if (ADDRESS_IN_RANGE(p, pool->arenaindex)) {
+	if (Py_ADDRESS_IN_RANGE(p, pool)) {
 		/* We're in charge of this block */
 		size = INDEX2SIZE(pool->szidx);
 		if (nbytes <= size) {
@@ -1373,3 +1397,14 @@
 }
 
 #endif	/* PYMALLOC_DEBUG */
+
+#ifdef Py_USING_MEMORY_DEBUGGER
+/* Make this function last so gcc won't inline it
+   since the definition is after the reference. */
+int
+Py_ADDRESS_IN_RANGE(void *P, poolp pool)
+{
+	return ((pool->arenaindex) < narenas &&
+		(uptr)(P) - arenas[pool->arenaindex] < (uptr)ARENA_SIZE);
+}
+#endif

Index: rangeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/rangeobject.c,v
retrieving revision 2.41.2.1
retrieving revision 2.41.2.2
diff -u -d -r2.41.2.1 -r2.41.2.2
--- rangeobject.c	28 Apr 2003 17:18:09 -0000	2.41.2.1
+++ rangeobject.c	7 Jan 2005 07:04:04 -0000	2.41.2.2
@@ -9,43 +9,6 @@
 	long	len;
 } rangeobject;
 
-PyObject *
-PyRange_New(long start, long len, long step, int reps)
-{
-	rangeobject *obj;
-
-	if (reps != 1) {
-		PyErr_SetString(PyExc_ValueError,
-			"PyRange_New's 'repetitions' argument must be 1");
-		return NULL;
-	}
-
-	obj = PyObject_New(rangeobject, &PyRange_Type);
-	if (obj == NULL)
-		return NULL;
-
-	if (len == 0) {
-		start = 0;
-		len = 0;
-		step = 1;
-	}
-	else {
-		long last = start + (len - 1) * step;
-		if ((step > 0) ?
-		    (last > (PyInt_GetMax() - step)) : 
-		    (last < (-1 - PyInt_GetMax() - step))) {
-			PyErr_SetString(PyExc_OverflowError,
-					"integer addition");
-			return NULL;
-		}			
-	}
-	obj->start = start;
-	obj->len   = len;
-	obj->step  = step;
-
-	return (PyObject *) obj;
-}
-
 /* Return number of items in range/xrange (lo, hi, step).  step > 0
  * required.  Return a value < 0 if & only if the true value is too
  * large to fit in a signed long.
@@ -78,6 +41,7 @@
 static PyObject *
 range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
 {
+	rangeobject *obj;
 	long ilow = 0, ihigh = 0, istep = 1;
 	long n;
 
@@ -106,7 +70,14 @@
 				"xrange() result has too many items");
 		return NULL;
 	}
-	return PyRange_New(ilow, n, istep, 1);
+
+	obj = PyObject_New(rangeobject, &PyRange_Type);
+	if (obj == NULL)
+		return NULL;
+	obj->start = ilow;
+	obj->len   = n;
+	obj->step  = istep;
+	return (PyObject *) obj;
 }
 
 PyDoc_STRVAR(range_doc,
@@ -144,7 +115,7 @@
 range_repr(rangeobject *r)
 {
 	PyObject *rtn;
-	
+
 	if (r->start == 0 && r->step == 1)
 		rtn = PyString_FromFormat("xrange(%ld)",
 					  r->start + r->len * r->step);
@@ -171,6 +142,15 @@
 };
 
 static PyObject * range_iter(PyObject *seq);
+static PyObject * range_reverse(PyObject *seq);
+
+PyDoc_STRVAR(reverse_doc,
+"Returns a reverse iterator.");
+
+static PyMethodDef range_methods[] = {
+	{"__reversed__",	(PyCFunction)range_reverse, METH_NOARGS, reverse_doc},
+ 	{NULL,		NULL}		/* sentinel */
+};
 
 PyTypeObject PyRange_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
@@ -201,7 +181,7 @@
 	0,				/* tp_weaklistoffset */
 	(getiterfunc)range_iter,	/* tp_iter */
 	0,				/* tp_iternext */
-	0,				/* tp_methods */	
+	range_methods,			/* tp_methods */
 	0,				/* tp_members */
 	0,				/* tp_getset */
 	0,				/* tp_base */
@@ -246,13 +226,51 @@
 }
 
 static PyObject *
+range_reverse(PyObject *seq)
+{
+	rangeiterobject *it;
+	long start, step, len;
+
+	if (!PyRange_Check(seq)) {
+		PyErr_BadInternalCall();
+		return NULL;
+	}
+	it = PyObject_New(rangeiterobject, &Pyrangeiter_Type);
+	if (it == NULL)
+		return NULL;
+
+	start = ((rangeobject *)seq)->start;
+	step = ((rangeobject *)seq)->step;
+	len = ((rangeobject *)seq)->len;
+
+	it->index = 0;
+	it->start = start + (len-1) * step;
+	it->step = -step;
+	it->len = len;
+
+	return (PyObject *)it;
+}
+
+static PyObject *
 rangeiter_next(rangeiterobject *r)
 {
-	if (r->index < r->len) 
+	if (r->index < r->len)
 		return PyInt_FromLong(r->start + (r->index++) * r->step);
 	return NULL;
 }
 
+static int
+rangeiter_len(rangeiterobject *r)
+{
+	return r->len - r->index;
+}
+
+static PySequenceMethods rangeiter_as_sequence = {
+	(inquiry)rangeiter_len,		/* sq_length */
+	0,				/* sq_concat */
+};
+
+
 static PyTypeObject Pyrangeiter_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,                                      /* ob_size */
@@ -267,7 +285,7 @@
 	0,                                      /* tp_compare */
 	0,                                      /* tp_repr */
 	0,                                      /* tp_as_number */
-	0,                                      /* tp_as_sequence */
+	&rangeiter_as_sequence,			/* tp_as_sequence */
 	0,                                      /* tp_as_mapping */
 	0,                                      /* tp_hash */
 	0,                                      /* tp_call */

Index: sliceobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/sliceobject.c,v
retrieving revision 2.15.2.1
retrieving revision 2.15.2.2
diff -u -d -r2.15.2.1 -r2.15.2.2
--- sliceobject.c	28 Apr 2003 17:18:08 -0000	2.15.2.1
+++ sliceobject.c	7 Jan 2005 07:04:05 -0000	2.15.2.2
@@ -278,6 +278,13 @@
 	return result;
 }
 
+static long
+slice_hash(PySliceObject *v)
+{
+	PyErr_SetString(PyExc_TypeError, "unhashable type");
+	return -1L;
+}
+
 PyTypeObject PySlice_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,			/* Number of items for varobject */
@@ -293,7 +300,7 @@
 	0,					/* tp_as_number */
 	0,	    				/* tp_as_sequence */
 	0,					/* tp_as_mapping */
-	0,					/* tp_hash */
+	(hashfunc)slice_hash,			/* tp_hash */
 	0,					/* tp_call */
 	0,					/* tp_str */
 	PyObject_GenericGetAttr,		/* tp_getattro */

Index: stringobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v
retrieving revision 2.168.2.1
retrieving revision 2.168.2.2
diff -u -d -r2.168.2.1 -r2.168.2.2
--- stringobject.c	28 Apr 2003 17:18:07 -0000	2.168.2.1
+++ stringobject.c	7 Jan 2005 07:04:05 -0000	2.168.2.2
@@ -8,10 +8,6 @@
 int null_strings, one_strings;
 #endif
 
-#if !defined(HAVE_LIMITS_H) && !defined(UCHAR_MAX)
-#define UCHAR_MAX 255
-#endif
-
 static PyStringObject *characters[UCHAR_MAX + 1];
 static PyStringObject *nullstring;
 
@@ -74,8 +70,7 @@
 	}
 
 	/* Inline PyObject_NewVar */
-	op = (PyStringObject *)
-		PyObject_MALLOC(sizeof(PyStringObject) + size * sizeof(char));
+	op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
 	if (op == NULL)
 		return PyErr_NoMemory();
 	PyObject_INIT_VAR(op, &PyString_Type, size);
@@ -130,8 +125,7 @@
 	}
 
 	/* Inline PyObject_NewVar */
-	op = (PyStringObject *)
-		PyObject_MALLOC(sizeof(PyStringObject) + size * sizeof(char));
+	op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
 	if (op == NULL)
 		return PyErr_NoMemory();
 	PyObject_INIT_VAR(op, &PyString_Type, size);
@@ -803,7 +797,7 @@
 PyString_Repr(PyObject *obj, int smartquotes)
 {
 	register PyStringObject* op = (PyStringObject*) obj;
-	size_t newsize = 2 + 4 * op->ob_size * sizeof(char);
+	size_t newsize = 2 + 4 * op->ob_size;
 	PyObject *v;
 	if (newsize > INT_MAX) {
 		PyErr_SetString(PyExc_OverflowError,
@@ -915,8 +909,7 @@
 	}
 	size = a->ob_size + b->ob_size;
 	/* Inline PyObject_NewVar */
-	op = (PyStringObject *)
-		PyObject_MALLOC(sizeof(PyStringObject) + size * sizeof(char));
+	op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
 	if (op == NULL)
 		return PyErr_NoMemory();
 	PyObject_INIT_VAR(op, &PyString_Type, size);
@@ -952,9 +945,8 @@
 		Py_INCREF(a);
 		return (PyObject *)a;
 	}
-	nbytes = size * sizeof(char);
-	if (nbytes / sizeof(char) != (size_t)size ||
-	    nbytes + sizeof(PyStringObject) <= nbytes) {
+	nbytes = (size_t)size;
+	if (nbytes + sizeof(PyStringObject) <= nbytes) {
 		PyErr_SetString(PyExc_OverflowError,
 			"repeated string is too long");
 		return NULL;
@@ -1286,12 +1278,35 @@
 
 #define STRIPNAME(i) (stripformat[i]+3)
 
+#define SPLIT_APPEND(data, left, right)				\
+	str = PyString_FromStringAndSize((data) + (left),	\
+					 (right) - (left));	\
+	if (str == NULL)					\
+		goto onError;					\
+	if (PyList_Append(list, str)) {				\
+		Py_DECREF(str);					\
+		goto onError;					\
+	}							\
+	else							\
+		Py_DECREF(str);
+
+#define SPLIT_INSERT(data, left, right)			 	\
+	str = PyString_FromStringAndSize((data) + (left),	\
+					 (right) - (left));	\
+	if (str == NULL)					\
+		goto onError;					\
+	if (PyList_Insert(list, 0, str)) {			\
+		Py_DECREF(str);					\
+		goto onError;					\
+	}							\
+	else							\
+		Py_DECREF(str);
 
 static PyObject *
 split_whitespace(const char *s, int len, int maxsplit)
 {
-	int i, j, err;
-	PyObject* item;
+	int i, j;
+	PyObject *str;
 	PyObject *list = PyList_New(0);
 
 	if (list == NULL)
@@ -1306,33 +1321,49 @@
 		if (j < i) {
 			if (maxsplit-- <= 0)
 				break;
-			item = PyString_FromStringAndSize(s+j, (int)(i-j));
-			if (item == NULL)
-				goto finally;
-			err = PyList_Append(list, item);
-			Py_DECREF(item);
-			if (err < 0)
-				goto finally;
+			SPLIT_APPEND(s, j, i);
 			while (i < len && isspace(Py_CHARMASK(s[i])))
 				i++;
 			j = i;
 		}
 	}
 	if (j < len) {
-		item = PyString_FromStringAndSize(s+j, (int)(len - j));
-		if (item == NULL)
-			goto finally;
-		err = PyList_Append(list, item);
-		Py_DECREF(item);
-		if (err < 0)
-			goto finally;
+		SPLIT_APPEND(s, j, len);
 	}
 	return list;
-  finally:
+  onError:
 	Py_DECREF(list);
 	return NULL;
 }
 
+static PyObject *
+split_char(const char *s, int len, char ch, int maxcount)
+{
+	register int i, j;
+	PyObject *str;
+	PyObject *list = PyList_New(0);
+
+	if (list == NULL)
+		return NULL;
+
+	for (i = j = 0; i < len; ) {
+		if (s[i] == ch) {
+			if (maxcount-- <= 0)
+				break;
+			SPLIT_APPEND(s, j, i);
+			i = j = i + 1;
+		} else
+			i++;
+	}
+	if (j <= len) {
+		SPLIT_APPEND(s, j, len);
+	}
+	return list;
+
+  onError:
+	Py_DECREF(list);
+	return NULL;
+}
 
 PyDoc_STRVAR(split__doc__,
 "S.split([sep [,maxsplit]]) -> list of strings\n\
@@ -1366,10 +1397,13 @@
 #endif
 	else if (PyObject_AsCharBuffer(subobj, &sub, &n))
 		return NULL;
+
 	if (n == 0) {
 		PyErr_SetString(PyExc_ValueError, "empty separator");
 		return NULL;
 	}
+	else if (n == 1)
+		return split_char(s, len, sub[0], maxsplit);
 
 	list = PyList_New(0);
 	if (list == NULL)
@@ -1407,6 +1441,148 @@
 	return NULL;
 }
 
+static PyObject *
+rsplit_whitespace(const char *s, int len, int maxsplit)
+{
+	int i, j;
+	PyObject *str;
+	PyObject *list = PyList_New(0);
+
+	if (list == NULL)
+		return NULL;
+
+	for (i = j = len - 1; i >= 0; ) {
+		while (i >= 0 && isspace(Py_CHARMASK(s[i])))
+			i--;
+		j = i;
+		while (i >= 0 && !isspace(Py_CHARMASK(s[i])))
+			i--;
+		if (j > i) {
+			if (maxsplit-- <= 0)
+				break;
+			SPLIT_INSERT(s, i + 1, j + 1);
+			while (i >= 0 && isspace(Py_CHARMASK(s[i])))
+				i--;
+			j = i;
+		}
+	}
+	if (j >= 0) {
+		SPLIT_INSERT(s, 0, j + 1);
+	}
+	return list;
+  onError:
+	Py_DECREF(list);
+	return NULL;
+}
+
+static PyObject *
+rsplit_char(const char *s, int len, char ch, int maxcount)
+{
+	register int i, j;
+	PyObject *str;
+	PyObject *list = PyList_New(0);
+
+	if (list == NULL)
+		return NULL;
+
+	for (i = j = len - 1; i >= 0; ) {
+		if (s[i] == ch) {
+			if (maxcount-- <= 0)
+				break;
+			SPLIT_INSERT(s, i + 1, j + 1);
+			j = i = i - 1;
+		} else
+			i--;
+	}
+	if (j >= -1) {
+		SPLIT_INSERT(s, 0, j + 1);
+	}
+	return list;
+
+ onError:
+	Py_DECREF(list);
+	return NULL;
+}
+
+PyDoc_STRVAR(rsplit__doc__,
+"S.rsplit([sep [,maxsplit]]) -> list of strings\n\
+\n\
+Return a list of the words in the string S, using sep as the\n\
+delimiter string, starting at the end of the string and working\n\
+to the front.  If maxsplit is given, at most maxsplit splits are\n\
+done. If sep is not specified or is None, any whitespace string\n\
+is a separator.");
+
+static PyObject *
+string_rsplit(PyStringObject *self, PyObject *args)
+{
+	int len = PyString_GET_SIZE(self), n, i, j, err;
+	int maxsplit = -1;
+	const char *s = PyString_AS_STRING(self), *sub;
+	PyObject *list, *item, *subobj = Py_None;
+
+	if (!PyArg_ParseTuple(args, "|Oi:rsplit", &subobj, &maxsplit))
+		return NULL;
+	if (maxsplit < 0)
+		maxsplit = INT_MAX;
+	if (subobj == Py_None)
+		return rsplit_whitespace(s, len, maxsplit);
+	if (PyString_Check(subobj)) {
+		sub = PyString_AS_STRING(subobj);
+		n = PyString_GET_SIZE(subobj);
+	}
+#ifdef Py_USING_UNICODE
+	else if (PyUnicode_Check(subobj))
+		return PyUnicode_RSplit((PyObject *)self, subobj, maxsplit);
+#endif
+	else if (PyObject_AsCharBuffer(subobj, &sub, &n))
+		return NULL;
+
+	if (n == 0) {
+		PyErr_SetString(PyExc_ValueError, "empty separator");
+		return NULL;
+	}
+	else if (n == 1)
+		return rsplit_char(s, len, sub[0], maxsplit);
+
+	list = PyList_New(0);
+	if (list == NULL)
+		return NULL;
+
+	j = len;
+	i = j - n;
+	while (i >= 0) {
+		if (s[i] == sub[0] && memcmp(s+i, sub, n) == 0) {
+			if (maxsplit-- <= 0)
+				break;
+			item = PyString_FromStringAndSize(s+i+n, (int)(j-i-n));
+			if (item == NULL)
+				goto fail;
+			err = PyList_Insert(list, 0, item);
+			Py_DECREF(item);
+			if (err < 0)
+				goto fail;
+			j = i;
+			i -= n;
+		}
+		else
+			i--;
+	}
+	item = PyString_FromStringAndSize(s, j);
+	if (item == NULL)
+		goto fail;
+	err = PyList_Insert(list, 0, item);
+	Py_DECREF(item);
+	if (err < 0)
+		goto fail;
+
+	return list;
+
+ fail:
+	Py_DECREF(list);
+	return NULL;
+}
+
 
 PyDoc_STRVAR(join__doc__,
 "S.join(sequence) -> string\n\
@@ -1442,22 +1618,18 @@
 	}
 	if (seqlen == 1) {
 		item = PySequence_Fast_GET_ITEM(seq, 0);
-		if (!PyString_Check(item) && !PyUnicode_Check(item)) {
-			PyErr_Format(PyExc_TypeError,
-				     "sequence item 0: expected string,"
-				     " %.80s found",
-				     item->ob_type->tp_name);
+		if (PyString_CheckExact(item) || PyUnicode_CheckExact(item)) {
+			Py_INCREF(item);
 			Py_DECREF(seq);
-			return NULL;
+			return item;
 		}
-		Py_INCREF(item);
-		Py_DECREF(seq);
-		return item;
 	}
 
-	/* There are at least two things to join.  Do a pre-pass to figure out
-	 * the total amount of space we'll need (sz), see whether any argument
-	 * is absurd, and defer to the Unicode join if appropriate.
+	/* There are at least two things to join, or else we have a subclass
+	 * of the builtin types in the sequence.  
+	 * Do a pre-pass to figure out the total amount of space we'll
+	 * need (sz), see whether any argument is absurd, and defer to
+	 * the Unicode join if appropriate.
 	 */
 	for (i = 0; i < seqlen; i++) {
 		const size_t old_sz = sz;
@@ -2308,11 +2480,11 @@
 
 
 PyDoc_STRVAR(replace__doc__,
-"S.replace (old, new[, maxsplit]) -> string\n\
+"S.replace (old, new[, count]) -> string\n\
 \n\
 Return a copy of string S with all occurrences of substring\n\
-old replaced by new.  If the optional argument maxsplit is\n\
-given, only the first maxsplit occurrences are replaced.");
+old replaced by new.  If the optional argument count is\n\
+given, only the first count occurrences are replaced.");
 
 static PyObject *
 string_replace(PyStringObject *self, PyObject *args)
@@ -2497,9 +2669,25 @@
 {
     char *encoding = NULL;
     char *errors = NULL;
+    PyObject *v;
+    
     if (!PyArg_ParseTuple(args, "|ss:encode", &encoding, &errors))
         return NULL;
-    return PyString_AsEncodedObject((PyObject *)self, encoding, errors);
+    v = PyString_AsEncodedObject((PyObject *)self, encoding, errors);
+    if (v == NULL)
+        goto onError;
+    if (!PyString_Check(v) && !PyUnicode_Check(v)) {
+        PyErr_Format(PyExc_TypeError,
+                     "encoder did not return a string/unicode object "
+                     "(type=%.400s)",
+                     v->ob_type->tp_name);
+        Py_DECREF(v);
+        return NULL;
+    }
+    return v;
+
+ onError:
+    return NULL;
 }
 
 
@@ -2518,9 +2706,25 @@
 {
     char *encoding = NULL;
     char *errors = NULL;
+    PyObject *v;
+    
     if (!PyArg_ParseTuple(args, "|ss:decode", &encoding, &errors))
         return NULL;
-    return PyString_AsDecodedObject((PyObject *)self, encoding, errors);
+    v = PyString_AsDecodedObject((PyObject *)self, encoding, errors);
+    if (v == NULL)
+        goto onError;
+    if (!PyString_Check(v) && !PyUnicode_Check(v)) {
+        PyErr_Format(PyExc_TypeError,
+                     "decoder did not return a string/unicode object "
+                     "(type=%.400s)",
+                     v->ob_type->tp_name);
+        Py_DECREF(v);
+        return NULL;
+    }
+    return v;
+
+ onError:
+    return NULL;
 }
 
 
@@ -2617,16 +2821,18 @@
 }
 
 PyDoc_STRVAR(ljust__doc__,
-"S.ljust(width) -> string\n"
+"S.ljust(width[, fillchar]) -> string\n"
 "\n"
 "Return S left justified in a string of length width. Padding is\n"
-"done using spaces.");
+"done using the specified fill character (default is a space).");
 
 static PyObject *
 string_ljust(PyStringObject *self, PyObject *args)
 {
     int width;
-    if (!PyArg_ParseTuple(args, "i:ljust", &width))
+    char fillchar = ' ';
+
+    if (!PyArg_ParseTuple(args, "i|c:ljust", &width, &fillchar))
         return NULL;
 
     if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {
@@ -2634,21 +2840,23 @@
         return (PyObject*) self;
     }
 
-    return pad(self, 0, width - PyString_GET_SIZE(self), ' ');
+    return pad(self, 0, width - PyString_GET_SIZE(self), fillchar);
 }
 
 
 PyDoc_STRVAR(rjust__doc__,
-"S.rjust(width) -> string\n"
+"S.rjust(width[, fillchar]) -> string\n"
 "\n"
 "Return S right justified in a string of length width. Padding is\n"
-"done using spaces.");
+"done using the specified fill character (default is a space)");
 
 static PyObject *
 string_rjust(PyStringObject *self, PyObject *args)
 {
     int width;
-    if (!PyArg_ParseTuple(args, "i:rjust", &width))
+    char fillchar = ' ';
+
+    if (!PyArg_ParseTuple(args, "i|c:rjust", &width, &fillchar))
         return NULL;
 
     if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {
@@ -2656,23 +2864,24 @@
         return (PyObject*) self;
     }
 
-    return pad(self, width - PyString_GET_SIZE(self), 0, ' ');
+    return pad(self, width - PyString_GET_SIZE(self), 0, fillchar);
 }
 
 
 PyDoc_STRVAR(center__doc__,
-"S.center(width) -> string\n"
+"S.center(width[, fillchar]) -> string\n"
 "\n"
-"Return S centered in a string of length width. Padding is done\n"
-"using spaces.");
+"Return S centered in a string of length width. Padding is\n"
+"done using the specified fill character (default is a space)");
 
 static PyObject *
 string_center(PyStringObject *self, PyObject *args)
 {
     int marg, left;
     int width;
+    char fillchar = ' ';
 
-    if (!PyArg_ParseTuple(args, "i:center", &width))
+    if (!PyArg_ParseTuple(args, "i|c:center", &width, &fillchar))
         return NULL;
 
     if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {
@@ -2683,7 +2892,7 @@
     marg = width - PyString_GET_SIZE(self);
     left = marg / 2 + (marg & width & 1);
 
-    return pad(self, left, marg - left, ' ');
+    return pad(self, left, marg - left, fillchar);
 }
 
 PyDoc_STRVAR(zfill__doc__,
@@ -2733,10 +2942,10 @@
 }
 
 PyDoc_STRVAR(isspace__doc__,
-"S.isspace() -> bool\n"
-"\n"
-"Return True if there are only whitespace characters in S,\n"
-"False otherwise.");
+"S.isspace() -> bool\n\
+\n\
+Return True if all characters in S are whitespace\n\
+and there is at least one character in S, False otherwise.");
 
 static PyObject*
 string_isspace(PyStringObject *self)
@@ -2766,7 +2975,7 @@
 PyDoc_STRVAR(isalpha__doc__,
 "S.isalpha() -> bool\n\
 \n\
-Return True if  all characters in S are alphabetic\n\
+Return True if all characters in S are alphabetic\n\
 and there is at least one character in S, False otherwise.");
 
 static PyObject*
@@ -2797,7 +3006,7 @@
 PyDoc_STRVAR(isalnum__doc__,
 "S.isalnum() -> bool\n\
 \n\
-Return True if  all characters in S are alphanumeric\n\
+Return True if all characters in S are alphanumeric\n\
 and there is at least one character in S, False otherwise.");
 
 static PyObject*
@@ -2828,8 +3037,8 @@
 PyDoc_STRVAR(isdigit__doc__,
 "S.isdigit() -> bool\n\
 \n\
-Return True if there are only digit characters in S,\n\
-False otherwise.");
+Return True if all characters in S are digits\n\
+and there is at least one character in S, False otherwise.");
 
 static PyObject*
 string_isdigit(PyStringObject *self)
@@ -2893,7 +3102,7 @@
 PyDoc_STRVAR(isupper__doc__,
 "S.isupper() -> bool\n\
 \n\
-Return True if  all cased characters in S are uppercase and there is\n\
+Return True if all cased characters in S are uppercase and there is\n\
 at least one cased character in S, False otherwise.");
 
 static PyObject*
@@ -2927,9 +3136,10 @@
 PyDoc_STRVAR(istitle__doc__,
 "S.istitle() -> bool\n\
 \n\
-Return True if S is a titlecased string, i.e. uppercase characters\n\
-may only follow uncased characters and lowercase characters only cased\n\
-ones. Return False otherwise.");
+Return True if S is a titlecased string and there is at least one\n\
+character in S, i.e. uppercase characters may only follow uncased\n\
+characters and lowercase characters only cased ones. Return False\n\
+otherwise.");
 
 static PyObject*
 string_istitle(PyStringObject *self, PyObject *uncased)
@@ -2979,17 +3189,6 @@
 Line breaks are not included in the resulting list unless keepends\n\
 is given and true.");
 
-#define SPLIT_APPEND(data, left, right)					\
-	str = PyString_FromStringAndSize(data + left, right - left);	\
-	if (!str)							\
-	    goto onError;						\
-	if (PyList_Append(list, str)) {					\
-	    Py_DECREF(str);						\
-	    goto onError;						\
-	}								\
-        else								\
-            Py_DECREF(str);
-
 static PyObject*
 string_splitlines(PyStringObject *self, PyObject *args)
 {
@@ -3058,6 +3257,7 @@
 	   string.maketrans(). */
 	{"join", (PyCFunction)string_join, METH_O, join__doc__},
 	{"split", (PyCFunction)string_split, METH_VARARGS, split__doc__},
+	{"rsplit", (PyCFunction)string_rsplit, METH_VARARGS, rsplit__doc__},
 	{"lower", (PyCFunction)string_lower, METH_NOARGS, lower__doc__},
 	{"upper", (PyCFunction)string_upper, METH_NOARGS, upper__doc__},
 	{"islower", (PyCFunction)string_islower, METH_NOARGS, islower__doc__},
@@ -3309,7 +3509,8 @@
 	register PyObject *v;
 	register PyStringObject *sv;
 	v = *pv;
-	if (!PyString_Check(v) || v->ob_refcnt != 1 || newsize < 0) {
+	if (!PyString_Check(v) || v->ob_refcnt != 1 || newsize < 0 ||
+	    PyString_CHECK_INTERNED(v)) {
 		*pv = 0;
 		Py_DECREF(v);
 		PyErr_BadInternalCall();
@@ -3319,8 +3520,7 @@
 	_Py_DEC_REFTOTAL;
 	_Py_ForgetReference(v);
 	*pv = (PyObject *)
-		PyObject_REALLOC((char *)v,
-			sizeof(PyStringObject) + newsize * sizeof(char));
+		PyObject_REALLOC((char *)v, sizeof(PyStringObject) + newsize);
 	if (*pv == NULL) {
 		PyObject_Del(v);
 		PyErr_NoMemory();
@@ -3330,6 +3530,7 @@
 	sv = (PyStringObject *) *pv;
 	sv->ob_size = newsize;
 	sv->ob_sval[newsize] = '\0';
+	sv->ob_shash = -1;	/* invalidate cached hash value */
 	return 0;
 }
 
@@ -3406,7 +3607,7 @@
 	PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c",
 		      (flags&F_ALT) ? "#" : "",
 		      prec, type);
-	PyOS_snprintf(buf, buflen, fmt, x);
+        PyOS_ascii_formatd(buf, buflen, fmt, x);
 	return strlen(buf);
 }
 
@@ -3559,6 +3760,7 @@
 	   worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine)
 	   + 1 + 1 = 24 */
 	char fmt[64];	/* plenty big enough! */
+	char *sign;
 	long x;
 
 	x = PyInt_AsLong(v);
@@ -3566,12 +3768,13 @@
 		PyErr_SetString(PyExc_TypeError, "int argument required");
 		return -1;
 	}
-	if (x < 0 && type != 'd' && type != 'i') {
-		if (PyErr_Warn(PyExc_FutureWarning,
-			       "%u/%o/%x/%X of negative int will return "
-			       "a signed string in Python 2.4 and up") < 0)
-			return -1;
+	if (x < 0 && type == 'u') {
+		type = 'd';
 	}
+	if (x < 0 && (type == 'x' || type == 'X' || type == 'o'))
+		sign = "-";
+	else
+		sign = "";
 	if (prec < 0)
 		prec = 1;
 
@@ -3597,24 +3800,27 @@
 		 * Note that this is the same approach as used in
 		 * formatint() in unicodeobject.c
 		 */
-		PyOS_snprintf(fmt, sizeof(fmt), "0%c%%.%dl%c",
-			      type, prec, type);
+		PyOS_snprintf(fmt, sizeof(fmt), "%s0%c%%.%dl%c",
+			      sign, type, prec, type);
 	}
 	else {
-		PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%dl%c",
-			      (flags&F_ALT) ? "#" : "",
+		PyOS_snprintf(fmt, sizeof(fmt), "%s%%%s.%dl%c",
+			      sign, (flags&F_ALT) ? "#" : "",
 			      prec, type);
 	}
 
-	/* buf = '+'/'-'/'0'/'0x' + '[0-9]'*max(prec, len(x in octal))
-	 * worst case buf = '0x' + [0-9]*prec, where prec >= 11
+	/* buf = '+'/'-'/'' + '0'/'0x'/'' + '[0-9]'*max(prec, len(x in octal))
+	 * worst case buf = '-0x' + [0-9]*prec, where prec >= 11
 	 */
-	if (buflen <= 13 || buflen <= (size_t)2 + (size_t)prec) {
+	if (buflen <= 14 || buflen <= (size_t)3 + (size_t)prec) {
 		PyErr_SetString(PyExc_OverflowError,
 		    "formatted integer is too long (precision too large?)");
 		return -1;
 	}
-	PyOS_snprintf(buf, buflen, fmt, x);
+	if (sign[0])
+		PyOS_snprintf(buf, buflen, fmt, -x);
+	else
+		PyOS_snprintf(buf, buflen, fmt, x);
 	return strlen(buf);
 }
 
@@ -3867,7 +4073,7 @@
 				}
 #endif
 				/* Fall through */
-  			case 'r':
+			case 'r':
 				if (c == 's')
 					temp = PyObject_Str(v);
 				else
@@ -3901,8 +4107,6 @@
 						prec, c, &pbuf, &len);
 					if (!temp)
 						goto error;
-					/* unbounded ints can always produce
-					   a sign character! */
 					sign = 1;
 				}
 				else {
@@ -3912,8 +4116,7 @@
 							flags, prec, c, v);
 					if (len < 0)
 						goto error;
-					/* only d conversion is signed */
-					sign = c == 'd';
+					sign = 1;
 				}
 				if (flags & F_ZERO)
 					fill = '0';
@@ -3921,8 +4124,11 @@
 			case 'e':
 			case 'E':
 			case 'f':
+			case 'F':
 			case 'g':
 			case 'G':
+				if (c == 'F')
+					c = 'f';
 				pbuf = formatbuf;
 				len = formatfloat(pbuf, sizeof(formatbuf),
 						  flags, prec, c, v);
@@ -4105,6 +4311,10 @@
 	PyObject *t;
 	if (s == NULL || !PyString_Check(s))
 		Py_FatalError("PyString_InternInPlace: strings only please!");
+	/* If it's a string subclass, we don't really know what putting
+	   it in the interned dict might do. */
+	if (!PyString_CheckExact(s))
+		return;
 	if (PyString_CHECK_INTERNED(s))
 		return;
 	if (interned == NULL) {
@@ -4114,36 +4324,22 @@
 			return;
 		}
 	}
-	if ((t = PyDict_GetItem(interned, (PyObject *)s)) != NULL) {
+	t = PyDict_GetItem(interned, (PyObject *)s);
+	if (t) {
 		Py_INCREF(t);
 		Py_DECREF(*p);
 		*p = t;
 		return;
 	}
-	/* Ensure that only true string objects appear in the intern dict */
-	if (!PyString_CheckExact(s)) {
-		t = PyString_FromStringAndSize(PyString_AS_STRING(s),
-						PyString_GET_SIZE(s));
-		if (t == NULL) {
-			PyErr_Clear();
-			return;
-		}
-	} else {
-		t = (PyObject*) s;
-		Py_INCREF(t);
-	}
 
-	if (PyDict_SetItem(interned, t, t) == 0) {
-		/* The two references in interned are not counted by
-		refcnt.  The string deallocator will take care of this */
-		((PyObject *)t)->ob_refcnt-=2;
-		PyString_CHECK_INTERNED(t) = SSTATE_INTERNED_MORTAL;
-		Py_DECREF(*p);
-		*p = t;
+	if (PyDict_SetItem(interned, (PyObject *)s, (PyObject *)s) < 0) {
+		PyErr_Clear();
 		return;
 	}
-	Py_DECREF(t);
-	PyErr_Clear();
+	/* The two references in interned are not counted by refcnt.
+	   The string deallocator will take care of this */
+	s->ob_refcnt -= 2;
+	PyString_CHECK_INTERNED(s) = SSTATE_INTERNED_MORTAL;
 }
 
 void

Index: tupleobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/tupleobject.c,v
retrieving revision 2.68.2.1
retrieving revision 2.68.2.2
diff -u -d -r2.68.2.1 -r2.68.2.2
--- tupleobject.c	28 Apr 2003 17:18:06 -0000	2.68.2.1
+++ tupleobject.c	7 Jan 2005 07:04:06 -0000	2.68.2.2
@@ -27,6 +27,7 @@
 PyTuple_New(register int size)
 {
 	register PyTupleObject *op;
+	int i;
 	if (size < 0) {
 		PyErr_BadInternalCall();
 		return NULL;
@@ -40,9 +41,7 @@
 #endif
 		return (PyObject *) op;
 	}
-	if (0 < size && size < MAXSAVESIZE &&
-	    (op = free_tuples[size]) != NULL)
-	{
+	if (size < MAXSAVESIZE && (op = free_tuples[size]) != NULL) {
 		free_tuples[size] = (PyTupleObject *) op->ob_item[0];
 		num_free_tuples[size]--;
 #ifdef COUNT_ALLOCS
@@ -70,7 +69,8 @@
 		if (op == NULL)
 			return NULL;
 	}
-	memset(op->ob_item, 0, sizeof(*op->ob_item) * size);
+	for (i=0; i < size; i++)
+		op->ob_item[i] = NULL;
 #if MAXSAVESIZE > 0
 	if (size == 0) {
 		free_tuples[0] = op;
@@ -130,6 +130,30 @@
 	return 0;
 }
 
+PyObject *
+PyTuple_Pack(int n, ...)
+{
+	int i;
+	PyObject *o;
+	PyObject *result;
+	PyObject **items;
+	va_list vargs;
+
+	va_start(vargs, n);
+	result = PyTuple_New(n);
+	if (result == NULL)
+		return NULL;
+	items = ((PyTupleObject *)result)->ob_item;
+	for (i = 0; i < n; i++) {
+		o = va_arg(vargs, PyObject *);
+		Py_INCREF(o);
+		items[i] = o;
+	}
+	va_end(vargs);
+	return result;
+}
+
+
 /* Methods */
 
 static void
@@ -232,21 +256,31 @@
 	return result;
 }
 
+/* The addend 82520, was selected from the range(0, 1000000) for 
+   generating the greatest number of prime multipliers for tuples 
+   upto length eight:
+
+     1082527, 1165049, 1082531, 1165057, 1247581, 1330103, 1082533, 
+     1330111, 1412633, 1165069, 1247599, 1495177, 1577699
+*/
+
 static long
 tuplehash(PyTupleObject *v)
 {
 	register long x, y;
 	register int len = v->ob_size;
 	register PyObject **p;
+	long mult = 1000003L;
 	x = 0x345678L;
 	p = v->ob_item;
 	while (--len >= 0) {
 		y = PyObject_Hash(*p++);
 		if (y == -1)
 			return -1;
-		x = (1000003*x) ^ y;
+		x = (x ^ y) * mult;
+		mult += 82520L + len + len;
 	}
-	x ^= v->ob_size;
+	x += 97531L;
 	if (x == -1)
 		x = -2;
 	return x;
@@ -284,7 +318,9 @@
 tupleslice(register PyTupleObject *a, register int ilow, register int ihigh)
 {
 	register PyTupleObject *np;
+	PyObject **src, **dest;
 	register int i;
+	int len;
 	if (ilow < 0)
 		ilow = 0;
 	if (ihigh > a->ob_size)
@@ -295,13 +331,16 @@
 		Py_INCREF(a);
 		return (PyObject *)a;
 	}
-	np = (PyTupleObject *)PyTuple_New(ihigh - ilow);
+	len = ihigh - ilow;
+	np = (PyTupleObject *)PyTuple_New(len);
 	if (np == NULL)
 		return NULL;
-	for (i = ilow; i < ihigh; i++) {
-		PyObject *v = a->ob_item[i];
+	src = a->ob_item + ilow;
+	dest = np->ob_item;
+	for (i = 0; i < len; i++) {
+		PyObject *v = src[i];
 		Py_INCREF(v);
-		np->ob_item[i - ilow] = v;
+		dest[i] = v;
 	}
 	return (PyObject *)np;
 }
@@ -321,6 +360,7 @@
 {
 	register int size;
 	register int i;
+	PyObject **src, **dest;
 	PyTupleObject *np;
 	if (!PyTuple_Check(bb)) {
 		PyErr_Format(PyExc_TypeError,
@@ -336,15 +376,19 @@
 	if (np == NULL) {
 		return NULL;
 	}
+	src = a->ob_item;
+	dest = np->ob_item;
 	for (i = 0; i < a->ob_size; i++) {
-		PyObject *v = a->ob_item[i];
+		PyObject *v = src[i];
 		Py_INCREF(v);
-		np->ob_item[i] = v;
+		dest[i] = v;
 	}
+	src = b->ob_item;
+	dest = np->ob_item + a->ob_size;
 	for (i = 0; i < b->ob_size; i++) {
-		PyObject *v = b->ob_item[i];
+		PyObject *v = src[i];
 		Py_INCREF(v);
-		np->ob_item[i + a->ob_size] = v;
+		dest[i] = v;
 	}
 	return (PyObject *)np;
 #undef b
@@ -356,7 +400,7 @@
 	int i, j;
 	int size;
 	PyTupleObject *np;
-	PyObject **p;
+	PyObject **p, **items;
 	if (n < 0)
 		n = 0;
 	if (a->ob_size == 0 || n == 1) {
@@ -376,9 +420,10 @@
 	if (np == NULL)
 		return NULL;
 	p = np->ob_item;
+	items = a->ob_item;
 	for (i = 0; i < n; i++) {
 		for (j = 0; j < a->ob_size; j++) {
-			*p = a->ob_item[j];
+			*p = items[j];
 			Py_INCREF(*p);
 			p++;
 		}
@@ -557,6 +602,7 @@
 		int start, stop, step, slicelength, cur, i;
 		PyObject* result;
 		PyObject* it;
+		PyObject **src, **dest;
 
 		if (PySlice_GetIndicesEx((PySliceObject*)item,
 				 PyTuple_GET_SIZE(self),
@@ -570,11 +616,13 @@
 		else {
 			result = PyTuple_New(slicelength);
 
+			src = self->ob_item;
+			dest = ((PyTupleObject *)result)->ob_item;
 			for (cur = start, i = 0; i < slicelength; 
 			     cur += step, i++) {
-				it = PyTuple_GET_ITEM(self, cur);
+				it = src[cur];
 				Py_INCREF(it);
-				PyTuple_SET_ITEM(result, i, it);
+				dest[i] = it;
 			}
 			
 			return result;
@@ -753,8 +801,6 @@
 		PyErr_BadInternalCall();
 		return NULL;
 	}
-	if (seq->ob_type->tp_as_sequence->sq_item != (intargfunc)tupleitem)
-		return PySeqIter_New(seq);
 	it = PyObject_GC_New(tupleiterobject, &PyTupleIter_Type);
 	if (it == NULL)
 		return NULL;
@@ -805,6 +851,19 @@
 	return NULL;
 }
 
+static int
+tupleiter_len(tupleiterobject *it)
+{
+	if (it->it_seq)
+		return PyTuple_GET_SIZE(it->it_seq) - it->it_index;
+	return 0;
+}
+
+static PySequenceMethods tupleiter_as_sequence = {
+	(inquiry)tupleiter_len,		/* sq_length */
+	0,				/* sq_concat */
+};
+
 PyTypeObject PyTupleIter_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,					/* ob_size */
@@ -819,7 +878,7 @@
 	0,					/* tp_compare */
 	0,					/* tp_repr */
 	0,					/* tp_as_number */
-	0,					/* tp_as_sequence */
+	&tupleiter_as_sequence,			/* tp_as_sequence */
 	0,					/* tp_as_mapping */
 	0,					/* tp_hash */
 	0,					/* tp_call */

Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.157.2.2
retrieving revision 2.157.2.3
diff -u -d -r2.157.2.2 -r2.157.2.3
--- typeobject.c	20 Mar 2004 19:46:51 -0000	2.157.2.2
+++ typeobject.c	7 Jan 2005 07:04:06 -0000	2.157.2.3
@@ -87,6 +87,10 @@
 
 	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
 		mod = PyDict_GetItemString(type->tp_dict, "__module__");
+		if (!mod) { 
+			PyErr_Format(PyExc_AttributeError, "__module__");
+			return 0;
+		}
 		Py_XINCREF(mod);
 		return mod;
 	}
@@ -163,7 +167,7 @@
 		}
 		else {
 			PyObject* tuple;
-			tuple = Py_BuildValue("OO", subclass, old_mro);
+			tuple = PyTuple_Pack(2, subclass, old_mro);
 			Py_DECREF(old_mro);
 			if (!tuple)
 				return -1;
@@ -258,8 +262,8 @@
 		for (i = 0; i < PyList_Size(temp); i++) {
 			PyTypeObject* cls;
 			PyObject* mro;
-			PyArg_ParseTuple(PyList_GET_ITEM(temp, i),
-					 "OO", &cls, &mro);
+			PyArg_UnpackTuple(PyList_GET_ITEM(temp, i),
+					 "", 2, 2, &cls, &mro);
 			Py_DECREF(cls->tp_mro);
 			cls->tp_mro = mro;
 			Py_INCREF(cls->tp_mro);
@@ -303,13 +307,16 @@
 	return r;
 
   bail:
+	Py_DECREF(type->tp_bases);
+	Py_DECREF(type->tp_base);
+	if (type->tp_mro != old_mro) {
+		Py_DECREF(type->tp_mro);
+	}
+
 	type->tp_bases = old_bases;
 	type->tp_base = old_base;
 	type->tp_mro = old_mro;
 
-	Py_DECREF(value);
-	Py_DECREF(new_base);
-
 	return -1;
 }
 
@@ -636,17 +643,37 @@
 	++_PyTrash_delete_nesting;
 	Py_TRASHCAN_SAFE_BEGIN(self);
 	--_PyTrash_delete_nesting;
-	_PyObject_GC_TRACK(self); /* We'll untrack for real later */
+	/* DO NOT restore GC tracking at this point.  weakref callbacks
+	 * (if any, and whether directly here or indirectly in something we
+	 * call) may trigger GC, and if self is tracked at that point, it
+	 * will look like trash to GC and GC will try to delete self again.
+	 */
+
+	/* Find the nearest base with a different tp_dealloc */
+	base = type;
+	while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
+		base = base->tp_base;
+		assert(base);
+	}
+
+	/* If we added a weaklist, we clear it.  Do this *before* calling
+	   the finalizer (__del__), clearing slots, or clearing the instance
+	   dict. */
+
+	if (type->tp_weaklistoffset && !base->tp_weaklistoffset)
+		PyObject_ClearWeakRefs(self);
 
 	/* Maybe call finalizer; exit early if resurrected */
 	if (type->tp_del) {
+		_PyObject_GC_TRACK(self);
 		type->tp_del(self);
 		if (self->ob_refcnt > 0)
-			goto endlabel;
+			goto endlabel;	/* resurrected */
+		else
+			_PyObject_GC_UNTRACK(self);
 	}
 
-	/* Find the nearest base with a different tp_dealloc
-	   and clear slots while we're at it */
+	/*  Clear slots up to the nearest base with a different tp_dealloc */
 	base = type;
 	while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
 		if (base->ob_size)
@@ -667,15 +694,11 @@
 		}
 	}
 
-	/* If we added weaklist, we clear it */
-	if (type->tp_weaklistoffset && !base->tp_weaklistoffset)
-		PyObject_ClearWeakRefs(self);
-
-	/* Finalize GC if the base doesn't do GC and we do */
-	if (!PyType_IS_GC(base))
-		_PyObject_GC_UNTRACK(self);
-
-	/* Call the base tp_dealloc() */
+	/* Call the base tp_dealloc(); first retrack self if
+	 * basedealloc knows about gc.
+	 */
+	if (PyType_IS_GC(base))
+		_PyObject_GC_TRACK(self);
 	assert(basedealloc);
 	basedealloc(self);
 
@@ -713,6 +736,16 @@
 		 trashcan begin
 		 GC track
 
+           Q. Why did the last question say "immediately GC-track again"?
+              It's nowhere near immediately.
+
+           A. Because the code *used* to re-track immediately.  Bad Idea.
+              self has a refcount of 0, and if gc ever gets its hands on it
+              (which can happen if any weakref callback gets invoked), it
+              looks like trash to gc too, and gc also tries to delete self
+              then.  But we're already deleting self.  Double dealloction is
+              a subtle disaster.
+
 	   Q. Why the bizarre (net-zero) manipulation of
 	      _PyTrash_delete_nesting around the trashcan macros?
 
@@ -1594,7 +1627,7 @@
 
 	/* Adjust for empty tuple bases */
 	if (nbases == 0) {
-		bases = Py_BuildValue("(O)", &PyBaseObject_Type);
+		bases = PyTuple_Pack(1, &PyBaseObject_Type);
 		if (bases == NULL)
 			return NULL;
 		nbases = 1;
@@ -1606,12 +1639,15 @@
 
 	/* Calculate best base, and check that all bases are type objects */
 	base = best_base(bases);
-	if (base == NULL)
+	if (base == NULL) {
+		Py_DECREF(bases);
 		return NULL;
+	}
 	if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) {
 		PyErr_Format(PyExc_TypeError,
 			     "type '%.100s' is not an acceptable base type",
 			     base->tp_name);
+		Py_DECREF(bases);
 		return NULL;
 	}
 
@@ -1635,22 +1671,24 @@
 
 		/* Make it into a tuple */
 		if (PyString_Check(slots))
-			slots = Py_BuildValue("(O)", slots);
+			slots = PyTuple_Pack(1, slots);
 		else
 			slots = PySequence_Tuple(slots);
-		if (slots == NULL)
+		if (slots == NULL) {
+			Py_DECREF(bases);
 			return NULL;
+		}
 		assert(PyTuple_Check(slots));
 
 		/* Are slots allowed? */
 		nslots = PyTuple_GET_SIZE(slots);
-		if (nslots > 0 && base->tp_itemsize != 0 && !PyType_Check(base)) {
-			/* for the special case of meta types, allow slots */
+		if (nslots > 0 && base->tp_itemsize != 0) {
 			PyErr_Format(PyExc_TypeError,
 				     "nonempty __slots__ "
 				     "not supported for subtype of '%s'",
 				     base->tp_name);
 		  bad_slots:
+			Py_DECREF(bases);
 			Py_DECREF(slots);
 			return NULL;
 		}
@@ -1756,6 +1794,7 @@
 	type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots);
 	if (type == NULL) {
 		Py_XDECREF(slots);
+		Py_DECREF(bases);
 		return NULL;
 	}
 
@@ -1986,6 +2025,7 @@
 			return meta_get(meta_attribute, (PyObject *)type,
 					(PyObject *)metatype);
 		}
+		Py_INCREF(meta_attribute);
 	}
 
 	/* No data descriptor found on metatype. Look in tp_dict of this
@@ -1994,6 +2034,9 @@
 	if (attribute != NULL) {
 		/* Implement descriptor functionality, if any */
 		descrgetfunc local_get = attribute->ob_type->tp_descr_get;
+
+		Py_XDECREF(meta_attribute);
+
 		if (local_get != NULL) {
 			/* NULL 2nd argument indicates the descriptor was
 			 * found on the target object itself (or a base)  */
@@ -2007,13 +2050,16 @@
 
 	/* No attribute found in local __dict__ (or bases): use the
 	 * descriptor from the metatype, if any */
-	if (meta_get != NULL)
-		return meta_get(meta_attribute, (PyObject *)type,
-				(PyObject *)metatype);
+	if (meta_get != NULL) {
+		PyObject *res;
+		res = meta_get(meta_attribute, (PyObject *)type,
+			       (PyObject *)metatype);
+		Py_DECREF(meta_attribute);
+		return res;
+	}
 
 	/* If an ordinary attribute was found on the metatype, return it now */
 	if (meta_attribute != NULL) {
-		Py_INCREF(meta_attribute);
 		return meta_attribute;
 	}
 
@@ -2529,8 +2575,11 @@
 	if (getstate != NULL) {
 		state = PyObject_CallObject(getstate, NULL);
 		Py_DECREF(getstate);
+		if (state == NULL)
+			goto end;
 	}
 	else {
+		PyErr_Clear();
 		state = PyObject_GetAttrString(obj, "__dict__");
 		if (state == NULL) {
 			PyErr_Clear();
@@ -2611,8 +2660,7 @@
 		PyTuple_SET_ITEM(args2, i+1, v);
 	}
 
-	res = Py_BuildValue("(OOOOO)",
-			    newobj, args2, state, listitems, dictitems);
+	res = PyTuple_Pack(5, newobj, args2, state, listitems, dictitems);
 
   end:
 	Py_XDECREF(cls);
@@ -2743,8 +2791,9 @@
 
 	for (; meth->ml_name != NULL; meth++) {
 		PyObject *descr;
-		if (PyDict_GetItemString(dict, meth->ml_name))
-			continue;
+		if (PyDict_GetItemString(dict, meth->ml_name) &&
+			!(meth->ml_flags & METH_COEXIST))
+				continue;
 		if (meth->ml_flags & METH_CLASS) {
 			if (meth->ml_flags & METH_STATIC) {
 				PyErr_SetString(PyExc_ValueError,
@@ -3038,8 +3087,25 @@
 		COPYSLOT(tp_dictoffset);
 		COPYSLOT(tp_init);
 		COPYSLOT(tp_alloc);
-		COPYSLOT(tp_free);
 		COPYSLOT(tp_is_gc);
+		if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) ==
+		    (base->tp_flags & Py_TPFLAGS_HAVE_GC)) {
+			/* They agree about gc. */
+			COPYSLOT(tp_free);
+		}
+		else if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) &&
+			 type->tp_free == NULL &&
+			 base->tp_free == _PyObject_Del) {
+			/* A bit of magic to plug in the correct default
+			 * tp_free function when a derived class adds gc,
+			 * didn't define tp_free, and the base uses the
+			 * default non-gc tp_free.
+			 */
+			type->tp_free = PyObject_GC_Del;
+		}
+		/* else they didn't agree about gc, and there isn't something
+		 * obvious to be done -- the type is on its own.
+		 */
 	}
 }
 
@@ -3071,8 +3137,10 @@
 
 	/* Initialize tp_base (defaults to BaseObject unless that's us) */
 	base = type->tp_base;
-	if (base == NULL && type != &PyBaseObject_Type)
+	if (base == NULL && type != &PyBaseObject_Type) {
 		base = type->tp_base = &PyBaseObject_Type;
+		Py_INCREF(base);
+	}
 
 	/* Initialize the base class */
 	if (base && base->tp_dict == NULL) {
@@ -3092,7 +3160,7 @@
 		if (base == NULL)
 			bases = PyTuple_New(0);
 		else
-			bases = Py_BuildValue("(O)", base);
+			bases = PyTuple_Pack(1, base);
 		if (bases == NULL)
 			goto error;
 		type->tp_bases = bases;
@@ -3143,6 +3211,19 @@
 			inherit_slots(type, (PyTypeObject *)b);
 	}
 
+	/* Sanity check for tp_free. */
+	if (PyType_IS_GC(type) && (type->tp_flags & Py_TPFLAGS_BASETYPE) &&
+	    (type->tp_free == NULL || type->tp_free == PyObject_Del)) {
+	    	/* This base class needs to call tp_free, but doesn't have
+	    	 * one, or its tp_free is for non-gc'ed objects.
+	    	 */
+		PyErr_Format(PyExc_TypeError, "type '%.100s' participates in "
+			     "gc and is a base type but has inappropriate "
+			     "tp_free slot",
+			     type->tp_name);
+		goto error;
+	}
+
 	/* if the type dictionary doesn't contain a __doc__, set it from
 	   the tp_doc slot.
 	 */
@@ -3240,6 +3321,22 @@
 	}
 }
 
+static int
+check_num_args(PyObject *ob, int n)
+{
+	if (!PyTuple_CheckExact(ob)) {
+		PyErr_SetString(PyExc_SystemError,
+		    "PyArg_UnpackTuple() argument list is not a tuple");
+		return 0;
+	}
+	if (n == PyTuple_GET_SIZE(ob))
+		return 1;
+	PyErr_Format(
+	    PyExc_TypeError, 
+	    "expected %d arguments, got %d", n, PyTuple_GET_SIZE(ob));
+	return 0;
+}
+
 /* Generic wrappers for overloadable 'operators' such as __getitem__ */
 
 /* There's a wrapper *function* for each distinct function typedef used
@@ -3254,7 +3351,7 @@
 	inquiry func = (inquiry)wrapped;
 	int res;
 
-	if (!PyArg_ParseTuple(args, ""))
+	if (!check_num_args(args, 0))
 		return NULL;
 	res = (*func)(self);
 	if (res == -1 && PyErr_Occurred())
@@ -3263,13 +3360,28 @@
 }
 
 static PyObject *
+wrap_inquirypred(PyObject *self, PyObject *args, void *wrapped)
+{
+	inquiry func = (inquiry)wrapped;
+	int res;
+
+	if (!check_num_args(args, 0))
+		return NULL;
+	res = (*func)(self);
+	if (res == -1 && PyErr_Occurred())
+		return NULL;
+	return PyBool_FromLong((long)res);
+}
+
+static PyObject *
 wrap_binaryfunc(PyObject *self, PyObject *args, void *wrapped)
 {
 	binaryfunc func = (binaryfunc)wrapped;
 	PyObject *other;
 
-	if (!PyArg_ParseTuple(args, "O", &other))
+	if (!check_num_args(args, 1))
 		return NULL;
+	other = PyTuple_GET_ITEM(args, 0);
 	return (*func)(self, other);
 }
 
@@ -3279,8 +3391,9 @@
 	binaryfunc func = (binaryfunc)wrapped;
 	PyObject *other;
 
-	if (!PyArg_ParseTuple(args, "O", &other))
+	if (!check_num_args(args, 1))
 		return NULL;
+	other = PyTuple_GET_ITEM(args, 0);
 	if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&
 	    !PyType_IsSubtype(other->ob_type, self->ob_type)) {
 		Py_INCREF(Py_NotImplemented);
@@ -3295,8 +3408,9 @@
 	binaryfunc func = (binaryfunc)wrapped;
 	PyObject *other;
 
-	if (!PyArg_ParseTuple(args, "O", &other))
+	if (!check_num_args(args, 1))
 		return NULL;
+	other = PyTuple_GET_ITEM(args, 0);
 	if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&
 	    !PyType_IsSubtype(other->ob_type, self->ob_type)) {
 		Py_INCREF(Py_NotImplemented);
@@ -3312,8 +3426,9 @@
 	PyObject *other, *res;
 	int ok;
 
-	if (!PyArg_ParseTuple(args, "O", &other))
+	if (!check_num_args(args, 1))
 		return NULL;
+	other = PyTuple_GET_ITEM(args, 0);
 	ok = func(&self, &other);
 	if (ok < 0)
 		return NULL;
@@ -3341,7 +3456,7 @@
 
 	/* Note: This wrapper only works for __pow__() */
 
-	if (!PyArg_ParseTuple(args, "O|O", &other, &third))
+	if (!PyArg_UnpackTuple(args, "", 1, 2, &other, &third))
 		return NULL;
 	return (*func)(self, other, third);
 }
@@ -3355,7 +3470,7 @@
 
 	/* Note: This wrapper only works for __pow__() */
 
-	if (!PyArg_ParseTuple(args, "O|O", &other, &third))
+	if (!PyArg_UnpackTuple(args, "", 1, 2, &other, &third))
 		return NULL;
 	return (*func)(other, self, third);
 }
@@ -3365,7 +3480,7 @@
 {
 	unaryfunc func = (unaryfunc)wrapped;
 
-	if (!PyArg_ParseTuple(args, ""))
+	if (!check_num_args(args, 0))
 		return NULL;
 	return (*func)(self);
 }
@@ -3415,7 +3530,7 @@
 			return NULL;
 		return (*func)(self, i);
 	}
-	PyArg_ParseTuple(args, "O", &arg);
+	check_num_args(args, 1);
 	assert(PyErr_Occurred());
 	return NULL;
 }
@@ -3438,7 +3553,7 @@
 	int i, res;
 	PyObject *arg, *value;
 
-	if (!PyArg_ParseTuple(args, "OO", &arg, &value))
+	if (!PyArg_UnpackTuple(args, "", 2, 2, &arg, &value))
 		return NULL;
 	i = getindex(self, arg);
 	if (i == -1 && PyErr_Occurred())
@@ -3457,8 +3572,9 @@
 	int i, res;
 	PyObject *arg;
 
-	if (!PyArg_ParseTuple(args, "O", &arg))
+	if (!check_num_args(args, 1))
 		return NULL;
+	arg = PyTuple_GET_ITEM(args, 0);
 	i = getindex(self, arg);
 	if (i == -1 && PyErr_Occurred())
 		return NULL;
@@ -3508,12 +3624,14 @@
 	int res;
 	PyObject *value;
 
-	if (!PyArg_ParseTuple(args, "O", &value))
+	if (!check_num_args(args, 1))
 		return NULL;
+	value = PyTuple_GET_ITEM(args, 0);
 	res = (*func)(self, value);
 	if (res == -1 && PyErr_Occurred())
 		return NULL;
-	return PyInt_FromLong((long)res);
+	else
+		return PyBool_FromLong(res);
 }
 
 static PyObject *
@@ -3523,7 +3641,7 @@
 	int res;
 	PyObject *key, *value;
 
-	if (!PyArg_ParseTuple(args, "OO", &key, &value))
+	if (!PyArg_UnpackTuple(args, "", 2, 2, &key, &value))
 		return NULL;
 	res = (*func)(self, key, value);
 	if (res == -1 && PyErr_Occurred())
@@ -3539,8 +3657,9 @@
 	int res;
 	PyObject *key;
 
-	if (!PyArg_ParseTuple(args, "O", &key))
+	if (!check_num_args(args, 1))
 		return NULL;
+	key = PyTuple_GET_ITEM(args, 0);
 	res = (*func)(self, key, NULL);
 	if (res == -1 && PyErr_Occurred())
 		return NULL;
@@ -3555,8 +3674,9 @@
 	int res;
 	PyObject *other;
 
-	if (!PyArg_ParseTuple(args, "O", &other))
+	if (!check_num_args(args, 1))
 		return NULL;
+	other = PyTuple_GET_ITEM(args, 0);
 	if (other->ob_type->tp_compare != func &&
 	    !PyType_IsSubtype(other->ob_type, self->ob_type)) {
 		PyErr_Format(
@@ -3598,7 +3718,7 @@
 	int res;
 	PyObject *name, *value;
 
-	if (!PyArg_ParseTuple(args, "OO", &name, &value))
+	if (!PyArg_UnpackTuple(args, "", 2, 2, &name, &value))
 		return NULL;
 	if (!hackcheck(self, func, "__setattr__"))
 		return NULL;
@@ -3616,8 +3736,9 @@
 	int res;
 	PyObject *name;
 
-	if (!PyArg_ParseTuple(args, "O", &name))
+	if (!check_num_args(args, 1))
 		return NULL;
+	name = PyTuple_GET_ITEM(args, 0);
 	if (!hackcheck(self, func, "__delattr__"))
 		return NULL;
 	res = (*func)(self, name, NULL);
@@ -3633,7 +3754,7 @@
 	hashfunc func = (hashfunc)wrapped;
 	long res;
 
-	if (!PyArg_ParseTuple(args, ""))
+	if (!check_num_args(args, 0))
 		return NULL;
 	res = (*func)(self);
 	if (res == -1 && PyErr_Occurred())
@@ -3655,8 +3776,9 @@
 	richcmpfunc func = (richcmpfunc)wrapped;
 	PyObject *other;
 
-	if (!PyArg_ParseTuple(args, "O", &other))
+	if (!check_num_args(args, 1))
 		return NULL;
+	other = PyTuple_GET_ITEM(args, 0);
 	return (*func)(self, other, op);
 }
 
@@ -3681,7 +3803,7 @@
 	unaryfunc func = (unaryfunc)wrapped;
 	PyObject *res;
 
-	if (!PyArg_ParseTuple(args, ""))
+	if (!check_num_args(args, 0))
 		return NULL;
 	res = (*func)(self);
 	if (res == NULL && !PyErr_Occurred())
@@ -3696,7 +3818,7 @@
 	PyObject *obj;
 	PyObject *type = NULL;
 
-	if (!PyArg_ParseTuple(args, "O|O", &obj, &type))
+	if (!PyArg_UnpackTuple(args, "", 1, 2, &obj, &type))
 		return NULL;
 	if (obj == Py_None)
 		obj = NULL;
@@ -3717,7 +3839,7 @@
 	PyObject *obj, *value;
 	int ret;
 
-	if (!PyArg_ParseTuple(args, "OO", &obj, &value))
+	if (!PyArg_UnpackTuple(args, "", 2, 2, &obj, &value))
 		return NULL;
 	ret = (*func)(self, obj, value);
 	if (ret < 0)
@@ -3733,8 +3855,9 @@
 	PyObject *obj;
 	int ret;
 
-	if (!PyArg_ParseTuple(args, "O", &obj))
+	if (!check_num_args(args, 1))
 		return NULL;
+	obj = PyTuple_GET_ITEM(args, 0);
 	ret = (*func)(self, obj, NULL);
 	if (ret < 0)
 		return NULL;
@@ -3827,7 +3950,12 @@
 	func = PyCFunction_New(tp_new_methoddef, (PyObject *)type);
 	if (func == NULL)
 		return -1;
-	return PyDict_SetItemString(type->tp_dict, "__new__", func);
+	if (PyDict_SetItemString(type->tp_dict, "__new__", func)) {
+		Py_DECREF(func);
+		return -1;
+	}
+	Py_DECREF(func);
+	return 0;
 }
 
 /* Slot wrappers that call the corresponding __foo__ slot.  See comments
@@ -4049,7 +4177,7 @@
 
 	func = lookup_maybe(self, "__contains__", &contains_str);
 	if (func != NULL) {
-		args = Py_BuildValue("(O)", value);
+		args = PyTuple_Pack(1, value);
 		if (args == NULL)
 			res = NULL;
 		else {
@@ -4149,7 +4277,15 @@
 		PyObject *temp = PyObject_Call(func, args, NULL);
 		Py_DECREF(args);
 		if (temp != NULL) {
-			result = PyObject_IsTrue(temp);
+			if (PyInt_CheckExact(temp) || PyBool_Check(temp))
+				result = PyObject_IsTrue(temp);
+			else {
+				PyErr_Format(PyExc_TypeError,
+					     "__nonzero__ should return "
+					     "bool or int, returned %s",
+					     temp->ob_type->tp_name);
+				result = -1;
+			}
 			Py_DECREF(temp);
 		}
 	}
@@ -4256,7 +4392,7 @@
 		PyErr_Clear();
 	}
 	else {
-		args = Py_BuildValue("(O)", other);
+		args = PyTuple_Pack(1, other);
 		if (args == NULL)
 			res = NULL;
 		else {
@@ -4485,7 +4621,7 @@
 		Py_INCREF(Py_NotImplemented);
 		return Py_NotImplemented;
 	}
-	args = Py_BuildValue("(O)", other);
+	args = PyTuple_Pack(1, other);
 	if (args == NULL)
 		res = NULL;
 	else {
@@ -4496,9 +4632,6 @@
 	return res;
 }
 
-/* Map rich comparison operators to their swapped version, e.g. LT --> GT */
-static int swapped_op[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE};
-
 static PyObject *
 slot_tp_richcompare(PyObject *self, PyObject *other, int op)
 {
@@ -4511,7 +4644,7 @@
 		Py_DECREF(res);
 	}
 	if (other->ob_type->tp_richcompare == slot_tp_richcompare) {
-		res = half_richcompare(other, self, swapped_op[op]);
+		res = half_richcompare(other, self, _Py_SwappedOp[op]);
 		if (res != Py_NotImplemented) {
 			return res;
 		}
@@ -4697,10 +4830,11 @@
 	}
 	assert(!PyType_IS_GC(self->ob_type) ||
 	       _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
-	/* If Py_REF_DEBUG, the original decref dropped _Py_RefTotal, but
-	 * _Py_NewReference bumped it again, so that's a wash.
-	 * If Py_TRACE_REFS, _Py_NewReference re-added self to the object
-	 * chain, so no more to do there either.
+	/* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
+	 * we need to undo that. */
+	_Py_DEC_REFTOTAL;
+	/* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
+	 * chain, so no more to do there.
 	 * If COUNT_ALLOCS, the original decref bumped tp_frees, and
 	 * _Py_NewReference bumped tp_allocs:  both of those need to be
 	 * undone.
@@ -4775,16 +4909,22 @@
 	SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item,
 	       "x.__getitem__(y) <==> x[y]"),
 	SQSLOT("__getslice__", sq_slice, slot_sq_slice, wrap_intintargfunc,
-	       "x.__getslice__(i, j) <==> x[i:j]"),
+	       "x.__getslice__(i, j) <==> x[i:j]\n\
+               \n\
+               Use of negative indices is not supported."),
 	SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem,
 	       "x.__setitem__(i, y) <==> x[i]=y"),
 	SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem,
 	       "x.__delitem__(y) <==> del x[y]"),
 	SQSLOT("__setslice__", sq_ass_slice, slot_sq_ass_slice,
 	       wrap_intintobjargproc,
-	       "x.__setslice__(i, j, y) <==> x[i:j]=y"),
+	       "x.__setslice__(i, j, y) <==> x[i:j]=y\n\
+               \n\
+               Use  of negative indices is not supported."),
 	SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice,
-	       "x.__delslice__(i, j) <==> del x[i:j]"),
+	       "x.__delslice__(i, j) <==> del x[i:j]\n\
+               \n\
+               Use of negative indices is not supported."),
 	SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc,
 	       "x.__contains__(y) <==> y in x"),
 	SQSLOT("__iadd__", sq_inplace_concat, slot_sq_inplace_concat,
@@ -4836,7 +4976,7 @@
 	UNSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc, "+x"),
 	UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc,
 	       "abs(x)"),
-	UNSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_inquiry,
+	UNSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_inquirypred,
 	       "x != 0"),
 	UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~x"),
 	BINSLOT("__lshift__", nb_lshift, slot_nb_lshift, "<<"),
@@ -5080,7 +5220,7 @@
 			   sanity checks and constructing a new argument
 			   list.  Cut all that nonsense short -- this speeds
 			   up instance creation tremendously. */
-			specific = type->tp_new;
+			specific = (void *)type->tp_new;
 			/* XXX I'm not 100% sure that there isn't a hole
 			   in this reasoning that requires additional
 			   sanity checks.  I'll buy the first person to
@@ -5320,7 +5460,7 @@
 	{"__self__",  T_OBJECT, offsetof(superobject, obj), READONLY,
 	 "the instance invoking super(); may be None"},
 	{"__self_class__", T_OBJECT, offsetof(superobject, obj_type), READONLY,
-	 "the type of the the instance invoking super(); may be None"},
+	 "the type of the instance invoking super(); may be None"},
 	{0}
 };
 
@@ -5400,7 +5540,15 @@
 				Py_INCREF(res);
 				f = res->ob_type->tp_descr_get;
 				if (f != NULL) {
-					tmp = f(res, su->obj,
+					tmp = f(res,
+						/* Only pass 'obj' param if
+						   this is instance-mode super 
+						   (See SF ID #743627)
+						*/
+						(su->obj == (PyObject *)
+							    su->obj_type 
+							? (PyObject *)NULL 
+							: su->obj),
 						(PyObject *)starttype);
 					Py_DECREF(res);
 					res = tmp;
@@ -5488,7 +5636,7 @@
 		return self;
 	}
 	if (su->ob_type != &PySuper_Type)
-		/* If su is an instance of a subclass of super,
+		/* If su is not an instance of a subclass of super,
 		   call its type */
 		return PyObject_CallFunction((PyObject *)su->ob_type,
 					     "OO", su->type, obj);

Index: unicodectype.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/unicodectype.c,v
retrieving revision 2.11.18.1
retrieving revision 2.11.18.2
diff -u -d -r2.11.18.1 -r2.11.18.2
--- unicodectype.c	28 Apr 2003 17:18:02 -0000	2.11.18.1
+++ unicodectype.c	7 Jan 2005 07:04:07 -0000	2.11.18.2
@@ -21,12 +21,12 @@
 #define UPPER_MASK 0x80
 
 typedef struct {
-    const unsigned short flags;
     const Py_UNICODE upper;
     const Py_UNICODE lower;
     const Py_UNICODE title;
     const unsigned char decimal;
     const unsigned char digit;
+    const unsigned short flags;
 } _PyUnicode_TypeRecord;
 
 #include "unicodetype_db.h"
@@ -36,9 +36,12 @@
 {
     int index;
 
+#ifdef Py_UNICODE_WIDE
     if (code >= 0x110000)
         index = 0;
-    else {
+    else
+#endif
+    {
         index = index1[(code>>SHIFT)];
         index = index2[(index<<SHIFT)+(code&((1<<SHIFT)-1))];
     }

Index: unicodeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/unicodeobject.c,v
retrieving revision 2.155.2.1
retrieving revision 2.155.2.2
diff -u -d -r2.155.2.1 -r2.155.2.2
--- unicodeobject.c	28 Apr 2003 17:18:01 -0000	2.155.2.1
+++ unicodeobject.c	7 Jan 2005 07:04:09 -0000	2.155.2.2
@@ -1,4 +1,4 @@
-/* 
+/*
 
 Unicode implementation based on original code by Fredrik Lundh,
 modified by Marc-Andre Lemburg <mal at lemburg.com> according to the
@@ -53,7 +53,7 @@
 
    The implementation will keep allocated Unicode memory intact for
    all objects on the free list having a size less than this
-   limit. This reduces malloc() overhead for small Unicode objects.  
+   limit. This reduces malloc() overhead for small Unicode objects.
[...2608 lines suppressed...]
+	}
 	pnew->str = PyMem_NEW(Py_UNICODE, n+1);
 	if (pnew->str == NULL) {
 		_Py_ForgetReference((PyObject *)pnew);
 		PyObject_Del(pnew);
+		Py_DECREF(tmp);
 		return PyErr_NoMemory();
 	}
 	Py_UNICODE_COPY(pnew->str, tmp->str, n+1);
@@ -6769,3 +7271,10 @@
     unicode_freelist = NULL;
     unicode_freelist_size = 0;
 }
+
+/*
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/

Index: unicodetype_db.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/unicodetype_db.h,v
retrieving revision 1.4.26.1
retrieving revision 1.4.26.2
diff -u -d -r1.4.26.1 -r1.4.26.2
--- unicodetype_db.h	28 Apr 2003 17:17:59 -0000	1.4.26.1
+++ unicodetype_db.h	7 Jan 2005 07:04:10 -0000	1.4.26.2
@@ -1,132 +1,132 @@
-/* this file was generated by Tools/unicode/makeunicodedata.py 2.2 */
+/* this file was generated by Tools/unicode/makeunicodedata.py 2.3 */
 
 /* a list of unique character type descriptors */
 const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = {
     {0, 0, 0, 0, 0, 0},
     {0, 0, 0, 0, 0, 0},
-    {32, 0, 0, 0, 0, 0},
-    {48, 0, 0, 0, 0, 0},
-    {6, 0, 0, 0, 0, 0},
-    {6, 0, 0, 0, 1, 1},
-    {6, 0, 0, 0, 2, 2},
-    {6, 0, 0, 0, 3, 3},
-    {6, 0, 0, 0, 4, 4},
-    {6, 0, 0, 0, 5, 5},
-    {6, 0, 0, 0, 6, 6},
-    {6, 0, 0, 0, 7, 7},
-    {6, 0, 0, 0, 8, 8},
-    {6, 0, 0, 0, 9, 9},
-    {129, 0, 32, 0, 0, 0},
-    {9, 65504, 0, 65504, 0, 0},
-    {9, 0, 0, 0, 0, 0},
-    {9, 743, 0, 743, 0, 0},
-    {9, 121, 0, 121, 0, 0},
-    {129, 0, 1, 0, 0, 0},
-    {9, 65535, 0, 65535, 0, 0},
-    {129, 0, 65337, 0, 0, 0},
-    {9, 65304, 0, 65304, 0, 0},
-    {129, 0, 65415, 0, 0, 0},
-    {9, 65236, 0, 65236, 0, 0},
-    {129, 0, 210, 0, 0, 0},
-    {129, 0, 206, 0, 0, 0},
-    {129, 0, 205, 0, 0, 0},
-    {129, 0, 79, 0, 0, 0},
-    {129, 0, 202, 0, 0, 0},
-    {129, 0, 203, 0, 0, 0},
-    {129, 0, 207, 0, 0, 0},
-    {9, 97, 0, 97, 0, 0},
-    {129, 0, 211, 0, 0, 0},
-    {129, 0, 209, 0, 0, 0},
-    {129, 0, 213, 0, 0, 0},
-    {9, 130, 0, 130, 0, 0},
-    {129, 0, 214, 0, 0, 0},
-    {129, 0, 218, 0, 0, 0},
-    {129, 0, 217, 0, 0, 0},
-    {129, 0, 219, 0, 0, 0},
-    {1, 0, 0, 0, 0, 0},
-    {9, 56, 0, 56, 0, 0},
-    {129, 0, 2, 1, 0, 0},
-    {65, 65535, 1, 0, 0, 0},
-    {9, 65534, 0, 65535, 0, 0},
-    {9, 65457, 0, 65457, 0, 0},
-    {129, 0, 65439, 0, 0, 0},
-    {129, 0, 65480, 0, 0, 0},
-    {129, 0, 65406, 0, 0, 0},
-    {9, 65326, 0, 65326, 0, 0},
-    {9, 65330, 0, 65330, 0, 0},
-    {9, 65331, 0, 65331, 0, 0},
-    {9, 65334, 0, 65334, 0, 0},
-    {9, 65333, 0, 65333, 0, 0},
-    {9, 65329, 0, 65329, 0, 0},
-    {9, 65327, 0, 65327, 0, 0},
-    {9, 65325, 0, 65325, 0, 0},
-    {9, 65323, 0, 65323, 0, 0},
-    {9, 65322, 0, 65322, 0, 0},
-    {9, 65318, 0, 65318, 0, 0},
-    {9, 65319, 0, 65319, 0, 0},
-    {9, 65317, 0, 65317, 0, 0},
-    {0, 84, 0, 84, 0, 0},
-    {129, 0, 38, 0, 0, 0},
-    {129, 0, 37, 0, 0, 0},
-    {129, 0, 64, 0, 0, 0},
-    {129, 0, 63, 0, 0, 0},
-    {9, 65498, 0, 65498, 0, 0},
-    {9, 65499, 0, 65499, 0, 0},
-    {9, 65505, 0, 65505, 0, 0},
-    {9, 65472, 0, 65472, 0, 0},
-    {9, 65473, 0, 65473, 0, 0},
-    {9, 65474, 0, 65474, 0, 0},
-    {9, 65479, 0, 65479, 0, 0},
-    {129, 0, 0, 0, 0, 0},
-    {9, 65489, 0, 65489, 0, 0},
-    {9, 65482, 0, 65482, 0, 0},
-    {9, 65450, 0, 65450, 0, 0},
-    {9, 65456, 0, 65456, 0, 0},
-    {129, 0, 65476, 0, 0, 0},
-    {9, 65440, 0, 65440, 0, 0},
-    {129, 0, 80, 0, 0, 0},
-    {129, 0, 48, 0, 0, 0},
-    {9, 65488, 0, 65488, 0, 0},
-    {9, 65477, 0, 65477, 0, 0},
-    {9, 8, 0, 8, 0, 0},
-    {129, 0, 65528, 0, 0, 0},
-    {9, 74, 0, 74, 0, 0},
-    {9, 86, 0, 86, 0, 0},
-    {9, 100, 0, 100, 0, 0},
-    {9, 128, 0, 128, 0, 0},
-    {9, 112, 0, 112, 0, 0},
-    {9, 126, 0, 126, 0, 0},
-    {65, 0, 65528, 0, 0, 0},
-    {9, 9, 0, 9, 0, 0},
-    {129, 0, 65462, 0, 0, 0},
-    {65, 0, 65527, 0, 0, 0},
-    {9, 58331, 0, 58331, 0, 0},
-    {129, 0, 65450, 0, 0, 0},
-    {129, 0, 65436, 0, 0, 0},
-    {9, 7, 0, 7, 0, 0},
-    {129, 0, 65424, 0, 0, 0},
-    {129, 0, 65529, 0, 0, 0},
-    {129, 0, 65408, 0, 0, 0},
-    {129, 0, 65410, 0, 0, 0},
-    {129, 0, 58019, 0, 0, 0},
-    {129, 0, 57153, 0, 0, 0},
-    {129, 0, 57274, 0, 0, 0},
-    {0, 0, 16, 0, 0, 0},
-    {0, 65520, 0, 65520, 0, 0},
-    {4, 0, 0, 0, 0, 1},
-    {4, 0, 0, 0, 0, 2},
-    {4, 0, 0, 0, 0, 3},
-    {4, 0, 0, 0, 0, 4},
-    {4, 0, 0, 0, 0, 5},
-    {4, 0, 0, 0, 0, 6},
-    {4, 0, 0, 0, 0, 7},
-    {4, 0, 0, 0, 0, 8},
-    {4, 0, 0, 0, 0, 9},
-    {0, 0, 26, 0, 0, 0},
-    {0, 65510, 0, 65510, 0, 0},
-    {4, 0, 0, 0, 0, 0},
-    {129, 0, 40, 0, 0, 0},
-    {9, 65496, 0, 65496, 0, 0},
+    {0, 0, 0, 0, 0, 32},
+    {0, 0, 0, 0, 0, 48},
+    {0, 0, 0, 0, 0, 6},
+    {0, 0, 0, 1, 1, 6},
+    {0, 0, 0, 2, 2, 6},
+    {0, 0, 0, 3, 3, 6},
+    {0, 0, 0, 4, 4, 6},
+    {0, 0, 0, 5, 5, 6},
+    {0, 0, 0, 6, 6, 6},
+    {0, 0, 0, 7, 7, 6},
+    {0, 0, 0, 8, 8, 6},
+    {0, 0, 0, 9, 9, 6},
+    {0, 32, 0, 0, 0, 129},
+    {65504, 0, 65504, 0, 0, 9},
+    {0, 0, 0, 0, 0, 9},
+    {743, 0, 743, 0, 0, 9},
+    {121, 0, 121, 0, 0, 9},
+    {0, 1, 0, 0, 0, 129},
+    {65535, 0, 65535, 0, 0, 9},
+    {0, 65337, 0, 0, 0, 129},
+    {65304, 0, 65304, 0, 0, 9},
+    {0, 65415, 0, 0, 0, 129},
+    {65236, 0, 65236, 0, 0, 9},
+    {0, 210, 0, 0, 0, 129},
+    {0, 206, 0, 0, 0, 129},
+    {0, 205, 0, 0, 0, 129},
+    {0, 79, 0, 0, 0, 129},
+    {0, 202, 0, 0, 0, 129},
+    {0, 203, 0, 0, 0, 129},
+    {0, 207, 0, 0, 0, 129},
+    {97, 0, 97, 0, 0, 9},
+    {0, 211, 0, 0, 0, 129},
+    {0, 209, 0, 0, 0, 129},
+    {0, 213, 0, 0, 0, 129},
+    {130, 0, 130, 0, 0, 9},
+    {0, 214, 0, 0, 0, 129},
+    {0, 218, 0, 0, 0, 129},
+    {0, 217, 0, 0, 0, 129},
+    {0, 219, 0, 0, 0, 129},
+    {0, 0, 0, 0, 0, 1},
+    {56, 0, 56, 0, 0, 9},
+    {0, 2, 1, 0, 0, 129},
+    {65535, 1, 0, 0, 0, 65},
+    {65534, 0, 65535, 0, 0, 9},
+    {65457, 0, 65457, 0, 0, 9},
+    {0, 65439, 0, 0, 0, 129},
+    {0, 65480, 0, 0, 0, 129},
+    {0, 65406, 0, 0, 0, 129},
+    {65326, 0, 65326, 0, 0, 9},
+    {65330, 0, 65330, 0, 0, 9},
+    {65331, 0, 65331, 0, 0, 9},
+    {65334, 0, 65334, 0, 0, 9},
+    {65333, 0, 65333, 0, 0, 9},
+    {65329, 0, 65329, 0, 0, 9},
+    {65327, 0, 65327, 0, 0, 9},
+    {65325, 0, 65325, 0, 0, 9},
+    {65323, 0, 65323, 0, 0, 9},
+    {65322, 0, 65322, 0, 0, 9},
+    {65318, 0, 65318, 0, 0, 9},
+    {65319, 0, 65319, 0, 0, 9},
+    {65317, 0, 65317, 0, 0, 9},
+    {84, 0, 84, 0, 0, 0},
+    {0, 38, 0, 0, 0, 129},
+    {0, 37, 0, 0, 0, 129},
+    {0, 64, 0, 0, 0, 129},
+    {0, 63, 0, 0, 0, 129},
+    {65498, 0, 65498, 0, 0, 9},
+    {65499, 0, 65499, 0, 0, 9},
+    {65505, 0, 65505, 0, 0, 9},
+    {65472, 0, 65472, 0, 0, 9},
+    {65473, 0, 65473, 0, 0, 9},
+    {65474, 0, 65474, 0, 0, 9},
+    {65479, 0, 65479, 0, 0, 9},
+    {0, 0, 0, 0, 0, 129},
+    {65489, 0, 65489, 0, 0, 9},
+    {65482, 0, 65482, 0, 0, 9},
+    {65450, 0, 65450, 0, 0, 9},
+    {65456, 0, 65456, 0, 0, 9},
+    {0, 65476, 0, 0, 0, 129},
+    {65440, 0, 65440, 0, 0, 9},
+    {0, 80, 0, 0, 0, 129},
+    {0, 48, 0, 0, 0, 129},
+    {65488, 0, 65488, 0, 0, 9},
+    {65477, 0, 65477, 0, 0, 9},
+    {8, 0, 8, 0, 0, 9},
+    {0, 65528, 0, 0, 0, 129},
+    {74, 0, 74, 0, 0, 9},
+    {86, 0, 86, 0, 0, 9},
+    {100, 0, 100, 0, 0, 9},
+    {128, 0, 128, 0, 0, 9},
+    {112, 0, 112, 0, 0, 9},
+    {126, 0, 126, 0, 0, 9},
+    {0, 65528, 0, 0, 0, 65},
+    {9, 0, 9, 0, 0, 9},
+    {0, 65462, 0, 0, 0, 129},
+    {0, 65527, 0, 0, 0, 65},
+    {58331, 0, 58331, 0, 0, 9},
+    {0, 65450, 0, 0, 0, 129},
+    {0, 65436, 0, 0, 0, 129},
+    {7, 0, 7, 0, 0, 9},
+    {0, 65424, 0, 0, 0, 129},
+    {0, 65529, 0, 0, 0, 129},
+    {0, 65408, 0, 0, 0, 129},
+    {0, 65410, 0, 0, 0, 129},
+    {0, 58019, 0, 0, 0, 129},
+    {0, 57153, 0, 0, 0, 129},
+    {0, 57274, 0, 0, 0, 129},
+    {0, 16, 0, 0, 0, 0},
+    {65520, 0, 65520, 0, 0, 0},
+    {0, 0, 0, 0, 1, 4},
+    {0, 0, 0, 0, 2, 4},
+    {0, 0, 0, 0, 3, 4},
+    {0, 0, 0, 0, 4, 4},
+    {0, 0, 0, 0, 5, 4},
+    {0, 0, 0, 0, 6, 4},
+    {0, 0, 0, 0, 7, 4},
+    {0, 0, 0, 0, 8, 4},
+    {0, 0, 0, 0, 9, 4},
+    {0, 26, 0, 0, 0, 0},
+    {65510, 0, 65510, 0, 0, 0},
+    {0, 0, 0, 0, 0, 4},
+    {0, 40, 0, 0, 0, 129},
+    {65496, 0, 65496, 0, 0, 9},
 };
 
 /* type indexes */

Index: weakrefobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/weakrefobject.c,v
retrieving revision 1.9.2.1
retrieving revision 1.9.2.2
diff -u -d -r1.9.2.1 -r1.9.2.2
--- weakrefobject.c	28 Apr 2003 17:17:59 -0000	1.9.2.1
+++ weakrefobject.c	7 Jan 2005 07:04:10 -0000	1.9.2.2
@@ -19,6 +19,15 @@
 }
 
 
+static void
+init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
+{
+    self->hash = -1;
+    self->wr_object = ob;
+    Py_XINCREF(callback);
+    self->wr_callback = callback;
+}
+
 static PyWeakReference *
 new_weakref(PyObject *ob, PyObject *callback)
 {
@@ -26,10 +35,7 @@
 
     result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
     if (result) {
-        result->hash = -1;
-        result->wr_object = ob;
-        Py_XINCREF(callback);
-        result->wr_callback = callback;
+        init_weakref(result, ob, callback);
         PyObject_GC_Track(result);
     }
     return result;
@@ -53,24 +59,50 @@
         if (*list == self)
             *list = self->wr_next;
         self->wr_object = Py_None;
-        self->wr_callback = NULL;
         if (self->wr_prev != NULL)
             self->wr_prev->wr_next = self->wr_next;
         if (self->wr_next != NULL)
             self->wr_next->wr_prev = self->wr_prev;
         self->wr_prev = NULL;
         self->wr_next = NULL;
-        Py_XDECREF(callback);
+    }
+    if (callback != NULL) {
+        Py_DECREF(callback);
+        self->wr_callback = NULL;
     }
 }
 
+/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
+ * the callback intact and uncalled.  It must be possible to call self's
+ * tp_dealloc() after calling this, so self has to be left in a sane enough
+ * state for that to work.  We expect tp_dealloc to decref the callback
+ * then.  The reason for not letting clear_weakref() decref the callback
+ * right now is that if the callback goes away, that may in turn trigger
+ * another callback (if a weak reference to the callback exists) -- running
+ * arbitrary Python code in the middle of gc is a disaster.  The convolution
+ * here allows gc to delay triggering such callbacks until the world is in
+ * a sane state again.
+ */
+void
+_PyWeakref_ClearRef(PyWeakReference *self)
+{
+    PyObject *callback;
+
+    assert(self != NULL);
+    assert(PyWeakref_Check(self));
+    /* Preserve and restore the callback around clear_weakref. */
+    callback = self->wr_callback;
+    self->wr_callback = NULL;
+    clear_weakref(self);
+    self->wr_callback = callback;
+}
 
 static void
-weakref_dealloc(PyWeakReference *self)
+weakref_dealloc(PyObject *self)
 {
-    PyObject_GC_UnTrack((PyObject *)self);
-    clear_weakref(self);
-    PyObject_GC_Del(self);
+    PyObject_GC_UnTrack(self);
+    clear_weakref((PyWeakReference *) self);
+    self->ob_type->tp_free(self);
 }
 
 
@@ -117,7 +149,7 @@
     self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
     return self->hash;
 }
-    
+
 
 static PyObject *
 weakref_repr(PyWeakReference *self)
@@ -167,6 +199,134 @@
                                 PyWeakref_GET_OBJECT(other), op);
 }
 
+/* Given the head of an object's list of weak references, extract the
+ * two callback-less refs (ref and proxy).  Used to determine if the
+ * shared references exist and to determine the back link for newly
+ * inserted references.
+ */
+static void
+get_basic_refs(PyWeakReference *head,
+               PyWeakReference **refp, PyWeakReference **proxyp)
+{
+    *refp = NULL;
+    *proxyp = NULL;
+
+    if (head != NULL && head->wr_callback == NULL) {
+        /* We need to be careful that the "basic refs" aren't
+           subclasses of the main types.  That complicates this a
+           little. */
+        if (PyWeakref_CheckRefExact(head)) {
+            *refp = head;
+            head = head->wr_next;
+        }
+        if (head != NULL
+            && head->wr_callback == NULL
+            && PyWeakref_CheckProxy(head)) {
+            *proxyp = head;
+            /* head = head->wr_next; */
+        }
+    }
+}
+
+/* Insert 'newref' in the list after 'prev'.  Both must be non-NULL. */
+static void
+insert_after(PyWeakReference *newref, PyWeakReference *prev)
+{
+    newref->wr_prev = prev;
+    newref->wr_next = prev->wr_next;
+    if (prev->wr_next != NULL)
+        prev->wr_next->wr_prev = newref;
+    prev->wr_next = newref;
+}
+
+/* Insert 'newref' at the head of the list; 'list' points to the variable
+ * that stores the head.
+ */
+static void
+insert_head(PyWeakReference *newref, PyWeakReference **list)
+{
+    PyWeakReference *next = *list;
+
+    newref->wr_prev = NULL;
+    newref->wr_next = next;
+    if (next != NULL)
+        next->wr_prev = newref;
+    *list = newref;
+}
+
+static int
+parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
+                        PyObject **obp, PyObject **callbackp)
+{
+    /* XXX Should check that kwargs == NULL or is empty. */
+    return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
+}
+
+static PyObject *
+weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyWeakReference *self = NULL;
+    PyObject *ob, *callback = NULL;
+
+    if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
+        PyWeakReference *ref, *proxy;
+        PyWeakReference **list;
+
+        if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) {
+            PyErr_Format(PyExc_TypeError,
+                         "cannot create weak reference to '%s' object",
+                         ob->ob_type->tp_name);
+            return NULL;
+        }
+        if (callback == Py_None)
+            callback = NULL;
+        list = GET_WEAKREFS_LISTPTR(ob);
+        get_basic_refs(*list, &ref, &proxy);
+        if (callback == NULL && type == &_PyWeakref_RefType) {
+            if (ref != NULL) {
+                /* We can re-use an existing reference. */
+                Py_INCREF(ref);
+                return (PyObject *)ref;
+            }
+        }
+        /* We have to create a new reference. */
+        /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
+           list on ob can be mutated.  This means that the ref and
+           proxy pointers we got back earlier may have been collected,
+           so we need to compute these values again before we use
+           them. */
+        self = (PyWeakReference *) (type->tp_alloc(type, 0));
+        if (self != NULL) {
+            init_weakref(self, ob, callback);
+            if (callback == NULL && type == &_PyWeakref_RefType) {
+                insert_head(self, list);
+            }
+            else {
+                PyWeakReference *prev;
+
+                get_basic_refs(*list, &ref, &proxy);
+                prev = (proxy == NULL) ? ref : proxy;
+                if (prev == NULL)
+                    insert_head(self, list);
+                else
+                    insert_after(self, prev);
+            }
+        }
+    }
+    return (PyObject *)self;
+}
+
+static int
+weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *tmp;
+
+    if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
+        return 0;
+    else
+        return 1;
+}
+
 
 PyTypeObject
 _PyWeakref_RefType = {
@@ -175,7 +335,7 @@
     "weakref",
     sizeof(PyWeakReference),
     0,
-    (destructor)weakref_dealloc,/*tp_dealloc*/
+    weakref_dealloc,            /*tp_dealloc*/
     0,	                        /*tp_print*/
     0,                          /*tp_getattr*/
     0,                          /*tp_setattr*/
@@ -184,18 +344,33 @@
     0,                          /*tp_as_number*/
     0,                          /*tp_as_sequence*/
     0,                          /*tp_as_mapping*/
-    (hashfunc)weakref_hash,      /*tp_hash*/
+    (hashfunc)weakref_hash,     /*tp_hash*/
     (ternaryfunc)weakref_call,  /*tp_call*/
     0,                          /*tp_str*/
     0,                          /*tp_getattro*/
     0,                          /*tp_setattro*/
     0,                          /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE,
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
+        | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
     0,                          /*tp_doc*/
     (traverseproc)gc_traverse,  /*tp_traverse*/
     (inquiry)gc_clear,          /*tp_clear*/
     (richcmpfunc)weakref_richcompare,	/*tp_richcompare*/
-    0,				/*tp_weaklistoffset*/
+    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*/
+    (initproc)weakref___init__, /*tp_init*/
+    PyType_GenericAlloc,        /*tp_alloc*/
+    weakref___new__,            /*tp_new*/
+    PyObject_GC_Del,            /*tp_free*/
 };
 
 
@@ -264,14 +439,6 @@
 WRAP_UNARY(proxy_str, PyObject_Str)
 WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
 
-static int
-proxy_print(PyWeakReference *proxy, FILE *fp, int flags)
-{
-    if (!proxy_checkref(proxy))
-        return -1;
-    return PyObject_Print(PyWeakref_GET_OBJECT(proxy), fp, flags);
-}
-
 static PyObject *
 proxy_repr(PyWeakReference *proxy)
 {
@@ -332,12 +499,12 @@
 WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
 WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
 
-static int 
+static int
 proxy_nonzero(PyWeakReference *proxy)
 {
     PyObject *o = PyWeakref_GET_OBJECT(proxy);
     if (!proxy_checkref(proxy))
-        return 1;
+        return -1;
     if (o->ob_type->tp_as_number &&
         o->ob_type->tp_as_number->nb_nonzero)
         return (*o->ob_type->tp_as_number->nb_nonzero)(o);
@@ -345,6 +512,15 @@
         return 1;
 }
 
+static void
+proxy_dealloc(PyWeakReference *self)
+{
+    if (self->wr_callback != NULL)
+        PyObject_GC_UnTrack((PyObject *)self);
+    clear_weakref(self);
+    PyObject_GC_Del(self);
+}
+
 /* sequence slots */
 
 static PyObject *
@@ -389,7 +565,11 @@
 {
     if (!proxy_checkref(proxy))
         return -1;
-    return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
+
+    if (value == NULL)
+        return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
+    else
+        return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
 }
 
 /* iterator slots */
@@ -474,8 +654,8 @@
     sizeof(PyWeakReference),
     0,
     /* methods */
-    (destructor)weakref_dealloc,        /* tp_dealloc */
-    (printfunc)proxy_print,             /* tp_print */
+    (destructor)proxy_dealloc,          /* tp_dealloc */
+    0,				        /* tp_print */
     0,				        /* tp_getattr */
     0, 				        /* tp_setattr */
     proxy_compare,		        /* tp_compare */
@@ -509,8 +689,8 @@
     sizeof(PyWeakReference),
     0,
     /* methods */
-    (destructor)weakref_dealloc,        /* tp_dealloc */
-    (printfunc)proxy_print,             /* tp_print */
+    (destructor)proxy_dealloc,          /* tp_dealloc */
+    0,				        /* tp_print */
     0,				        /* tp_getattr */
     0, 				        /* tp_setattr */
     proxy_compare,		        /* tp_compare */
@@ -536,56 +716,6 @@
 };
 
 
-/* Given the head of an object's list of weak references, extract the
- * two callback-less refs (ref and proxy).  Used to determine if the
- * shared references exist and to determine the back link for newly
- * inserted references.
- */
-static void
-get_basic_refs(PyWeakReference *head,
-               PyWeakReference **refp, PyWeakReference **proxyp)
-{
-    *refp = NULL;
-    *proxyp = NULL;
-
-    if (head != NULL && head->wr_callback == NULL) {
-        if (head->ob_type == &_PyWeakref_RefType) {
-            *refp = head;
-            head = head->wr_next;
-        }
-        if (head != NULL && head->wr_callback == NULL) {
-            *proxyp = head;
-            head = head->wr_next;
-        }
-    }
-}
-
-/* Insert 'newref' in the list after 'prev'.  Both must be non-NULL. */
-static void
-insert_after(PyWeakReference *newref, PyWeakReference *prev)
-{
-    newref->wr_prev = prev;
-    newref->wr_next = prev->wr_next;
-    if (prev->wr_next != NULL)
-        prev->wr_next->wr_prev = newref;
-    prev->wr_next = newref;
-}
-
-/* Insert 'newref' at the head of the list; 'list' points to the variable
- * that stores the head.
- */
-static void
-insert_head(PyWeakReference *newref, PyWeakReference **list)
-{
-    PyWeakReference *next = *list;
-
-    newref->wr_prev = NULL;
-    newref->wr_next = next;
-    if (next != NULL)
-        next->wr_prev = newref;
-    *list = newref;
-}
-
 
 PyObject *
 PyWeakref_NewRef(PyObject *ob, PyObject *callback)
@@ -602,20 +732,39 @@
     }
     list = GET_WEAKREFS_LISTPTR(ob);
     get_basic_refs(*list, &ref, &proxy);
-    if (callback == NULL || callback == Py_None)
+    if (callback == Py_None)
+        callback = NULL;
+    if (callback == NULL)
         /* return existing weak reference if it exists */
         result = ref;
     if (result != NULL)
-        Py_XINCREF(result);
+        Py_INCREF(result);
     else {
+        /* Note: new_weakref() can trigger cyclic GC, so the weakref
+           list on ob can be mutated.  This means that the ref and
+           proxy pointers we got back earlier may have been collected,
+           so we need to compute these values again before we use
+           them. */
         result = new_weakref(ob, callback);
         if (result != NULL) {
+            get_basic_refs(*list, &ref, &proxy);
             if (callback == NULL) {
-                insert_head(result, list);
+                if (ref == NULL)
+                    insert_head(result, list);
+                else {
+                    /* Someone else added a ref without a callback
+                       during GC.  Return that one instead of this one
+                       to avoid violating the invariants of the list
+                       of weakrefs for ob. */
+                    Py_DECREF(result);
+                    Py_INCREF(ref);
+                    result = ref;
+                }
             }
             else {
-                PyWeakReference *prev = (proxy == NULL) ? ref : proxy;
+                PyWeakReference *prev;
 
+                prev = (proxy == NULL) ? ref : proxy;
                 if (prev == NULL)
                     insert_head(result, list);
                 else
@@ -642,12 +791,19 @@
     }
     list = GET_WEAKREFS_LISTPTR(ob);
     get_basic_refs(*list, &ref, &proxy);
+    if (callback == Py_None)
+        callback = NULL;
     if (callback == NULL)
         /* attempt to return an existing weak reference if it exists */
         result = proxy;
     if (result != NULL)
-        Py_XINCREF(result);
+        Py_INCREF(result);
     else {
+        /* Note: new_weakref() can trigger cyclic GC, so the weakref
+           list on ob can be mutated.  This means that the ref and
+           proxy pointers we got back earlier may have been collected,
+           so we need to compute these values again before we use
+           them. */
         result = new_weakref(ob, callback);
         if (result != NULL) {
             PyWeakReference *prev;
@@ -656,8 +812,19 @@
                 result->ob_type = &_PyWeakref_CallableProxyType;
             else
                 result->ob_type = &_PyWeakref_ProxyType;
-            if (callback == NULL)
+            get_basic_refs(*list, &ref, &proxy);
+            if (callback == NULL) {
+                if (proxy != NULL) {
+                    /* Someone else added a proxy without a callback
+                       during GC.  Return that one instead of this one
+                       to avoid violating the invariants of the list
+                       of weakrefs for ob. */
+                    Py_DECREF(result);
+                    Py_INCREF(result = proxy);
+                    goto skip_insert;
+                }
                 prev = ref;
+            }
             else
                 prev = (proxy == NULL) ? ref : proxy;
 
@@ -665,6 +832,8 @@
                 insert_head(result, list);
             else
                 insert_after(result, prev);
+        skip_insert:
+            ;
         }
     }
     return (PyObject *) result;
@@ -681,7 +850,9 @@
     return PyWeakref_GET_OBJECT(ref);
 }
 
-
+/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
+ * handle_weakrefs().
+ */
 static void
 handle_callback(PyWeakReference *ref, PyObject *callback)
 {
@@ -730,8 +901,10 @@
 
             current->wr_callback = NULL;
             clear_weakref(current);
-            handle_callback(current, callback);
-            Py_DECREF(callback);
+            if (callback != NULL) {
+                handle_callback(current, callback);
+                Py_DECREF(callback);
+            }
         }
         else {
             PyObject *tuple = PyTuple_New(count * 2);
@@ -748,10 +921,12 @@
                 current = next;
             }
             for (i = 0; i < count; ++i) {
-                PyObject *current = PyTuple_GET_ITEM(tuple, i * 2);
                 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
 
-                handle_callback((PyWeakReference *)current, callback);
+                if (callback != NULL) {
+                    PyObject *current = PyTuple_GET_ITEM(tuple, i * 2);
+                    handle_callback((PyWeakReference *)current, callback);
+                }
             }
             Py_DECREF(tuple);
         }

--- xxobject.c DELETED ---



More information about the Python-checkins mailing list