[Python-checkins] r76191 - in sandbox/trunk/newgil: Doc/library/collections.rst Doc/library/csv.rst Lib/importlib/_bootstrap.py Lib/importlib/test/source/test_file_loader.py Lib/subprocess.py Lib/test/lock_tests.py Lib/test/test_builtin.py Lib/test/test_signal.py Lib/test/test_threading.py Lib/threading.py Misc/ACKS Misc/NEWS Misc/Vim/vimrc Modules/_threadmodule.c Tools/scripts/db2pickle.py Tools/scripts/pickle2db.py Tools/scripts/redemo.py Tools/scripts/win_add2path.py

antoine.pitrou python-checkins at python.org
Tue Nov 10 20:16:31 CET 2009


Author: antoine.pitrou
Date: Tue Nov 10 20:16:31 2009
New Revision: 76191

Log:
Merged revisions 76146,76149,76155-76156,76158,76165,76170,76173,76177,76185,76188-76189 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/branches/py3k

................
  r76146 | brett.cannon | 2009-11-08 00:55:05 +0100 (dim., 08 nov. 2009) | 6 lines
  
  When trying to write new bytecode, importlib was not catching the IOError
  thrown if the file happened to be read-only to keep the failure silent.
  
  Fixes issue #7187. Thanks, Dave Malcolm for the report and analysis of the
  problem.
................
  r76149 | antoine.pitrou | 2009-11-08 01:30:04 +0100 (dim., 08 nov. 2009) | 11 lines
  
  Merged revisions 76148 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r76148 | antoine.pitrou | 2009-11-08 01:24:12 +0100 (dim., 08 nov. 2009) | 4 lines
    
    Kill a small potential leak in test_threading.
    The leak may not manifest itself if the OS re-uses the same thread ids
    (I suppose Neal's machine doesn't :-))
  ........
................
  r76155 | brett.cannon | 2009-11-08 22:41:27 +0100 (dim., 08 nov. 2009) | 10 lines
  
  Blocked revisions 76154 via svnmerge
  
  ........
    r76154 | brett.cannon | 2009-11-08 13:35:28 -0800 (Sun, 08 Nov 2009) | 4 lines
    
    Properly detect whether a C file is using tabs or spaces for Vim.
    
    Closes issue #5611. Thanks Kirk McDonald and Johannes Hoff.
  ........
................
  r76156 | benjamin.peterson | 2009-11-09 01:42:58 +0100 (lun., 09 nov. 2009) | 1 line
  
  fix some imports
................
  r76158 | benjamin.peterson | 2009-11-09 01:49:19 +0100 (lun., 09 nov. 2009) | 1 line
  
  convert to use print() function
................
  r76165 | r.david.murray | 2009-11-09 15:21:38 +0100 (lun., 09 nov. 2009) | 9 lines
  
  Merged revisions 76163 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r76163 | r.david.murray | 2009-11-09 09:18:14 -0500 (Mon, 09 Nov 2009) | 2 lines
    
    Remove redundant sentence.
  ........
................
  r76170 | eric.smith | 2009-11-09 16:23:15 +0100 (lun., 09 nov. 2009) | 9 lines
  
  Merged revisions 76168 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r76168 | eric.smith | 2009-11-09 10:16:23 -0500 (Mon, 09 Nov 2009) | 1 line
    
    Issue 7294: Fixed URL in a comment.
  ........
