summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/calendar.py4
-rw-r--r--Lib/decimal.py162
-rw-r--r--Lib/numbers.py5
-rw-r--r--Lib/test/cjkencodings_test.py6
-rw-r--r--Lib/test/test_codecmaps_hk.py3
-rw-r--r--Lib/test/test_contains.py165
-rw-r--r--Lib/test/test_decimal.py20
-rw-r--r--Lib/test/test_defaultdict.py23
-rw-r--r--Lib/test/test_iterlen.py1
-rw-r--r--Lib/test/test_largefile.py314
-rw-r--r--Lib/test/test_rational.py2
-rw-r--r--Lib/test/test_urllib2.py9
-rw-r--r--Lib/urllib2.py5
13 files changed, 411 insertions, 308 deletions
diff --git a/Lib/calendar.py b/Lib/calendar.py
index 071bc06..283bdcf 100644
--- a/Lib/calendar.py
+++ b/Lib/calendar.py
@@ -179,8 +179,8 @@ class Calendar(object):
def itermonthdays(self, year, month):
"""
- Like itermonthdates(), but will yield day numbers tuples. For days
- outside the specified month the day number is 0.
+ Like itermonthdates(), but will yield day numbers. For days outside
+ the specified month the day number is 0.
"""
for date in self.itermonthdates(year, month):
if date.month != month:
diff --git a/Lib/decimal.py b/Lib/decimal.py
index 5207a47..55faf99 100644
--- a/Lib/decimal.py
+++ b/Lib/decimal.py
@@ -718,6 +718,39 @@ class Decimal(_numbers.Real, _numbers.Inexact):
return other._fix_nan(context)
return 0
+ def _compare_check_nans(self, other, context):
+ """Version of _check_nans used for the signaling comparisons
+ compare_signal, __le__, __lt__, __ge__, __gt__.
+
+ Signal InvalidOperation if either self or other is a (quiet
+ or signaling) NaN. Signaling NaNs take precedence over quiet
+ NaNs.
+
+ Return 0 if neither operand is a NaN.
+
+ """
+ if context is None:
+ context = getcontext()
+
+ if self._is_special or other._is_special:
+ if self.is_snan():
+ return context._raise_error(InvalidOperation,
+ 'comparison involving sNaN',
+ self)
+ elif other.is_snan():
+ return context._raise_error(InvalidOperation,
+ 'comparison involving sNaN',
+ other)
+ elif self.is_qnan():
+ return context._raise_error(InvalidOperation,
+ 'comparison involving NaN',
+ self)
+ elif other.is_qnan():
+ return context._raise_error(InvalidOperation,
+ 'comparison involving NaN',
+ other)
+ return 0
+
def __bool__(self):
"""Return True if self is nonzero; otherwise return False.
@@ -725,18 +758,13 @@ class Decimal(_numbers.Real, _numbers.Inexact):
"""
return self._is_special or self._int != '0'
- def __cmp__(self, other):
- other = _convert_other(other)
- if other is NotImplemented:
- # Never return NotImplemented
- return 1
+ def _cmp(self, other):
+ """Compare the two non-NaN decimal instances self and other.
- if self._is_special or other._is_special:
- # check for nans, without raising on a signaling nan
- if self._isnan() or other._isnan():
- return 1 # Comparison involving NaN's always reports self > other
+ Returns -1 if self < other, 0 if self == other and 1
+ if self > other. This routine is for internal use only."""
- # INF = INF
+ if self._is_special or other._is_special:
return cmp(self._isinfinity(), other._isinfinity())
# check for zeros; note that cmp(0, -0) should return 0
@@ -765,35 +793,72 @@ class Decimal(_numbers.Real, _numbers.Inexact):
else: # self_adjusted < other_adjusted
return -((-1)**self._sign)
+ # Note: The Decimal standard doesn't cover rich comparisons for
+ # Decimals. In particular, the specification is silent on the
+ # subject of what should happen for a comparison involving a NaN.
+ # We take the following approach:
+ #
+ # == comparisons involving a NaN always return False
+ # != comparisons involving a NaN always return True
+ # <, >, <= and >= comparisons involving a (quiet or signaling)
+ # NaN signal InvalidOperation, and return False if the
+ # InvalidOperation is trapped.
+ #
+ # This behavior is designed to conform as closely as possible to
+ # that specified by IEEE 754.
+
def __eq__(self, other):
- if not isinstance(other, (Decimal, int)):
- return NotImplemented
- return self.__cmp__(other) == 0
+ other = _convert_other(other)
+ if other is NotImplemented:
+ return other
+ if self.is_nan() or other.is_nan():
+ return False
+ return self._cmp(other) == 0
def __ne__(self, other):
- if not isinstance(other, (Decimal, int)):
- return NotImplemented
- return self.__cmp__(other) != 0
+ other = _convert_other(other)
+ if other is NotImplemented:
+ return other
+ if self.is_nan() or other.is_nan():
+ return True
+ return self._cmp(other) != 0
- def __lt__(self, other):
- if not isinstance(other, (Decimal, int)):
- return NotImplemented
- return self.__cmp__(other) < 0
- def __le__(self, other):
- if not isinstance(other, (Decimal, int)):
- return NotImplemented
- return self.__cmp__(other) <= 0
+ def __lt__(self, other, context=None):
+ other = _convert_other(other)
+ if other is NotImplemented:
+ return other
+ ans = self._compare_check_nans(other, context)
+ if ans:
+ return False
+ return self._cmp(other) < 0
- def __gt__(self, other):
- if not isinstance(other, (Decimal, int)):
- return NotImplemented
- return self.__cmp__(other) > 0
+ def __le__(self, other, context=None):
+ other = _convert_other(other)
+ if other is NotImplemented:
+ return other
+ ans = self._compare_check_nans(other, context)
+ if ans:
+ return False
+ return self._cmp(other) <= 0
- def __ge__(self, other):
- if not isinstance(other, (Decimal, int)):
- return NotImplemented
- return self.__cmp__(other) >= 0
+ def __gt__(self, other, context=None):
+ other = _convert_other(other)
+ if other is NotImplemented:
+ return other
+ ans = self._compare_check_nans(other, context)
+ if ans:
+ return False
+ return self._cmp(other) > 0
+
+ def __ge__(self, other, context=None):
+ other = _convert_other(other)
+ if other is NotImplemented:
+ return other
+ ans = self._compare_check_nans(other, context)
+ if ans:
+ return False
+ return self._cmp(other) >= 0
def compare(self, other, context=None):
"""Compares one to another.
@@ -812,7 +877,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
if ans:
return ans
- return Decimal(self.__cmp__(other))
+ return Decimal(self._cmp(other))
def __hash__(self):
"""x.__hash__() <==> hash(x)"""
@@ -2463,7 +2528,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
return other._fix_nan(context)
return self._check_nans(other, context)
- c = self.__cmp__(other)
+ c = self._cmp(other)
if c == 0:
# If both operands are finite and equal in numerical value
# then an ordering is applied:
@@ -2505,7 +2570,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
return other._fix_nan(context)
return self._check_nans(other, context)
- c = self.__cmp__(other)
+ c = self._cmp(other)
if c == 0:
c = self.compare_total(other)
@@ -2553,23 +2618,10 @@ class Decimal(_numbers.Real, _numbers.Inexact):
It's pretty much like compare(), but all NaNs signal, with signaling
NaNs taking precedence over quiet NaNs.
"""
- if context is None:
- context = getcontext()
-
- self_is_nan = self._isnan()
- other_is_nan = other._isnan()
- if self_is_nan == 2:
- return context._raise_error(InvalidOperation, 'sNaN',
- self)
- if other_is_nan == 2:
- return context._raise_error(InvalidOperation, 'sNaN',
- other)
- if self_is_nan:
- return context._raise_error(InvalidOperation, 'NaN in compare_signal',
- self)
- if other_is_nan:
- return context._raise_error(InvalidOperation, 'NaN in compare_signal',
- other)
+ other = _convert_other(other, raiseit = True)
+ ans = self._compare_check_nans(other, context)
+ if ans:
+ return ans
return self.compare(other, context=context)
def compare_total(self, other):
@@ -3076,7 +3128,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
return other._fix_nan(context)
return self._check_nans(other, context)
- c = self.copy_abs().__cmp__(other.copy_abs())
+ c = self.copy_abs()._cmp(other.copy_abs())
if c == 0:
c = self.compare_total(other)
@@ -3106,7 +3158,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
return other._fix_nan(context)
return self._check_nans(other, context)
- c = self.copy_abs().__cmp__(other.copy_abs())
+ c = self.copy_abs()._cmp(other.copy_abs())
if c == 0:
c = self.compare_total(other)
@@ -3181,7 +3233,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
if ans:
return ans
- comparison = self.__cmp__(other)
+ comparison = self._cmp(other)
if comparison == 0:
return self.copy_sign(other)
diff --git a/Lib/numbers.py b/Lib/numbers.py
index 4dd5ca7..b5150d2 100644
--- a/Lib/numbers.py
+++ b/Lib/numbers.py
@@ -154,7 +154,10 @@ class Complex(Number):
"""self == other"""
raise NotImplementedError
- # __ne__ is inherited from object and negates whatever __eq__ does.
+ def __ne__(self, other):
+ """self != other"""
+ # The default __ne__ doesn't negate __eq__ until 3.0.
+ return not (self == other)
Complex.register(complex)
diff --git a/Lib/test/cjkencodings_test.py b/Lib/test/cjkencodings_test.py
index 72f4bdc..7e55f37 100644
--- a/Lib/test/cjkencodings_test.py
+++ b/Lib/test/cjkencodings_test.py
@@ -64,8 +64,10 @@ b"\x88\x91\xe5\x80\x91\xe6\x89\x80\x0a\xe8\xa6\x81\xe8\xa8\x8e\xe8"
b"\xab\x96\xe7\x9a\x84\xe5\x95\x8f\xe9\xa1\x8c\xe5\xb0\xb1\xe6\x98"
b"\xaf\x3a\x0a\x0a"),
'big5hkscs': (
-b"\x88\x45\x88\x5c\x8a\x73\x8b\xda\x8d\xd8\x0a",
-b"\xf0\xa0\x84\x8c\xc4\x9a\xe9\xb5\xae\xe7\xbd\x93\xe6\xb4\x86\x0a"),
+b"\x88\x45\x88\x5c\x8a\x73\x8b\xda\x8d\xd8\x0a\x88\x66\x88\x62\x88"
+b"\xa7\x20\x88\xa7\x88\xa3\x0a",
+b"\xf0\xa0\x84\x8c\xc4\x9a\xe9\xb5\xae\xe7\xbd\x93\xe6\xb4\x86\x0a"
+b"\xc3\x8a\xc3\x8a\xcc\x84\xc3\xaa\x20\xc3\xaa\xc3\xaa\xcc\x84\x0a"),
'cp949': (
b"\x8c\x63\xb9\xe6\xb0\xa2\xc7\xcf\x20\xbc\x84\xbd\xc3\xc4\xdd\xb6"
b"\xf3\x0a\x0a\xa8\xc0\xa8\xc0\xb3\xb3\x21\x21\x20\xec\xd7\xce\xfa"
diff --git a/Lib/test/test_codecmaps_hk.py b/Lib/test/test_codecmaps_hk.py
index 1068d0b..362ab7f 100644
--- a/Lib/test/test_codecmaps_hk.py
+++ b/Lib/test/test_codecmaps_hk.py
@@ -11,10 +11,11 @@ import unittest
class TestBig5HKSCSMap(test_multibytecodec_support.TestBase_Mapping,
unittest.TestCase):
encoding = 'big5hkscs'
- mapfileurl = 'http://people.freebsd.org/~perky/i18n/BIG5HKSCS.TXT'
+ mapfileurl = 'http://people.freebsd.org/~perky/i18n/BIG5HKSCS-2004.TXT'
def test_main():
test_support.run_unittest(__name__)
if __name__ == "__main__":
+ test_support.use_resources = ['urlfetch']
test_main()
diff --git a/Lib/test/test_contains.py b/Lib/test/test_contains.py
index b55057d..5ab80e4 100644
--- a/Lib/test/test_contains.py
+++ b/Lib/test/test_contains.py
@@ -1,103 +1,88 @@
-from test.test_support import TestFailed
+from test.test_support import run_unittest
+import unittest
-class base_set:
+class base_set:
def __init__(self, el):
self.el = el
class set(base_set):
-
def __contains__(self, el):
return self.el == el
class seq(base_set):
-
def __getitem__(self, n):
return [self.el][n]
-def check(ok, *args):
- if not ok:
- raise TestFailed(" ".join(map(str, args)))
-
-a = base_set(1)
-b = set(1)
-c = seq(1)
-
-check(1 in b, "1 not in set(1)")
-check(0 not in b, "0 in set(1)")
-check(1 in c, "1 not in seq(1)")
-check(0 not in c, "0 in seq(1)")
-
-try:
- 1 in a
- check(0, "in base_set did not raise error")
-except TypeError:
- pass
-
-try:
- 1 not in a
- check(0, "not in base_set did not raise error")
-except TypeError:
- pass
-
-# Test char in string
-
-check('c' in 'abc', "'c' not in 'abc'")
-check('d' not in 'abc', "'d' in 'abc'")
-
-check('' in '', "'' not in ''")
-check('' in 'abc', "'' not in 'abc'")
-
-try:
- None in 'abc'
- check(0, "None in 'abc' did not raise error")
-except TypeError:
- pass
-
-
-# A collection of tests on builtin sequence types
-a = list(range(10))
-for i in a:
- check(i in a, "%r not in %r" % (i, a))
-check(16 not in a, "16 not in %r" % (a,))
-check(a not in a, "%s not in %r" % (a, a))
-
-a = tuple(a)
-for i in a:
- check(i in a, "%r not in %r" % (i, a))
-check(16 not in a, "16 not in %r" % (a,))
-check(a not in a, "%r not in %r" % (a, a))
-
-class Deviant1:
- """Behaves strangely when compared
-
- This class is designed to make sure that the contains code
- works when the list is modified during the check.
- """
-
- aList = list(range(15))
-
- def __cmp__(self, other):
- if other == 12:
- self.aList.remove(12)
- self.aList.remove(13)
- self.aList.remove(14)
- return 1
-
-check(Deviant1() not in Deviant1.aList, "Deviant1 failed")
-
-class Deviant2:
- """Behaves strangely when compared
-
- This class raises an exception during comparison. That in
- turn causes the comparison to fail with a TypeError.
- """
-
- def __cmp__(self, other):
- if other == 4:
- raise RuntimeError("gotcha")
-
-try:
- check(Deviant2() not in a, "oops")
-except TypeError:
- pass
+class TestContains(unittest.TestCase):
+ def test_common_tests(self):
+ a = base_set(1)
+ b = set(1)
+ c = seq(1)
+ self.assert_(1 in b)
+ self.assert_(0 not in b)
+ self.assert_(1 in c)
+ self.assert_(0 not in c)
+ self.assertRaises(TypeError, lambda: 1 in a)
+ self.assertRaises(TypeError, lambda: 1 not in a)
+
+ # test char in string
+ self.assert_('c' in 'abc')
+ self.assert_('d' not in 'abc')
+
+ self.assert_('' in '')
+ self.assert_('' in 'abc')
+
+ self.assertRaises(TypeError, lambda: None in 'abc')
+
+ def test_builtin_sequence_types(self):
+ # a collection of tests on builtin sequence types
+ a = range(10)
+ for i in a:
+ self.assert_(i in a)
+ self.assert_(16 not in a)
+ self.assert_(a not in a)
+
+ a = tuple(a)
+ for i in a:
+ self.assert_(i in a)
+ self.assert_(16 not in a)
+ self.assert_(a not in a)
+
+ class Deviant1:
+ """Behaves strangely when compared
+
+ This class is designed to make sure that the contains code
+ works when the list is modified during the check.
+ """
+ aList = range(15)
+ def __cmp__(self, other):
+ if other == 12:
+ self.aList.remove(12)
+ self.aList.remove(13)
+ self.aList.remove(14)
+ return 1
+
+ self.assert_(Deviant1() not in Deviant1.aList)
+
+ class Deviant2:
+ """Behaves strangely when compared
+
+ This class raises an exception during comparison. That in
+ turn causes the comparison to fail with a TypeError.
+ """
+ def __cmp__(self, other):
+ if other == 4:
+ raise RuntimeError("gotcha")
+
+ try:
+ self.assert_(Deviant2() not in a)
+ except TypeError:
+ pass
+
+
+def test_main():
+ run_unittest(TestContains)
+
+if __name__ == '__main__':
+ test_main()
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
index e051ada..1ef0ad3 100644
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -833,6 +833,19 @@ class DecimalArithmeticOperatorsTest(unittest.TestCase):
self.assertEqual(-Decimal(45), Decimal(-45)) # -
self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
+ def test_nan_comparisons(self):
+ n = Decimal('NaN')
+ s = Decimal('sNaN')
+ i = Decimal('Inf')
+ f = Decimal('2')
+ for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
+ (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
+ self.assert_(x != y)
+ self.assert_(not (x == y))
+ self.assert_(not (x < y))
+ self.assert_(not (x <= y))
+ self.assert_(not (x > y))
+ self.assert_(not (x >= y))
# The following are two functions used to test threading in the next class
@@ -1137,7 +1150,12 @@ class DecimalUsabilityTest(unittest.TestCase):
checkSameDec("__abs__")
checkSameDec("__add__", True)
checkSameDec("__divmod__", True)
- checkSameDec("__cmp__", True)
+ checkSameDec("__eq__", True)
+ checkSameDec("__ne__", True)
+ checkSameDec("__le__", True)
+ checkSameDec("__lt__", True)
+ checkSameDec("__ge__", True)
+ checkSameDec("__gt__", True)
checkSameDec("__float__")
checkSameDec("__floordiv__", True)
checkSameDec("__hash__")
diff --git a/Lib/test/test_defaultdict.py b/Lib/test/test_defaultdict.py
index 18c1eb6..6eb25ad 100644
--- a/Lib/test/test_defaultdict.py
+++ b/Lib/test/test_defaultdict.py
@@ -141,6 +141,29 @@ class TestDefaultDict(unittest.TestCase):
else:
self.fail("expected KeyError")
+ def test_recursive_repr(self):
+ # Issue2045: stack overflow when default_factory is a bound method
+ class sub(defaultdict):
+ def __init__(self):
+ self.default_factory = self._factory
+ def _factory(self):
+ return []
+ d = sub()
+ self.assert_(repr(d).startswith(
+ "defaultdict(<bound method sub._factory of defaultdict(..."))
+
+ # NOTE: printing a subclass of a builtin type does not call its
+ # tp_print slot. So this part is essentially the same test as above.
+ tfn = tempfile.mktemp()
+ try:
+ f = open(tfn, "w+")
+ try:
+ print(d, file=f)
+ finally:
+ f.close()
+ finally:
+ os.remove(tfn)
+
def test_main():
test_support.run_unittest(TestDefaultDict)
diff --git a/Lib/test/test_iterlen.py b/Lib/test/test_iterlen.py
index 75e7a16..46aefaa 100644
--- a/Lib/test/test_iterlen.py
+++ b/Lib/test/test_iterlen.py
@@ -196,7 +196,6 @@ class TestListReversed(TestInvariantWithoutMutations):
self.assertEqual(len(it), 0)
-
def test_main():
unittests = [
TestRepeat,
diff --git a/Lib/test/test_largefile.py b/Lib/test/test_largefile.py
index 6d2e27d..f7697d2 100644
--- a/Lib/test/test_largefile.py
+++ b/Lib/test/test_largefile.py
@@ -1,12 +1,12 @@
-#!python
+"""Test largefile support on system where this makes sense.
+"""
-#----------------------------------------------------------------------
-# test largefile support on system where this makes sense
-#
-#----------------------------------------------------------------------
-
-from test import test_support
-import os, stat, sys
+import os
+import stat
+import sys
+import unittest
+from test.test_support import run_unittest, TESTFN, verbose, requires, \
+ TestSkipped, unlink
try:
import signal
@@ -17,154 +17,160 @@ try:
except (ImportError, AttributeError):
pass
-
# create >2GB file (2GB = 2147483648 bytes)
size = 2500000000
-name = test_support.TESTFN
-
-
-# On Windows and Mac OSX this test comsumes large resources; It takes
-# a long time to build the >2GB file and takes >2GB of disk space
-# therefore the resource must be enabled to run this test. If not,
-# nothing after this line stanza will be executed.
-if sys.platform[:3] == 'win' or sys.platform == 'darwin':
- test_support.requires(
- 'largefile',
- 'test requires %s bytes and a long time to run' % str(size))
-else:
- # Only run if the current filesystem supports large files.
- # (Skip this test on Windows, since we now always support large files.)
- f = open(test_support.TESTFN, 'wb')
- try:
- # 2**31 == 2147483648
- f.seek(2147483649)
- # Seeking is not enough of a test: you must write and flush, too!
- f.write(b"x")
- f.flush()
- except (IOError, OverflowError):
- f.close()
- os.unlink(test_support.TESTFN)
- raise test_support.TestSkipped(
- "filesystem does not have largefile support")
- else:
- f.close()
-def expect(got_this, expect_this):
- if test_support.verbose:
- print('%r =?= %r ...' % (got_this, expect_this), end=' ')
- if got_this != expect_this:
- if test_support.verbose:
- print('no')
- raise test_support.TestFailed('got %r, but expected %r'
- % (got_this, expect_this))
+class TestCase(unittest.TestCase):
+ """Test that each file function works as expected for a large
+ (i.e. > 2GB, do we have to check > 4GB) files.
+ """
+
+ def test_seek(self):
+ if verbose:
+ print('create large file via seek (may be sparse file) ...')
+ f = open(TESTFN, 'wb')
+ try:
+ f.write('z')
+ f.seek(0)
+ f.seek(size)
+ f.write('a')
+ f.flush()
+ if verbose:
+ print('check file size with os.fstat')
+ self.assertEqual(os.fstat(f.fileno())[stat.ST_SIZE], size+1)
+ finally:
+ f.close()
+
+ def test_osstat(self):
+ if verbose:
+ print('check file size with os.stat')
+ self.assertEqual(os.stat(TESTFN)[stat.ST_SIZE], size+1)
+
+ def test_seek_read(self):
+ if verbose:
+ print('play around with seek() and read() with the built largefile')
+ f = open(TESTFN, 'rb')
+ try:
+ self.assertEqual(f.tell(), 0)
+ self.assertEqual(f.read(1), 'z')
+ self.assertEqual(f.tell(), 1)
+ f.seek(0)
+ self.assertEqual(f.tell(), 0)
+ f.seek(0, 0)
+ self.assertEqual(f.tell(), 0)
+ f.seek(42)
+ self.assertEqual(f.tell(), 42)
+ f.seek(42, 0)
+ self.assertEqual(f.tell(), 42)
+ f.seek(42, 1)
+ self.assertEqual(f.tell(), 84)
+ f.seek(0, 1)
+ self.assertEqual(f.tell(), 84)
+ f.seek(0, 2) # seek from the end
+ self.assertEqual(f.tell(), size + 1 + 0)
+ f.seek(-10, 2)
+ self.assertEqual(f.tell(), size + 1 - 10)
+ f.seek(-size-1, 2)
+ self.assertEqual(f.tell(), 0)
+ f.seek(size)
+ self.assertEqual(f.tell(), size)
+ # the 'a' that was written at the end of file above
+ self.assertEqual(f.read(1), 'a')
+ f.seek(-size-1, 1)
+ self.assertEqual(f.read(1), 'z')
+ self.assertEqual(f.tell(), 1)
+ finally:
+ f.close()
+
+ def test_lseek(self):
+ if verbose:
+ print('play around with os.lseek() with the built largefile')
+ f = open(TESTFN, 'rb')
+ try:
+ self.assertEqual(os.lseek(f.fileno(), 0, 0), 0)
+ self.assertEqual(os.lseek(f.fileno(), 42, 0), 42)
+ self.assertEqual(os.lseek(f.fileno(), 42, 1), 84)
+ self.assertEqual(os.lseek(f.fileno(), 0, 1), 84)
+ self.assertEqual(os.lseek(f.fileno(), 0, 2), size+1+0)
+ self.assertEqual(os.lseek(f.fileno(), -10, 2), size+1-10)
+ self.assertEqual(os.lseek(f.fileno(), -size-1, 2), 0)
+ self.assertEqual(os.lseek(f.fileno(), size, 0), size)
+ # the 'a' that was written at the end of file above
+ self.assertEqual(f.read(1), 'a')
+ finally:
+ f.close()
+
+ def test_truncate(self):
+ if verbose:
+ print('try truncate')
+ f = open(TESTFN, 'r+b')
+ # this is already decided before start running the test suite
+ # but we do it anyway for extra protection
+ if not hasattr(f, 'truncate'):
+ raise TestSkipped("open().truncate() not available on this system")
+ try:
+ f.seek(0, 2)
+ # else we've lost track of the true size
+ self.assertEqual(f.tell(), size+1)
+ # Cut it back via seek + truncate with no argument.
+ newsize = size - 10
+ f.seek(newsize)
+ f.truncate()
+ self.assertEqual(f.tell(), newsize) # else pointer moved
+ f.seek(0, 2)
+ self.assertEqual(f.tell(), newsize) # else wasn't truncated
+ # Ensure that truncate(smaller than true size) shrinks
+ # the file.
+ newsize -= 1
+ f.seek(42)
+ f.truncate(newsize)
+ self.assertEqual(f.tell(), 42) # else pointer moved
+ f.seek(0, 2)
+ self.assertEqual(f.tell(), newsize) # else wasn't truncated
+ # XXX truncate(larger than true size) is ill-defined
+ # across platform; cut it waaaaay back
+ f.seek(0)
+ f.truncate(1)
+ self.assertEqual(f.tell(), 0) # else pointer moved
+ self.assertEqual(len(f.read()), 1) # else wasn't truncated
+ finally:
+ f.close()
+
+def main_test():
+ # On Windows and Mac OSX this test comsumes large resources; It
+ # takes a long time to build the >2GB file and takes >2GB of disk
+ # space therefore the resource must be enabled to run this test.
+ # If not, nothing after this line stanza will be executed.
+ if sys.platform[:3] == 'win' or sys.platform == 'darwin':
+ requires('largefile',
+ 'test requires %s bytes and a long time to run' % str(size))
else:
- if test_support.verbose:
- print('yes')
-
-
-# test that each file function works as expected for a large (i.e. >2GB, do
-# we have to check >4GB) files
-
-if test_support.verbose:
- print('create large file via seek (may be sparse file) ...')
-f = open(name, 'wb')
-try:
- f.write(b'z')
- f.seek(0)
- f.seek(size)
- f.write(b'a')
- f.flush()
- if test_support.verbose:
- print('check file size with os.fstat')
- expect(os.fstat(f.fileno())[stat.ST_SIZE], size+1)
-finally:
- f.close()
-if test_support.verbose:
- print('check file size with os.stat')
-expect(os.stat(name)[stat.ST_SIZE], size+1)
-
-if test_support.verbose:
- print('play around with seek() and read() with the built largefile')
-f = open(name, 'rb')
-try:
- expect(f.tell(), 0)
- expect(f.read(1), b'z')
- expect(f.tell(), 1)
- f.seek(0)
- expect(f.tell(), 0)
- f.seek(0, 0)
- expect(f.tell(), 0)
- f.seek(42)
- expect(f.tell(), 42)
- f.seek(42, 0)
- expect(f.tell(), 42)
- f.seek(42, 1)
- expect(f.tell(), 84)
- f.seek(0, 1)
- expect(f.tell(), 84)
- f.seek(0, 2) # seek from the end
- expect(f.tell(), size + 1 + 0)
- f.seek(-10, 2)
- expect(f.tell(), size + 1 - 10)
- f.seek(-size-1, 2)
- expect(f.tell(), 0)
- f.seek(size)
- expect(f.tell(), size)
- expect(f.read(1), b'a') # the 'a' that was written at the end of file above
- f.seek(-size-1, 1)
- expect(f.read(1), b'z')
- expect(f.tell(), 1)
-finally:
- f.close()
-
-if test_support.verbose:
- print('play around with os.lseek() with the built largefile')
-f = open(name, 'rb')
-try:
- expect(os.lseek(f.fileno(), 0, 0), 0)
- expect(os.lseek(f.fileno(), 42, 0), 42)
- expect(os.lseek(f.fileno(), 42, 1), 84)
- expect(os.lseek(f.fileno(), 0, 1), 84)
- expect(os.lseek(f.fileno(), 0, 2), size+1+0)
- expect(os.lseek(f.fileno(), -10, 2), size+1-10)
- expect(os.lseek(f.fileno(), -size-1, 2), 0)
- expect(os.lseek(f.fileno(), size, 0), size)
- expect(f.read(1), b'a') # the 'a' that was written at the end of file above
-finally:
- f.close()
-
-if hasattr(f, 'truncate'):
- if test_support.verbose:
- print('try truncate')
- f = open(name, 'r+b')
- try:
- f.seek(0, 2)
- expect(f.tell(), size+1) # else we've lost track of the true size
- # Cut it back via seek + truncate with no argument.
- newsize = size - 10
- f.seek(newsize)
- f.truncate()
- expect(f.tell(), newsize) # else pointer moved
- f.seek(0, 2)
- expect(f.tell(), newsize) # else wasn't truncated
- # Ensure that truncate(smaller than true size) shrinks the file.
- newsize -= 1
- f.seek(42)
- f.truncate(newsize)
- expect(f.tell(), 42) # else pointer moved
- f.seek(0, 2)
- expect(f.tell(), newsize) # else wasn't truncated
-
- # XXX truncate(larger than true size) is ill-defined across platforms
-
- # cut it waaaaay back
- f.seek(0)
- f.truncate(1)
- expect(f.tell(), 0) # else pointer moved
- expect(len(f.read()), 1) # else wasn't truncated
-
- finally:
- f.close()
-
-os.unlink(name)
+ # Only run if the current filesystem supports large files.
+ # (Skip this test on Windows, since we now always support
+ # large files.)
+ f = open(TESTFN, 'wb')
+ try:
+ # 2**31 == 2147483648
+ f.seek(2147483649)
+ # Seeking is not enough of a test: you must write and
+ # flush, too!
+ f.write("x")
+ f.flush()
+ except (IOError, OverflowError):
+ f.close()
+ unlink(TESTFN)
+ raise TestSkipped("filesystem does not have largefile support")
+ else:
+ f.close()
+ suite = unittest.TestSuite()
+ suite.addTest(TestCase('test_seek'))
+ suite.addTest(TestCase('test_osstat'))
+ suite.addTest(TestCase('test_seek_read'))
+ suite.addTest(TestCase('test_lseek'))
+ f = open(TESTFN, 'w')
+ if hasattr(f, 'truncate'):
+ suite.addTest(TestCase('test_truncate'))
+
+if __name__ == '__main__':
+ main_test()
diff --git a/Lib/test/test_rational.py b/Lib/test/test_rational.py
index 4f248be..92d8a14 100644
--- a/Lib/test/test_rational.py
+++ b/Lib/test/test_rational.py
@@ -328,6 +328,8 @@ class RationalTest(unittest.TestCase):
self.assertFalse(R(2, 3) <= R(1, 2))
self.assertTrue(R(1, 2) == R(1, 2))
self.assertFalse(R(1, 2) == R(1, 3))
+ self.assertFalse(R(1, 2) != R(1, 2))
+ self.assertTrue(R(1, 2) != R(1, 3))
def testMixedLess(self):
self.assertTrue(2 < R(5, 2))
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index 393e997..199119a 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -817,6 +817,8 @@ class HandlerTests(unittest.TestCase):
method = getattr(h, "http_error_%s" % code)
req = Request(from_url, data)
req.add_header("Nonsense", "viking=withhold")
+ if data is not None:
+ req.add_header("Content-Length", str(len(data)))
req.add_unredirected_header("Spam", "spam")
try:
method(req, MockFile(), code, "Blah",
@@ -829,6 +831,13 @@ class HandlerTests(unittest.TestCase):
self.assertEqual(o.req.get_method(), "GET")
except AttributeError:
self.assert_(not o.req.has_data())
+
+ # now it's a GET, there should not be headers regarding content
+ # (possibly dragged from before being a POST)
+ headers = [x.lower() for x in o.req.headers]
+ self.assertTrue("content-length" not in headers)
+ self.assertTrue("content-type" not in headers)
+
self.assertEqual(o.req.headers["Nonsense"],
"viking=withhold")
self.assert_("Spam" not in o.req.headers)
diff --git a/Lib/urllib2.py b/Lib/urllib2.py
index 3ad0b15..91c632c 100644
--- a/Lib/urllib2.py
+++ b/Lib/urllib2.py
@@ -531,8 +531,11 @@ class HTTPRedirectHandler(BaseHandler):
# do the same.
# be conciliant with URIs containing a space
newurl = newurl.replace(' ', '%20')
+ newheaders = dict((k,v) for k,v in req.headers.items()
+ if k.lower() not in ("content-length", "content-type")
+ )
return Request(newurl,
- headers=req.headers,
+ headers=newheaders,
origin_req_host=req.get_origin_req_host(),
unverifiable=True)
else: