Merged revisions 64119,64147,64150,64165,64219-64221,64229-64230,64233,64235,64253,64278,64280,64301,64303,64320,64328,64338-64339 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r64119 | andrew.kuchling | 2008-06-11 14:53:14 +0200 (mer., 11 juin 2008) | 1 line

  Note PEP 371 section
........
  r64147 | benjamin.peterson | 2008-06-11 22:04:30 +0200 (mer., 11 juin 2008) | 2 lines

  update ACKS and NEWs for multiprocessing
........
  r64150 | georg.brandl | 2008-06-11 22:28:06 +0200 (mer., 11 juin 2008) | 2 lines

  Can we agree to put dots at entry ends? Thanks.
........
  r64165 | armin.rigo | 2008-06-12 11:50:58 +0200 (jeu., 12 juin 2008) | 3 lines

  Sounds obvious, but I didn't even realize that you can put non-string
  keys in type dictionaries without using this locals() hack.
........
  r64219 | neal.norwitz | 2008-06-13 08:00:46 +0200 (ven., 13 juin 2008) | 1 line

  Check for memory alloc failure
........
  r64220 | neal.norwitz | 2008-06-13 08:02:26 +0200 (ven., 13 juin 2008) | 3 lines

  Fix some memory dealloc problems when exceptions occur.
  It caused: "Fatal Python error: UNREF invalid object" in the DoubleTest.
........
  r64221 | neal.norwitz | 2008-06-13 08:03:25 +0200 (ven., 13 juin 2008) | 3 lines

  Fix typo in method name.  The LT class implemented less than.  The LE class
  should implement less than or equal to (as the code does).
........
  r64229 | georg.brandl | 2008-06-13 15:26:54 +0200 (ven., 13 juin 2008) | 2 lines

  Clarification.
........
  r64230 | robert.schuppenies | 2008-06-13 15:29:37 +0200 (ven., 13 juin 2008) | 2 lines

  Fixed: sys.getsizeof does not take the actual length of the tuples into account.
........
  r64233 | benjamin.peterson | 2008-06-13 17:11:50 +0200 (ven., 13 juin 2008) | 2 lines

  platform.uname now tries to fill empty values even when os.uname is present
........
  r64235 | benjamin.peterson | 2008-06-13 17:41:09 +0200 (ven., 13 juin 2008) | 1 line

  set svn:ignore on multiprocessing
........
  r64253 | andrew.kuchling | 2008-06-13 21:38:18 +0200 (ven., 13 juin 2008) | 1 line

  Typo fixes
........
  r64278 | martin.v.loewis | 2008-06-14 16:24:47 +0200 (sam., 14 juin 2008) | 2 lines

  Disable UAC by default.
........
  r64280 | gregory.p.smith | 2008-06-14 19:34:09 +0200 (sam., 14 juin 2008) | 3 lines

  silence the test when it is skipped on some platforms.  should fix a
  buildbot.
........
  r64301 | georg.brandl | 2008-06-15 21:54:36 +0200 (dim., 15 juin 2008) | 2 lines

  Forward-port new test from r64300.
........
  r64303 | raymond.hettinger | 2008-06-16 03:42:40 +0200 (lun., 16 juin 2008) | 1 line

  Issue 3116: fix quadratic behavior in marshal.dumps().
........
  r64320 | georg.brandl | 2008-06-16 23:00:47 +0200 (lun., 16 juin 2008) | 2 lines

  Add Jesse Noller to the developers list.
........
  r64328 | georg.brandl | 2008-06-17 11:01:35 +0200 (mar., 17 juin 2008) | 2 lines

  Split the HTML index.
........
  r64338 | vinay.sajip | 2008-06-17 13:02:14 +0200 (mar., 17 juin 2008) | 1 line

  Bug #3126: StreamHandler and FileHandler check before calling "flush" and "close" that the stream object has these, using hasattr (thanks to bobf for the patch).
........
  r64339 | vinay.sajip | 2008-06-17 13:04:02 +0200 (mar., 17 juin 2008) | 1 line

  Updated with fix for #3126.
........
diff --git a/Doc/conf.py b/Doc/conf.py
index 8b1514b..0cfbea6 100644
--- a/Doc/conf.py
+++ b/Doc/conf.py
@@ -95,6 +95,9 @@
 # Output file base name for HTML help builder.
 htmlhelp_basename = 'python' + release.replace('.', '')
 
+# Split the index
+html_split_index = True
+
 
 # Options for LaTeX output
 # ------------------------
diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst
index 3bdfab4..bd0b02a 100644
--- a/Doc/library/optparse.rst
+++ b/Doc/library/optparse.rst
@@ -636,9 +636,9 @@
 option involved in the error; be sure to do the same when calling
 ``parser.error()`` from your application code.
 