................
  r76173 | antoine.pitrou | 2009-11-09 17:08:16 +0100 (lun., 09 nov. 2009) | 11 lines
  
  Merged revisions 76172 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r76172 | antoine.pitrou | 2009-11-09 17:00:11 +0100 (lun., 09 nov. 2009) | 5 lines
    
    Issue #7282: Fix a memory leak when an RLock was used in a thread other
    than those started through `threading.Thread` (for example, using
    `thread.start_new_thread()`.
  ........
................
  r76177 | mark.dickinson | 2009-11-09 18:12:30 +0100 (lun., 09 nov. 2009) | 13 lines
  
  Merged revisions 76176 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r76176 | mark.dickinson | 2009-11-09 17:03:34 +0000 (Mon, 09 Nov 2009) | 7 lines
    
    Issue #7251: Break out round tests for large values into a separate
    test function, and skip that test on Linux/alpha systems with a broken
    system round function.
    
    This should turn the Debian/alpha buildbot green.
  ........
................
  r76185 | mark.dickinson | 2009-11-09 21:08:57 +0100 (lun., 09 nov. 2009) | 9 lines
  
  Merged revisions 76182 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r76182 | mark.dickinson | 2009-11-09 19:54:51 +0000 (Mon, 09 Nov 2009) | 1 line
    
    Add extra information to a test_signal failure message to aid diagnosis of buildbot failure.
  ........
................
  r76188 | raymond.hettinger | 2009-11-10 19:35:46 +0100 (mar., 10 nov. 2009) | 1 line
  
  Show example of how to make a sorted dictionary
................
  r76189 | antoine.pitrou | 2009-11-10 19:46:01 +0100 (mar., 10 nov. 2009) | 6 lines
  
  Issue #3001: Add a C implementation of recursive locks which is used by
  default when instantiating a `Threading.RLock` object. This makes 
  recursive locks as fast as regular non-recursive locks (previously,
  they were slower by 10x to 15x).
................


Modified:
   sandbox/trunk/newgil/   (props changed)
   sandbox/trunk/newgil/Doc/library/collections.rst
   sandbox/trunk/newgil/Doc/library/csv.rst
   sandbox/trunk/newgil/Lib/importlib/_bootstrap.py
   sandbox/trunk/newgil/Lib/importlib/test/source/test_file_loader.py
   sandbox/trunk/newgil/Lib/subprocess.py
   sandbox/trunk/newgil/Lib/test/lock_tests.py
   sandbox/trunk/newgil/Lib/test/test_builtin.py
   sandbox/trunk/newgil/Lib/test/test_signal.py
   sandbox/trunk/newgil/Lib/test/test_threading.py
   sandbox/trunk/newgil/Lib/threading.py
   sandbox/trunk/newgil/Misc/ACKS
   sandbox/trunk/newgil/Misc/NEWS
   sandbox/trunk/newgil/Misc/Vim/vimrc
   sandbox/trunk/newgil/Modules/_threadmodule.c
   sandbox/trunk/newgil/Tools/scripts/db2pickle.py
   sandbox/trunk/newgil/Tools/scripts/pickle2db.py
   sandbox/trunk/newgil/Tools/scripts/redemo.py
   sandbox/trunk/newgil/Tools/scripts/win_add2path.py

Modified: sandbox/trunk/newgil/Doc/library/collections.rst
==============================================================================
--- sandbox/trunk/newgil/Doc/library/collections.rst	(original)
+++ sandbox/trunk/newgil/Doc/library/collections.rst	Tue Nov 10 20:16:31 2009
@@ -862,6 +862,28 @@
    `Equivalent OrderedDict recipe <http://code.activestate.com/recipes/576693/>`_
    that runs on Python 2.4 or later.
 
+Since an ordered dictionary remembers its insertion order, it can be used
+in conjuction with sorting to make a sorted dictionary::
+
+    >>> # regular unsorted dictionary
+    >>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
+
+    >>> # dictionary sorted by key
+    >>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
+    OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
+
+    >>> # dictionary sorted by value
+    >>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
+    OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
+
+    >>> # dictionary sorted by length of the key string
+    >>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
+    OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
+
+The new sorted dictionaries maintain their sort order when entries
+are deleted.  But when new keys are added, the keys are appended
+to the end and the sort is not maintained.
+
 
 :class:`UserDict` objects
 -------------------------

Modified: sandbox/trunk/newgil/Doc/library/csv.rst
==============================================================================
--- sandbox/trunk/newgil/Doc/library/csv.rst	(original)
+++ sandbox/trunk/newgil/Doc/library/csv.rst	Tue Nov 10 20:16:31 2009
@@ -141,13 +141,12 @@
    Create an object which operates like a regular reader but maps the information
    read into a dict whose keys are given by the optional  *fieldnames* parameter.
    If the *fieldnames* parameter is omitted, the values in the first row of the
-   *csvfile* will be used as the fieldnames. If the row read has fewer fields than
-   the fieldnames sequence, the value of *restval* will be used as the default
-   value.  If the row read has more fields than the fieldnames sequence, the
-   remaining data is added as a sequence keyed by the value of *restkey*.  If the
-   row read has fewer fields than the fieldnames sequence, the remaining keys take
-   the value of the optional *restval* parameter.  Any other optional or keyword
-   arguments are passed to the underlying :class:`reader` instance.
+   *csvfile* will be used as the fieldnames.  If the row read has more fields
+   than the fieldnames sequence, the remaining data is added as a sequence
+   keyed by the value of *restkey*.  If the row read has fewer fields than the
+   fieldnames sequence, the remaining keys take the value of the optional
+   *restval* parameter.  Any other optional or keyword arguments are passed to
+   the underlying :class:`reader` instance.
 
 
 .. class:: DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)

