Commit 8f374fd1 authored by Éric Araujo's avatar Éric Araujo

Branch merge

parents 4f25d149 5172db37
......@@ -347,6 +347,8 @@ is a separate error indicator for each thread.
error checking. *fd* should be a valid file descriptor. The function should
only be called from the main thread.
.. versionadded:: 2.6
.. cfunction:: PyObject* PyErr_NewException(char *name, PyObject *base, PyObject *dict)
......
......@@ -474,7 +474,7 @@ the fork, and releasing them afterwards. In addition, it resets any
:ref:`lock-objects` in the child. When extending or embedding Python, there
is no way to inform Python of additional (non-Python) locks that need to be
acquired before or reset after a fork. OS facilities such as
:cfunc:`posix_atfork` would need to be used to accomplish the same thing.
:cfunc:`pthread_atfork` would need to be used to accomplish the same thing.
Additionally, when extending or embedding Python, calling :cfunc:`fork`
directly rather than through :func:`os.fork` (and returning to or calling
into Python) may result in a deadlock by one of Python's internal locks
......@@ -906,7 +906,7 @@ a worker thread and the actual call than made at the earliest convenience by the
main thread where it has possession of the global interpreter lock and can
perform any Python API calls.
.. cfunction:: void Py_AddPendingCall( int (*func)(void *, void *arg) )
.. cfunction:: int Py_AddPendingCall(int (*func)(void *), void *arg)
.. index:: single: Py_AddPendingCall()
......
......@@ -108,6 +108,9 @@ Object Protocol
Python expression ``o1 op o2``, where ``op`` is the operator corresponding to
*opid*.
.. note::
If *o1* and *o2* are the same object, :cfunc:`PyObject_RichCompareBool`
will always return ``1`` for :const:`Py_EQ` and ``0`` for :const:`Py_NE`.
.. cfunction:: int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
......
......@@ -152,7 +152,7 @@ The directives are:
Describes global data in a module, including both variables and values used
as "defined constants." Class and object attributes are not documented
using this environment.
using this directive.
.. describe:: exception
......@@ -165,7 +165,7 @@ The directives are:
parameters, enclosing optional parameters in brackets. Default values can be
given if it enhances clarity. For example::
.. function:: Timer.repeat([repeat=3[, number=1000000]])
.. function:: repeat([repeat=3[, number=1000000]])
Object methods are not documented using this directive. Bound object methods
placed in the module namespace as part of the public interface of the module
......@@ -186,13 +186,30 @@ The directives are:
Describes an object data attribute. The description should include
information about the type of the data to be expected and whether it may be
changed directly.
changed directly. This directive should be nested in a class directive,
like in this example::
.. class:: Spam
Description of the class.
.. data:: ham
Description of the attribute.
If is also possible to document an attribute outside of a class directive,
for example if the documentation for different attributes and methods is
split in multiple sections. The class name should then be included
explicitly::
.. data:: Spam.eggs
.. describe:: method
Describes an object method. The parameters should not include the ``self``
parameter. The description should include similar information to that
described for ``function``.
described for ``function``. This method should be nested in a class
method, like in the example above.
.. describe:: opcode
......
......@@ -308,7 +308,7 @@ http://www.pythonology.com/success
buying, but the publishers have made the first chapter available on
the Web.
http://home.pacbell.net/ouster/scripting.html
http://www.tcl.tk/doc/scripting.html
John Ousterhout's white paper on scripting is a good argument for the utility of
scripting languages, though naturally enough, he emphasizes Tcl, the language he
developed. Most of the arguments would apply to any scripting language.
......
This diff is collapsed.
......@@ -818,6 +818,9 @@ semantics pass-in keyword arguments using a regular unordered dictionary.
`Equivalent OrderedDict recipe <http://code.activestate.com/recipes/576693/>`_
that runs on Python 2.4 or later.
:class:`OrderedDict` Examples and Recipes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Since an ordered dictionary remembers its insertion order, it can be used
in conjuction with sorting to make a sorted dictionary::
......@@ -846,12 +849,29 @@ If a new entry overwrites an existing entry, the
original insertion position is changed and moved to the end::
class LastUpdatedOrderedDict(OrderedDict):
'Store items in the order the keys were last added'
def __setitem__(self, key, value):
if key in self:
del self[key]
OrderedDict.__setitem__(self, key, value)
An ordered dictionary can combined with the :class:`Counter` class
so that the counter remembers the order elements are first encountered::
class OrderedCounter(Counter, OrderedDict):
'Counter that remembers the order elements are first encountered'
def __init__(self, iterable=None, **kwds):
OrderedDict.__init__(self)
Counter.__init__(self, iterable, **kwds)
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
def __reduce__(self):
return self.__class__, (OrderedDict(self),)
.. _abstract-base-classes:
......
......@@ -96,6 +96,9 @@ write-back, as will be the keys within each section.
This class does not
support the magical interpolation behavior.
All option names are passed through the :meth:`optionxform` method. Its
default implementation converts option names to lower case.
.. versionadded:: 2.3
.. versionchanged:: 2.6
......@@ -116,10 +119,9 @@ write-back, as will be the keys within each section.
*defaults*.
All option names used in interpolation will be passed through the
:meth:`optionxform` method just like any other option name reference. For
example, using the default implementation of :meth:`optionxform` (which converts
option names to lower case), the values ``foo %(bar)s`` and ``foo %(BAR)s`` are
equivalent.
:meth:`optionxform` method just like any other option name reference. Using
the default implementation of :meth:`optionxform`, the values ``foo %(bar)s``
and ``foo %(BAR)s`` are equivalent.
.. versionadded:: 2.3
......
......@@ -74,15 +74,29 @@ in :mod:`logging` itself) and defining handlers which are declared either in
.. versionadded:: 2.7
.. function:: fileConfig(fname[, defaults])
.. function:: fileConfig(fname, defaults=None, disable_existing_loggers=True)
Reads the logging configuration from a :mod:`configparser`\-format file named
*fname*. This function can be called several times from an application,
allowing an end user to select from various pre-canned
Reads the logging configuration from a :mod:`configparser`\-format file
named *fname*. This function can be called several times from an
application, allowing an end user to select from various pre-canned
configurations (if the developer provides a mechanism to present the choices
and load the chosen configuration). Defaults to be passed to the ConfigParser
can be specified in the *defaults* argument.
and load the chosen configuration).
:param defaults: Defaults to be passed to the ConfigParser can be specified
in this argument.
:param disable_existing_loggers: If specified as ``False``, loggers which
exist when this call is made are left
alone. The default is ``True`` because this
enables old behaviour in a backward-
compatible way. This behaviour is to
disable any existing loggers unless they or
their ancestors are explicitly named in the
logging configuration.
.. versionchanged:: 2.6
The ``disable_existing_loggers`` keyword argument was added. Previously,
existing loggers were *always* disabled.
.. function:: listen(port=DEFAULT_LOGGING_CONFIG_PORT)
......
......@@ -28,7 +28,7 @@ Windows.
.. note::
Functionality within this package requires that the ``__main__`` method be
Functionality within this package requires that the ``__main__`` module be
importable by the children. This is covered in :ref:`multiprocessing-programming`
however it is worth pointing out here. This means that some examples, such
as the :class:`multiprocessing.Pool` examples will not work in the
......
......@@ -204,6 +204,8 @@ The :mod:`signal` module defines the following functions:
attempting to call it from other threads will cause a :exc:`ValueError`
exception to be raised.
.. versionadded:: 2.6
.. function:: siginterrupt(signalnum, flag)
......
......@@ -178,9 +178,10 @@ This module defines one class called :class:`Popen`:
:attr:`stdout`, :attr:`stdin` and :attr:`stderr` are not updated by the
communicate() method.
The *startupinfo* and *creationflags*, if given, will be passed to the
underlying CreateProcess() function. They can specify things such as appearance
of the main window and priority for the new process. (Windows only)
If given, *startupinfo* will be a :class:`STARTUPINFO` object, which is
passed to the underlying ``CreateProcess`` function.
*creationflags*, if given, can be :data:`CREATE_NEW_CONSOLE` or
:data:`CREATE_NEW_PROCESS_GROUP`. (Windows only)
.. data:: PIPE
......@@ -200,7 +201,7 @@ This module defines one class called :class:`Popen`:
Convenience Functions
^^^^^^^^^^^^^^^^^^^^^
This module also defines two shortcut functions:
This module also defines the following shortcut functions:
.. function:: call(*popenargs, **kwargs)
......@@ -413,6 +414,109 @@ The following attributes are also available:
``N`` (Unix only).
Windows Popen Helpers
---------------------
The :class:`STARTUPINFO` class and following constants are only available
on Windows.
.. class:: STARTUPINFO()
Partial support of the Windows
`STARTUPINFO <http://msdn.microsoft.com/en-us/library/ms686331(v=vs.85).aspx>`__
structure is used for :class:`Popen` creation.
.. attribute:: dwFlags
A bit field that determines whether certain :class:`STARTUPINFO` members
are used when the process creates a window. ::
si = subprocess.STARTUPINFO()
si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW
.. attribute:: hStdInput
If :attr:`dwFlags` specifies :data:`STARTF_USESTDHANDLES`, this member is
the standard input handle for the process. If :data:`STARTF_USESTDHANDLES`
is not specified, the default for standard input is the keyboard buffer.
.. attribute:: hStdOutput
If :attr:`dwFlags` specifies :data:`STARTF_USESTDHANDLES`, this member is
the standard output handle for the process. Otherwise, this member is
ignored and the default for standard output is the console window's
buffer.
.. attribute:: hStdError
If :attr:`dwFlags` specifies :data:`STARTF_USESTDHANDLES`, this member is
the standard error handle for the process. Otherwise, this member is
ignored and the default for standard error is the console window's buffer.
.. attribute:: wShowWindow
If :attr:`dwFlags` specifies :data:`STARTF_USESHOWWINDOW`, this member
can be any of the values that can be specified in the ``nCmdShow``
parameter for the
`ShowWindow <http://msdn.microsoft.com/en-us/library/ms633548(v=vs.85).aspx>`__
function, except for ``SW_SHOWDEFAULT``. Otherwise, this member is
ignored.
:data:`SW_HIDE` is provided for this attribute. It is used when
:class:`Popen` is called with ``shell=True``.
Constants
^^^^^^^^^
The :mod:`subprocess` module exposes the following constants.
.. data:: STD_INPUT_HANDLE
The standard input device. Initially, this is the console input buffer,
``CONIN$``.
.. data:: STD_OUTPUT_HANDLE
The standard output device. Initially, this is the active console screen
buffer, ``CONOUT$``.
.. data:: STD_ERROR_HANDLE
The standard error device. Initially, this is the active console screen
buffer, ``CONOUT$``.
.. data:: SW_HIDE
Hides the window. Another window will be activated.
.. data:: STARTF_USESTDHANDLES
Specifies that the :attr:`STARTUPINFO.hStdInput`,
:attr:`STARTUPINFO.hStdOutput`, and :attr:`STARTUPINFO.hStdError` members
contain additional information.
.. data:: STARTF_USESHOWWINDOW
Specifies that the :attr:`STARTUPINFO.wShowWindow` member contains
additional information.
.. data:: CREATE_NEW_CONSOLE
The new process has a new console, instead of inheriting its parent's
console (the default).
This flag is always set when :class:`Popen` is created with ``shell=True``.
.. data:: CREATE_NEW_PROCESS_GROUP
A :class:`Popen` ``creationflags`` parameter to specify that a new process
group will be created. This flag is necessary for using :func:`os.kill`
on the subprocess.
This flag is ignored if :data:`CREATE_NEW_CONSOLE` is specified.
.. _subprocess-replacements:
Replacing Older Functions with the subprocess Module
......
......@@ -562,6 +562,30 @@ always available.
``version_info`` value may be used for a more human-friendly encoding of the
same information.
The ``hexversion`` is a 32-bit number with the following layout
+-------------------------+------------------------------------------------+
| bits (big endian order) | meaning |
+=========================+================================================+
| :const:`1-8` | ``PY_MAJOR_VERSION`` (the ``2`` in |
| | ``2.1.0a3``) |
+-------------------------+------------------------------------------------+
| :const:`9-16` | ``PY_MINOR_VERSION`` (the ``1`` in |
| | ``2.1.0a3``) |
+-------------------------+------------------------------------------------+
| :const:`17-24` | ``PY_MICRO_VERSION`` (the ``0`` in |
| | ``2.1.0a3``) |
+-------------------------+------------------------------------------------+
| :const:`25-28` | ``PY_RELEASE_LEVEL`` (``0xA`` for alpha, |
| | ``0xB`` for beta, ``0xC`` for gamma and |
| | ``0xF`` for final) |
+-------------------------+------------------------------------------------+
| :const:`29-32` | ``PY_RELEASE_SERIAL`` (the ``3`` in |
| | ``2.1.0a3``) |
+-------------------------+------------------------------------------------+
thus ``2.1.0a3`` is hexversion ``0x020100a3``
.. versionadded:: 1.5.2
......
......@@ -167,15 +167,15 @@ High-level interface
the download is interrupted.
The *Content-Length* is treated as a lower bound: if there's more data to read,
urlretrieve reads more data, but if less data is available, it raises the
exception.
:func:`urlretrieve` reads more data, but if less data is available, it raises
the exception.
You can still retrieve the downloaded data in this case, it is stored in the
:attr:`content` attribute of the exception instance.
If no *Content-Length* header was supplied, urlretrieve can not check the size
of the data it has downloaded, and just returns it. In this case you just have
to assume that the download was successful.
If no *Content-Length* header was supplied, :func:`urlretrieve` can not check
the size of the data it has downloaded, and just returns it. In this case you
just have to assume that the download was successful.
.. data:: _urlopener
......
......@@ -111,6 +111,7 @@ PyAPI_FUNC(void) PyThreadState_Clear(PyThreadState *);
PyAPI_FUNC(void) PyThreadState_Delete(PyThreadState *);
#ifdef WITH_THREAD
PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void);
PyAPI_FUNC(void) _PyGILState_Reinit(void);
#endif
PyAPI_FUNC(PyThreadState *) PyThreadState_Get(void);
......
......@@ -29,17 +29,8 @@ It has the following interface (key and data are strings):
list = d.keys() # return a list of all existing keys (slow!)
Future versions may change the order in which implementations are
tested for existence, add interfaces to other dbm-like
tested for existence, and add interfaces to other dbm-like
implementations.
The open function has an optional second argument. This can be 'r',
for read-only access, 'w', for read-write access of an existing
database, 'c' for read-write access to a new or existing database, and
'n' for read-write access to a new database. The default is 'r'.
Note: 'r' and 'w' fail if the database doesn't exist; 'c' creates it
only if it doesn't exist; and 'n' always creates a new database.
"""
class error(Exception):
......@@ -63,7 +54,18 @@ if not _defaultmod:
error = tuple(_errors)
def open(file, flag = 'r', mode = 0666):
def open(file, flag='r', mode=0666):
"""Open or create database at path given by *file*.
Optional argument *flag* can be 'r' (default) for read-only access, 'w'
for read-write access of an existing database, 'c' for read-write access
to a new or existing database, and 'n' for read-write access to a new
database.
Note: 'r' and 'w' fail if the database doesn't exist; 'c' creates it
only if it doesn't exist; and 'n' always creates a new database.
"""
# guess the type of an existing database
from whichdb import whichdb
result=whichdb(file)
......
This diff is collapsed.
......@@ -306,17 +306,20 @@ class sdist(Command):
rstrip_ws=1,
collapse_join=1)
while 1:
line = template.readline()
if line is None: # end of file
break
try:
self.filelist.process_template_line(line)
except DistutilsTemplateError, msg:
self.warn("%s, line %d: %s" % (template.filename,
template.current_line,
msg))
try:
while 1:
line = template.readline()
if line is None: # end of file
break
try:
self.filelist.process_template_line(line)
except DistutilsTemplateError, msg:
self.warn("%s, line %d: %s" % (template.filename,
template.current_line,
msg))
finally:
template.close()
def prune_file_list(self):
"""Prune off branches that might slip into the file list as created
......
......@@ -62,7 +62,7 @@ def unix_getpass(prompt='Password: ', stream=None):
try:
old = termios.tcgetattr(fd) # a copy to save
new = old[:]
new[3] &= ~(termios.ECHO|termios.ISIG) # 3 == 'lflags'
new[3] &= ~termios.ECHO # 3 == 'lflags'
tcsetattr_flags = termios.TCSAFLUSH
if hasattr(termios, 'TCSASOFT'):
tcsetattr_flags |= termios.TCSASOFT
......
......@@ -441,8 +441,15 @@ __all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call",
"check_output", "CalledProcessError"]
if mswindows:
from _subprocess import CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP
__all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP"])
from _subprocess import (CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP,
STD_INPUT_HANDLE, STD_OUTPUT_HANDLE,
STD_ERROR_HANDLE, SW_HIDE,
STARTF_USESTDHANDLES, STARTF_USESHOWWINDOW)
__all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP",
"STD_INPUT_HANDLE", "STD_OUTPUT_HANDLE",
"STD_ERROR_HANDLE", "SW_HIDE",
"STARTF_USESTDHANDLES", "STARTF_USESHOWWINDOW"])
try:
MAXFD = os.sysconf("SC_OPEN_MAX")
except:
......
......@@ -2239,6 +2239,8 @@ class TarFile(object):
if hasattr(os, "symlink") and hasattr(os, "link"):
# For systems that support symbolic and hard links.
if tarinfo.issym():
if os.path.exists(targetpath):
os.unlink(targetpath)
os.symlink(tarinfo.linkname, targetpath)
else:
# See extract().
......
......@@ -1177,6 +1177,63 @@ class MixinStrUnicodeUserStringTest:
# mixed use of str and unicode
self.assertEqual('a/b/c'.rpartition(u'/'), ('a/b', '/', 'c'))
def test_none_arguments(self):
# issue 11828
s = 'hello'
self.checkequal(2, s, 'find', 'l', None)
self.checkequal(3, s, 'find', 'l', -2, None)
self.checkequal(2, s, 'find', 'l', None, -2)
self.checkequal(0, s, 'find', 'h', None, None)
self.checkequal(3, s, 'rfind', 'l', None)
self.checkequal(3, s, 'rfind', 'l', -2, None)
self.checkequal(2, s, 'rfind', 'l', None, -2)
self.checkequal(0, s, 'rfind', 'h', None, None)
self.checkequal(2, s, 'index', 'l', None)
self.checkequal(3, s, 'index', 'l', -2, None)
self.checkequal(2, s, 'index', 'l', None, -2)
self.checkequal(0, s, 'index', 'h', None, None)
self.checkequal(3, s, 'rindex', 'l', None)
self.checkequal(3, s, 'rindex', 'l', -2, None)
self.checkequal(2, s, 'rindex', 'l', None, -2)
self.checkequal(0, s, 'rindex', 'h', None, None)
self.checkequal(2, s, 'count', 'l', None)
self.checkequal(1, s, 'count', 'l', -2, None)
self.checkequal(1, s, 'count', 'l', None, -2)
self.checkequal(0, s, 'count', 'x', None, None)
self.checkequal(True, s, 'endswith', 'o', None)
self.checkequal(True, s, 'endswith', 'lo', -2, None)
self.checkequal(True, s, 'endswith', 'l', None, -2)
self.checkequal(False, s, 'endswith', 'x', None, None)
self.checkequal(True, s, 'startswith', 'h', None)
self.checkequal(True, s, 'startswith', 'l', -2, None)
self.checkequal(True, s, 'startswith', 'h', None, -2)
self.checkequal(False, s, 'startswith', 'x', None, None)
def test_find_etc_raise_correct_error_messages(self):
# issue 11828
s = 'hello'
x = 'x'
self.assertRaisesRegexp(TypeError, r'\bfind\b', s.find,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'\brfind\b', s.rfind,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'\bindex\b', s.index,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'\brindex\b', s.rindex,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'^count\(', s.count,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'^startswith\(', s.startswith,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'^endswith\(', s.endswith,
x, None, None, None)
class MixinStrStringUserStringTest:
# Additional tests for 8bit strings, i.e. str, UserString and
# the string module
......
......@@ -456,6 +456,68 @@ class BaseBytesTest(unittest.TestCase):
self.assertEqual([ord(b[i:i+1]) for i in range(len(b))],
[0, 65, 127, 128, 255])
def test_none_arguments(self):
# issue 11828
b = self.type2test(b'hello')
l = self.type2test(b'l')
h = self.type2test(b'h')
x = self.type2test(b'x')
o = self.type2test(b'o')
self.assertEqual(2, b.find(l, None))
self.assertEqual(3, b.find(l, -2, None))
self.assertEqual(2, b.find(l, None, -2))
self.assertEqual(0, b.find(h, None, None))
self.assertEqual(3, b.rfind(l, None))
self.assertEqual(3, b.rfind(l, -2, None))
self.assertEqual(2, b.rfind(l, None, -2))
self.assertEqual(0, b.rfind(h, None, None))
self.assertEqual(2, b.index(l, None))
self.assertEqual(3, b.index(l, -2, None))
self.assertEqual(2, b.index(l, None, -2))
self.assertEqual(0, b.index(h, None, None))
self.assertEqual(3, b.rindex(l, None))
self.assertEqual(3, b.rindex(l, -2, None))
self.assertEqual(2, b.rindex(l, None, -2))
self.assertEqual(0, b.rindex(h, None, None))
self.assertEqual(2, b.count(l, None))
self.assertEqual(1, b.count(l, -2, None))
self.assertEqual(1, b.count(l, None, -2))
self.assertEqual(0, b.count(x, None, None))
self.assertEqual(True, b.endswith(o, None))
self.assertEqual(True, b.endswith(o, -2, None))
self.assertEqual(True, b.endswith(l, None, -2))
self.assertEqual(False, b.endswith(x, None, None))
self.assertEqual(True, b.startswith(h, None))
self.assertEqual(True, b.startswith(l, -2, None))
self.assertEqual(True, b.startswith(h, None, -2))
self.assertEqual(False, b.startswith(x, None, None))
def test_find_etc_raise_correct_error_messages(self):
# issue 11828
b = self.type2test(b'hello')
x = self.type2test(b'x')
self.assertRaisesRegexp(TypeError, r'\bfind\b', b.find,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'\brfind\b', b.rfind,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'\bindex\b', b.index,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'\brindex\b', b.rindex,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'\bcount\b', b.count,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'\bstartswith\b', b.startswith,
x, None, None, None)
self.assertRaisesRegexp(TypeError, r'\bendswith\b', b.endswith,
x, None, None, None)
class ByteArrayTest(BaseBytesTest):
type2test = bytearray
......
......@@ -689,6 +689,15 @@ class TestCounter(unittest.TestCase):
self.assertEqual(len(dup), len(words))
self.assertEqual(type(dup), type(words))
def test_copy_subclass(self):
class MyCounter(Counter):
pass
c = MyCounter('slartibartfast')
d = c.copy()
self.assertEqual(d, c)
self.assertEqual(len(d), len(c))
self.assertEqual(type(d), type(c))
def test_conversions(self):
# Convert to: set, list, dict
s = 'she sells sea shells by the sea shore'
......
......@@ -6,6 +6,7 @@ import subprocess
import re
import pydoc
import inspect
import keyword
import unittest
import xml.etree
import test.test_support
......@@ -351,9 +352,16 @@ class TestDescriptions(unittest.TestCase):
self.assertIn('_asdict', helptext)
class TestHelper(unittest.TestCase):
def test_keywords(self):
self.assertEqual(sorted(pydoc.Helper.keywords),
sorted(keyword.kwlist))
def test_main():
test.test_support.run_unittest(PyDocDocTest,
TestDescriptions)
TestDescriptions,
TestHelper)
if __name__ == "__main__":
test_main()
......@@ -11,6 +11,7 @@ import unittest
from test import test_support
import os
from os import path
from time import sleep
startfile = test_support.get_attribute(os, 'startfile')
......@@ -26,11 +27,16 @@ class TestCase(unittest.TestCase):
empty = path.join(path.dirname(__file__), "empty.vbs")
startfile(empty)
startfile(empty, "open")
# Give the child process some time to exit before we finish.
# Otherwise the cleanup code will not be able to delete the cwd,
# because it is still in use.
sleep(0.1)
def test_empty_u(self):
empty = path.join(path.dirname(__file__), "empty.vbs")
startfile(unicode(empty, "mbcs"))
startfile(unicode(empty, "mbcs"), "open")
sleep(0.1)
def test_main():
test_support.run_unittest(TestCase)
......
......@@ -414,7 +414,18 @@ class StrTest(
self.assertEqual('Andr\202 x'.decode('ascii', 'replace'),
'Andr\202 x'.decode(encoding='ascii', errors='replace'))
def test_startswith_endswith_errors(self):
with self.assertRaises(UnicodeDecodeError):
'\xff'.startswith(u'x')
with self.assertRaises(UnicodeDecodeError):
'\xff'.endswith(u'x')
for meth in ('foo'.startswith, 'foo'.endswith):
with self.assertRaises(TypeError) as cm:
meth(['f'])
exc = str(cm.exception)
self.assertIn('unicode', exc)
self.assertIn('str', exc)
self.assertIn('tuple', exc)
def test_main():
test_support.run_unittest(StrTest)
......
......@@ -843,6 +843,34 @@ class WriteTest(WriteTestBase):
finally:
os.chdir(cwd)
@unittest.skipUnless(hasattr(os, 'symlink'), "needs os.symlink")
def test_extractall_symlinks(self):
# Test if extractall works properly when tarfile contains symlinks
tempdir = os.path.join(TEMPDIR, "testsymlinks")
temparchive = os.path.join(TEMPDIR, "testsymlinks.tar")
os.mkdir(tempdir)
try:
source_file = os.path.join(tempdir,'source')
target_file = os.path.join(tempdir,'symlink')
with open(source_file,'w') as f:
f.write('something\n')
os.symlink(source_file, target_file)
tar = tarfile.open(temparchive,'w')
tar.add(source_file, arcname=os.path.basename(source_file))
tar.add(target_file, arcname=os.path.basename(target_file))
tar.close()
# Let's extract it to the location which contains the symlink
tar = tarfile.open(temparchive,'r')
# this should not raise OSError: [Errno 17] File exists
try:
tar.extractall(path=tempdir)
except OSError:
self.fail("extractall failed with symlinked files")
finally:
tar.close()
finally:
os.unlink(temparchive)
shutil.rmtree(tempdir)
class StreamWriteTest(WriteTestBase):
......
......@@ -442,6 +442,17 @@ class UnicodeTest(
return u'\u1234'
self.assertEqual('%s' % Wrapper(), u'\u1234')
def test_startswith_endswith_errors(self):
for meth in (u'foo'.startswith, u'foo'.endswith):
with self.assertRaises(UnicodeDecodeError):
meth('\xff')
with self.assertRaises(TypeError) as cm:
meth(['f'])
exc = str(cm.exception)
self.assertIn('unicode', exc)
self.assertIn('str', exc)
self.assertIn('tuple', exc)
@test_support.run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
def test_format_float(self):
# should not format with a comma, but always with C locale
......
This diff is collapsed.
......@@ -169,6 +169,10 @@ class TestCase(object):
maxDiff = 80*8
# If a string is longer than _diffThreshold, use normal comparison instead
# of difflib. See #11763.
_diffThreshold = 2**16
# Attribute used by TestSuite for classSetUp
_classSetupFailed = False
......@@ -900,6 +904,10 @@ class TestCase(object):
'Second argument is not a string')
if first != second:
# don't use difflib if the strings are too long
if (len(first) > self._diffThreshold or
len(second) > self._diffThreshold):
self._baseAssertEqual(first, second, msg)
firstlines = first.splitlines(True)
secondlines = second.splitlines(True)
if len(firstlines) == 1 and first.strip('\r\n') == first:
......
......@@ -667,6 +667,42 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
else:
self.fail('assertMultiLineEqual did not fail')
def testAssertEqual_diffThreshold(self):
# check threshold value
self.assertEqual(self._diffThreshold, 2**16)
# disable madDiff to get diff markers
self.maxDiff = None
# set a lower threshold value and add a cleanup to restore it
old_threshold = self._diffThreshold
self._diffThreshold = 2**8
self.addCleanup(lambda: setattr(self, '_diffThreshold', old_threshold))
# under the threshold: diff marker (^) in error message
s = u'x' * (2**7)
with self.assertRaises(self.failureException) as cm:
self.assertEqual(s + 'a', s + 'b')
self.assertIn('^', str(cm.exception))
self.assertEqual(s + 'a', s + 'a')
# over the threshold: diff not used and marker (^) not in error message
s = u'x' * (2**9)
# if the path that uses difflib is taken, _truncateMessage will be
# called -- replace it with explodingTruncation to verify that this
# doesn't happen
def explodingTruncation(message, diff):
raise SystemError('this should not be raised')
old_truncate = self._truncateMessage
self._truncateMessage = explodingTruncation
self.addCleanup(lambda: setattr(self, '_truncateMessage', old_truncate))
s1, s2 = s + 'a', s + 'b'
with self.assertRaises(self.failureException) as cm:
self.assertEqual(s1, s2)
self.assertNotIn('^', str(cm.exception))
self.assertEqual(str(cm.exception), '%r != %r' % (s1, s2))
self.assertEqual(s + 'a', s + 'a')
def testAssertItemsEqual(self):
a = object()
self.assertItemsEqual([1, 2, 3], [3, 2, 1])
......
......@@ -60,6 +60,7 @@ Donald Beaudry
David Beazley
Robin Becker
Neal Becker
Torsten Becker
Bill Bedford
Reimer Behrends
Ben Bell
......@@ -410,6 +411,7 @@ Irmen de Jong
Lucas de Jonge
John Jorgensen
Jens B. Jorgensen
Sijin Joseph
Andreas Jung
Tattoo Mabonzo K.
Bob Kahn
......@@ -794,6 +796,7 @@ Steven Taschuk
Monty Taylor
Amy Taylor
Anatoly Techtonik
Mikhail Terekhov
Tobias Thelen
James Thomas
Robin Thomas
......
......@@ -9,6 +9,13 @@ What's New in Python 2.7.2?
Core and Builtins
-----------------
- Issue #10517: After fork(), reinitialize the TLS used by the PyGILState_*
APIs, to avoid a crash with the pthread implementation in RHEL 5. Patch
by Charles-François Natali.
- Issue #6780: fix starts/endswith error message to mention that tuples are
accepted too.
- Issue #5057: fix a bug in the peepholer that led to non-portable pyc files
between narrow and wide builds while optimizing BINARY_SUBSCR on non-BMP
chars (e.g. u"\U00012345"[0]).
......@@ -43,6 +50,9 @@ Core and Builtins
rather than the Py_IsInitialized flag, avoiding a Fatal Python
error in certain circumstances when an import is done in __del__.
- issue #11828: startswith and endswith don't accept None as slice index.
Patch by Torsten Becker.
- Issue #10674: Remove unused 'dictmaker' rule from grammar.
- Issue #10596: Fix float.__mod__ to have the same behaviour as
......@@ -55,9 +65,29 @@ Core and Builtins
Library
-------
- Issue #10761: Fix tarfile.extractall failure when symlinked files are
present. Initial patch by Scott Leerssen.
- Issue #11763: don't use difflib in TestCase.assertMultiLineEqual if the
strings are too long.
- Issue #11236: getpass.getpass responds to ctrl-c or ctrl-z on terminal.
- Issue #11768: The signal handler of the signal module only calls
Py_AddPendingCall() for the first signal to fix a deadlock on reentrant or
parallel calls. PyErr_SetInterrupt() writes also into the wake up file.
- Issue #11875: collections.OrderedDict's __reduce__ was temporarily
mutating the object instead of just working on a copy.
- Issue #11442: Add a charset parameter to the Content-type in SimpleHTTPServer
to avoid XSS attacks.
- Issue #11467: Fix urlparse behavior when handling urls which contains scheme
specific part only digits. Patch by Santoso Wijaya.
- collections.Counter().copy() now works correctly for subclasses.
- Issue #11474: Fix the bug with url2pathname() handling of '/C|/' on Windows.
Patch by Santoso Wijaya.
......@@ -358,6 +388,8 @@ IDLE
Tests
-----
- Fix test_startfile to wait for child process to terminate before finishing.
- Issue #11719: Fix message about unexpected test_msilib skip on non-Windows
platforms. Patch by Nadeem Vawda.
......
......@@ -166,6 +166,20 @@ checksignals_witharg(void * unused)
return PyErr_CheckSignals();
}
static void
trip_signal(int sig_num)
{
Handlers[sig_num].tripped = 1;
if (is_tripped)
return;
/* Set is_tripped after setting .tripped, as it gets
cleared in PyErr_CheckSignals() before .tripped. */
is_tripped = 1;
Py_AddPendingCall(checksignals_witharg, NULL);
if (wakeup_fd != -1)
write(wakeup_fd, "\0", 1);
}
static void
signal_handler(int sig_num)
{
......@@ -183,13 +197,7 @@ signal_handler(int sig_num)
if (getpid() == main_pid)
#endif
{
Handlers[sig_num].tripped = 1;
/* Set is_tripped after setting .tripped, as it gets
cleared in PyErr_CheckSignals() before .tripped. */
is_tripped = 1;
Py_AddPendingCall(checksignals_witharg, NULL);
if (wakeup_fd != -1)
write(wakeup_fd, "\0", 1);
trip_signal(sig_num);
}
#ifndef HAVE_SIGACTION
......@@ -934,9 +942,7 @@ PyErr_CheckSignals(void)
void
PyErr_SetInterrupt(void)
{
is_tripped = 1;
Handlers[SIGINT].tripped = 1;
Py_AddPendingCall((int (*)(void *))PyErr_CheckSignals, NULL);
trip_signal(SIGINT);
}
void
......@@ -970,6 +976,7 @@ void
PyOS_AfterFork(void)
{
#ifdef WITH_THREAD
_PyGILState_Reinit();
PyEval_ReInitThreads();
main_thread = PyThread_get_thread_ident();
main_pid = getpid();
......
......@@ -1149,8 +1149,8 @@ bytearray_find_internal(PyByteArrayObject *self, PyObject *args, int dir)
Py_ssize_t start=0, end=PY_SSIZE_T_MAX;
Py_ssize_t res;
if (!PyArg_ParseTuple(args, "O|O&O&:find/rfind/index/rindex", &subobj,
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
if (!stringlib_parse_args_finds("find/rfind/index/rindex",
args, &subobj, &start, &end))
return -2;
if (_getbuffer(subobj, &subbuf) < 0)
return -2;
......@@ -1200,8 +1200,7 @@ bytearray_count(PyByteArrayObject *self, PyObject *args)
Py_buffer vsub;
PyObject *count_obj;
if (!PyArg_ParseTuple(args, "O|O&O&:count", &sub_obj,
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
if (!stringlib_parse_args_finds("count", args, &sub_obj, &start, &end))
return NULL;
if (_getbuffer(sub_obj, &vsub) < 0)
......@@ -1359,8 +1358,7 @@ bytearray_startswith(PyByteArrayObject *self, PyObject *args)
PyObject *subobj;
int result;
if (!PyArg_ParseTuple(args, "O|O&O&:startswith", &subobj,
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))
return NULL;
if (PyTuple_Check(subobj)) {
Py_ssize_t i;
......@@ -1399,8 +1397,7 @@ bytearray_endswith(PyByteArrayObject *self, PyObject *args)
PyObject *subobj;
int result;
if (!PyArg_ParseTuple(args, "O|O&O&:endswith", &subobj,
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end))
return NULL;
if (PyTuple_Check(subobj)) {
Py_ssize_t i;
......
......@@ -93,32 +93,33 @@ stringlib_contains_obj(PyObject* str, PyObject* sub)
#endif /* STRINGLIB_WANT_CONTAINS_OBJ */
#if STRINGLIB_IS_UNICODE
/*
This function is a helper for the "find" family (find, rfind, index,
rindex) of unicodeobject.c file, because they all have the same
behaviour for the arguments.
rindex) and for count, startswith and endswith, because they all have
the same behaviour for the arguments.
It does not touch the variables received until it knows everything
is ok.
Note that we receive a pointer to the pointer of the substring object,
so when we create that object in this function we don't DECREF it,
because it continues living in the caller functions (those functions,
after finishing using the substring, must DECREF it).
*/
#define FORMAT_BUFFER_SIZE 50
Py_LOCAL_INLINE(int)
_ParseTupleFinds (PyObject *args, PyObject **substring,
Py_ssize_t *start, Py_ssize_t *end) {
PyObject *tmp_substring;
stringlib_parse_args_finds(const char * function_name, PyObject *args,
PyObject **subobj,
Py_ssize_t *start, Py_ssize_t *end)
{
PyObject *tmp_subobj;
Py_ssize_t tmp_start = 0;
Py_ssize_t tmp_end = PY_SSIZE_T_MAX;
PyObject *obj_start=Py_None, *obj_end=Py_None;
char format[FORMAT_BUFFER_SIZE] = "O|OO:";
size_t len = strlen(format);
if (!PyArg_ParseTuple(args, "O|OO:find", &tmp_substring,
&obj_start, &obj_end))
strncpy(format + len, function_name, FORMAT_BUFFER_SIZE - len - 1);
format[FORMAT_BUFFER_SIZE - 1] = '\0';
if (!PyArg_ParseTuple(args, format, &tmp_subobj, &obj_start, &obj_end))
return 0;
/* To support None in "start" and "end" arguments, meaning
......@@ -131,16 +132,44 @@ _ParseTupleFinds (PyObject *args, PyObject **substring,
if (!_PyEval_SliceIndex(obj_end, &tmp_end))
return 0;
tmp_substring = PyUnicode_FromObject(tmp_substring);
if (!tmp_substring)
return 0;
*start = tmp_start;
*end = tmp_end;
*substring = tmp_substring;
*subobj = tmp_subobj;
return 1;
}
#undef FORMAT_BUFFER_SIZE
#if STRINGLIB_IS_UNICODE
/*
Wraps stringlib_parse_args_finds() and additionally ensures that the
first argument is a unicode object.
Note that we receive a pointer to the pointer of the substring object,
so when we create that object in this function we don't DECREF it,
because it continues living in the caller functions (those functions,
after finishing using the substring, must DECREF it).
*/
Py_LOCAL_INLINE(int)
stringlib_parse_args_finds_unicode(const char * function_name, PyObject *args,
PyUnicodeObject **substring,
Py_ssize_t *start, Py_ssize_t *end)
{
PyObject *tmp_substring;
if(stringlib_parse_args_finds(function_name, args, &tmp_substring,
start, end)) {
tmp_substring = PyUnicode_FromObject(tmp_substring);
if (!tmp_substring)
return 0;
*substring = (PyUnicodeObject *)tmp_substring;
return 1;
}
return 0;
}
#endif /* STRINGLIB_IS_UNICODE */
#endif /* STRINGLIB_FIND_H */
......@@ -1693,19 +1693,9 @@ string_find_internal(PyStringObject *self, PyObject *args, int dir)
const char *sub;
Py_ssize_t sub_len;
Py_ssize_t start=0, end=PY_SSIZE_T_MAX;
PyObject *obj_start=Py_None, *obj_end=Py_None;
if (!PyArg_ParseTuple(args, "O|OO:find/rfind/index/rindex", &subobj,
&obj_start, &obj_end))
return -2;
/* To support None in "start" and "end" arguments, meaning
the same as if they were not passed.
*/
if (obj_start != Py_None)
if (!_PyEval_SliceIndex(obj_start, &start))
return -2;
if (obj_end != Py_None)
if (!_PyEval_SliceIndex(obj_end, &end))
if (!stringlib_parse_args_finds("find/rfind/index/rindex",
args, &subobj, &start, &end))
return -2;
if (PyString_Check(subobj)) {
......@@ -2117,8 +2107,7 @@ string_count(PyStringObject *self, PyObject *args)
Py_ssize_t sub_len;
Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
if (!PyArg_ParseTuple(args, "O|O&O&:count", &sub_obj,
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
if (!stringlib_parse_args_finds("count", args, &sub_obj, &start, &end))
return NULL;
if (PyString_Check(sub_obj)) {
......@@ -2912,8 +2901,7 @@ string_startswith(PyStringObject *self, PyObject *args)
PyObject *subobj;
int result;
if (!PyArg_ParseTuple(args, "O|O&O&:startswith", &subobj,
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))
return NULL;
if (PyTuple_Check(subobj)) {
Py_ssize_t i;
......@@ -2930,8 +2918,12 @@ string_startswith(PyStringObject *self, PyObject *args)
Py_RETURN_FALSE;
}
result = _string_tailmatch(self, subobj, start, end, -1);
if (result == -1)
if (result == -1) {
if (PyErr_ExceptionMatches(PyExc_TypeError))
PyErr_Format(PyExc_TypeError, "startswith first arg must be str, "
"unicode, or tuple, not %s", Py_TYPE(subobj)->tp_name);
return NULL;
}
else
return PyBool_FromLong(result);
}
......@@ -2953,8 +2945,7 @@ string_endswith(PyStringObject *self, PyObject *args)
PyObject *subobj;
int result;
if (!PyArg_ParseTuple(args, "O|O&O&:endswith", &subobj,
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end))
return NULL;
if (PyTuple_Check(subobj)) {
Py_ssize_t i;
......@@ -2971,8 +2962,12 @@ string_endswith(PyStringObject *self, PyObject *args)
Py_RETURN_FALSE;
}
result = _string_tailmatch(self, subobj, start, end, +1);
if (result == -1)
if (result == -1) {
if (PyErr_ExceptionMatches(PyExc_TypeError))
PyErr_Format(PyExc_TypeError, "endswith first arg must be str, "
"unicode, or tuple, not %s", Py_TYPE(subobj)->tp_name);
return NULL;
}
else
return PyBool_FromLong(result);
}
......
......@@ -6308,13 +6308,8 @@ unicode_count(PyUnicodeObject *self, PyObject *args)
Py_ssize_t end = PY_SSIZE_T_MAX;
PyObject *result;
if (!PyArg_ParseTuple(args, "O|O&O&:count", &substring,
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
return NULL;
substring = (PyUnicodeObject *)PyUnicode_FromObject(
(PyObject *)substring);
if (substring == NULL)
if (!stringlib_parse_args_finds_unicode("count", args, &substring,
&start, &end))
return NULL;
ADJUST_INDICES(start, end, self->length);
......@@ -6504,12 +6499,13 @@ Return -1 on failure.");
static PyObject *
unicode_find(PyUnicodeObject *self, PyObject *args)
{
PyObject *substring;
PyUnicodeObject *substring;
Py_ssize_t start;
Py_ssize_t end;
Py_ssize_t result;
if (!_ParseTupleFinds(args, &substring, &start, &end))
if (!stringlib_parse_args_finds_unicode("find", args, &substring,
&start, &end))
return NULL;
result = stringlib_find_slice(
......@@ -6570,11 +6566,12 @@ static PyObject *
unicode_index(PyUnicodeObject *self, PyObject *args)
{
Py_ssize_t result;
PyObject *substring;
PyUnicodeObject *substring;
Py_ssize_t start;
Py_ssize_t end;
if (!_ParseTupleFinds(args, &substring, &start, &end))
if (!stringlib_parse_args_finds_unicode("index", args, &substring,
&start, &end))
return NULL;
result = stringlib_find_slice(
......@@ -7237,12 +7234,13 @@ Return -1 on failure.");
static PyObject *
unicode_rfind(PyUnicodeObject *self, PyObject *args)
{
PyObject *substring;
PyUnicodeObject *substring;
Py_ssize_t start;
Py_ssize_t end;
Py_ssize_t result;
if (!_ParseTupleFinds(args, &substring, &start, &end))
if (!stringlib_parse_args_finds_unicode("rfind", args, &substring,
&start, &end))
return NULL;
result = stringlib_rfind_slice(
......@@ -7264,12 +7262,13 @@ Like S.rfind() but raise ValueError when the substring is not found.");
static PyObject *
unicode_rindex(PyUnicodeObject *self, PyObject *args)
{
PyObject *substring;
PyUnicodeObject *substring;
Py_ssize_t start;
Py_ssize_t end;
Py_ssize_t result;
if (!_ParseTupleFinds(args, &substring, &start, &end))
if (!stringlib_parse_args_finds_unicode("rindex", args, &substring,
&start, &end))
return NULL;
result = stringlib_rfind_slice(
......@@ -7648,8 +7647,7 @@ unicode_startswith(PyUnicodeObject *self,
Py_ssize_t end = PY_SSIZE_T_MAX;
int result;
if (!PyArg_ParseTuple(args, "O|O&O&:startswith", &subobj,
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))
return NULL;
if (PyTuple_Check(subobj)) {
Py_ssize_t i;
......@@ -7668,8 +7666,12 @@ unicode_startswith(PyUnicodeObject *self,
Py_RETURN_FALSE;
}
substring = (PyUnicodeObject *)PyUnicode_FromObject(subobj);
if (substring == NULL)
if (substring == NULL) {
if (PyErr_ExceptionMatches(PyExc_TypeError))
PyErr_Format(PyExc_TypeError, "startswith first arg must be str, "
"unicode, or tuple, not %s", Py_TYPE(subobj)->tp_name);
return NULL;
}
result = tailmatch(self, substring, start, end, -1);
Py_DECREF(substring);
return PyBool_FromLong(result);
......@@ -7694,8 +7696,7 @@ unicode_endswith(PyUnicodeObject *self,
Py_ssize_t end = PY_SSIZE_T_MAX;
int result;
if (!PyArg_ParseTuple(args, "O|O&O&:endswith", &subobj,
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end))
return NULL;
if (PyTuple_Check(subobj)) {
Py_ssize_t i;
......@@ -7713,9 +7714,12 @@ unicode_endswith(PyUnicodeObject *self,
Py_RETURN_FALSE;
}
substring = (PyUnicodeObject *)PyUnicode_FromObject(subobj);
if (substring == NULL)
if (substring == NULL) {
if (PyErr_ExceptionMatches(PyExc_TypeError))
PyErr_Format(PyExc_TypeError, "endswith first arg must be str, "
"unicode, or tuple, not %s", Py_TYPE(subobj)->tp_name);
return NULL;
}
result = tailmatch(self, substring, start, end, +1);
Py_DECREF(substring);
return PyBool_FromLong(result);
......
......@@ -537,6 +537,23 @@ _PyGILState_Fini(void)
autoInterpreterState = NULL;
}
/* Reset the TLS key - called by PyOS_AfterFork.
* This should not be necessary, but some - buggy - pthread implementations
* don't flush TLS on fork, see issue #10517.
*/
void
_PyGILState_Reinit(void)
{
PyThreadState *tstate = PyGILState_GetThisThreadState();
PyThread_delete_key(autoTLSkey);
if ((autoTLSkey = PyThread_create_key()) == -1)
Py_FatalError("Could not allocate TLS entry");
/* re-associate the current thread state with the new key */
if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0)
Py_FatalError("Couldn't create autoTLSkey mapping");
}
/* When a thread state is created for a thread by some mechanism other than
PyGILState_Ensure, it's important that the GILState machinery knows about
it so it doesn't try to create another thread state for the thread (this is
......
......@@ -278,7 +278,7 @@ class Test:
for i in calibration_loops:
pass
t = timer() - t
prep_times.append(t)
prep_times.append(t / CALIBRATION_LOOPS)
min_prep_time = min(prep_times)
if _debug:
print
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment