summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/c-api/module.rst8
-rw-r--r--Doc/library/collections.rst11
-rw-r--r--Doc/library/ftplib.rst20
-rw-r--r--Doc/library/os.path.rst4
-rw-r--r--Doc/tutorial/inputoutput.rst19
-rw-r--r--Doc/whatsnew/2.6.rst64
-rw-r--r--Include/genobject.h3
-rw-r--r--Include/unicodeobject.h2
-rw-r--r--Lib/bsddb/test/test_associate.py10
-rw-r--r--Lib/bsddb/test/test_compare.py8
-rw-r--r--Lib/bsddb/test/test_cursor_pget_bug.py7
-rw-r--r--Lib/bsddb/test/test_pickle.py6
-rw-r--r--Lib/bsddb/test/test_sequence.py7
-rw-r--r--Lib/bsddb/test/test_thread.py12
-rwxr-xr-xLib/rational.py37
-rw-r--r--Lib/re.py7
-rw-r--r--Lib/test/test_asynchat.py46
-rw-r--r--Lib/test/test_dict.py8
-rw-r--r--Lib/test/test_generators.py20
-rw-r--r--Lib/test/test_rational.py40
-rw-r--r--Lib/test/test_resource.py10
-rw-r--r--Lib/test/test_telnetlib.py11
-rw-r--r--Lib/test/test_urllibnet.py40
-rw-r--r--Lib/test/test_xmlrpc.py42
-rw-r--r--Lib/test/test_zipfile.py1
-rw-r--r--Modules/_cursesmodule.c11
-rw-r--r--Modules/mathmodule.c6
-rw-r--r--Modules/mmapmodule.c44
-rw-r--r--Objects/dictobject.c2
-rw-r--r--Objects/genobject.c5
-rw-r--r--Objects/listobject.c13
-rw-r--r--Objects/setobject.c14
-rw-r--r--setup.py9
33 files changed, 376 insertions, 171 deletions
diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst
index 5ccdc63..9be2a11 100644
--- a/Doc/c-api/module.rst
+++ b/Doc/c-api/module.rst
@@ -18,12 +18,12 @@ There are only a few functions special to module objects.
is exposed to Python programs as ``types.ModuleType``.
-.. cmacro:: int PyModule_Check(PyObject *p)
+.. cfunction:: int PyModule_Check(PyObject *p)
Return true if *p* is a module object, or a subtype of a module object.
-.. cmacro:: int PyModule_CheckExact(PyObject *p)
+.. cfunction:: int PyModule_CheckExact(PyObject *p)
Return true if *p* is a module object, but not a subtype of
:cdata:`PyModule_Type`.
@@ -94,7 +94,7 @@ There are only a few functions special to module objects.
null-terminated. Return ``-1`` on error, ``0`` on success.
-.. cmacro:: int PyModule_AddIntMacro(PyObject *module, macro)
+.. cfunction:: int PyModule_AddIntMacro(PyObject *module, macro)
Add an int constant to *module*. The name and the value are taken from
*macro*. For example ``PyModule_AddConstant(module, AF_INET)`` adds the int
@@ -102,7 +102,7 @@ There are only a few functions special to module objects.
Return ``-1`` on error, ``0`` on success.
-.. cmacro:: int PyModule_AddStringMacro(PyObject *module, macro)
+.. cfunction:: int PyModule_AddStringMacro(PyObject *module, macro)
Add a string constant to *module*.
diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst
index d138d23..e13e32b 100644
--- a/Doc/library/collections.rst
+++ b/Doc/library/collections.rst
@@ -557,16 +557,7 @@ a fixed-width print format::
Point: x= 3.000 y= 4.000 hypot= 5.000
Point: x=14.000 y= 0.714 hypot=14.018
-Another use for subclassing is to replace performance critcal methods with
-faster versions that bypass error-checking::
-
- class Point(namedtuple('Point', 'x y')):
- __slots__ = ()
- _make = classmethod(tuple.__new__)
- def _replace(self, _map=map, **kwds):
- return self._make(_map(kwds.get, ('x', 'y'), self))
-
-The subclasses shown above set ``__slots__`` to an empty tuple. This keeps
+The subclass shown above sets ``__slots__`` to an empty tuple. This keeps
keep memory requirements low by preventing the creation of instance dictionaries.
diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst
index 2c06ac7..9e99190 100644
--- a/Doc/library/ftplib.rst
+++ b/Doc/library/ftplib.rst
@@ -176,11 +176,12 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
.. method:: FTP.retrlines(command[, callback])
- Retrieve a file or directory listing in ASCII transfer mode. *command* should be
- an appropriate ``RETR`` command (see :meth:`retrbinary`) or a ``LIST`` command
- (usually just the string ``'LIST'``). The *callback* function is called for
- each line, with the trailing CRLF stripped. The default *callback* prints the
- line to ``sys.stdout``.
+ Retrieve a file or directory listing in ASCII transfer mode. *command*
+ should be an appropriate ``RETR`` command (see :meth:`retrbinary`) or a
+ command such as ``LIST``, ``NLST`` or ``MLSD`` (usually just the string
+ ``'LIST'``). The *callback* function is called for each line, with the
+ trailing CRLF stripped. The default *callback* prints the line to
+ ``sys.stdout``.
.. method:: FTP.set_pasv(boolean)
@@ -190,20 +191,23 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
it is on by default.)
-.. method:: FTP.storbinary(command, file[, blocksize])
+.. method:: FTP.storbinary(command, file[, blocksize, callback])
Store a file in binary transfer mode. *command* should be an appropriate
``STOR`` command: ``"STOR filename"``. *file* is an open file object which is
read until EOF using its :meth:`read` method in blocks of size *blocksize* to
provide the data to be stored. The *blocksize* argument defaults to 8192.
+ *callback* is an optional single parameter callable that is called
+ on each block of data after it is sent.
-.. method:: FTP.storlines(command, file)
+.. method:: FTP.storlines(command, file[, callback])
Store a file in ASCII transfer mode. *command* should be an appropriate
``STOR`` command (see :meth:`storbinary`). Lines are read until EOF from the
open file object *file* using its :meth:`readline` method to provide the data to
- be stored.
+ be stored. *callback* is an optional single parameter callable
+ that is called on each line after it is sent.
.. method:: FTP.transfercmd(cmd[, rest])
diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst
index b176524..4d7f0a4 100644
--- a/Doc/library/os.path.rst
+++ b/Doc/library/os.path.rst
@@ -130,7 +130,9 @@ write files see :func:`open`, and for accessing the filesystem see the
.. function:: isabs(path)
- Return ``True`` if *path* is an absolute pathname (begins with a slash).
+ Return ``True`` if *path* is an absolute pathname. On Unix, that means it
+ begins with a slash, on Windows that it begins with a (back)slash after chopping
+ off a potential drive letter.
.. function:: isfile(path)
diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst
index d4cad87..acd82d5 100644
--- a/Doc/tutorial/inputoutput.rst
+++ b/Doc/tutorial/inputoutput.rst
@@ -195,16 +195,15 @@ automatically added to the end. ``'r+'`` opens the file for both reading and
writing. The *mode* argument is optional; ``'r'`` will be assumed if it's
omitted.
-``'b'`` appended to the mode opens the file in binary mode, so there are
-also modes like ``'rb'``, ``'wb'``, and ``'r+b'``. Python distinguishes
-between text and binary files. Binary files are read and written without
-any data transformation. In text mode, platform-specific newline
-representations are automatically converted to newlines when read and
-newline characters are automatically converted to the proper
-platform-specific representation when written. This makes writing portable
-code which reads or writes text files easier. In addition, when reading
-from or writing to text files, the data are automatically decoded or
-encoding, respectively, using the encoding associated with the file.
+On Windows and the Macintosh, ``'b'`` appended to the mode opens the file in
+binary mode, so there are also modes like ``'rb'``, ``'wb'``, and ``'r+b'``.
+Windows makes a distinction between text and binary files; the end-of-line
+characters in text files are automatically altered slightly when data is read or
+written. This behind-the-scenes modification to file data is fine for ASCII
+text files, but it'll corrupt binary data like that in :file:`JPEG` or
+:file:`EXE` files. Be very careful to use binary mode when reading and writing
+such files. On Unix, it doesn't hurt to append a ``'b'`` to the mode, so
+you can use it platform-independently for all binary files.
This behind-the-scenes modification to file data is fine for text files, but
will corrupt binary data like that in :file:`JPEG` or :file:`EXE` files. Be
diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst
index 83101bd..cbc8b8f 100644
--- a/Doc/whatsnew/2.6.rst
+++ b/Doc/whatsnew/2.6.rst
@@ -3,6 +3,7 @@
****************************
.. XXX mention switch to Roundup for bug tracking
+.. XXX add trademark info for Apple, Microsoft.
:Author: A.M. Kuchling
:Release: |release|
@@ -909,7 +910,13 @@ complete list of changes, or look through the CVS logs for all the details.
* An optional ``timeout`` parameter was added to the
:class:`ftplib.FTP` class constructor as well as the :meth:`connect`
method, specifying a timeout measured in seconds. (Added by Facundo
- Batista.)
+ Batista.) Also, the :class:`FTP` class's
+ :meth:`storbinary` and :meth:`storlines`
+ now take an optional *callback* parameter that will be called with
+ each block of data after the data has been sent.
+ (Contributed by Phil Schwartz.)
+
+ .. Patch 1221598
* The :func:`reduce` built-in function is also available in the
:mod:`functools` module. In Python 3.0, the built-in is dropped and it's
@@ -1041,6 +1048,13 @@ complete list of changes, or look through the CVS logs for all the details.
.. Patch 1137
+* The :mod:`Queue` module now provides queue classes that retrieve entries
+ in different orders. The :class:`PriorityQueue` class stores
+ queued items in a heap and retrieves them in priority order,
+ and :class:`LifoQueue` retrieves the most recently added entries first,
+ meaning that it behaves like a stack.
+ (Contributed by Raymond Hettinger.)
+
* The :mod:`random` module's :class:`Random` objects can
now be pickled on a 32-bit system and unpickled on a 64-bit
system, and vice versa. Unfortunately, this change also means
@@ -1304,6 +1318,47 @@ XXX Certain features require the OpenSSL package to be installed, notably
SSL module documentation.
+
+.. ======================================================================
+
+plistlib: A Property-List Parser
+--------------------------------------------------
+
+A commonly-used format on MacOS X is the ``.plist`` format,
+which stores basic data types (numbers, strings, lists,
+and dictionaries) and serializes them into an XML-based format.
+(It's a lot like the XML-RPC serialization of data types.)
+
+Despite being primarily used on MacOS X, the format
+has nothing Mac-specific about it and the Python implementation works
+on any platform that Python supports, so the :mod:`plistlib` module
+has been promoted to the standard library.
+
+Using the module is simple::
+
+ import sys
+ import plistlib
+ import datetime
+
+ # Create data structure
+ data_struct = dict(lastAccessed=datetime.datetime.now(),
+ version=1,
+ categories=('Personal', 'Shared', 'Private'))
+
+ # Create string containing XML.
+ plist_str = plistlib.writePlistToString(data_struct)
+ new_struct = plistlib.readPlistFromString(plist_str)
+ print data_struct
+ print new_struct
+
+ # Write data structure to a file and read it back.
+ plistlib.writePlist(data_struct, '/tmp/customizations.plist')
+ new_struct = plistlib.readPlist('/tmp/customizations.plist')
+
+ # read/writePlist accepts file-like objects as well as paths.
+ plistlib.writePlist(data_struct, sys.stdout)
+
+
.. ======================================================================
@@ -1351,6 +1406,13 @@ Changes to Python's build process and to the C API include:
.. Issue 1629
+* Distutils now places C extensions it builds in a
+ different directory when running on a debug version of Python.
+ (Contributed by Collin Winter.)
+
+ .. Patch 1530959
+
+
.. ======================================================================
diff --git a/Include/genobject.h b/Include/genobject.h
index 11c6823..135561b 100644
--- a/Include/genobject.h
+++ b/Include/genobject.h
@@ -18,6 +18,9 @@ typedef struct {
/* True if generator is being executed. */
int gi_running;
+
+ /* The code object backing the generator */
+ PyObject *gi_code;
/* List of weak reference. */
PyObject *gi_weakreflist;
diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h
index 106228d..d7808a4 100644
--- a/Include/unicodeobject.h
+++ b/Include/unicodeobject.h
@@ -1,6 +1,8 @@
#ifndef Py_UNICODEOBJECT_H
#define Py_UNICODEOBJECT_H
+#include <stdarg.h>
+
/*
Unicode implementation based on original code by Fredrik Lundh,
diff --git a/Lib/bsddb/test/test_associate.py b/Lib/bsddb/test/test_associate.py
index 7d0dceb..ab7b600 100644
--- a/Lib/bsddb/test/test_associate.py
+++ b/Lib/bsddb/test/test_associate.py
@@ -141,7 +141,15 @@ class AssociateTestCase(unittest.TestCase):
def setUp(self):
self.filename = self.__class__.__name__ + '.db'
- self.homeDir = tempfile.mkdtemp()
+ homeDir = os.path.join(tempfile.gettempdir(), 'db_home')
+ self.homeDir = homeDir
+ try:
+ os.mkdir(homeDir)
+ except os.error:
+ import glob
+ files = glob.glob(os.path.join(self.homeDir, '*'))
+ for file in files:
+ os.remove(file)
self.env = db.DBEnv()
self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL |
db.DB_INIT_LOCK | db.DB_THREAD | self.envFlags)
diff --git a/Lib/bsddb/test/test_compare.py b/Lib/bsddb/test/test_compare.py
index f823a75..eefc7c2 100644
--- a/Lib/bsddb/test/test_compare.py
+++ b/Lib/bsddb/test/test_compare.py
@@ -6,6 +6,7 @@ import shutil
import sys, os, re
from io import StringIO
import tempfile
+import test_all
import unittest
try:
@@ -55,7 +56,12 @@ class AbstractBtreeKeyCompareTestCase (unittest.TestCase):
def setUp (self):
self.filename = self.__class__.__name__ + '.db'
- self.homeDir = tempfile.mkdtemp()
+ homeDir = os.path.join (tempfile.gettempdir(), 'db_home')
+ self.homeDir = homeDir
+ try:
+ os.mkdir (homeDir)
+ except os.error:
+ pass
env = db.DBEnv ()
env.open (self.homeDir,
diff --git a/Lib/bsddb/test/test_cursor_pget_bug.py b/Lib/bsddb/test/test_cursor_pget_bug.py
index 2af12bf..32dd8a5 100644
--- a/Lib/bsddb/test/test_cursor_pget_bug.py
+++ b/Lib/bsddb/test/test_cursor_pget_bug.py
@@ -1,4 +1,5 @@
import unittest
+import tempfile
import sys, os, glob
import shutil
import tempfile
@@ -13,7 +14,11 @@ class pget_bugTestCase(unittest.TestCase):
db_name = 'test-cursor_pget.db'
def setUp(self):
- self.homeDir = tempfile.mkdtemp()
+ self.homeDir = os.path.join(tempfile.gettempdir(), 'db_home')
+ try:
+ os.mkdir(self.homeDir)
+ except os.error:
+ pass
self.env = db.DBEnv()
self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL)
self.primary_db = db.DB(self.env)
diff --git a/Lib/bsddb/test/test_pickle.py b/Lib/bsddb/test/test_pickle.py
index 3bedab7..9b413c4 100644
--- a/Lib/bsddb/test/test_pickle.py
+++ b/Lib/bsddb/test/test_pickle.py
@@ -4,6 +4,7 @@ import sys, os
import pickle
import tempfile
import unittest
+import tempfile
import glob
try:
@@ -21,7 +22,10 @@ class pickleTestCase(unittest.TestCase):
db_name = 'test-dbobj.db'
def setUp(self):
- self.homeDir = tempfile.mkdtemp()
+ homeDir = os.path.join(tempfile.gettempdir(), 'db_home')
+ self.homeDir = homeDir
+ try: os.mkdir(homeDir)
+ except os.error: pass
def tearDown(self):
if hasattr(self, 'db'):
diff --git a/Lib/bsddb/test/test_sequence.py b/Lib/bsddb/test/test_sequence.py
index 25a354c..f998df7 100644
--- a/Lib/bsddb/test/test_sequence.py
+++ b/Lib/bsddb/test/test_sequence.py
@@ -17,8 +17,11 @@ from bsddb.test.test_all import verbose
class DBSequenceTest(unittest.TestCase):
def setUp(self):
self.int_32_max = 0x100000000
- self.homeDir = tempfile.mkdtemp()
- old_tempfile_tempdir = tempfile.tempdir
+ self.homeDir = os.path.join(tempfile.gettempdir(), 'db_home')
+ try:
+ os.mkdir(self.homeDir)
+ except os.error:
+ pass
tempfile.tempdir = self.homeDir
self.filename = os.path.split(tempfile.mktemp())[1]
tempfile.tempdir = old_tempfile_tempdir
diff --git a/Lib/bsddb/test/test_thread.py b/Lib/bsddb/test/test_thread.py
index 4a75384..a347911 100644
--- a/Lib/bsddb/test/test_thread.py
+++ b/Lib/bsddb/test/test_thread.py
@@ -47,7 +47,12 @@ class BaseThreadedTestCase(unittest.TestCase):
if verbose:
dbutils._deadlock_VerboseFile = sys.stdout
- self.homeDir = tempfile.mkdtemp()
+ homeDir = os.path.join(tempfile.gettempdir(), 'db_home')
+ self.homeDir = homeDir
+ try:
+ os.mkdir(homeDir)
+ except OSError, e:
+ if e.errno != errno.EEXIST: raise
self.env = db.DBEnv()
self.setEnvOpts()
self.env.open(self.homeDir, self.envflags | db.DB_CREATE)
@@ -61,7 +66,10 @@ class BaseThreadedTestCase(unittest.TestCase):
def tearDown(self):
self.d.close()
self.env.close()
- shutil.rmtree(self.homeDir)
+ try:
+ shutil.rmtree(self.homeDir)
+ except OSError, e:
+ if e.errno != errno.EEXIST: raise
def setEnvOpts(self):
pass
diff --git a/Lib/rational.py b/Lib/rational.py
index 89b622c..da75ab1 100755
--- a/Lib/rational.py
+++ b/Lib/rational.py
@@ -13,8 +13,8 @@ __all__ = ["Rational"]
RationalAbc = numbers.Rational
-def _gcd(a, b): # XXX This is a useful function. Consider making it public.
- """Calculate the Greatest Common Divisor.
+def gcd(a, b):
+ """Calculate the Greatest Common Divisor of a and b.
Unless b==0, the result will have the same sign as b (so that when
b is divided by it, the result comes out positive).
@@ -39,8 +39,8 @@ def _binary_float_to_ratio(x):
>>> _binary_float_to_ratio(-.25)
(-1, 4)
"""
- # XXX Consider moving this to to floatobject.c
- # with a name like float.as_intger_ratio()
+ # XXX Move this to floatobject.c with a name like
+ # float.as_integer_ratio()
if x == 0:
return 0, 1
@@ -79,12 +79,9 @@ def _binary_float_to_ratio(x):
_RATIONAL_FORMAT = re.compile(
- r'^\s*(?P<sign>[-+]?)(?P<num>\d+)(?:/(?P<denom>\d+))?\s*$')
+ r'^\s*(?P<sign>[-+]?)(?P<num>\d+)'
+ r'(?:/(?P<denom>\d+)|\.(?P<decimal>\d+))?\s*$')
-# XXX Consider accepting decimal strings as input since they are exact.
-# Rational("2.01") --> s="2.01" ; Rational.from_decimal(Decimal(s)) --> Rational(201, 100)"
-# If you want to avoid going through the decimal module, just parse the string directly:
-# s.partition('.') --> ('2', '.', '01') --> Rational(int('2'+'01'), 10**len('01')) --> Rational(201, 100)
class Rational(RationalAbc):
"""This class implements rational numbers.
@@ -95,7 +92,7 @@ class Rational(RationalAbc):
Rational() == 0.
Rationals can also be constructed from strings of the form
- '[-+]?[0-9]+(/[0-9]+)?', optionally surrounded by spaces.
+ '[-+]?[0-9]+((/|.)[0-9]+)?', optionally surrounded by spaces.
"""
@@ -105,7 +102,8 @@ class Rational(RationalAbc):
def __new__(cls, numerator=0, denominator=1):
"""Constructs a Rational.
- Takes a string, another Rational, or a numerator/denominator pair.
+ Takes a string like '3/2' or '1.5', another Rational, or a
+ numerator/denominator pair.
"""
self = super(Rational, cls).__new__(cls)
@@ -117,9 +115,18 @@ class Rational(RationalAbc):
m = _RATIONAL_FORMAT.match(input)
if m is None:
raise ValueError('Invalid literal for Rational: ' + input)
- numerator = int(m.group('num'))
- # Default denominator to 1. That's the only optional group.
- denominator = int(m.group('denom') or 1)
+ numerator = m.group('num')
+ decimal = m.group('decimal')
+ if decimal:
+ # The literal is a decimal number.
+ numerator = int(numerator + decimal)
+ denominator = 10**len(decimal)
+ else:
+ # The literal is an integer or fraction.
+ numerator = int(numerator)
+ # Default denominator to 1.
+ denominator = int(m.group('denom') or 1)
+
if m.group('sign') == '-':
numerator = -numerator
@@ -138,7 +145,7 @@ class Rational(RationalAbc):
if denominator == 0:
raise ZeroDivisionError('Rational(%s, 0)' % numerator)
- g = _gcd(numerator, denominator)
+ g = gcd(numerator, denominator)
self.numerator = int(numerator // g)
self.denominator = int(denominator // g)
return self
diff --git a/Lib/re.py b/Lib/re.py
index 91b119c..962c2d7 100644
--- a/Lib/re.py
+++ b/Lib/re.py
@@ -38,7 +38,7 @@ The special characters are:
*?,+?,?? Non-greedy versions of the previous three special characters.
{m,n} Matches from m to n repetitions of the preceding RE.
{m,n}? Non-greedy version of the above.
- "\\" Either escapes special characters or signals a special sequence.
+ "\\" Either escapes special characters or signals a special sequence.
[] Indicates a set of characters.
A "^" as the first character indicates a complementing set.
"|" A|B, creates an RE that will match either A or B.
@@ -51,6 +51,10 @@ The special characters are:
(?#...) A comment; ignored.
(?=...) Matches if ... matches next, but doesn't consume the string.
(?!...) Matches if ... doesn't match next.
+ (?<=...) Matches if preceded by ... (must be fixed length).
+ (?<!...) Matches if not preceded by ... (must be fixed length).
+ (?(id/name)yes|no) Matches yes pattern if the group with id/name matched,
+ the (optional) no pattern otherwise.
The special sequences consist of "\\" and a character from the list
below. If the ordinary character is not on the list, then the
@@ -77,6 +81,7 @@ This module exports the following functions:
subn Same as sub, but also return the number of substitutions made.
split Split a string by the occurrences of a pattern.
findall Find all occurrences of a pattern in a string.
+ finditer Return an iterator yielding a match object for each match.
compile Compile a pattern into a RegexObject.
purge Clear the regular expression cache.
escape Backslash all non-alphanumerics in a string.
diff --git a/Lib/test/test_asynchat.py b/Lib/test/test_asynchat.py
index 83b0972..2912057 100644
--- a/Lib/test/test_asynchat.py
+++ b/Lib/test/test_asynchat.py
@@ -15,12 +15,17 @@ class echo_server(threading.Thread):
# client each send
chunk_size = 1
+ def __init__(self, event):
+ threading.Thread.__init__(self)
+ self.event = event
+
def run(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
global PORT
PORT = test_support.bind_port(sock, HOST, PORT)
sock.listen(1)
+ self.event.set()
conn, client = sock.accept()
self.buffer = b""
# collect data until quit message is seen
@@ -74,6 +79,16 @@ class echo_client(asynchat.async_chat):
self.buffer = b""
+def start_echo_server():
+ event = threading.Event()
+ s = echo_server(event)
+ s.start()
+ event.wait()
+ event.clear()
+ time.sleep(0.01) # Give server time to start accepting.
+ return s, event
+
+
class TestAsynchat(unittest.TestCase):
usepoll = False
@@ -84,10 +99,13 @@ class TestAsynchat(unittest.TestCase):
pass
def line_terminator_check(self, term, server_chunk):
- s = echo_server()
+ event = threading.Event()
+ s = echo_server(event)
s.chunk_size = server_chunk
s.start()
- time.sleep(0.5) # Give server time to initialize
+ event.wait()
+ event.clear()
+ time.sleep(0.01) # Give server time to start accepting.
c = echo_client(term)
c.push(b"hello ")
c.push(bytes("world%s" % term, "ascii"))
@@ -119,9 +137,7 @@ class TestAsynchat(unittest.TestCase):
def numeric_terminator_check(self, termlen):
# Try reading a fixed number of bytes
- s = echo_server()
- s.start()
- time.sleep(0.5) # Give server time to initialize
+ s, event = start_echo_server()
c = echo_client(termlen)
data = b"hello world, I'm not dead yet!\n"
c.push(data)
@@ -141,9 +157,7 @@ class TestAsynchat(unittest.TestCase):
def test_none_terminator(self):
# Try reading a fixed number of bytes
- s = echo_server()
- s.start()
- time.sleep(0.5) # Give server time to initialize
+ s, event = start_echo_server()
c = echo_client(None)
data = b"hello world, I'm not dead yet!\n"
c.push(data)
@@ -155,9 +169,7 @@ class TestAsynchat(unittest.TestCase):
self.assertEqual(c.buffer, data)
def test_simple_producer(self):
- s = echo_server()
- s.start()
- time.sleep(0.5) # Give server time to initialize
+ s, event = start_echo_server()
c = echo_client(b'\n')
data = b"hello world\nI'm not dead yet!\n"
p = asynchat.simple_producer(data+SERVER_QUIT, buffer_size=8)
@@ -168,9 +180,7 @@ class TestAsynchat(unittest.TestCase):
self.assertEqual(c.contents, [b"hello world", b"I'm not dead yet!"])
def test_string_producer(self):
- s = echo_server()
- s.start()
- time.sleep(0.5) # Give server time to initialize
+ s, event = start_echo_server()
c = echo_client(b'\n')
data = b"hello world\nI'm not dead yet!\n"
c.push_with_producer(data+SERVER_QUIT)
@@ -181,9 +191,7 @@ class TestAsynchat(unittest.TestCase):
def test_empty_line(self):
# checks that empty lines are handled correctly
- s = echo_server()
- s.start()
- time.sleep(0.5) # Give server time to initialize
+ s, event = start_echo_server()
c = echo_client(b'\n')
c.push(b"hello world\n\nI'm not dead yet!\n")
c.push(SERVER_QUIT)
@@ -194,9 +202,7 @@ class TestAsynchat(unittest.TestCase):
[b"hello world", b"", b"I'm not dead yet!"])
def test_close_when_done(self):
- s = echo_server()
- s.start()
- time.sleep(0.5) # Give server time to initialize
+ s, event = start_echo_server()
c = echo_client(b'\n')
c.push(b"hello world\nI'm not dead yet!\n")
c.push(SERVER_QUIT)
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
index 53e6446..6a0b3c1 100644
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -191,14 +191,6 @@ class DictTest(unittest.TestCase):
self.assertRaises(ValueError, {}.update, [(1, 2, 3)])
- # SF #1615701: make d.update(m) honor __getitem__() and keys() in dict subclasses
- class KeyUpperDict(dict):
- def __getitem__(self, key):
- return key.upper()
- d.clear()
- d.update(KeyUpperDict.fromkeys('abc'))
- self.assertEqual(d, {'a':'A', 'b':'B', 'c':'C'})
-
def test_fromkeys(self):
self.assertEqual(dict.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
d = {}
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index 892535d..04f1359 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -382,7 +382,7 @@ From the Iterators list, about the types of these things.
>>> type(i)
<type 'generator'>
>>> [s for s in dir(i) if not s.startswith('_')]
-['close', 'gi_frame', 'gi_running', 'send', 'throw']
+['close', 'gi_code', 'gi_frame', 'gi_running', 'send', 'throw']
>>> print(i.__next__.__doc__)
x.__next__() <==> next(x)
>>> iter(i) is i
@@ -899,6 +899,24 @@ This one caused a crash (see SF bug 567538):
>>> print(next(g))
Traceback (most recent call last):
StopIteration
+
+
+Test the gi_code attribute
+
+>>> def f():
+... yield 5
+...
+>>> g = f()
+>>> g.gi_code is f.__code__
+True
+>>> next(g)
+5
+>>> next(g)
+Traceback (most recent call last):
+StopIteration
+>>> g.gi_code is f.__code__
+True
+
"""
# conjoin is a simple backtracking generator, named in honor of Icon's
diff --git a/Lib/test/test_rational.py b/Lib/test/test_rational.py
index 729527f..284a42a 100644
--- a/Lib/test/test_rational.py
+++ b/Lib/test/test_rational.py
@@ -9,10 +9,28 @@ import unittest
from copy import copy, deepcopy
from pickle import dumps, loads
R = rational.Rational
+gcd = rational.gcd
+
+
+class GcdTest(unittest.TestCase):
+
+ def testMisc(self):
+ self.assertEquals(0, gcd(0, 0))
+ self.assertEquals(1, gcd(1, 0))
+ self.assertEquals(-1, gcd(-1, 0))
+ self.assertEquals(1, gcd(0, 1))
+ self.assertEquals(-1, gcd(0, -1))
+ self.assertEquals(1, gcd(7, 1))
+ self.assertEquals(-1, gcd(7, -1))
+ self.assertEquals(1, gcd(-23, 15))
+ self.assertEquals(12, gcd(120, 84))
+ self.assertEquals(-12, gcd(84, -120))
+
def _components(r):
return (r.numerator, r.denominator)
+
class RationalTest(unittest.TestCase):
def assertTypedEquals(self, expected, actual):
@@ -57,6 +75,8 @@ class RationalTest(unittest.TestCase):
self.assertEquals((-3, 2), _components(R("-3/2 ")))
self.assertEquals((3, 2), _components(R(" 03/02 \n ")))
self.assertEquals((3, 2), _components(R(" 03/02 \n ")))
+ self.assertEquals((16, 5), _components(R(" 3.2 ")))
+ self.assertEquals((-16, 5), _components(R(" -3.2 ")))
self.assertRaisesMessage(
ZeroDivisionError, "Rational(3, 0)",
@@ -76,9 +96,21 @@ class RationalTest(unittest.TestCase):
ValueError, "Invalid literal for Rational: + 3/2",
R, "+ 3/2")
self.assertRaisesMessage(
- # Only parse fractions, not decimals.
- ValueError, "Invalid literal for Rational: 3.2",
- R, "3.2")
+ # Avoid treating '.' as a regex special character.
+ ValueError, "Invalid literal for Rational: 3a2",
+ R, "3a2")
+ self.assertRaisesMessage(
+ # Only parse ordinary decimals, not scientific form.
+ ValueError, "Invalid literal for Rational: 3.2e4",
+ R, "3.2e4")
+ self.assertRaisesMessage(
+ # Don't accept combinations of decimals and rationals.
+ ValueError, "Invalid literal for Rational: 3/7.2",
+ R, "3/7.2")
+ self.assertRaisesMessage(
+ # Don't accept combinations of decimals and rationals.
+ ValueError, "Invalid literal for Rational: 3.2/7",
+ R, "3.2/7")
def testImmutable(self):
r = R(7, 3)
@@ -370,7 +402,7 @@ class RationalTest(unittest.TestCase):
self.assertEqual(id(r), id(deepcopy(r)))
def test_main():
- run_unittest(RationalTest)
+ run_unittest(RationalTest, GcdTest)
if __name__ == '__main__':
test_main()
diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py
index 1216560..987c8d7 100644
--- a/Lib/test/test_resource.py
+++ b/Lib/test/test_resource.py
@@ -15,7 +15,6 @@ class ResourceTest(unittest.TestCase):
self.assertRaises(TypeError, resource.setrlimit, 42, 42, 42)
def test_fsize_ismax(self):
-
try:
(cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE)
except AttributeError:
@@ -54,6 +53,13 @@ class ResourceTest(unittest.TestCase):
try:
f.write(b"Y")
f.flush()
+ # On some systems (e.g., Ubuntu on hppa) the flush()
+ # doesn't always cause the exception, but the close()
+ # does eventually. Try closing several times in
+ # an attempt to ensure the file is really synced and
+ # the exception raised.
+ for i in range(5):
+ f.close()
except IOError:
if not limit_set:
raise
@@ -63,10 +69,10 @@ class ResourceTest(unittest.TestCase):
resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max))
finally:
f.close()
- os.unlink(test_support.TESTFN)
finally:
if limit_set:
resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max))
+ test_support.unlink(test_support.TESTFN)
def test_fsize_toobig(self):
# Be sure that setrlimit is checking for really large values
diff --git a/Lib/test/test_telnetlib.py b/Lib/test/test_telnetlib.py
index c48de04..3a53ad9 100644
--- a/Lib/test/test_telnetlib.py
+++ b/Lib/test/test_telnetlib.py
@@ -7,13 +7,13 @@ from unittest import TestCase
from test import test_support
-def server(evt, ready):
+def server(evt):
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serv.settimeout(3)
serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serv.bind(("", 9091))
serv.listen(5)
- ready.set()
+ evt.set()
try:
conn, addr = serv.accept()
except socket.timeout:
@@ -26,9 +26,10 @@ class GeneralTests(TestCase):
def setUp(self):
self.evt = threading.Event()
- ready = threading.Event()
- threading.Thread(target=server, args=(self.evt, ready)).start()
- ready.wait()
+ threading.Thread(target=server, args=(self.evt,)).start()
+ self.evt.wait()
+ self.evt.clear()
+ time.sleep(.1)
def tearDown(self):
self.evt.wait()
diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py
index a7d3805..c9a483a 100644
--- a/Lib/test/test_urllibnet.py
+++ b/Lib/test/test_urllibnet.py
@@ -9,6 +9,20 @@ import sys
import os
import mimetools
+
+def _open_with_retry(func, host, *args, **kwargs):
+ # Connecting to remote hosts is flaky. Make it more robust
+ # by retrying the connection several times.
+ for i in range(3):
+ try:
+ return func(host, *args, **kwargs)
+ except IOError, last_exc:
+ continue
+ except:
+ raise
+ raise last_exc
+
+
class URLTimeoutTest(unittest.TestCase):
TIMEOUT = 10.0
@@ -20,7 +34,7 @@ class URLTimeoutTest(unittest.TestCase):
socket.setdefaulttimeout(None)
def testURLread(self):
- f = urllib.urlopen("http://www.python.org/")
+ f = _open_with_retry(urllib.urlopen, "http://www.python.org/")
x = f.read()
class urlopenNetworkTests(unittest.TestCase):
@@ -38,9 +52,12 @@ class urlopenNetworkTests(unittest.TestCase):
"""
+ def urlopen(self, *args):
+ return _open_with_retry(urllib.urlopen, *args)
+
def test_basic(self):
# Simple test expected to pass.
- open_url = urllib.urlopen("http://www.python.org/")
+ open_url = self.urlopen("http://www.python.org/")
for attr in ("read", "readline", "readlines", "fileno", "close",
"info", "geturl"):
self.assert_(hasattr(open_url, attr), "object returned from "
@@ -52,7 +69,7 @@ class urlopenNetworkTests(unittest.TestCase):
def test_readlines(self):
# Test both readline and readlines.
- open_url = urllib.urlopen("http://www.python.org/")
+ open_url = self.urlopen("http://www.python.org/")
try:
self.assert_(isinstance(open_url.readline(), bytes),
"readline did not return bytes")
@@ -63,7 +80,7 @@ class urlopenNetworkTests(unittest.TestCase):
def test_info(self):
# Test 'info'.
- open_url = urllib.urlopen("http://www.python.org/")
+ open_url = self.urlopen("http://www.python.org/")
try:
info_obj = open_url.info()
finally:
@@ -76,7 +93,7 @@ class urlopenNetworkTests(unittest.TestCase):
def test_geturl(self):
# Make sure same URL as opened is returned by geturl.
URL = "http://www.python.org/"
- open_url = urllib.urlopen(URL)
+ open_url = self.urlopen(URL)
try:
gotten_url = open_url.geturl()
finally:
@@ -100,7 +117,7 @@ class urlopenNetworkTests(unittest.TestCase):
# test can't pass on Windows.
return
# Make sure fd returned by fileno is valid.
- open_url = urllib.urlopen("http://www.python.org/")
+ open_url = self.urlopen("http://www.python.org/")
fd = open_url.fileno()
FILE = os.fdopen(fd)
try:
@@ -125,9 +142,12 @@ class urlopenNetworkTests(unittest.TestCase):
class urlretrieveNetworkTests(unittest.TestCase):
"""Tests urllib.urlretrieve using the network."""
+ def urlretrieve(self, *args):
+ return _open_with_retry(urllib.urlretrieve, *args)
+
def test_basic(self):
# Test basic functionality.
- file_location,info = urllib.urlretrieve("http://www.python.org/")
+ file_location,info = self.urlretrieve("http://www.python.org/")
self.assert_(os.path.exists(file_location), "file location returned by"
" urlretrieve is not a valid path")
FILE = open(file_location)
@@ -140,8 +160,8 @@ class urlretrieveNetworkTests(unittest.TestCase):
def test_specified_path(self):
# Make sure that specifying the location of the file to write to works.
- file_location,info = urllib.urlretrieve("http://www.python.org/",
- test_support.TESTFN)
+ file_location,info = self.urlretrieve("http://www.python.org/",
+ test_support.TESTFN)
self.assertEqual(file_location, test_support.TESTFN)
self.assert_(os.path.exists(file_location))
FILE = open(file_location)
@@ -153,7 +173,7 @@ class urlretrieveNetworkTests(unittest.TestCase):
def test_header(self):
# Make sure header returned as 2nd value from urlretrieve is good.
- file_location, header = urllib.urlretrieve("http://www.python.org/")
+ file_location, header = self.urlretrieve("http://www.python.org/")
os.unlink(file_location)
self.assert_(isinstance(header, mimetools.Message),
"header is not an instance of mimetools.Message")
diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py
index 16ef798..7b5af9e 100644
--- a/Lib/test/test_xmlrpc.py
+++ b/Lib/test/test_xmlrpc.py
@@ -261,6 +261,9 @@ class BinaryTestCase(unittest.TestCase):
PORT = None
+# The evt is set twice. First when the server is ready to serve.
+# Second when the server has been shutdown. The user must clear
+# the event after it has been set the first time to catch the second set.
def http_server(evt, numrequests):
class TestInstanceClass:
def div(self, x, y):
@@ -287,6 +290,7 @@ def http_server(evt, numrequests):
serv.register_function(lambda x,y: x+y, 'add')
serv.register_function(my_function)
serv.register_instance(TestInstanceClass())
+ evt.set()
# handle up to 'numrequests' requests
while numrequests > 0:
@@ -300,14 +304,16 @@ def http_server(evt, numrequests):
PORT = None
evt.set()
-def stop_serving():
- global PORT
- if PORT is None:
- return
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.connect(('localhost', int(PORT)))
- sock.send(b"")
- sock.close()
+# This function prevents errors like:
+# <ProtocolError for localhost:57527/RPC2: 500 Internal Server Error>
+def is_unavailable_exception(e):
+ '''Returns True if the given ProtocolError is the product of a server-side
+ exception caused by the 'temporarily unavailable' response sometimes
+ given by operations on non-blocking sockets.'''
+
+ # sometimes we get a -1 error code and/or empty headers
+ if e.errcode == -1 or e.headers is None:
+ return True
class SimpleServerTestCase(unittest.TestCase):
@@ -320,13 +326,9 @@ class SimpleServerTestCase(unittest.TestCase):
serv_args = (self.evt, 1)
threading.Thread(target=http_server, args=serv_args).start()
- # wait for port to be assigned to server
- n = 1000
- while n > 0 and PORT is None:
- time.sleep(0.001)
- n -= 1
-
- time.sleep(0.5)
+ # wait for the server to be ready
+ self.evt.wait()
+ self.evt.clear()
def tearDown(self):
# wait on the server thread to terminate
@@ -457,13 +459,9 @@ class FailingServerTestCase(unittest.TestCase):
serv_args = (self.evt, 1)
threading.Thread(target=http_server, args=serv_args).start()
- # wait for port to be assigned to server
- n = 1000
- while n > 0 and PORT is None:
- time.sleep(0.001)
- n -= 1
-
- time.sleep(0.5)
+ # wait for the server to be ready
+ self.evt.wait()
+ self.evt.clear()
def tearDown(self):
# wait on the server thread to terminate
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index 1b14d2a..c4f8f79 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -309,6 +309,7 @@ class TestsWithSourceFile(unittest.TestCase):
correctfile = os.path.join(os.getcwd(), fpath[1:])
else:
correctfile = os.path.join(os.getcwd(), fpath)
+ correctfile = os.path.normpath(correctfile)
self.assertEqual(writtenfile, correctfile)
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index a4536e4..06202e0 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -1711,11 +1711,20 @@ NoArgTrueFalseFunction(has_colors)
NoArgTrueFalseFunction(has_ic)
NoArgTrueFalseFunction(has_il)
NoArgTrueFalseFunction(isendwin)
-NoArgNoReturnVoidFunction(filter)
NoArgNoReturnVoidFunction(flushinp)
NoArgNoReturnVoidFunction(noqiflush)
static PyObject *
+PyCurses_filter(PyObject *self)
+{
+ /* not checking for PyCursesInitialised here since filter() must
+ be called before initscr() */
+ filter();
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
PyCurses_Color_Content(PyObject *self, PyObject *args)
{
short color,r,g,b;
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index 4730680..873059f 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -291,9 +291,9 @@ loghelper(PyObject* arg, double (*func)(double), char *funcname)
"math domain error");
return NULL;
}
- /* Value is ~= x * 2**(e*SHIFT), so the log ~=
- log(x) + log(2) * e * SHIFT.
- CAUTION: e*SHIFT may overflow using int arithmetic,
+ /* Value is ~= x * 2**(e*PyLong_SHIFT), so the log ~=
+ log(x) + log(2) * e * PyLong_SHIFT.
+ CAUTION: e*PyLong_SHIFT may overflow using int arithmetic,
so force use of double. */
x = func(x) + (e * (double)PyLong_SHIFT) * func(2.0);
return PyFloat_FromDouble(x);
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index f50347c..c83af0d 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -259,8 +259,8 @@ mmap_gfind(mmap_object *self,
int reverse)
{
Py_ssize_t start = self->pos;
- Py_ssize_t end = self->size;
- char *needle;
+ Py_ssize_t end = self->size;
+ const char *needle;
Py_ssize_t len;
CHECK_VALID(NULL);
@@ -268,8 +268,8 @@ mmap_gfind(mmap_object *self,
&needle, &len, &start, &end)) {
return NULL;
} else {
- char *p;
- char sign = reverse ? -1 : 1;
+ const char *p, *start_p, *end_p;
+ int sign = reverse ? -1 : 1;
if (start < 0)
start += self->size;
@@ -285,11 +285,11 @@ mmap_gfind(mmap_object *self,
else if ((size_t)end > self->size)
end = self->size;
- start += (Py_ssize_t)self->data;
- end += (Py_ssize_t)self->data;
+ start_p = self->data + start;
+ end_p = self->data + end;
- for (p = (char *)(reverse ? end - len : start);
- p >= (char *)start && p + len <= (char *)end; p+=sign) {
+ for (p = (reverse ? end_p - len : start_p);
+ (p >= start_p) && (p + len <= end_p); p += sign) {
Py_ssize_t i;
for (i = 0; i < len && needle[i] == p[i]; ++i)
/* nothing */;
@@ -543,23 +543,21 @@ mmap_flush_method(mmap_object *self, PyObject *args)
if ((size_t)(offset + size) > self->size) {
PyErr_SetString(PyExc_ValueError, "flush values out of range");
return NULL;
- } else {
+ }
#ifdef MS_WINDOWS
- return PyLong_FromLong((long)
- FlushViewOfFile(self->data+offset, size));
-#endif /* MS_WINDOWS */
-#ifdef UNIX
- /* XXX semantics of return value? */
- /* XXX flags for msync? */
- if (-1 == msync(self->data + offset, size,
- MS_SYNC))
- {
- PyErr_SetFromErrno(mmap_module_error);
- return NULL;
- }
- return PyLong_FromLong(0);
-#endif /* UNIX */
+ return PyLong_FromLong((long) FlushViewOfFile(self->data+offset, size));
+#elif defined(UNIX)
+ /* XXX semantics of return value? */
+ /* XXX flags for msync? */
+ if (-1 == msync(self->data + offset, size, MS_SYNC)) {
+ PyErr_SetFromErrno(mmap_module_error);
+ return NULL;
}
+ return PyLong_FromLong(0);
+#else
+ PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
+ return NULL;
+#endif
}
static PyObject *
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 3d7ba55..6a1938e 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1379,7 +1379,7 @@ PyDict_Merge(PyObject *a, PyObject *b, int override)
return -1;
}
mp = (PyDictObject*)a;
- if (PyDict_CheckExact(b)) {
+ if (PyDict_Check(b)) {
other = (PyDictObject*)b;
if (other == mp || other->ma_used == 0)
/* a.update(a) or a.update({}); nothing to do */
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 7becca2..5897867 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -11,6 +11,7 @@ static int
gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
{
Py_VISIT((PyObject *)gen->gi_frame);
+ Py_VISIT(gen->gi_code);
return 0;
}
@@ -35,6 +36,7 @@ gen_dealloc(PyGenObject *gen)
_PyObject_GC_UNTRACK(self);
Py_CLEAR(gen->gi_frame);
+ Py_CLEAR(gen->gi_code);
PyObject_GC_Del(gen);
}
@@ -283,6 +285,7 @@ gen_iternext(PyGenObject *gen)
static PyMemberDef gen_memberlist[] = {
{"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY},
{"gi_running", T_INT, offsetof(PyGenObject, gi_running), READONLY},
+ {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY},
{NULL} /* Sentinel */
};
@@ -353,6 +356,8 @@ PyGen_New(PyFrameObject *f)
return NULL;
}
gen->gi_frame = f;
+ Py_INCREF(f->f_code);
+ gen->gi_code = (PyObject *)(f->f_code);
gen->gi_running = 0;
gen->gi_weakreflist = NULL;
_PyObject_GC_TRACK(gen);
diff --git a/Objects/listobject.c b/Objects/listobject.c
index b62bba5..4bc5ca9 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -466,7 +466,7 @@ list_repeat(PyListObject *a, Py_ssize_t n)
if (n && size/n != Py_SIZE(a))
return PyErr_NoMemory();
if (size == 0)
- return PyList_New(0);
+ return PyList_New(0);
np = (PyListObject *) PyList_New(size);
if (np == NULL)
return NULL;
@@ -633,11 +633,11 @@ static PyObject *
list_inplace_repeat(PyListObject *self, Py_ssize_t n)
{
PyObject **items;
- Py_ssize_t size, i, j, p, newsize;
+ Py_ssize_t size, i, j, p;
size = PyList_GET_SIZE(self);
- if (size == 0) {
+ if (size == 0 || n == 1) {
Py_INCREF(self);
return (PyObject *)self;
}
@@ -648,10 +648,11 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n)
return (PyObject *)self;
}
- newsize = size * n;
- if (newsize/n != size)
+ if (size > PY_SSIZE_T_MAX / n) {
return PyErr_NoMemory();
- if (list_resize(self, newsize) == -1)
+ }
+
+ if (list_resize(self, size*n) == -1)
return NULL;
p = size;
diff --git a/Objects/setobject.c b/Objects/setobject.c
index c7fb633..b37db44 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -904,7 +904,7 @@ set_update_internal(PySetObject *so, PyObject *other)
{
PyObject *key, *it;
- if (PyAnySet_CheckExact(other))
+ if (PyAnySet_Check(other))
return set_merge(so, other);
if (PyDict_CheckExact(other)) {
@@ -1199,7 +1199,7 @@ set_intersection(PySetObject *so, PyObject *other)
if (result == NULL)
return NULL;
- if (PyAnySet_CheckExact(other)) {
+ if (PyAnySet_Check(other)) {
Py_ssize_t pos = 0;
setentry *entry;
@@ -1390,7 +1390,7 @@ set_difference_update_internal(PySetObject *so, PyObject *other)
if ((PyObject *)so == other)
return set_clear_internal(so);
- if (PyAnySet_CheckExact(other)) {
+ if (PyAnySet_Check(other)) {
setentry *entry;
Py_ssize_t pos = 0;
@@ -1439,7 +1439,7 @@ set_difference(PySetObject *so, PyObject *other)
setentry *entry;
Py_ssize_t pos = 0;
- if (!PyAnySet_CheckExact(other) && !PyDict_CheckExact(other)) {
+ if (!PyAnySet_Check(other) && !PyDict_CheckExact(other)) {
result = set_copy(so);
if (result == NULL)
return NULL;
@@ -1546,7 +1546,7 @@ set_symmetric_difference_update(PySetObject *so, PyObject *other)
Py_RETURN_NONE;
}
- if (PyAnySet_CheckExact(other)) {
+ if (PyAnySet_Check(other)) {
Py_INCREF(other);
otherset = (PySetObject *)other;
} else {
@@ -1629,7 +1629,7 @@ set_issubset(PySetObject *so, PyObject *other)
setentry *entry;
Py_ssize_t pos = 0;
- if (!PyAnySet_CheckExact(other)) {
+ if (!PyAnySet_Check(other)) {
PyObject *tmp, *result;
tmp = make_new_set(&PySet_Type, other);
if (tmp == NULL)
@@ -1658,7 +1658,7 @@ set_issuperset(PySetObject *so, PyObject *other)
{
PyObject *tmp, *result;
- if (!PyAnySet_CheckExact(other)) {
+ if (!PyAnySet_Check(other)) {
tmp = make_new_set(&PySet_Type, other);
if (tmp == NULL)
return NULL;
diff --git a/setup.py b/setup.py
index 4c51bab..92f6f91 100644
--- a/setup.py
+++ b/setup.py
@@ -4,6 +4,7 @@
__version__ = "$Revision$"
import sys, os, imp, re, optparse
+from glob import glob
from distutils import log
from distutils import sysconfig
@@ -142,12 +143,20 @@ class PyBuildExt(build_ext):
self.distribution.scripts = [os.path.join(srcdir, filename)
for filename in self.distribution.scripts]
+ # Python header files
+ headers = glob("Include/*.h") + ["pyconfig.h"]
+
for ext in self.extensions[:]:
ext.sources = [ find_module_file(filename, moddirlist)
for filename in ext.sources ]
if ext.depends is not None:
ext.depends = [find_module_file(filename, alldirlist)
for filename in ext.depends]
+ else:
+ ext.depends = []
+ # re-compile extensions if a header file has been changed
+ ext.depends.extend(headers)
+
ext.include_dirs.append( '.' ) # to get config.h
for incdir in incdirlist:
ext.include_dirs.append( os.path.join(srcdir, incdir) )