Modified: sandbox/trunk/newgil/Lib/importlib/_bootstrap.py
==============================================================================
--- sandbox/trunk/newgil/Lib/importlib/_bootstrap.py	(original)
+++ sandbox/trunk/newgil/Lib/importlib/_bootstrap.py	Tue Nov 10 20:16:31 2009
@@ -526,9 +526,9 @@
         bytecode_path = self.bytecode_path(name)
         if not bytecode_path:
             bytecode_path = self._base_path + _suffix_list(imp.PY_COMPILED)[0]
-        file = _io.FileIO(bytecode_path, 'w')  # Assuming bytes.
         try:
-            with _closing(file) as bytecode_file:
+            # Assuming bytes.
+            with _closing(_io.FileIO(bytecode_path, 'w')) as bytecode_file:
                 bytecode_file.write(data)
                 return True
         except IOError as exc:

Modified: sandbox/trunk/newgil/Lib/importlib/test/source/test_file_loader.py
==============================================================================
--- sandbox/trunk/newgil/Lib/importlib/test/source/test_file_loader.py	(original)
+++ sandbox/trunk/newgil/Lib/importlib/test/source/test_file_loader.py	Tue Nov 10 20:16:31 2009
@@ -6,6 +6,7 @@
 import imp
 import os
 import py_compile
+import stat
 import sys
 import unittest
 
@@ -121,6 +122,10 @@
     But if the marshal data is bad, even if the magic number and timestamp
     work, a ValueError is raised and the source is not used [bad marshal].
 
+    The case of not being able to write out the bytecode must also be handled
+    as it's possible it was made read-only. In that instance the attempt to
+    write the bytecode should fail silently [bytecode read-only].
+
     """
 
     def import_(self, file, module_name):
@@ -159,6 +164,7 @@
                 self.assertEqual(bytecode_file.read(4), source_timestamp)
 
     # [bad marshal]
+    @source_util.writes_bytecode_files
     def test_bad_marshal(self):
         with source_util.create_modules('_temp') as mapping:
             bytecode_path = source_util.bytecode_path(mapping['_temp'])
@@ -172,6 +178,26 @@
                 self.import_(mapping['_temp'], '_temp')
             self.assertTrue('_temp' not in sys.modules)
 
+    # [bytecode read-only]
+    @source_util.writes_bytecode_files
+    def test_read_only_bytecode(self):
+        with source_util.create_modules('_temp') as mapping:
+            # Create bytecode that will need to be re-created.
+            py_compile.compile(mapping['_temp'])
+            bytecode_path = source_util.bytecode_path(mapping['_temp'])
+            with open(bytecode_path, 'r+b') as bytecode_file:
+                bytecode_file.seek(0)
+                bytecode_file.write(b'\x00\x00\x00\x00')
+            # Make the bytecode read-only.
+            os.chmod(bytecode_path,
+                        stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
+            try:
+                # Should not raise IOError!
+                self.import_(mapping['_temp'], '_temp')
+            finally:
+                # Make writable for eventual clean-up.
+                os.chmod(bytecode_path, stat.S_IWUSR)
+
 
 def test_main():
     from test.support import run_unittest

Modified: sandbox/trunk/newgil/Lib/subprocess.py
==============================================================================
--- sandbox/trunk/newgil/Lib/subprocess.py	(original)
+++ sandbox/trunk/newgil/Lib/subprocess.py	Tue Nov 10 20:16:31 2009
@@ -497,7 +497,9 @@
     """
 
     # See
-    # http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp
+    # http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
+    # or search http://msdn.microsoft.com for
+    # "Parsing C++ Command-Line Arguments"
     result = []
     needquote = False
     for arg in seq:

Modified: sandbox/trunk/newgil/Lib/test/lock_tests.py
==============================================================================
--- sandbox/trunk/newgil/Lib/test/lock_tests.py	(original)
+++ sandbox/trunk/newgil/Lib/test/lock_tests.py	Tue Nov 10 20:16:31 2009
@@ -130,6 +130,19 @@
         # Check the lock is unacquired
         Bunch(f, 1).wait_for_finished()
 
