[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