-If :mod:`optparse`'s default error-handling behaviour does not suite your needs,
-you'll need to subclass OptionParser and override ``exit()`` and/or
-:meth:`error`.
+If :mod:`optparse`'s default error-handling behaviour does not suit your needs,
+you'll need to subclass OptionParser and override its :meth:`exit` and/or
+:meth:`error` methods.
 
 
 .. _optparse-putting-it-all-together:
diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst
index c4c9093..f3b03e7 100644
--- a/Doc/whatsnew/2.6.rst
+++ b/Doc/whatsnew/2.6.rst
@@ -521,6 +521,21 @@
   
 .. ======================================================================
 
+.. _pep-0371:
+
+PEP 371: The ``multiprocessing`` Package
+=====================================================
+
+XXX write this.
+
+.. seealso::
+
+   :pep:`371` - Per-user ``site-packages`` Directory
+     PEP written by Jesse Noller and Richard Oudkerk; 
+     implemented by Jesse Noller.
+
+.. ======================================================================
+
 .. _pep-3101:
 
 PEP 3101: Advanced String Formatting
diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
index 742eac2..9727d4f 100644
--- a/Lib/logging/__init__.py
+++ b/Lib/logging/__init__.py
@@ -731,7 +731,7 @@
         """
         Flushes the stream.
         """
-        if self.stream:
+        if self.stream and hasattr(self.stream, "flush"):
             self.stream.flush()
 
     def emit(self, record):
@@ -787,7 +787,8 @@
         """
         if self.stream:
             self.flush()
-            self.stream.close()
+            if hasattr(self.stream, "close"):
+                self.stream.close()
             StreamHandler.close(self)
             self.stream = None
 
diff --git a/Lib/platform.py b/Lib/platform.py
index 8447d41..33033ff 100755
--- a/Lib/platform.py
+++ b/Lib/platform.py
@@ -1066,23 +1066,30 @@
 
     """
     global _uname_cache
+    no_os_uname = 0
 
     if _uname_cache is not None:
         return _uname_cache
 
+    processor = ''
+
     # Get some infos from the builtin os.uname API...
     try:
         system,node,release,version,machine = os.uname()
-
     except AttributeError:
-        # Hmm, no uname... we'll have to poke around the system then.
-        system = sys.platform
-        release = ''
-        version = ''
-        node = _node()
-        machine = ''
-        processor = ''
-        use_syscmd_ver = 1
+        no_os_uname = 1
+
+    if no_os_uname or not filter(None, (system, node, release, version, machine)):
+        # Hmm, no there is either no uname or uname has returned
+        #'unknowns'... we'll have to poke around the system then.
+        if no_os_uname:
+            system = sys.platform
+            release = ''
+            version = ''
+            node = _node()
+            machine = ''
+
+        use_syscmd_ver = 01
 
         # Try win32_ver() on win32 platforms
         if system == 'win32':
@@ -1093,8 +1100,10 @@
             # available on Win XP and later; see
             # http://support.microsoft.com/kb/888731 and
             # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
-            machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
-            processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
+            if not machine:
+                machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
+            if not processor:
+                processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
 
         # Try the 'ver' system command available on some
         # platforms
@@ -1136,30 +1145,28 @@
             release,(version,stage,nonrel),machine = mac_ver()
             system = 'MacOS'
 
-    else:
-        # System specific extensions
-        if system == 'OpenVMS':
-            # OpenVMS seems to have release and version mixed up
-            if not release or release == '0':
-                release = version
-                version = ''
-            # Get processor information
-            try:
-                import vms_lib
-            except ImportError:
-                pass
-            else:
-                csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
-                if (cpu_number >= 128):
-                    processor = 'Alpha'
-                else:
-                    processor = 'VAX'
+    # System specific extensions
+    if system == 'OpenVMS':
+        # OpenVMS seems to have release and version mixed up
+        if not release or release == '0':
+            release = version
+            version = ''
+        # Get processor information
+        try:
+            import vms_lib
+        except ImportError:
+            pass
         else:
-            # Get processor information from the uname system command
-            processor = _syscmd_uname('-p','')
+            csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
+            if (cpu_number >= 128):
+                processor = 'Alpha'
+            else:
+                processor = 'VAX'
+    if not processor:
+        # Get processor information from the uname system command
+        processor = _syscmd_uname('-p','')
 
-    # 'unknown' is not really any useful as information; we'll convert
-    # it to '' which is more portable
+    #If any unknowns still exist, replace them with ''s, which are more portable
     if system == 'unknown':
         system = ''
     if node == 'unknown':