+    def test_thread_leak(self):
+        # The lock shouldn't leak a Thread instance when used from a foreign
+        # (non-threading) thread.
+        lock = self.locktype()
+        def f():
+            lock.acquire()
+            lock.release()
+        n = len(threading.enumerate())
+        # We run many threads in the hope that existing threads ids won't
+        # be recycled.
+        Bunch(f, 15).wait_for_finished()
+        self.assertEqual(n, len(threading.enumerate()))
+
 
 class LockTests(BaseLockTests):
     """

Modified: sandbox/trunk/newgil/Lib/test/test_builtin.py
==============================================================================
--- sandbox/trunk/newgil/Lib/test/test_builtin.py	(original)
+++ sandbox/trunk/newgil/Lib/test/test_builtin.py	Tue Nov 10 20:16:31 2009
@@ -1,5 +1,6 @@
 # Python test set -- built-in functions
 
+import platform
 import test.support, unittest
 from test.support import fcmp, TESTFN, unlink,  run_unittest, \
                               run_with_locale
@@ -1123,6 +1124,27 @@
         self.assertRaises(TypeError, round, t)
         self.assertRaises(TypeError, round, t, 0)
 
+    # Some versions of glibc for alpha have a bug that affects
+    # float -> integer rounding (floor, ceil, rint, round) for
+    # values in the range [2**52, 2**53).  See:
+    #
+    #   http://sources.redhat.com/bugzilla/show_bug.cgi?id=5350
+    #
+    # We skip this test on Linux/alpha if it would fail.
+    linux_alpha = (platform.system().startswith('Linux') and
+                   platform.machine().startswith('alpha'))
+    system_round_bug = round(5e15+1) != 5e15+1
+    @unittest.skipIf(linux_alpha and system_round_bug,
+                     "test will fail;  failure is probably due to a "
+                     "buggy system round function")
+    def test_round_large(self):
+        # Issue #1869: integral floats should remain unchanged
+        self.assertEqual(round(5e15-1), 5e15-1)
+        self.assertEqual(round(5e15), 5e15)
+        self.assertEqual(round(5e15+1), 5e15+1)
+        self.assertEqual(round(5e15+2), 5e15+2)
+        self.assertEqual(round(5e15+3), 5e15+3)
+
     def test_setattr(self):
         setattr(sys, 'spam', 1)
         self.assertEqual(sys.spam, 1)

Modified: sandbox/trunk/newgil/Lib/test/test_signal.py
==============================================================================
--- sandbox/trunk/newgil/Lib/test/test_signal.py	(original)
+++ sandbox/trunk/newgil/Lib/test/test_signal.py	Tue Nov 10 20:16:31 2009
@@ -367,7 +367,9 @@
             if signal.getitimer(self.itimer) == (0.0, 0.0):
                 break # sig_vtalrm handler stopped this itimer
         else:
-            self.fail('timeout waiting for sig_vtalrm signal')
+            self.fail('timeout waiting for sig_vtalrm signal; '
+                      'signal.getitimer(self.itimer) gives: %s' %
+                       (signal.getitimer(self.itimer),))
 
         # virtual itimer should be (0.0, 0.0) now
         self.assertEquals(signal.getitimer(self.itimer), (0.0, 0.0))

Modified: sandbox/trunk/newgil/Lib/test/test_threading.py
==============================================================================
--- sandbox/trunk/newgil/Lib/test/test_threading.py	(original)
+++ sandbox/trunk/newgil/Lib/test/test_threading.py	Tue Nov 10 20:16:31 2009
@@ -113,6 +113,8 @@
         _thread.start_new_thread(f, ())
         done.wait()
         self.assertFalse(ident[0] is None)
+        # Kill the "immortal" _DummyThread
+        del threading._active[ident[0]]
 
     # run with a small(ish) thread stack size (256kB)
     def test_various_ops_small_stack(self):
@@ -141,11 +143,9 @@
     def test_foreign_thread(self):
         # Check that a "foreign" thread can use the threading module.
         def f(mutex):
-            # Acquiring an RLock forces an entry for the foreign
+            # Calling current_thread() forces an entry for the foreign
             # thread to get made in the threading._active map.
-            r = threading.RLock()
-            r.acquire()
-            r.release()
+            threading.current_thread()
             mutex.release()
 
         mutex = threading.Lock()
@@ -506,8 +506,11 @@
 class LockTests(lock_tests.LockTests):
     locktype = staticmethod(threading.Lock)
 
-class RLockTests(lock_tests.RLockTests):
-    locktype = staticmethod(threading.RLock)
+class PyRLockTests(lock_tests.RLockTests):
+    locktype = staticmethod(threading._PyRLock)
+
+class CRLockTests(lock_tests.RLockTests):
+    locktype = staticmethod(threading._CRLock)
 
 class EventTests(lock_tests.EventTests):
     eventtype = staticmethod(threading.Event)
@@ -527,7 +530,7 @@
 
 
 def test_main():
-    test.support.run_unittest(LockTests, RLockTests, EventTests,
+    test.support.run_unittest(LockTests, PyRLockTests, CRLockTests, EventTests,
                               ConditionAsRLockTests, ConditionTests,
                               SemaphoreTests, BoundedSemaphoreTests,
                               ThreadTests,

Modified: sandbox/trunk/newgil/Lib/threading.py
==============================================================================
--- sandbox/trunk/newgil/Lib/threading.py	(original)
+++ sandbox/trunk/newgil/Lib/threading.py	Tue Nov 10 20:16:31 2009
@@ -27,6 +27,10 @@
 _allocate_lock = _thread.allocate_lock
 _get_ident = _thread.get_ident
 ThreadError = _thread.error
+try:
+    _CRLock = _thread.RLock
+except AttributeError:
+    _CRLock = None
 del _thread
 
 
@@ -79,8 +83,12 @@
 
 Lock = _allocate_lock
 
-def RLock(*args, **kwargs):
-    return _RLock(*args, **kwargs)
+def RLock(verbose=None, *args, **kwargs):
+    if verbose is None:
+        verbose = _VERBOSE
+    if (__debug__ and verbose) or _CRLock is None:
+        return _PyRLock(verbose, *args, **kwargs)
+    return _CRLock(*args, **kwargs)
 
 class _RLock(_Verbose):
 
@@ -92,14 +100,16 @@
 
     def __repr__(self):
         owner = self._owner
-        return "<%s(%s, %d)>" % (
-                self.__class__.__name__,
-                owner and owner.name,
-                self._count)
+        try:
+            owner = _active[owner].name
+        except KeyError:
+            pass
+        return "<%s owner=%r count=%d>" % (
+                self.__class__.__name__, owner, self._count)
 
     def acquire(self, blocking=True):
-        me = current_thread()
-        if self._owner is me:
+        me = _get_ident()
+        if self._owner == me:
             self._count = self._count + 1
             if __debug__:
                 self._note("%s.acquire(%s): recursive success", self, blocking)
@@ -118,7 +128,7 @@
     __enter__ = acquire
 
     def release(self):
-        if self._owner is not current_thread():
+        if self._owner != _get_ident():
             raise RuntimeError("cannot release un-acquired lock")
         self._count = count = self._count - 1
         if not count:
@@ -152,7 +162,9 @@
         return (count, owner)
 
     def _is_owned(self):
-        return self._owner is current_thread()
+        return self._owner == _get_ident()
+
+_PyRLock = _RLock
 
 
 def Condition(*args, **kwargs):

Modified: sandbox/trunk/newgil/Misc/ACKS
==============================================================================
--- sandbox/trunk/newgil/Misc/ACKS	(original)
+++ sandbox/trunk/newgil/Misc/ACKS	Tue Nov 10 20:16:31 2009
@@ -472,6 +472,7 @@
 Don MacMillen
 Steve Majewski
 Grzegorz Makarewicz
+Dave Malcolm
 Ken Manheimer
 Vladimir Marangozov
 David Marek

Modified: sandbox/trunk/newgil/Misc/NEWS
==============================================================================
--- sandbox/trunk/newgil/Misc/NEWS	(original)
+++ sandbox/trunk/newgil/Misc/NEWS	Tue Nov 10 20:16:31 2009
@@ -123,6 +123,18 @@
 Library
 -------
 
+- Issue #3001: Add a C implementation of recursive locks which is used by
+  default when instantiating a `threading.RLock` object. This makes 
+  recursive locks as fast as regular non-recursive locks (previously,
+  they were slower by 10x to 15x).
+
+- Issue #7282: Fix a memory leak when an RLock was used in a thread other
+  than those started through `threading.Thread` (for example, using
+  `_thread.start_new_thread()`).
+
+- Issue #7187: Importlib would not silence the IOError raised when trying to
+  write new bytecode when it was made read-only.
+
 - Issue #7264: Fix a possible deadlock when deallocating thread-local objects
   which are part of a reference cycle.
 

Modified: sandbox/trunk/newgil/Misc/Vim/vimrc
==============================================================================
--- sandbox/trunk/newgil/Misc/Vim/vimrc	(original)
+++ sandbox/trunk/newgil/Misc/Vim/vimrc	Tue Nov 10 20:16:31 2009
@@ -15,35 +15,32 @@
 " Only basic settings needed to enforce the style guidelines are set.
 " Some suggested options are listed but commented out at the end of this file.
 
-
-" Number of spaces to use for an indent.
-" This will affect Ctrl-T and 'autoindent'.
-" Python: 4 spaces
-" C: 4 spaces
-au BufRead,BufNewFile *.py,*pyw set shiftwidth=4
-au BufRead *.c,*.h set shiftwidth=8
-au BufNewFile *.c,*.h set shiftwidth=4
-
 " Number of spaces that a pre-existing tab is equal to.
 " For the amount of space used for a new tab use shiftwidth.
-" Python: 8
-" C: 8
 au BufRead,BufNewFile *py,*pyw,*.c,*.h set tabstop=8
 
-" Replace tabs with the equivalent number of spaces.
-" Also have an autocmd for Makefiles since they require hard tabs.
-" Python: yes
-" C: yes
-" Makefile: no
-au BufRead,BufNewFile *.py,*.pyw,*.c,*.h set expandtab
+" What to use for an indent.
+" This will affect Ctrl-T and 'autoindent'.
+" Python: 4 spaces
+" C: tabs (pre-existing files) or 4 spaces (new files)
+au BufRead,BufNewFile *.py,*pyw set shiftwidth=4
+au BufRead,BufNewFile *.py,*.pyw set expandtab
+fu Select_c_style()
+    if search('^\t', 'n', 150)
+        set shiftwidth=8
+        set noexpandtab
+    el 
+        set shiftwidth=4
+        set expandtab
+    en
+endf
+au BufRead,BufNewFile *.c,*.h call Select_c_style()
 au BufRead,BufNewFile Makefile* set noexpandtab
 
-" Use the below highlight group when displaying bad whitespace is desired
+" Use the below highlight group when displaying bad whitespace is desired.
 highlight BadWhitespace ctermbg=red guibg=red
 
 " Display tabs at the beginning of a line in Python mode as bad.
-" Should be done for C code, but not until all code has been moved to 4-space
-"   indents.
 au BufRead,BufNewFile *.py,*.pyw match BadWhitespace /^\t\+/
 " Make trailing whitespace be flagged as bad.
 au BufRead,BufNewFile *.py,*.pyw,*.c,*.h match BadWhitespace /\s\+$/

Modified: sandbox/trunk/newgil/Modules/_threadmodule.c
==============================================================================
--- sandbox/trunk/newgil/Modules/_threadmodule.c	(original)
+++ sandbox/trunk/newgil/Modules/_threadmodule.c	Tue Nov 10 20:16:31 2009
@@ -155,6 +155,273 @@
 	lock_methods,			/*tp_methods*/
 };
 
+/* Recursive lock objects */
+
+typedef struct {
+	PyObject_HEAD
+	PyThread_type_lock rlock_lock;
+	long rlock_owner;
+	unsigned long rlock_count;
+	PyObject *in_weakreflist;
+} rlockobject;
+
+static void
+rlock_dealloc(rlockobject *self)
+{
+	assert(self->rlock_lock);
+	if (self->in_weakreflist != NULL)
+		PyObject_ClearWeakRefs((PyObject *) self);
+	/* Unlock the lock so it's safe to free it */
+	if (self->rlock_count > 0)
+		PyThread_release_lock(self->rlock_lock);
+	
+	PyThread_free_lock(self->rlock_lock);
+	Py_TYPE(self)->tp_free(self);
+}
+
+static PyObject *
+rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
+{
+	char *kwlist[] = {"blocking", NULL};
+	int blocking = 1;
+	long tid;
+	int r = 1;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:acquire", kwlist,
+				         &blocking))
+		return NULL;
+
+	tid = PyThread_get_thread_ident();
+	if (self->rlock_count > 0 && tid == self->rlock_owner) {
+		unsigned long count = self->rlock_count + 1;
+		if (count <= self->rlock_count) {
+			PyErr_SetString(PyExc_OverflowError,
+					"Internal lock count overflowed");
+			return NULL;
+		}
+		self->rlock_count = count;
+		Py_RETURN_TRUE;
+	}
+
+	if (self->rlock_count > 0 ||
+	    !PyThread_acquire_lock(self->rlock_lock, 0)) {
+		if (!blocking) {
+			Py_RETURN_FALSE;
+		}
+		Py_BEGIN_ALLOW_THREADS
+		r = PyThread_acquire_lock(self->rlock_lock, blocking);
+		Py_END_ALLOW_THREADS
+	}
+	if (r) {
+		assert(self->rlock_count == 0);
+		self->rlock_owner = tid;
+		self->rlock_count = 1;
+	}
+
+	return PyBool_FromLong(r);
+}
+
+PyDoc_STRVAR(rlock_acquire_doc,
+"acquire(blocking=True) -> bool\n\
+\n\
+Lock the lock.  `blocking` indicates whether we should wait\n\
+for the lock to be available or not.  If `blocking` is False\n\
+and another thread holds the lock, the method will return False\n\
+immediately.  If `blocking` is True and another thread holds\n\
+the lock, the method will wait for the lock to be released,\n\
+take it and then return True.\n\
+(note: the blocking operation is not interruptible.)\n\
+\n\
+In all other cases, the method will return True immediately.\n\
+Precisely, if the current thread already holds the lock, its\n\
+internal counter is simply incremented. If nobody holds the lock,\n\
+the lock is taken and its internal counter initialized to 1.");
+
+static PyObject *
+rlock_release(rlockobject *self)
+{
+	long tid = PyThread_get_thread_ident();
+
+	if (self->rlock_count == 0 || self->rlock_owner != tid) {
+		PyErr_SetString(PyExc_RuntimeError,
+				"cannot release un-acquired lock");
+		return NULL;
+	}
+	if (--self->rlock_count == 0) {
+		self->rlock_owner = 0;
+		PyThread_release_lock(self->rlock_lock);
+	}
+	Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(rlock_release_doc,
+"release()\n\
+\n\
+Release the lock, allowing another thread that is blocked waiting for\n\
+the lock to acquire the lock.  The lock must be in the locked state,\n\
+and must be locked by the same thread that unlocks it; otherwise a\n\
+`RuntimeError` is raised.\n\
+\n\
+Do note that if the lock was acquire()d several times in a row by the\n\
+current thread, release() needs to be called as many times for the lock\n\
+to be available for other threads.");
+
+static PyObject *
+rlock_acquire_restore(rlockobject *self, PyObject *arg)
+{
+	long owner;
+	unsigned long count;
+	int r = 1;
+
+	if (!PyArg_ParseTuple(arg, "kl:_acquire_restore", &count, &owner))
+		return NULL;
+
+	if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
+		Py_BEGIN_ALLOW_THREADS
+		r = PyThread_acquire_lock(self->rlock_lock, 1);
+		Py_END_ALLOW_THREADS
+	}
+	if (!r) {
+		PyErr_SetString(ThreadError, "couldn't acquire lock");
+		return NULL;
+	}
+	assert(self->rlock_count == 0);
+	self->rlock_owner = owner;
+	self->rlock_count = count;
+	Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(rlock_acquire_restore_doc,
+"_acquire_restore(state) -> None\n\
+\n\
+For internal use by `threading.Condition`.");
+
+static PyObject *
+rlock_release_save(rlockobject *self)
+{
+	long owner;
+	unsigned long count;
+
+	owner = self->rlock_owner;
+	count = self->rlock_count;
+	self->rlock_count = 0;
+	self->rlock_owner = 0;
+	PyThread_release_lock(self->rlock_lock);
+	return Py_BuildValue("kl", count, owner);
+}
+
+PyDoc_STRVAR(rlock_release_save_doc,
+"_release_save() -> tuple\n\
+\n\
+For internal use by `threading.Condition`.");
+
+
+static PyObject *
+rlock_is_owned(rlockobject *self)
+{
+	long tid = PyThread_get_thread_ident();
+	
+	if (self->rlock_count > 0 && self->rlock_owner == tid) {
+		Py_RETURN_TRUE;
+	}
+	Py_RETURN_FALSE;
+}
+
+PyDoc_STRVAR(rlock_is_owned_doc,
+"_is_owned() -> bool\n\
+\n\
+For internal use by `threading.Condition`.");
+
+static PyObject *
+rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	rlockobject *self;
+
+	self = (rlockobject *) type->tp_alloc(type, 0);
+	if (self != NULL) {
+		self->rlock_lock = PyThread_allocate_lock();
+		if (self->rlock_lock == NULL) {
+			type->tp_free(self);
+			PyErr_SetString(ThreadError, "can't allocate lock");
+			return NULL;
+		}
+		self->in_weakreflist = NULL;
+		self->rlock_owner = 0;
+		self->rlock_count = 0;
+	}
+
+	return (PyObject *) self;
+}
+
+static PyObject *
+rlock_repr(rlockobject *self)
+{
+	return PyUnicode_FromFormat("<%s owner=%ld count=%lu>",
+		Py_TYPE(self)->tp_name, self->rlock_owner, self->rlock_count);
+}
+
+
+static PyMethodDef rlock_methods[] = {
+	{"acquire",      (PyCFunction)rlock_acquire, 
+	 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
+	{"release",      (PyCFunction)rlock_release, 
+	 METH_NOARGS, rlock_release_doc},
+	{"_is_owned",     (PyCFunction)rlock_is_owned,  
+	 METH_NOARGS, rlock_is_owned_doc},
+	{"_acquire_restore", (PyCFunction)rlock_acquire_restore,
+	 METH_O, rlock_acquire_restore_doc},
+	{"_release_save", (PyCFunction)rlock_release_save,
+	 METH_NOARGS, rlock_release_save_doc},
+	{"__enter__",    (PyCFunction)rlock_acquire,
+	 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
+	{"__exit__",    (PyCFunction)rlock_release,
+	 METH_VARARGS, rlock_release_doc},
+	{NULL,           NULL}		/* sentinel */
+};
+
+
+static PyTypeObject RLocktype = {
+	PyVarObject_HEAD_INIT(&PyType_Type, 0)
+	"_thread.RLock",		/*tp_name*/
+	sizeof(rlockobject),		/*tp_size*/
+	0,				/*tp_itemsize*/
+	/* methods */
+	(destructor)rlock_dealloc,	/*tp_dealloc*/
+	0,				/*tp_print*/
+	0,				/*tp_getattr*/
+	0,				/*tp_setattr*/
+	0,				/*tp_reserved*/
+	(reprfunc)rlock_repr,		/*tp_repr*/
+	0,				/*tp_as_number*/
+	0,				/*tp_as_sequence*/
+	0,				/*tp_as_mapping*/
+	0,				/*tp_hash*/
+	0,				/*tp_call*/
+	0,				/*tp_str*/
+	0,				/*tp_getattro*/
+	0,				/*tp_setattro*/
+	0,				/*tp_as_buffer*/
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+	0,				/*tp_doc*/
+	0,				/*tp_traverse*/
+	0,				/*tp_clear*/
+	0,				/*tp_richcompare*/
+	offsetof(rlockobject, in_weakreflist), /*tp_weaklistoffset*/
+	0,				/*tp_iter*/
+	0,				/*tp_iternext*/
+	rlock_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 */
+	rlock_new			/* tp_new */
+};
+
 static lockobject *
 newlockobject(void)
 {
@@ -752,6 +1019,8 @@
 		return NULL;
 	if (PyType_Ready(&Locktype) < 0)
 		return NULL;
+	if (PyType_Ready(&RLocktype) < 0)
+		return NULL;
 
 	/* Create the module and add the functions */
 	m = PyModule_Create(&threadmodule);
@@ -766,6 +1035,10 @@
 	Py_INCREF(&Locktype);
 	PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
 
+	Py_INCREF(&RLocktype);
+	if (PyModule_AddObject(m, "RLock", (PyObject *)&RLocktype) < 0)
+		return NULL;
+
 	Py_INCREF(&localtype);
 	if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
 		return NULL;

Modified: sandbox/trunk/newgil/Tools/scripts/db2pickle.py
==============================================================================
--- sandbox/trunk/newgil/Tools/scripts/db2pickle.py	(original)
+++ sandbox/trunk/newgil/Tools/scripts/db2pickle.py	Tue Nov 10 20:16:31 2009
@@ -33,12 +33,12 @@
 except ImportError:
     gdbm = None
 try:
-    import dbm as anydbm
+    import dbm.ndbm as anydbm
 except ImportError:
     anydbm = None
 import sys
 try:
-    import cPickle as pickle
+    import pickle as pickle
 except ImportError:
     import pickle
 

Modified: sandbox/trunk/newgil/Tools/scripts/pickle2db.py
==============================================================================
--- sandbox/trunk/newgil/Tools/scripts/pickle2db.py	(original)
+++ sandbox/trunk/newgil/Tools/scripts/pickle2db.py	Tue Nov 10 20:16:31 2009
@@ -38,12 +38,12 @@
 except ImportError:
     gdbm = None
 try:
-    import dbm as anydbm
+    import dbm.ndbm as anydbm
 except ImportError:
     anydbm = None
 import sys
 try:
-    import cPickle as pickle
+    import pickle as pickle
 except ImportError:
     import pickle
 

Modified: sandbox/trunk/newgil/Tools/scripts/redemo.py
==============================================================================
--- sandbox/trunk/newgil/Tools/scripts/redemo.py	(original)
+++ sandbox/trunk/newgil/Tools/scripts/redemo.py	Tue Nov 10 20:16:31 2009
@@ -1,6 +1,6 @@
 """Basic regular expression demostration facility (Perl style syntax)."""
 
-from Tkinter import *
+from tkinter import *
 import re
 
 class ReDemo:

Modified: sandbox/trunk/newgil/Tools/scripts/win_add2path.py
==============================================================================
--- sandbox/trunk/newgil/Tools/scripts/win_add2path.py	(original)
+++ sandbox/trunk/newgil/Tools/scripts/win_add2path.py	Tue Nov 10 20:16:31 2009
@@ -45,13 +45,13 @@
 def main():
     paths, envpath = modify()
     if len(paths) > 1:
-        print "Path(s) added:"
-        print '\n'.join(paths[1:])
+        print("Path(s) added:")
+        print('\n'.join(paths[1:]))
     else:
-        print "No path was added"
-    print "\nPATH is now:\n%s\n" % envpath
-    print "Expanded:"
-    print winreg.ExpandEnvironmentStrings(envpath)
+        print("No path was added")
+    print("\nPATH is now:\n%s\n" % envpath)
+    print("Expanded:")
+    print(winreg.ExpandEnvironmentStrings(envpath))
 
 if __name__ == '__main__':
     main()


More information about the Python-checkins mailing list