Merged revisions 60143-60149 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r60143 | georg.brandl | 2008-01-20 15:50:05 +0100 (Sun, 20 Jan 2008) | 3 lines

  Switch mmap from old Py_FindMethod to new PyObject_GenericGetAttr attribute access.
  Fixes #1087735.
........
  r60145 | georg.brandl | 2008-01-20 20:40:58 +0100 (Sun, 20 Jan 2008) | 2 lines

  Add blurb about executable scripts on Windows. #760657.
........
  r60146 | georg.brandl | 2008-01-20 20:48:40 +0100 (Sun, 20 Jan 2008) | 2 lines

  #1219903: fix tp_richcompare docs.
........
  r60147 | georg.brandl | 2008-01-20 22:10:08 +0100 (Sun, 20 Jan 2008) | 2 lines

  Fix markup.
........
  r60148 | gregory.p.smith | 2008-01-21 08:11:11 +0100 (Mon, 21 Jan 2008) | 14 lines

  Provide a sanity check during PyThreadState_DeleteCurrent() and
  PyThreadState_Delete() to avoid an infinite loop when the tstate list
  is messed up and has somehow becomes circular and does not contain the
  current thread.

  I don't know how this happens but it does, *very* rarely.  On more than
  one hardware platform.  I have not been able to reproduce it manually.

  Attaching to a process where its happening: it has always been in an
  infinite loop over a single element tstate list that is not the tstate
  we're looking to delete.  It has been in t_bootstrap()'s call to
  PyThreadState_DeleteCurrent() as a pthread is exiting.
........
  r60149 | georg.brandl | 2008-01-21 11:24:59 +0100 (Mon, 21 Jan 2008) | 2 lines

  #1269: fix a bug in pstats.add_callers() and add a unit test file for pstats.
........
This commit is contained in:
Christian Heimes 2008-01-21 11:20:28 +00:00
parent 9bd667ad03
commit e1c981161c
7 changed files with 97 additions and 22 deletions

View File

@ -649,13 +649,19 @@ The following three fields only exist if the
.. cmember:: richcmpfunc PyTypeObject.tp_richcompare
An optional pointer to the rich comparison function.
An optional pointer to the rich comparison function, whose signature is
``PyObject *tp_richcompare(PyObject *a, PyObject *b, int op)``.
The signature is the same as for :cfunc:`PyObject_RichCompare`. The function
should return the result of the comparison (usually ``Py_True`` or
``Py_False``). If the comparison is undefined, it must return
``Py_NotImplemented``, if another error occurred it must return ``NULL`` and set
an exception condition.
The function should return the result of the comparison (usually ``Py_True``
or ``Py_False``). If the comparison is undefined, it must return
``Py_NotImplemented``, if another error occurred it must return ``NULL`` and
set an exception condition.
.. note::
If you want to implement a type for which only a limited set of
comparisons makes sense (e.g. ``==`` and ``!=``, but not ``<`` and
friends), directly raise :exc:`TypeError` in the rich comparison function.
This field is inherited by subtypes together with :attr:`tp_compare` and
:attr:`tp_hash`: a subtype inherits all three of :attr:`tp_compare`,
@ -681,10 +687,10 @@ The following three fields only exist if the
| :const:`Py_GE` | ``>=`` |
+----------------+------------+
The next field only exists if the :const:`Py_TPFLAGS_HAVE_WEAKREFS` flag bit is
set.
.. cmember:: long PyTypeObject.tp_weaklistoffset
If the instances of this type are weakly referenceable, this field is greater

View File

@ -169,6 +169,12 @@ The script can be given an executable mode, or permission, using the
$ chmod +x myscript.py
On Windows systems, there is no notion of an "executable mode". The Python
installer automatically associates ``.py`` files with ``python.exe`` so that
a double-click on a Python file will run it as a script. The extension can
also be ``.pyw``, in that case, the console window that normally appears is
suppressed.
Source Code Encoding
--------------------

View File

