summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/c-api/method.rst6
-rw-r--r--Doc/c-api/set.rst4
-rw-r--r--Doc/c-api/tuple.rst4
-rw-r--r--Doc/c-api/type.rst2
-rw-r--r--Doc/c-api/unicode.rst5
-rw-r--r--Doc/library/ctypes.rst1
-rw-r--r--Doc/library/decimal.rst63
-rw-r--r--Doc/whatsnew/2.6.rst2
-rw-r--r--Include/classobject.h1
-rw-r--r--Include/frameobject.h2
-rw-r--r--Include/methodobject.h2
-rw-r--r--Include/tupleobject.h2
-rw-r--r--Include/unicodeobject.h4
-rw-r--r--Lib/SocketServer.py6
-rwxr-xr-xLib/UserString.py2
-rw-r--r--Lib/idlelib/EditorWindow.py55
-rw-r--r--Lib/idlelib/NEWS.txt6
-rw-r--r--Lib/idlelib/ScriptBinding.py13
-rw-r--r--Lib/idlelib/configDialog.py3
-rw-r--r--Lib/test/test_complex.py14
-rw-r--r--Lib/test/test_descr.py17
-rw-r--r--Lib/test/test_gc.py22
-rw-r--r--Lib/test/test_mmap.py7
-rw-r--r--Misc/NEWS39
-rwxr-xr-xMisc/build.sh28
-rw-r--r--Modules/gcmodule.c22
-rw-r--r--Modules/mmapmodule.c4
-rw-r--r--Objects/abstract.c30
-rw-r--r--Objects/classobject.c13
-rw-r--r--Objects/complexobject.c47
-rw-r--r--Objects/descrobject.c2
-rw-r--r--Objects/frameobject.c14
-rw-r--r--Objects/methodobject.c13
-rw-r--r--Objects/tupleobject.c25
-rw-r--r--Objects/unicodeobject.c33
35 files changed, 401 insertions, 112 deletions
diff --git a/Doc/c-api/method.rst b/Doc/c-api/method.rst
index 9d25571..9ee49ba 100644
--- a/Doc/c-api/method.rst
+++ b/Doc/c-api/method.rst
@@ -92,3 +92,9 @@ no longer available.
.. cfunction:: PyObject* PyMethod_GET_SELF(PyObject *meth)
Macro version of :cfunc:`PyMethod_Self` which avoids error checking.
+
+
+.. cfunction:: int PyMethod_ClearFreeList(void)
+
+ Clear the free list. Return the total number of freed items.
+
diff --git a/Doc/c-api/set.rst b/Doc/c-api/set.rst
index 14d8eab..1560717 100644
--- a/Doc/c-api/set.rst
+++ b/Doc/c-api/set.rst
@@ -54,15 +54,11 @@ the constructor functions work with any iterable Python object.
Return true if *p* is a :class:`set` object or an instance of a subtype.
- .. versionadded:: 2.6
-
.. cfunction:: int PyFrozenSet_Check(PyObject *p)
Return true if *p* is a :class:`frozenset` object or an instance of a
subtype.
- .. versionadded:: 2.6
-
.. cfunction:: int PyAnySet_Check(PyObject *p)
Return true if *p* is a :class:`set` object, a :class:`frozenset` object, or an
diff --git a/Doc/c-api/tuple.rst b/Doc/c-api/tuple.rst
index eb661fb..c0e53fb 100644
--- a/Doc/c-api/tuple.rst
+++ b/Doc/c-api/tuple.rst
@@ -105,3 +105,7 @@ Tuple Objects
this function. If the object referenced by ``*p`` is replaced, the original
``*p`` is destroyed. On failure, returns ``-1`` and sets ``*p`` to *NULL*, and
raises :exc:`MemoryError` or :exc:`SystemError`.
+
+.. cfunction:: int PyMethod_ClearFreeList(void)
+
+ Clear the free list. Return the total number of freed items.
diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst
index d1d4e45..bc0eeef 100644
--- a/Doc/c-api/type.rst
+++ b/Doc/c-api/type.rst
@@ -37,8 +37,6 @@ Type Objects
Clears the internal lookup cache. Return the current version tag.
- .. versionadded:: 2.6
-
.. cfunction:: int PyType_HasFeature(PyObject *o, int feature)
diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
index 886ba65..448cf68 100644
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -83,6 +83,11 @@ access internal read-only data of Unicode objects:
Return a pointer to the internal buffer of the object. *o* has to be a
:ctype:`PyUnicodeObject` (not checked).
+
+.. cfunction:: int PyUnicode_ClearFreeList(void)
+
+ Clear the free list. Return the total number of freed items.
+
Unicode provides many different character properties. The most often needed ones
are available through these macros which are mapped to C functions depending on
the Python configuration.
diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst
index 3c305ed..b2d672f 100644
--- a/Doc/library/ctypes.rst
+++ b/Doc/library/ctypes.rst
@@ -2010,7 +2010,6 @@ Fundamental data types
their methods and attributes.
.. versionchanged:: 2.6
-
ctypes data types that are not and do not contain pointers can
now be pickled.
diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst
index afba964..b0845e9 100644
--- a/Doc/library/decimal.rst
+++ b/Doc/library/decimal.rst
@@ -1352,19 +1352,15 @@ to work with the :class:`Decimal` class::
'<.02>'
"""
- q = Decimal((0, (1,), -places)) # 2 places --> '0.01'
- sign, digits, exp = value.quantize(q).as_tuple()
- assert exp == -places
+ q = Decimal(10) ** -places # 2 places --> '0.01'
+ sign, digits, exp = value.quantize(q).as_tuple()
result = []
digits = map(str, digits)
build, next = result.append, digits.pop
if sign:
build(trailneg)
for i in range(places):
- if digits:
- build(next())
- else:
- build('0')
+ build(next() if digits else '0')
build(dp)
i = 0
while digits:
@@ -1374,12 +1370,8 @@ to work with the :class:`Decimal` class::
i = 0
build(sep)
build(curr)
- if sign:
- build(neg)
- else:
- build(pos)
- result.reverse()
- return ''.join(result)
+ build(neg if sign else pos)
+ return ''.join(reversed(result))
def pi():
"""Compute Pi to the current precision.
@@ -1482,7 +1474,7 @@ Decimal FAQ
Q. It is cumbersome to type ``decimal.Decimal('1234.5')``. Is there a way to
minimize typing when using the interactive interpreter?
-\A. Some users abbreviate the constructor to just a single letter::
+A. Some users abbreviate the constructor to just a single letter::
>>> D = decimal.Decimal
>>> D('1.23') + D('3.45')
@@ -1513,9 +1505,36 @@ the :const:`Inexact` trap is set, it is also useful for validation::
Q. Once I have valid two place inputs, how do I maintain that invariant
throughout an application?
-A. Some operations like addition and subtraction automatically preserve fixed
-point. Others, like multiplication and division, change the number of decimal
-places and need to be followed-up with a :meth:`quantize` step.
+A. Some operations like addition, subtraction, and multiplication by an integer
+will automatically preserve fixed point. Others operations, like division and
+non-integer multiplication, will change the number of decimal places and need to
+be followed-up with a :meth:`quantize` step::
+
+ >>> a = Decimal('102.72') # Initial fixed-point values
+ >>> b = Decimal('3.17')
+ >>> a + b # Addition preserves fixed-point
+ Decimal('105.89')
+ >>> a - b
+ Decimal('99.55')
+ >>> a * 42 # So does integer multiplication
+ Decimal('4314.24')
+ >>> (a * b).quantize(TWOPLACES) # Must quantize non-integer multiplication
+ Decimal('325.62')
+ >>> (b / a).quantize(TWOPLACES) # And quantize division
+ Decimal('0.03')
+
+In developing fixed-point applications, it is convenient to define functions
+to handle the :meth:`quantize` step::
+
+ >>> def mul(x, y, fp=TWOPLACES):
+ ... return (x * y).quantize(fp)
+ >>> def div(x, y, fp=TWOPLACES):
+ ... return (x / y).quantize(fp)
+
+ >>> mul(a, b) # Automatically preserve fixed-point
+ Decimal('325.62')
+ >>> div(b, a)
+ Decimal('0.03')
Q. There are many ways to express the same value. The numbers :const:`200`,
:const:`200.000`, :const:`2E2`, and :const:`.02E+4` all have the same value at
@@ -1537,6 +1556,16 @@ of significant places in the coefficient. For example, expressing
:const:`5.0E+3` as :const:`5000` keeps the value constant but cannot show the
original's two-place significance.
+If an application does not care about tracking significance, it is easy to
+remove the exponent and trailing zeroes, losing signficance, but keeping the
+value unchanged::
+
+ >>> def remove_exponent(d):
+ ... return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
+
+ >>> remove_exponent(Decimal('5E+3'))
+ Decimal('5000')
+
Q. Is there a way to convert a regular float to a :class:`Decimal`?
A. Yes, all binary floating point numbers can be exactly expressed as a
diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst
index d37c5ac..dae9b09 100644
--- a/Doc/whatsnew/2.6.rst
+++ b/Doc/whatsnew/2.6.rst
@@ -825,7 +825,7 @@ complete list of changes, or look through the CVS logs for all the details.
int int
>>> var._asdict()
{'size': 4, 'type': 'int', 'id': 1, 'name': 'frequency'}
- >>> v2 = var._replace('name', 'amplitude')
+ >>> v2 = var._replace(name='amplitude')
>>> v2
variable(id=1, name='amplitude', type='int', size=4)
diff --git a/Include/classobject.h b/Include/classobject.h
index f6789d1..b7eebe5 100644
--- a/Include/classobject.h
+++ b/Include/classobject.h
@@ -31,6 +31,7 @@ PyAPI_FUNC(PyObject *) PyMethod_Self(PyObject *);
#define PyMethod_GET_SELF(meth) \
(((PyMethodObject *)meth) -> im_self)
+PyAPI_FUNC(int) PyMethod_ClearFreeList(void);
typedef struct {
PyObject_HEAD
diff --git a/Include/frameobject.h b/Include/frameobject.h
index 05877f9..d2afe8b 100644
--- a/Include/frameobject.h
+++ b/Include/frameobject.h
@@ -73,6 +73,8 @@ PyAPI_FUNC(PyObject **) PyFrame_ExtendStack(PyFrameObject *, int, int);
PyAPI_FUNC(void) PyFrame_LocalsToFast(PyFrameObject *, int);
PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *);
+PyAPI_FUNC(int) PyFrame_ClearFreeList(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/Include/methodobject.h b/Include/methodobject.h
index 48e780e..cd1d265 100644
--- a/Include/methodobject.h
+++ b/Include/methodobject.h
@@ -85,6 +85,8 @@ typedef struct {
PyObject *m_module; /* The __module__ attribute, can be anything */
} PyCFunctionObject;
+PyAPI_FUNC(int) PyCFunction_ClearFreeList(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/Include/tupleobject.h b/Include/tupleobject.h
index 018ef2f..7a887d1 100644
--- a/Include/tupleobject.h
+++ b/Include/tupleobject.h
@@ -53,6 +53,8 @@ PyAPI_FUNC(PyObject *) PyTuple_Pack(Py_ssize_t, ...);
/* Macro, *only* to be used to fill in brand new tuples */
#define PyTuple_SET_ITEM(op, i, v) (((PyTupleObject *)(op))->ob_item[i] = v)
+PyAPI_FUNC(int) PyTuple_ClearFreeList(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h
index 3954289..5e6c227 100644
--- a/Include/unicodeobject.h
+++ b/Include/unicodeobject.h
@@ -210,6 +210,7 @@ typedef PY_UNICODE_TYPE Py_UNICODE;
# define _PyUnicode_AsDefaultEncodedString _PyUnicodeUCS2_AsDefaultEncodedString
# define _PyUnicode_Fini _PyUnicodeUCS2_Fini
# define _PyUnicode_Init _PyUnicodeUCS2_Init
+# define PyUnicode_ClearFreeList PyUnicodeUCS2_ClearFreelist
# define _PyUnicode_IsAlpha _PyUnicodeUCS2_IsAlpha
# define _PyUnicode_IsDecimalDigit _PyUnicodeUCS2_IsDecimalDigit
# define _PyUnicode_IsDigit _PyUnicodeUCS2_IsDigit
@@ -303,6 +304,7 @@ typedef PY_UNICODE_TYPE Py_UNICODE;
# define _PyUnicode_AsDefaultEncodedString _PyUnicodeUCS4_AsDefaultEncodedString
# define _PyUnicode_Fini _PyUnicodeUCS4_Fini
# define _PyUnicode_Init _PyUnicodeUCS4_Init
+# define PyUnicode_ClearFreeList PyUnicodeUCS2_ClearFreelist
# define _PyUnicode_IsAlpha _PyUnicodeUCS4_IsAlpha
# define _PyUnicode_IsDecimalDigit _PyUnicodeUCS4_IsDecimalDigit
# define _PyUnicode_IsDigit _PyUnicodeUCS4_IsDigit
@@ -413,6 +415,8 @@ extern const unsigned char _Py_ascii_whitespace[];
extern "C" {
#endif
+PyAPI_FUNC(int) PyUnicode_ClearFreeList(void);
+
/* --- Unicode Type ------------------------------------------------------- */
typedef struct {
diff --git a/Lib/SocketServer.py b/Lib/SocketServer.py
index f62b7df..9c5d4c2 100644
--- a/Lib/SocketServer.py
+++ b/Lib/SocketServer.py
@@ -452,7 +452,11 @@ class ForkingMixIn:
except os.error:
pid = None
if not pid: break
- self.active_children.remove(pid)
+ try:
+ self.active_children.remove(pid)
+ except ValueError as e:
+ raise ValueError('%s. x=%d and list=%r' % (e.message, pid,
+ self.active_children))
def handle_timeout(self):
"""Wait for zombies after self.timeout seconds of inactivity.
diff --git a/Lib/UserString.py b/Lib/UserString.py
index 27b2b53..704ea59 100755
--- a/Lib/UserString.py
+++ b/Lib/UserString.py
@@ -162,8 +162,6 @@ class UserString(collections.Sequence):
def upper(self): return self.__class__(self.data.upper())
def zfill(self, width): return self.__class__(self.data.zfill(width))
-collections.Sequence.register(UserString)
-
class MutableString(UserString, collections.MutableSequence):
"""mutable string objects
diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py
index 0cd668a..e1d9ba3 100644
--- a/Lib/idlelib/EditorWindow.py
+++ b/Lib/idlelib/EditorWindow.py
@@ -109,16 +109,6 @@ class EditorWindow(object):
self.width = idleConf.GetOption('main','EditorWindow','width')
self.text = text = MultiCallCreator(Text)(
text_frame, name='text', padx=5, wrap='none',
- foreground=idleConf.GetHighlight(currentTheme,
- 'normal',fgBg='fg'),
- background=idleConf.GetHighlight(currentTheme,
- 'normal',fgBg='bg'),
- highlightcolor=idleConf.GetHighlight(currentTheme,
- 'hilite',fgBg='fg'),
- highlightbackground=idleConf.GetHighlight(currentTheme,
- 'hilite',fgBg='bg'),
- insertbackground=idleConf.GetHighlight(currentTheme,
- 'cursor',fgBg='fg'),
width=self.width,
height=idleConf.GetOption('main','EditorWindow','height') )
self.top.focused_widget = self.text
@@ -225,7 +215,6 @@ class EditorWindow(object):
# Making the initial values larger slows things down more often.
self.num_context_lines = 50, 500, 5000000
self.per = per = self.Percolator(text)
- self.color = None
self.undo = undo = self.UndoDelegator()
per.insertfilter(undo)
text.undo_block_start = undo.undo_block_start
@@ -236,6 +225,7 @@ class EditorWindow(object):
io.set_filename_change_hook(self.filename_change_hook)
self.good_load = False
self.set_indentation_params(False)
+ self.color = None # initialized below in self.ResetColorizer
if filename:
if os.path.exists(filename) and not os.path.isdir(filename):
if io.loadfile(filename):
@@ -247,6 +237,7 @@ class EditorWindow(object):
per.insertfilter(color)
else:
io.set_filename(filename)
+ self.ResetColorizer()
self.saved_change_hook()
self.update_recent_files_list()
self.load_extensions()
@@ -561,36 +552,42 @@ class EditorWindow(object):
self.flist.filename_changed_edit(self)
self.saved_change_hook()
self.top.update_windowlist_registry(self)
- if self.ispythonsource(self.io.filename):
- self.addcolorizer()
- else:
- self.rmcolorizer()
+ self.ResetColorizer()
- def addcolorizer(self):
+ def _addcolorizer(self):
if self.color:
return
- self.per.removefilter(self.undo)
- self.color = self.ColorDelegator()
- self.per.insertfilter(self.color)
- self.per.insertfilter(self.undo)
+ if self.ispythonsource(self.io.filename):
+ self.color = self.ColorDelegator()
+ # can add more colorizers here...
+ if self.color:
+ self.per.removefilter(self.undo)
+ self.per.insertfilter(self.color)
+ self.per.insertfilter(self.undo)
- def rmcolorizer(self):
+ def _rmcolorizer(self):
if not self.color:
return
self.color.removecolors()
- self.per.removefilter(self.undo)
self.per.removefilter(self.color)
self.color = None
- self.per.insertfilter(self.undo)
def ResetColorizer(self):
- "Update the colour theme if it is changed"
- # Called from configDialog.py
- if self.color:
- self.color = self.ColorDelegator()
- self.per.insertfilter(self.color)
+ "Update the colour theme"
+ # Called from self.filename_change_hook and from configDialog.py
+ self._rmcolorizer()
+ self._addcolorizer()
theme = idleConf.GetOption('main','Theme','name')
- self.text.config(idleConf.GetHighlight(theme, "normal"))
+ normal_colors = idleConf.GetHighlight(theme, 'normal')
+ cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg')
+ select_colors = idleConf.GetHighlight(theme, 'hilite')
+ self.text.config(
+ foreground=normal_colors['foreground'],
+ background=normal_colors['background'],
+ insertbackground=cursor_color,
+ selectforeground=select_colors['foreground'],
+ selectbackground=select_colors['background'],
+ )
IDENTCHARS = string.ascii_letters + string.digits + "_"
diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt
index cd8565c..1885421 100644
--- a/Lib/idlelib/NEWS.txt
+++ b/Lib/idlelib/NEWS.txt
@@ -45,6 +45,12 @@ What's New in IDLE 2.6a1?
*Release date: XX-XXX-200X* UNRELEASED, but merged into 3.0
+- Configured selection highlighting colors were ignored; updating highlighting
+ in the config dialog would cause non-Python files to be colored as if they
+ were Python source; improve use of ColorDelagator. Patch 1334. Tal Einat.
+
+- ScriptBinding event handlers weren't returning 'break'. Patch 2050, Tal Einat.
+
- There was an error on exit if no sys.exitfunc was defined. Issue 1647.
- Could not open files in .idlerc directory if latter was hidden on Windows.
diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py
index ae530e5..226c66c 100644
--- a/Lib/idlelib/ScriptBinding.py
+++ b/Lib/idlelib/ScriptBinding.py
@@ -55,11 +55,11 @@ class ScriptBinding:
def check_module_event(self, event):
filename = self.getfilename()
if not filename:
- return
+ return 'break'
if not self.checksyntax(filename):
- return
+ return 'break'
if not self.tabnanny(filename):
- return
+ return 'break'
def tabnanny(self, filename):
f = open(filename, 'r')
@@ -120,12 +120,12 @@ class ScriptBinding:
"""
filename = self.getfilename()
if not filename:
- return
+ return 'break'
code = self.checksyntax(filename)
if not code:
- return
+ return 'break'
if not self.tabnanny(filename):
- return
+ return 'break'
shell = self.shell
interp = shell.interp
if PyShell.use_subprocess:
@@ -148,6 +148,7 @@ class ScriptBinding:
# go to __stderr__. With subprocess, they go to the shell.
# Need to change streams in PyShell.ModifiedInterpreter.
interp.runcode(code)
+ return 'break'
def getfilename(self):
"""Get source filename. If not saved, offer to save (or create) file
diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py
index d0e4066..b750dcd 100644
--- a/Lib/idlelib/configDialog.py
+++ b/Lib/idlelib/configDialog.py
@@ -1114,15 +1114,12 @@ class ConfigDialog(Toplevel):
def ActivateConfigChanges(self):
"Dynamically apply configuration changes"
winInstances = self.parent.instance_dict.keys()
- theme = idleConf.CurrentTheme()
- cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg')
for instance in winInstances:
instance.ResetColorizer()
instance.ResetFont()
instance.set_notabs_indentwidth()
instance.ApplyKeybindings()
instance.reset_help_menu_entries()
- instance.text.configure(insertbackground=cursor_color)
def Cancel(self):
self.destroy()
diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py
index 42dc3cf..fbed4f2 100644
--- a/Lib/test/test_complex.py
+++ b/Lib/test/test_complex.py
@@ -4,6 +4,8 @@ from test import test_support
from random import random
from math import atan2
+INF = float("inf")
+NAN = float("nan")
# These tests ensure that complex math does the right thing
class ComplexTest(unittest.TestCase):
@@ -316,6 +318,18 @@ class ComplexTest(unittest.TestCase):
self.assertEqual(-6j,complex(repr(-6j)))
self.assertEqual(6j,complex(repr(6j)))
+ self.assertEqual(repr(complex(1., INF)), "(1+inf*j)")
+ self.assertEqual(repr(complex(1., -INF)), "(1-inf*j)")
+ self.assertEqual(repr(complex(INF, 1)), "(inf+1j)")
+ self.assertEqual(repr(complex(-INF, INF)), "(-inf+inf*j)")
+ self.assertEqual(repr(complex(NAN, 1)), "(nan+1j)")
+ self.assertEqual(repr(complex(1, NAN)), "(1+nan*j)")
+ self.assertEqual(repr(complex(NAN, NAN)), "(nan+nan*j)")
+
+ self.assertEqual(repr(complex(0, INF)), "inf*j")
+ self.assertEqual(repr(complex(0, -INF)), "-inf*j")
+ self.assertEqual(repr(complex(0, NAN)), "nan*j")
+
def test_neg(self):
self.assertEqual(-(1+6j), -1-6j)
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index d28a84a..288afd4 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1067,6 +1067,23 @@ order (MRO) for bases """
a.foo = 42
self.assertEqual(a.__dict__, {"foo": 42})
+ def test_slots_descriptor(self):
+ # Issue2115: slot descriptors did not correctly check
+ # the type of the given object
+ import abc
+ class MyABC(metaclass=abc.ABCMeta):
+ __slots__ = "a"
+
+ class Unrelated(object):
+ pass
+ MyABC.register(Unrelated)
+
+ u = Unrelated()
+ self.assert_(isinstance(u, MyABC))
+
+ # This used to crash
+ self.assertRaises(TypeError, MyABC.a.__set__, u, 3)
+
def test_dynamics(self):
# Testing class attribute propagation...
class D(object):
diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py
index bae0038..9d5e0ea 100644
--- a/Lib/test/test_gc.py
+++ b/Lib/test/test_gc.py
@@ -236,21 +236,33 @@ class GCTests(unittest.TestCase):
gc.disable()
gc.set_threshold(*thresholds)
+ # The following two tests are fragile:
+ # They precisely count the number of allocations,
+ # which is highly implementation-dependent.
+ # For example:
+ # - disposed tuples are not freed, but reused
+ # - the call to assertEqual somehow avoids building its args tuple
def test_get_count(self):
+ # Avoid future allocation of method object
+ assertEqual = self.assertEqual
gc.collect()
- self.assertEqual(gc.get_count(), (0, 0, 0))
+ assertEqual(gc.get_count(), (0, 0, 0))
a = dict()
- self.assertEqual(gc.get_count(), (1, 0, 0))
+ # since gc.collect(), we created two objects:
+ # the dict, and the tuple returned by get_count()
+ assertEqual(gc.get_count(), (2, 0, 0))
def test_collect_generations(self):
+ # Avoid future allocation of method object
+ assertEqual = self.assertEqual
gc.collect()
a = dict()
gc.collect(0)
- self.assertEqual(gc.get_count(), (0, 1, 0))
+ assertEqual(gc.get_count(), (0, 1, 0))
gc.collect(1)
- self.assertEqual(gc.get_count(), (0, 0, 1))
+ assertEqual(gc.get_count(), (0, 0, 1))
gc.collect(2)
- self.assertEqual(gc.get_count(), (0, 0, 0))
+ assertEqual(gc.get_count(), (0, 0, 0))
def test_trashcan(self):
class Ouch:
diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py
index f6ee371..c3f7dbb 100644
--- a/Lib/test/test_mmap.py
+++ b/Lib/test/test_mmap.py
@@ -425,6 +425,13 @@ class MmapTests(unittest.TestCase):
return mmap.mmap.__new__(klass, -1, *args, **kwargs)
anon_mmap(PAGESIZE)
+ def test_prot_readonly(self):
+ mapsize = 10
+ open(TESTFN, "wb").write(b"a"*mapsize)
+ f = open(TESTFN, "rb")
+ m = mmap.mmap(f.fileno(), mapsize, prot=mmap.PROT_READ)
+ self.assertRaises(TypeError, m.write, "foo")
+
def test_main():
run_unittest(MmapTests)
diff --git a/Misc/NEWS b/Misc/NEWS
index 9ef3407..9025aa4 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,39 @@ What's New in Python 3.0a3?
Core and Builtins
-----------------
+<<<<<<< .working
+=======
+- Issue #2115: Important speedup in setting __slot__ attributes. Also
+ prevent a possible crash: an Abstract Base Class would try to access a slot
+ on a registered virtual subclass.
+
+- Fixed repr() and str() of complex numbers with infinity or nan as real or
+ imaginary part.
+
+- Clear all free list during a gc.collect() of the highest generation in order
+ to allow pymalloc to free more arenas. Python may give back memory to the
+ OS earlier.
+
+- Issue #2045: Fix an infinite recursion triggered when printing a subclass of
+ collections.defaultdict, if its default_factory is set to a bound method.
+
+- Fixed a minor memory leak in dictobject.c. The content of the free
+ list was not freed on interpreter shutdown.
+
+- Limit free list of method and builtin function objects to 256 entries
+ each.
+
+- Patch #1953: Added ``sys._compact_freelists()`` and the C API functions
+ ``PyInt_CompactFreeList`` and ``PyFloat_CompactFreeList``
+ to compact the internal free lists of pre-allocted ints and floats.
+
+- Bug #1983: Fixed return type of fork(), fork1() and forkpty() calls.
+ Python expected the return type int but the fork familie returns pi_t.
+
+- Issue #1678380: Fix a bug that identifies 0j and -0j when they appear
+ in the same code unit.
+
+>>>>>>> .merge-right.r60845
- Issue #2025 : Add tuple.count() and tuple.index() methods to comply with
the collections.Sequence API.
@@ -67,7 +100,13 @@ Core and Builtins
Extension Modules
-----------------
+<<<<<<< .working
- Issue #1762972: Readded the reload() function as imp.reload()
+=======
+- Bug #2111: mmap segfaults when trying to write a block opened with PROT_READ
+
+- #2063: correct order of utime and stime in os.times() result on Windows.
+>>>>>>> .merge-right.r60845
Library
diff --git a/Misc/build.sh b/Misc/build.sh
index 91a8cbc..70034c4 100755
--- a/Misc/build.sh
+++ b/Misc/build.sh
@@ -92,6 +92,24 @@ update_status() {
echo "<li><a href=\"$2\">$1</a> <font size=\"-1\">($time seconds)</font></li>" >> $RESULT_FILE
}
+place_summary_first() {
+ testf=$1
+ sed -n '/^[0-9][0-9]* tests OK\./,$p' < $testf \
+ | egrep -v '\[[0-9]+ refs\]' > $testf.tmp
+ echo "" >> $testf.tmp
+ cat $testf >> $testf.tmp
+ mv $testf.tmp $testf
+}
+
+count_failures () {
+ testf=$1
+ n=`grep -ic " failed:" $testf`
+ if [ $n -eq 1 ] ; then
+ n=`grep " failed:" $testf | sed -e 's/ .*//'`
+ fi
+ echo $n
+}
+
mail_on_failure() {
if [ "$NUM_FAILURES" != "0" ]; then
dest=$FAILURE_MAILTO
@@ -187,14 +205,16 @@ if [ $err = 0 -a "$BUILD_DISABLED" != "yes" ]; then
F=make-test.out
start=`current_time`
$PYTHON $REGRTEST_ARGS $ALWAYS_SKIP >& build/$F
- NUM_FAILURES=`grep -ic " failed:" build/$F`
+ NUM_FAILURES=`count_failures build/$F`
+ place_summary_first build/$F
update_status "Testing basics ($NUM_FAILURES failures)" "$F" $start
mail_on_failure "basics" build/$F
F=make-test-opt.out
start=`current_time`
$PYTHON -O $REGRTEST_ARGS $ALWAYS_SKIP >& build/$F
- NUM_FAILURES=`grep -ic " failed:" build/$F`
+ NUM_FAILURES=`count_failures build/$F`
+ place_summary_first build/$F
update_status "Testing opt ($NUM_FAILURES failures)" "$F" $start
mail_on_failure "opt" build/$F
@@ -206,6 +226,7 @@ if [ $err = 0 -a "$BUILD_DISABLED" != "yes" ]; then
$PYTHON $REGRTEST_ARGS -R 4:3:$REFLOG -u network $LEAKY_SKIPS >& build/$F
LEAK_PAT="($LEAKY_TESTS|sum=0)"
NUM_FAILURES=`egrep -vc "$LEAK_PAT" $REFLOG`
+ place_summary_first build/$F
update_status "Testing refleaks ($NUM_FAILURES failures)" "$F" $start
mail_on_failure "refleak" $REFLOG "$LEAK_PAT"
@@ -215,7 +236,8 @@ if [ $err = 0 -a "$BUILD_DISABLED" != "yes" ]; then
## skip curses when running from cron since there's no terminal
## skip sound since it's not setup on the PSF box (/dev/dsp)
$PYTHON $REGRTEST_ARGS -uall -x test_curses test_linuxaudiodev test_ossaudiodev $_ALWAYS_SKIP >& build/$F
- NUM_FAILURES=`grep -ic " failed:" build/$F`
+ NUM_FAILURES=`count_failures build/$F`
+ place_summary_first build/$F
update_status "Testing all except curses and sound ($NUM_FAILURES failures)" "$F" $start
mail_on_failure "all" build/$F
fi
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index d449a2b..f332231 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -19,6 +19,7 @@
*/
#include "Python.h"
+#include "frameobject.h" /* for PyFrame_ClearFreeList */
/* Get an object's GC head */
#define AS_GC(o) ((PyGC_Head *)(o)-1)
@@ -687,6 +688,21 @@ delete_garbage(PyGC_Head *collectable, PyGC_Head *old)
}
}
+/* Clear all free lists
+ * All free lists are cleared during the collection of the highest generation.
+ * Allocated items in the free list may keep a pymalloc arena occupied.
+ * Clearing the free lists may give back memory to the OS earlier.
+ */
+static void
+clear_freelists(void)
+{
+ (void)PyMethod_ClearFreeList();
+ (void)PyFrame_ClearFreeList();
+ (void)PyCFunction_ClearFreeList();
+ (void)PyTuple_ClearFreeList();
+ (void)PyUnicode_ClearFreeList();
+}
+
/* This is the main function. Read this to understand how the
* collection process works. */
static Py_ssize_t
@@ -839,6 +855,12 @@ collect(int generation)
*/
(void)handle_finalizers(&finalizers, old);
+ /* Clear free list only during the collection of the higest
+ * generation */
+ if (generation == NUM_GENERATIONS-1) {
+ clear_freelists();
+ }
+
if (PyErr_Occurred()) {
if (gc_str == NULL)
gc_str = PyUnicode_FromString("garbage collection");
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index c83af0d..b77dda5 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -1043,6 +1043,10 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
"mmap invalid access parameter.");
}
+ if (prot == PROT_READ) {
+ access = ACCESS_READ;
+ }
+
#ifdef HAVE_FSTAT
# ifdef __VMS
/* on OpenVMS we must ensure that all bytes are written to the file */
diff --git a/Objects/abstract.c b/Objects/abstract.c
index b50b43e..bb6c301 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1405,13 +1405,19 @@ PyNumber_Float(PyObject *o)
PyObject *
PyNumber_ToBase(PyObject *n, int base)
{
- PyObject *res;
+ PyObject *res = NULL;
PyObject *index = PyNumber_Index(n);
if (!index)
return NULL;
- assert(PyLong_Check(index));
- res = _PyLong_Format(index, base);
+ if (PyLong_Check(index))
+ res = _PyLong_Format(index, base);
+ else
+ /* It should not be possible to get here, as
+ PyNumber_Index already has a check for the same
+ condition */
+ PyErr_SetString(PyExc_ValueError, "PyNumber_ToBase: index not "
+ "int or long");
Py_DECREF(index);
return res;
}
@@ -2540,10 +2546,17 @@ recursive_isinstance(PyObject *inst, PyObject *cls, int recursion_depth)
int
PyObject_IsInstance(PyObject *inst, PyObject *cls)
{
+ static PyObject *name = NULL;
PyObject *t, *v, *tb;
PyObject *checker;
PyErr_Fetch(&t, &v, &tb);
- checker = PyObject_GetAttrString(cls, "__instancecheck__");
+
+ if (name == NULL) {
+ name = PyUnicode_InternFromString("__instancecheck__");
+ if (name == NULL)
+ return -1;
+ }
+ checker = PyObject_GetAttr(cls, name);
PyErr_Restore(t, v, tb);
if (checker != NULL) {
PyObject *res;
@@ -2611,10 +2624,17 @@ recursive_issubclass(PyObject *derived, PyObject *cls, int recursion_depth)
int
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
{
+ static PyObject *name = NULL;
PyObject *t, *v, *tb;
PyObject *checker;
PyErr_Fetch(&t, &v, &tb);
- checker = PyObject_GetAttrString(cls, "__subclasscheck__");
+
+ if (name == NULL) {
+ name = PyUnicode_InternFromString("__subclasscheck__");
+ if (name == NULL)
+ return -1;
+ }
+ checker = PyObject_GetAttr(cls, name);
PyErr_Restore(t, v, tb);
if (checker != NULL) {
PyObject *res;
diff --git a/Objects/classobject.c b/Objects/classobject.c
index be7ba2d..0e131eb 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -382,9 +382,11 @@ PyTypeObject PyMethod_Type = {
/* Clear out the free list */
-void
-PyMethod_Fini(void)
+int
+PyMethod_ClearFreeList(void)
{
+ int freelist_size = numfree;
+
while (free_list) {
PyMethodObject *im = free_list;
free_list = (PyMethodObject *)(im->im_self);
@@ -392,6 +394,13 @@ PyMethod_Fini(void)
numfree--;
}
assert(numfree == 0);
+ return freelist_size;
+}
+
+void
+PyMethod_Fini(void)
+{
+ (void)PyMethod_ClearFreeList();
}
/* ------------------------------------------------------------------------
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index a08253e..a47cd54 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -314,16 +314,49 @@ complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision)
{
char format[32];
if (v->cval.real == 0.) {
- PyOS_snprintf(format, sizeof(format), "%%.%ig", precision);
- PyOS_ascii_formatd(buf, bufsz - 1, format, v->cval.imag);
- strncat(buf, "j", 1);
+ if (!Py_IS_FINITE(v->cval.imag)) {
+ if (Py_IS_NAN(v->cval.imag))
+ strncpy(buf, "nan*j", 6);
+ /* else if (copysign(1, v->cval.imag) == 1) */
+ else if (v->cval.imag > 0)
+ strncpy(buf, "inf*j", 6);
+ else
+ strncpy(buf, "-inf*j", 7);
+ }
+ else {
+ PyOS_snprintf(format, sizeof(format), "%%.%ig", precision);
+ PyOS_ascii_formatd(buf, bufsz - 1, format, v->cval.imag);
+ strncat(buf, "j", 1);
+ }
} else {
char re[64], im[64];
/* Format imaginary part with sign, real part without */
- PyOS_snprintf(format, sizeof(format), "%%.%ig", precision);
- PyOS_ascii_formatd(re, sizeof(re), format, v->cval.real);
- PyOS_snprintf(format, sizeof(format), "%%+.%ig", precision);
- PyOS_ascii_formatd(im, sizeof(im), format, v->cval.imag);
+ if (!Py_IS_FINITE(v->cval.real)) {
+ if (Py_IS_NAN(v->cval.real))
+ strncpy(re, "nan", 4);
+ /* else if (copysign(1, v->cval.real) == 1) */
+ else if (v->cval.real > 0)
+ strncpy(re, "inf", 4);
+ else
+ strncpy(re, "-inf", 5);
+ }
+ else {
+ PyOS_snprintf(format, sizeof(format), "%%.%ig", precision);
+ PyOS_ascii_formatd(re, sizeof(re), format, v->cval.real);
+ }
+ if (!Py_IS_FINITE(v->cval.imag)) {
+ if (Py_IS_NAN(v->cval.imag))
+ strncpy(im, "+nan*", 6);
+ /* else if (copysign(1, v->cval.imag) == 1) */
+ else if (v->cval.imag > 0)
+ strncpy(im, "+inf*", 6);
+ else
+ strncpy(im, "-inf*", 6);
+ }
+ else {
+ PyOS_snprintf(format, sizeof(format), "%%+.%ig", precision);
+ PyOS_ascii_formatd(im, sizeof(im), format, v->cval.imag);
+ }
PyOS_snprintf(buf, bufsz, "(%s%sj)", re, im);
}
}
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 0926817..17bdf5c 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -168,7 +168,7 @@ descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
int *pres)
{
assert(obj != NULL);
- if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
+ if (!PyObject_TypeCheck(obj, descr->d_type)) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' for '%.100s' objects "
"doesn't apply to '%.100s' object",
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 658ce1d..7815f92 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -897,10 +897,11 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
}
/* Clear out the free list */
-
-void
-PyFrame_Fini(void)
+int
+PyFrame_ClearFreeList(void)
{
+ int freelist_size = numfree;
+
while (free_list != NULL) {
PyFrameObject *f = free_list;
free_list = free_list->f_back;
@@ -908,6 +909,13 @@ PyFrame_Fini(void)
--numfree;
}
assert(numfree == 0);
+ return freelist_size;
+}
+
+void
+PyFrame_Fini(void)
+{
+ (void)PyFrame_ClearFreeList();
Py_XDECREF(builtin_object);
builtin_object = NULL;
}
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 7a82d89..2c1db73 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -319,9 +319,11 @@ Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name)
/* Clear out the free list */
-void
-PyCFunction_Fini(void)
+int
+PyCFunction_ClearFreeList(void)
{
+ int freelist_size = numfree;
+
while (free_list) {
PyCFunctionObject *v = free_list;
free_list = (PyCFunctionObject *)(v->m_self);
@@ -329,6 +331,13 @@ PyCFunction_Fini(void)
numfree--;
}
assert(numfree == 0);
+ return freelist_size;
+}
+
+void
+PyCFunction_Fini(void)
+{
+ (void)PyCFunction_ClearFreeList();
}
/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index df69db9..9a53cfa 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -807,19 +807,18 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
return 0;
}
-void
-PyTuple_Fini(void)
+int
+PyTuple_ClearFreeList(void)
{
+ int freelist_size = 0;
#if PyTuple_MAXSAVESIZE > 0
int i;
-
- Py_XDECREF(free_list[0]);
- free_list[0] = NULL;
-
for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {
PyTupleObject *p, *q;
p = free_list[i];
+ freelist_size += numfree[i];
free_list[i] = NULL;
+ numfree[i] = 0;
while (p) {
q = p;
p = (PyTupleObject *)(p->ob_item[0]);
@@ -827,6 +826,20 @@ PyTuple_Fini(void)
}
}
#endif
+ return freelist_size;
+}
+
+void
+PyTuple_Fini(void)
+{
+#if PyTuple_MAXSAVESIZE > 0
+ /* empty tuples are used all over the place and applications may
+ * rely on the fact that an empty tuple is a singleton. */
+ Py_XDECREF(free_list[0]);
+ free_list[0] = NULL;
+
+ (void)PyTuple_ClearFreeList();
+#endif
}
/*********************** Tuple Iterator **************************/
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 4f0de1e..86d8b54 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -9111,10 +9111,29 @@ void _PyUnicode_Init(void)
/* Finalize the Unicode implementation */
+int
+PyUnicode_ClearFreeList(void)
+{
+ int freelist_size = numfree;
+ PyUnicodeObject *u;
+
+ for (u = free_list; u != NULL;) {
+ PyUnicodeObject *v = u;
+ u = *(PyUnicodeObject **)u;
+ if (v->str)
+ PyMem_DEL(v->str);
+ Py_XDECREF(v->defenc);
+ PyObject_Del(v);
+ numfree--;
+ }
+ free_list = NULL;
+ assert(numfree == 0);
+ return freelist_size;
+}
+
void
_PyUnicode_Fini(void)
{
- PyUnicodeObject *u;
int i;
Py_XDECREF(unicode_empty);
@@ -9126,17 +9145,7 @@ _PyUnicode_Fini(void)
unicode_latin1[i] = NULL;
}
}
-
- for (u = free_list; u != NULL;) {
- PyUnicodeObject *v = u;
- u = *(PyUnicodeObject **)u;
- if (v->str)
- PyMem_DEL(v->str);
- Py_XDECREF(v->defenc);
- PyObject_Del(v);
- }
- free_list = NULL;
- numfree = 0;
+ (void)PyUnicode_ClearFreeList();
}
void