diff --git a/Lib/test/crashers/loosing_mro_ref.py b/Lib/test/crashers/loosing_mro_ref.py
index 5ecde63..a8c6e63 100644
--- a/Lib/test/crashers/loosing_mro_ref.py
+++ b/Lib/test/crashers/loosing_mro_ref.py
@@ -27,10 +27,9 @@
 class Base2(object):
     mykey = 'from Base2'
 
-class X(Base):
-    # you can't add a non-string key to X.__dict__, but it can be
-    # there from the beginning :-)
-    locals()[MyKey()] = 5
+# you can't add a non-string key to X.__dict__, but it can be
+# there from the beginning :-)
+X = type('X', (Base,), {MyKey(): 5})
 
 print(X.mykey)
 # I get a segfault, or a slightly wrong assertion error in a debug build.
diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py
index 1a34ff8..acfe1f1 100644
--- a/Lib/test/test_grammar.py
+++ b/Lib/test/test_grammar.py
@@ -335,6 +335,7 @@
         self.assertEquals(l5(1, 2), 5)
         self.assertEquals(l5(1, 2, 3), 6)
         check_syntax_error(self, "lambda x: x = 2")
+        check_syntax_error(self, "lambda (None,): None")
         l6 = lambda x, y, *, k=20: x+y+k
         self.assertEquals(l6(1,2), 1+2+20)
         self.assertEquals(l6(1,2,k=10), 1+2+10)
diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py
index 1c7c97f..fba4fd7 100644
--- a/Lib/test/test_heapq.py
+++ b/Lib/test/test_heapq.py
@@ -211,10 +211,11 @@
         class LE:
             def __init__(self, x):
                 self.x = x
-            def __lt__(self, other):
+            def __le__(self, other):
                 return self.x >= other.x
         data = [random.random() for i in range(100)]
         target = sorted(data, reverse=True)
+        print("HASATTR", hasattr(LE(0), "__lt__"), LE(0).__lt__)
         self.assertEqual(hsort(data, LT), target)
         self.assertEqual(hsort(data, LE), target)
 
diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py
index 917f626..616e665 100644
--- a/Lib/test/test_struct.py
+++ b/Lib/test/test_struct.py
@@ -8,6 +8,7 @@
 
 import sys
 ISBIGENDIAN = sys.byteorder == "big"
+IS32BIT = sys.maxsize == 0x7fffffff
 del sys
 
 try:
@@ -580,6 +581,11 @@
             for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
                 self.assertTrue(struct.unpack('>?', c)[0])
 
+    if IS32BIT:
+        def test_crasher(self):
+            self.assertRaises(MemoryError, struct.pack, "357913941b", "a")
+
+
 def test_main():
     run_unittest(StructTest)
 
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 4049802..08fc909 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -520,6 +520,9 @@
         self.check_sizeof(32768, h + self.align(2) + 2)
         self.check_sizeof(32768*32768-1, h + self.align(2) + 2)
         self.check_sizeof(32768*32768, h + self.align(2) + 4)
+        # tuple
+        self.check_sizeof((), h)
+        self.check_sizeof((1,2,3), h + 3*p)
 
 
 def test_main():
diff --git a/Misc/ACKS b/Misc/ACKS
index f34163a..31fd5d3 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -486,6 +486,7 @@
 Gustavo Niemeyer
 Oscar Nierstrasz
 Hrvoje Niksic
+Jesse Noller
 Bill Noon
 Stefan Norberg
 Tim Northover
@@ -502,6 +503,7 @@
 Douglas Orr
 Denis S. Otkidach
 Michael Otteneder
+R. M. Oudkerk
 Russel Owen
 Ondrej Palkovsky
 Mike Pall
@@ -673,6 +675,7 @@
 Monty Taylor
 Amy Taylor
 Tobias Thelen
+James Thomas
 Robin Thomas
 Eric Tiedemann
 Tracy Tims
diff --git a/Misc/developers.txt b/Misc/developers.txt
index 2904a68..9db80fb 100644
--- a/Misc/developers.txt
+++ b/Misc/developers.txt
@@ -17,6 +17,9 @@
 Permissions History
 -------------------
 
+- Jesse Noller was given SVN access on 16 June 2008 by Georg Brandl,
+  for work on the multiprocessing module.
+
 - Gregor Lingl was given SVN access on 10 June 2008 by MvL,
   for work on the turtle module.
 
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index 53677c0..0a305ed 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -1815,6 +1815,8 @@
 		return NULL;
 	}
 	shape = PyTuple_New(dict->ndim);
+	if (shape == NULL)
+		return NULL;
 	for (i = 0; i < (int)dict->ndim; ++i)
 		PyTuple_SET_ITEM(shape, i, PyLong_FromSsize_t(dict->shape[i]));
 
diff --git a/Modules/_struct.c b/Modules/_struct.c
index e7cbd4b..6be4557 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -1383,6 +1383,12 @@
 		}
 	}
 