@ -297,14 +297,14 @@ These environment variables influence Python's behavior.
.. envvar:: PYTHONHOME
Change the location of the standard Python libraries. By default, the
libraries are searched in :file:`{prefix}/lib/python<version>` and
:file:`{exec_prefix}/lib/python<version>`, where :file:`{prefix}` and
libraries are searched in :file:`{prefix}/lib/python{version}` and
:file:`{exec_prefix}/lib/python{version}`, where :file:`{prefix}` and
:file:`{exec_prefix}` are installation-dependent directories, both defaulting
to :file:`/usr/local`.
When :envvar:`PYTHONHOME` is set to a single directory, its value replaces
both :file:`{prefix}` and :file:`{exec_prefix}`. To specify different values
for these, set :envvar:`PYTHONHOME` to :file:`{prefix}:{exec_prefix}``.
for these, set :envvar:`PYTHONHOME` to :file:`{prefix}:{exec_prefix}`.
.. envvar:: PYTHONPATH
@ -314,7 +314,7 @@ These environment variables influence Python's behavior.
colons. Non-existent directories are silently ignored.
The default search path is installation dependent, but generally begins with
:file:`{prefix}/lib/python<version>`` (see :envvar:`PYTHONHOME` above). It
:file:`{prefix}/lib/python{version}`` (see :envvar:`PYTHONHOME` above). It
is *always* appended to :envvar:`PYTHONPATH`.
If a script argument is given, the directory containing the script is

View File

@ -511,7 +511,8 @@ def add_callers(target, source):
new_callers[func] = caller
for func, caller in source.items():
if func in new_callers:
new_callers[func] = caller + new_callers[func]
new_callers[func] = tuple([i[0] + i[1] for i in
zip(caller, new_callers[func])])
else:
new_callers[func] = caller
return new_callers

26
Lib/test/test_pstats.py Normal file
View File

@ -0,0 +1,26 @@
import unittest
from test import test_support
import pstats
class AddCallersTestCase(unittest.TestCase):
"""Tests for pstats.add_callers helper."""
def test_combine_results(self):
"""pstats.add_callers should combine the call results of both target
and source by adding the call time. See issue1269."""
target = {"a": (1, 2, 3, 4)}
source = {"a": (1, 2, 3, 4), "b": (5, 6, 7, 8)}
new_callers = pstats.add_callers(target, source)
self.assertEqual(new_callers, {'a': (2, 4, 6, 8), 'b': (5, 6, 7, 8)})
def test_main():
test_support.run_unittest(
AddCallersTestCase
)
if __name__ == "__main__":
test_main()

View File

@ -666,12 +666,6 @@ mmap_buffer_releasebuf(mmap_object *self, Py_buffer *view)
self->exports--;
}
static PyObject *
mmap_object_getattr(mmap_object *self, char *name)
{
return Py_FindMethod(mmap_object_methods, (PyObject *)self, name);
}
static Py_ssize_t
mmap_length(mmap_object *self)
{
@ -901,6 +895,30 @@ static PyBufferProcs mmap_as_buffer = {
(releasebufferproc)mmap_buffer_releasebuf,
};
PyDoc_STRVAR(mmap_doc,
"Windows: mmap(fileno, length[, tagname[, access[, offset]]])\n\
\n\
Maps length bytes from the file specified by the file handle fileno,\n\
and returns a mmap object. If length is larger than the current size\n\
of the file, the file is extended to contain length bytes. If length\n\
is 0, the maximum length of the map is the current size of the file,\n\
except that if the file is empty Windows raises an exception (you cannot\n\
create an empty mapping on Windows).\n\
\n\
Unix: mmap(fileno, length[, flags[, prot[, access[, offset]]]])\n\
\n\
Maps length bytes from the file specified by the file descriptor fileno,\n\
and returns a mmap object. If length is 0, the maximum length of the map\n\
will be the current size of the file when mmap is called.\n\
flags specifies the nature of the mapping. MAP_PRIVATE creates a\n\
private copy-on-write mapping, so changes to the contents of the mmap\n\
object will be private to this process, and MAP_SHARED`creates a mapping\n\
that's shared with all other processes mapping the same areas of the file.\n\
The default value is MAP_SHARED.\n\
\n\
To map anonymous memory, pass -1 as the fileno (both versions).");
static PyTypeObject mmap_object_type = {
PyVarObject_HEAD_INIT(0, 0) /* patched in module init */
"mmap.mmap", /* tp_name */
@ -909,7 +927,7 @@ static PyTypeObject mmap_object_type = {
/* methods */
(destructor) mmap_object_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc) mmap_object_getattr, /* tp_getattr */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
@ -919,11 +937,19 @@ static PyTypeObject mmap_object_type = {
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
PyObject_GenericGetAttr, /*tp_getattro*/
0, /*tp_setattro*/
&mmap_as_buffer, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
mmap_doc, /*tp_doc*/
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
mmap_object_methods, /* tp_methods */
};
@ -1265,7 +1291,7 @@ new_mmap_object(PyObject *self, PyObject *args, PyObject *kwdict)
/* List of functions exported by this module */
static struct PyMethodDef mmap_functions[] = {
{"mmap", (PyCFunction) new_mmap_object,
METH_VARARGS|METH_KEYWORDS},
METH_VARARGS|METH_KEYWORDS, mmap_doc},
{NULL, NULL} /* Sentinel */
};

View File

@ -242,6 +242,7 @@ tstate_delete_common(PyThreadState *tstate)
{
PyInterpreterState *interp;
PyThreadState **p;
PyThreadState *prev_p = NULL;
if (tstate == NULL)
Py_FatalError("PyThreadState_Delete: NULL tstate");
interp = tstate->interp;
@ -254,6 +255,15 @@ tstate_delete_common(PyThreadState *tstate)
"PyThreadState_Delete: invalid tstate");
if (*p == tstate)
break;
if (*p == prev_p)
Py_FatalError(
"PyThreadState_Delete: small circular list(!)"
" and tstate not found.");
prev_p = *p;
if ((*p)->next == interp->tstate_head)
Py_FatalError(
"PyThreadState_Delete: circular list(!) and"
" tstate not found.");
}
*p = tstate->next;
HEAD_UNLOCK();