+	/* check for overflow */
+	if ((len + 1) > (PY_SSIZE_T_MAX / sizeof(formatcode))) {
+		PyErr_NoMemory();
+		return -1;
+	}
+
 	self->s_size = size;
 	self->s_len = len;
 	codes = PyMem_MALLOC((len + 1) * sizeof(formatcode));
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index da2e9c2..3e26369 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -421,6 +421,9 @@
 	if (op == NULL) {
 		return NULL;
 	}
+	op->ob_descr = descr;
+	op->allocated = size;
+	op->weakreflist = NULL;
 	Py_SIZE(op) = size;
 	if (size <= 0) {
 		op->ob_item = NULL;
@@ -428,13 +431,10 @@
 	else {
 		op->ob_item = PyMem_NEW(char, nbytes);
 		if (op->ob_item == NULL) {
-			PyObject_Del(op);
+			Py_DECREF(op);
 			return PyErr_NoMemory();
 		}
 	}
-	op->ob_descr = descr;
-	op->allocated = size;
-	op->weakreflist = NULL;
         op->ob_exports = 0;
 	return (PyObject *) op;
 }
@@ -808,11 +808,15 @@
 			     "can only extend with array of same kind");
 		return -1;
 	}
+	if ((Py_SIZE(self) > PY_SSIZE_T_MAX - Py_SIZE(b)) ||
+		((Py_SIZE(self) + Py_SIZE(b)) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) {
+		PyErr_NoMemory();
+		return -1;
+	}
 	size = Py_SIZE(self) + Py_SIZE(b);
         PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize);
         if (self->ob_item == NULL) {
-                PyObject_Del(self);
-                PyErr_NoMemory();
+		PyErr_NoMemory();
 		return -1;
         }
 	memcpy(self->ob_item + Py_SIZE(self)*self->ob_descr->itemsize,
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 819253c..7ff957e 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -683,13 +683,25 @@
 	
 }
 
+static PyObject *
+tuple_sizeof(PyTupleObject *self)
+{
+	Py_ssize_t res;
+
+	res = PyTuple_Type.tp_basicsize + Py_SIZE(self) * sizeof(PyObject *);
+	return PyLong_FromSsize_t(res);
+}
+
 PyDoc_STRVAR(index_doc,
 "T.index(value, [start, [stop]]) -> integer -- return first index of value");
 PyDoc_STRVAR(count_doc,
 "T.count(value) -> integer -- return number of occurrences of value");
+PyDoc_STRVAR(sizeof_doc,
+"T.__sizeof__() -- size of T in memory, in bytes");
 
 static PyMethodDef tuple_methods[] = {
 	{"__getnewargs__",	(PyCFunction)tuple_getnewargs,	METH_NOARGS},
+	{"__sizeof__",	(PyCFunction)tuple_sizeof, METH_NOARGS, sizeof_doc},
 	{"index",	(PyCFunction)tupleindex,  METH_VARARGS, index_doc},
 	{"count",	(PyCFunction)tuplecount,  METH_O, count_doc},
 	{NULL,		NULL}		/* sentinel */
diff --git a/Python/marshal.c b/Python/marshal.c
index d4755c9..e3619a6 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -70,7 +70,7 @@
 	size = PyBytes_Size(p->str);
 	newsize = size + size + 1024;
 	if (newsize > 32*1024*1024) {
-		newsize = size + 1024*1024;
+		newsize = size + (size >> 3);	/* 12.5% overallocation */
 	}
 	if (_PyBytes_Resize(&p->str, newsize) != 0) {
 		p->ptr = p->end = NULL;
diff --git a/Tools/msi/msilib.py b/Tools/msi/msilib.py
index 9245a22..6b8a2b5 100644
--- a/Tools/msi/msilib.py
+++ b/Tools/msi/msilib.py
@@ -284,7 +284,8 @@
 
 def init_database(name, schema,
                   ProductName, ProductCode, ProductVersion,
-                  Manufacturer):
+                  Manufacturer,
+                  request_uac = False):
     try:
         os.unlink(name)
     except OSError:
@@ -306,7 +307,11 @@
     si.SetProperty(PID_AUTHOR, Manufacturer)
     si.SetProperty(PID_TEMPLATE, msi_type)
     si.SetProperty(PID_REVNUMBER, gen_uuid())
-    si.SetProperty(PID_WORDCOUNT, 2) # long file names, compressed, original media
+    if request_uac:
+        wc = 2 # long file names, compressed, original media
+    else:
+        wc = 2 | 8 # +never invoke UAC
+    si.SetProperty(PID_WORDCOUNT, wc)
     si.SetProperty(PID_PAGECOUNT, 200)
     si.SetProperty(PID_APPNAME, "Python MSI Library")
     # XXX more properties