SF.net SVN: jython:[7220] trunk/jython/Lib/test

[email protected] Sat, 12 Mar 2011 20:13:36 +0000
Newsgroups gmane.comp.lang.jython.cvs
Message-ID <[email protected]>
Revision: 7220
          http://jython.svn.sourceforge.net/jython/?rev=7220&view=rev
Author:   fwierzbicki
Date:     2011-03-12 20:13:35 +0000 (Sat, 12 Mar 2011)

Log Message:
-----------
Tests added from Python 2.6 - these should be reviewed for deletion after we
switch to the 2.6 Lib.

Added Paths:
-----------
    trunk/jython/Lib/test/exception_hierarchy.txt
    trunk/jython/Lib/test/output/test_global
    trunk/jython/Lib/test/output/test_grammar
    trunk/jython/Lib/test/test_asynchat.py
    trunk/jython/Lib/test/test_base64.py
    trunk/jython/Lib/test/test_contextlib.py
    trunk/jython/Lib/test/test_datetime.py
    trunk/jython/Lib/test/test_email.py
    trunk/jython/Lib/test/test_email_renamed.py
    trunk/jython/Lib/test/test_gettext.py
    trunk/jython/Lib/test/test_global.py
    trunk/jython/Lib/test/test_threading_local.py
    trunk/jython/Lib/test/test_wsgiref.py

Added: trunk/jython/Lib/test/exception_hierarchy.txt
===================================================================
--- trunk/jython/Lib/test/exception_hierarchy.txt	                        (rev 0)
+++ trunk/jython/Lib/test/exception_hierarchy.txt	2011-03-12 20:13:35 UTC (rev 7220)
@@ -0,0 +1,49 @@
+BaseException
+ +-- SystemExit
+ +-- KeyboardInterrupt
+ +-- GeneratorExit
+ +-- Exception
+      +-- StopIteration
+      +-- StandardError
+      |    +-- ArithmeticError
+      |    |    +-- FloatingPointError
+      |    |    +-- OverflowError
+      |    |    +-- ZeroDivisionError
+      |    +-- AssertionError
+      |    +-- AttributeError
+      |    +-- EnvironmentError
+      |    |    +-- IOError
+      |    |    +-- OSError
+      |    |         +-- WindowsError (Windows)
+      |    |         +-- VMSError (VMS)
+      |    +-- EOFError
+      |    +-- ImportError
+      |    +-- LookupError
+      |    |    +-- IndexError
+      |    |    +-- KeyError
+      |    +-- MemoryError
+      |    +-- NameError
+      |    |    +-- UnboundLocalError
+      |    +-- ReferenceError
+      |    +-- RuntimeError
+      |    |    +-- NotImplementedError
+      |    +-- SyntaxError
+      |    |    +-- IndentationError
+      |    |         +-- TabError
+      |    +-- SystemError
+      |    +-- TypeError
+      |    +-- ValueError
+      |         +-- UnicodeError
+      |              +-- UnicodeDecodeError
+      |              +-- UnicodeEncodeError
+      |              +-- UnicodeTranslateError
+      +-- Warning
+           +-- DeprecationWarning
+           +-- PendingDeprecationWarning
+           +-- RuntimeWarning
+           +-- SyntaxWarning
+           +-- UserWarning
+           +-- FutureWarning
+	   +-- ImportWarning
+	   +-- UnicodeWarning
+	   +-- BytesWarning

Added: trunk/jython/Lib/test/output/test_global
===================================================================
--- trunk/jython/Lib/test/output/test_global	                        (rev 0)
+++ trunk/jython/Lib/test/output/test_global	2011-03-12 20:13:35 UTC (rev 7220)
@@ -0,0 +1 @@
+test_global

Added: trunk/jython/Lib/test/output/test_grammar
===================================================================
--- trunk/jython/Lib/test/output/test_grammar	                        (rev 0)
+++ trunk/jython/Lib/test/output/test_grammar	2011-03-12 20:13:35 UTC (rev 7220)
@@ -0,0 +1 @@
+test_grammar

Added: trunk/jython/Lib/test/test_asynchat.py
===================================================================
--- trunk/jython/Lib/test/test_asynchat.py	                        (rev 0)
+++ trunk/jython/Lib/test/test_asynchat.py	2011-03-12 20:13:35 UTC (rev 7220)
@@ -0,0 +1,93 @@
+# test asynchat -- requires threading
+
+import thread # If this fails, we can't test this module
+import asyncore, asynchat, socket, threading, time
+import unittest
+from test import test_support
+
+HOST = "127.0.0.1"
+PORT = 54322
+
+class echo_server(threading.Thread):
+
+    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)
+        sock.listen(1)
+        conn, client = sock.accept()
+        buffer = ""
+        while "\n" not in buffer:
+            data = conn.recv(1)
+            if not data:
+                break
+            buffer = buffer + data
+        while buffer:
+            n = conn.send(buffer)
+            buffer = buffer[n:]
+        conn.close()
+        sock.close()
+
+class echo_client(asynchat.async_chat):
+
+    def __init__(self, terminator):
+        asynchat.async_chat.__init__(self)
+        self.contents = None
+        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.connect((HOST, PORT))
+        self.set_terminator(terminator)
+        self.buffer = ""
+
+    def handle_connect(self):
+        pass
+        ##print "Connected"
+
+    def collect_incoming_data(self, data):
+        self.buffer = self.buffer + data
+
+    def found_terminator(self):
+        #print "Received:", repr(self.buffer)
+        self.contents = self.buffer
+        self.buffer = ""
+        self.close()
+
+
+class TestAsynchat(unittest.TestCase):
+    def setUp (self):
+        pass
+
+    def tearDown (self):
+        pass
+
+    def test_line_terminator(self):
+        s = echo_server()
+        s.start()
+        time.sleep(1) # Give server time to initialize
+        c = echo_client('\n')
+        c.push("hello ")
+        c.push("world\n")
+        asyncore.loop()
+        s.join()
+
+        self.assertEqual(c.contents, 'hello world')
+
+    def test_numeric_terminator(self):
+        # Try reading a fixed number of bytes
+        s = echo_server()
+        s.start()
+        time.sleep(1) # Give server time to initialize
+        c = echo_client(6L)
+        c.push("hello ")
+        c.push("world\n")
+        asyncore.loop()
+        s.join()
+
+        self.assertEqual(c.contents, 'hello ')
+
+
+def test_main(verbose=None):
+    test_support.run_unittest(TestAsynchat)
+
+if __name__ == "__main__":
+    test_main(verbose=True)

Added: trunk/jython/Lib/test/test_base64.py
===================================================================
--- trunk/jython/Lib/test/test_base64.py	                        (rev 0)
+++ trunk/jython/Lib/test/test_base64.py	2011-03-12 20:13:35 UTC (rev 7220)
@@ -0,0 +1,190 @@
+import unittest
+from test import test_support
+import base64
+
+
+
+class LegacyBase64TestCase(unittest.TestCase):
+    def test_encodestring(self):
+        eq = self.assertEqual
+        eq(base64.encodestring("www.python.org"), "d3d3LnB5dGhvbi5vcmc=\n")
+        eq(base64.encodestring("a"), "YQ==\n")
+        eq(base64.encodestring("ab"), "YWI=\n")
+        eq(base64.encodestring("abc"), "YWJj\n")
+        eq(base64.encodestring(""), "")
+        eq(base64.encodestring("abcdefghijklmnopqrstuvwxyz"
+                               "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                               "0123456789!@#0^&*();:<>,. []{}"),
+           "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
+           "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT"
+           "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n")
+
+    def test_decodestring(self):
+        eq = self.assertEqual
+        eq(base64.decodestring("d3d3LnB5dGhvbi5vcmc=\n"), "www.python.org")
+        eq(base64.decodestring("YQ==\n"), "a")
+        eq(base64.decodestring("YWI=\n"), "ab")
+        eq(base64.decodestring("YWJj\n"), "abc")
+        eq(base64.decodestring("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
+                               "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT"
+                               "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n"),
+           "abcdefghijklmnopqrstuvwxyz"
+           "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+           "0123456789!@#0^&*();:<>,. []{}")
+        eq(base64.decodestring(''), '')
+
+    def test_encode(self):
+        eq = self.assertEqual
+        from cStringIO import StringIO
+        infp = StringIO('abcdefghijklmnopqrstuvwxyz'
+                        'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+                        '0123456789!@#0^&*();:<>,. []{}')
+        outfp = StringIO()
+        base64.encode(infp, outfp)
+        eq(outfp.getvalue(),
+           'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE'
+           'RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT'
+           'Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n')
+
+    def test_decode(self):
+        from cStringIO import StringIO
+        infp = StringIO('d3d3LnB5dGhvbi5vcmc=')
+        outfp = StringIO()
+        base64.decode(infp, outfp)
+        self.assertEqual(outfp.getvalue(), 'www.python.org')
+
+
+
+class BaseXYTestCase(unittest.TestCase):
+    def test_b64encode(self):
+        eq = self.assertEqual
+        # Test default alphabet
+        eq(base64.b64encode("www.python.org"), "d3d3LnB5dGhvbi5vcmc=")
+        eq(base64.b64encode('\x00'), 'AA==')
+        eq(base64.b64encode("a"), "YQ==")
+        eq(base64.b64encode("ab"), "YWI=")
+        eq(base64.b64encode("abc"), "YWJj")
+        eq(base64.b64encode(""), "")
+        eq(base64.b64encode("abcdefghijklmnopqrstuvwxyz"
+                            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                            "0123456789!@#0^&*();:<>,. []{}"),
+           "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
+           "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT"
+           "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==")
+        # Test with arbitrary alternative characters
+        eq(base64.b64encode('\xd3V\xbeo\xf7\x1d', altchars='*$'), '01a*b$cd')
+        # Test standard alphabet
+        eq(base64.standard_b64encode("www.python.org"), "d3d3LnB5dGhvbi5vcmc=")
+        eq(base64.standard_b64encode("a"), "YQ==")
+        eq(base64.standard_b64encode("ab"), "YWI=")
+        eq(base64.standard_b64encode("abc"), "YWJj")
+        eq(base64.standard_b64encode(""), "")
+        eq(base64.standard_b64encode("abcdefghijklmnopqrstuvwxyz"
+                                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                     "0123456789!@#0^&*();:<>,. []{}"),
+           "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
+           "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT"
+           "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==")
+        # Test with 'URL safe' alternative characters
+        eq(base64.urlsafe_b64encode('\xd3V\xbeo\xf7\x1d'), '01a-b_cd')
+
+    def test_b64decode(self):
+        eq = self.assertEqual
+        eq(base64.b64decode("d3d3LnB5dGhvbi5vcmc="), "www.python.org")
+        eq(base64.b64decode('AA=='), '\x00')
+        eq(base64.b64decode("YQ=="), "a")
+        eq(base64.b64decode("YWI="), "ab")
+        eq(base64.b64decode("YWJj"), "abc")
+        eq(base64.b64decode("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
+                            "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT"
+                            "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ=="),
+           "abcdefghijklmnopqrstuvwxyz"
+           "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+           "0123456789!@#0^&*();:<>,. []{}")
+        eq(base64.b64decode(''), '')
+        # Test with arbitrary alternative characters
+        eq(base64.b64decode('01a*b$cd', altchars='*$'), '\xd3V\xbeo\xf7\x1d')
+        # Test standard alphabet
+        eq(base64.standard_b64decode("d3d3LnB5dGhvbi5vcmc="), "www.python.org")
+        eq(base64.standard_b64decode("YQ=="), "a")
+        eq(base64.standard_b64decode("YWI="), "ab")
+        eq(base64.standard_b64decode("YWJj"), "abc")
+        eq(base64.standard_b64decode(""), "")
+        eq(base64.standard_b64decode("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
+                                     "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT"
+                                     "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ=="),
+           "abcdefghijklmnopqrstuvwxyz"
+           "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+           "0123456789!@#0^&*();:<>,. []{}")
+        # Test with 'URL safe' alternative characters
+        eq(base64.urlsafe_b64decode('01a-b_cd'), '\xd3V\xbeo\xf7\x1d')
+
+    def test_b64decode_error(self):
+        self.assertRaises(TypeError, base64.b64decode, 'abc')
+
+    def test_b32encode(self):
+        eq = self.assertEqual
+        eq(base64.b32encode(''), '')
+        eq(base64.b32encode('\x00'), 'AA======')
+        eq(base64.b32encode('a'), 'ME======')
+        eq(base64.b32encode('ab'), 'MFRA====')
+        eq(base64.b32encode('abc'), 'MFRGG===')
+        eq(base64.b32encode('abcd'), 'MFRGGZA=')
+        eq(base64.b32encode('abcde'), 'MFRGGZDF')
+
+    def test_b32decode(self):
+        eq = self.assertEqual
+        eq(base64.b32decode(''), '')
+        eq(base64.b32decode('AA======'), '\x00')
+        eq(base64.b32decode('ME======'), 'a')
+        eq(base64.b32decode('MFRA===='), 'ab')
+        eq(base64.b32decode('MFRGG==='), 'abc')
+        eq(base64.b32decode('MFRGGZA='), 'abcd')
+        eq(base64.b32decode('MFRGGZDF'), 'abcde')
+
+    def test_b32decode_casefold(self):
+        eq = self.assertEqual
+        eq(base64.b32decode('', True), '')
+        eq(base64.b32decode('ME======', True), 'a')
+        eq(base64.b32decode('MFRA====', True), 'ab')
+        eq(base64.b32decode('MFRGG===', True), 'abc')
+        eq(base64.b32decode('MFRGGZA=', True), 'abcd')
+        eq(base64.b32decode('MFRGGZDF', True), 'abcde')
+        # Lower cases
+        eq(base64.b32decode('me======', True), 'a')
+        eq(base64.b32decode('mfra====', True), 'ab')
+        eq(base64.b32decode('mfrgg===', True), 'abc')
+        eq(base64.b32decode('mfrggza=', True), 'abcd')
+        eq(base64.b32decode('mfrggzdf', True), 'abcde')
+        # Expected exceptions
+        self.assertRaises(TypeError, base64.b32decode, 'me======')
+        # Mapping zero and one
+        eq(base64.b32decode('MLO23456'), 'b\xdd\xad\xf3\xbe')
+        eq(base64.b32decode('M1023456', map01='L'), 'b\xdd\xad\xf3\xbe')
+        eq(base64.b32decode('M1023456', map01='I'), 'b\x1d\xad\xf3\xbe')
+
+    def test_b32decode_error(self):
+        self.assertRaises(TypeError, base64.b32decode, 'abc')
+        self.assertRaises(TypeError, base64.b32decode, 'ABCDEF==')
+
+    def test_b16encode(self):
+        eq = self.assertEqual
+        eq(base64.b16encode('\x01\x02\xab\xcd\xef'), '0102ABCDEF')
+        eq(base64.b16encode('\x00'), '00')
+
+    def test_b16decode(self):
+        eq = self.assertEqual
+        eq(base64.b16decode('0102ABCDEF'), '\x01\x02\xab\xcd\xef')
+        eq(base64.b16decode('00'), '\x00')
+        # Lower case is not allowed without a flag
+        self.assertRaises(TypeError, base64.b16decode, '0102abcdef')
+        # Case fold
+        eq(base64.b16decode('0102abcdef', True), '\x01\x02\xab\xcd\xef')
+
+
+
+def test_main():
+    test_support.run_unittest(__name__)
+
+if __name__ == '__main__':
+    test_main()

Added: trunk/jython/Lib/test/test_contextlib.py
===================================================================
--- trunk/jython/Lib/test/test_contextlib.py	                        (rev 0)
+++ trunk/jython/Lib/test/test_contextlib.py	2011-03-12 20:13:35 UTC (rev 7220)
@@ -0,0 +1,337 @@
+"""Unit tests for contextlib.py, and other context managers."""
+
+import sys
+import os
+import decimal
+import tempfile
+import unittest
+import threading
+from contextlib import *  # Tests __all__
+from test import test_support
+
+class ContextManagerTestCase(unittest.TestCase):
+
+    def test_contextmanager_plain(self):
+        state = []
+        @contextmanager
+        def woohoo():
+            state.append(1)
+            yield 42
+            state.append(999)
+        with woohoo() as x:
+            self.assertEqual(state, [1])
+            self.assertEqual(x, 42)
+            state.append(x)
+        self.assertEqual(state, [1, 42, 999])
+
+    def test_contextmanager_finally(self):
+        state = []
+        @contextmanager
+        def woohoo():
+            state.append(1)
+            try:
+                yield 42
+            finally:
+                state.append(999)
+        try:
+            with woohoo() as x:
+                self.assertEqual(state, [1])
+                self.assertEqual(x, 42)
+                state.append(x)
+                raise ZeroDivisionError()
+        except ZeroDivisionError:
+            pass
+        else:
+            self.fail("Expected ZeroDivisionError")
+        self.assertEqual(state, [1, 42, 999])
+
+    def test_contextmanager_no_reraise(self):
+        @contextmanager
+        def whee():
+            yield
+        ctx = whee()
+        ctx.__enter__()
+        # Calling __exit__ should not result in an exception
+        self.failIf(ctx.__exit__(TypeError, TypeError("foo"), None))
+
+    def test_contextmanager_trap_yield_after_throw(self):
+        @contextmanager
+        def whoo():
+            try:
+                yield
+            except:
+                yield
+        ctx = whoo()
+        ctx.__enter__()
+        self.assertRaises(
+            RuntimeError, ctx.__exit__, TypeError, TypeError("foo"), None
+        )
+
+    def test_contextmanager_except(self):
+        state = []
+        @contextmanager
+        def woohoo():
+            state.append(1)
+            try:
+                yield 42
+            except ZeroDivisionError, e:
+                state.append(e.args[0])
+                self.assertEqual(state, [1, 42, 999])
+        with woohoo() as x:
+            self.assertEqual(state, [1])
+            self.assertEqual(x, 42)
+            state.append(x)
+            raise ZeroDivisionError(999)
+        self.assertEqual(state, [1, 42, 999])
+
+    def test_contextmanager_attribs(self):
+        def attribs(**kw):
+            def decorate(func):
+                for k,v in kw.items():
+                    setattr(func,k,v)
+                return func
+            return decorate
+        @contextmanager
+        @attribs(foo='bar')
+        def baz(spam):
+            """Whee!"""
+        self.assertEqual(baz.__name__,'baz')
+        self.assertEqual(baz.foo, 'bar')
+        self.assertEqual(baz.__doc__, "Whee!")
+
+class NestedTestCase(unittest.TestCase):
+
+    # XXX This needs more work
+
+    def test_nested(self):
+        @contextmanager
+        def a():
+            yield 1
+        @contextmanager
+        def b():
+            yield 2
+        @contextmanager
+        def c():
+            yield 3
+        with nested(a(), b(), c()) as (x, y, z):
+            self.assertEqual(x, 1)
+            self.assertEqual(y, 2)
+            self.assertEqual(z, 3)
+
+    def test_nested_cleanup(self):
+        state = []
+        @contextmanager
+        def a():
+            state.append(1)
+            try:
+                yield 2
+            finally:
+                state.append(3)
+        @contextmanager
+        def b():
+            state.append(4)
+            try:
+                yield 5
+            finally:
+                state.append(6)
+        try:
+            with nested(a(), b()) as (x, y):
+                state.append(x)
+                state.append(y)
+                1 // 0
+        except ZeroDivisionError:
+            self.assertEqual(state, [1, 4, 2, 5, 6, 3])
+        else:
+            self.fail("Didn't raise ZeroDivisionError")
+
+    def test_nested_right_exception(self):
+        state = []
+        @contextmanager
+        def a():
+            yield 1
+        class b(object):
+            def __enter__(self):
+                return 2
+            def __exit__(self, *exc_info):
+                try:
+                    raise Exception()
+                except:
+                    pass
+        try:
+            with nested(a(), b()) as (x, y):
+                1 // 0
+        except ZeroDivisionError:
+            self.assertEqual((x, y), (1, 2))
+        except Exception:
+            self.fail("Reraised wrong exception")
+        else:
+            self.fail("Didn't raise ZeroDivisionError")
+
+    def test_nested_b_swallows(self):
+        @contextmanager
+        def a():
+            yield
+        @contextmanager
+        def b():
+            try:
+                yield
+            except:
+                # Swallow the exception
+                pass
+        try:
+            with nested(a(), b()):
+                1 // 0
+        except ZeroDivisionError:
+            self.fail("Didn't swallow ZeroDivisionError")
+
+    def test_nested_break(self):
+        @contextmanager
+        def a():
+            yield
+        state = 0
+        while True:
+            state += 1
+            with nested(a(), a()):
+                break
+            state += 10
+        self.assertEqual(state, 1)
+
+    def test_nested_continue(self):
+        @contextmanager
+        def a():
+            yield
+        state = 0
+        while state < 3:
+            state += 1
+            with nested(a(), a()):
+                continue
+            state += 10
+        self.assertEqual(state, 3)
+
+    def test_nested_return(self):
+        @contextmanager
+        def a():
+            try:
+                yield
+            except:
+                pass
+        def foo():
+            with nested(a(), a()):
+                return 1
+            return 10
+        self.assertEqual(foo(), 1)
+
+class ClosingTestCase(unittest.TestCase):
+
+    # XXX This needs more work
+
+    def test_closing(self):
+        state = []
+        class C:
+            def close(self):
+                state.append(1)
+        x = C()
+        self.assertEqual(state, [])
+        with closing(x) as y:
+            self.assertEqual(x, y)
+        self.assertEqual(state, [1])
+
+    def test_closing_error(self):
+        state = []
+        class C:
+            def close(self):
+                state.append(1)
+        x = C()
+        self.assertEqual(state, [])
+        try:
+            with closing(x) as y:
+                self.assertEqual(x, y)
+                1 // 0
+        except ZeroDivisionError:
+            self.assertEqual(state, [1])
+        else:
+            self.fail("Didn't raise ZeroDivisionError")
+
+class FileContextTestCase(unittest.TestCase):
+
+    def testWithOpen(self):
+        tfn = tempfile.mktemp()
+        try:
+            f = None
+            with open(tfn, "w") as f:
+                self.failIf(f.closed)
+                f.write("Booh\n")
+            self.failUnless(f.closed)
+            f = None
+            try:
+                with open(tfn, "r") as f:
+                    self.failIf(f.closed)
+                    self.assertEqual(f.read(), "Booh\n")
+                    1 // 0
+            except ZeroDivisionError:
+                self.failUnless(f.closed)
+            else:
+                self.fail("Didn't raise ZeroDivisionError")
+        finally:
+            try:
+                os.remove(tfn)
+            except os.error:
+                pass
+
+class LockContextTestCase(unittest.TestCase):
+
+    def boilerPlate(self, lock, locked):
+        self.failIf(locked())
+        with lock:
+            self.failUnless(locked())
+        self.failIf(locked())
+        try:
+            with lock:
+                self.failUnless(locked())
+                1 // 0
+        except ZeroDivisionError:
+            self.failIf(locked())
+        else:
+            self.fail("Didn't raise ZeroDivisionError")
+
+    def testWithLock(self):
+        lock = threading.Lock()
+        self.boilerPlate(lock, lock.locked)
+
+    def testWithRLock(self):
+        lock = threading.RLock()
+        self.boilerPlate(lock, lock._is_owned)
+
+    def testWithCondition(self):
+        lock = threading.Condition()
+        def locked():
+            return lock._is_owned()
+        self.boilerPlate(lock, locked)
+
+    def testWithSemaphore(self):
+        lock = threading.Semaphore()
+        def locked():
+            if lock.acquire(False):
+                lock.release()
+                return False
+            else:
+                return True
+        self.boilerPlate(lock, locked)
+
+    def testWithBoundedSemaphore(self):
+        lock = threading.BoundedSemaphore()
+        def locked():
+            if lock.acquire(False):
+                lock.release()
+                return False
+            else:
+                return True
+        self.boilerPlate(lock, locked)
+
+# This is needed to make the test actually run under regrtest.py!
+def test_main():
+    test_support.run_unittest(__name__)
+
+
+if __name__ == "__main__":
+    test_main()

Added: trunk/jython/Lib/test/test_datetime.py
===================================================================
--- trunk/jython/Lib/test/test_datetime.py	                        (rev 0)
+++ trunk/jython/Lib/test/test_datetime.py	2011-03-12 20:13:35 UTC (rev 7220)
@@ -0,0 +1,3367 @@
+"""Test date/time type.
+
+See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases
+"""
+
+import sys
+import pickle
+import cPickle
+import unittest
+
+from test import test_support
+
+from datetime import MINYEAR, MAXYEAR
+from datetime import timedelta
+from datetime import tzinfo
+from datetime import time
+from datetime import date, datetime
+
+pickle_choices = [(pickler, unpickler, proto)
+                  for pickler in pickle, cPickle
+                  for unpickler in pickle, cPickle
+                  for proto in range(3)]
+assert len(pickle_choices) == 2*2*3
+
+# An arbitrary collection of objects of non-datetime types, for testing
+# mixed-type comparisons.
+OTHERSTUFF = (10, 10L, 34.5, "abc", {}, [], ())
+
+
+#############################################################################
+# module tests
+
+class TestModule(unittest.TestCase):
+
+    def test_constants(self):
+        import datetime
+        self.assertEqual(datetime.MINYEAR, 1)
+        self.assertEqual(datetime.MAXYEAR, 9999)
+
+#############################################################################
+# tzinfo tests
+
+class FixedOffset(tzinfo):
+    def __init__(self, offset, name, dstoffset=42):
+        if isinstance(offset, int):
+            offset = timedelta(minutes=offset)
+        if isinstance(dstoffset, int):
+            dstoffset = timedelta(minutes=dstoffset)
+        self.__offset = offset
+        self.__name = name
+        self.__dstoffset = dstoffset
+    def __repr__(self):
+        return self.__name.lower()
+    def utcoffset(self, dt):
+        return self.__offset
+    def tzname(self, dt):
+        return self.__name
+    def dst(self, dt):
+        return self.__dstoffset
+
+class PicklableFixedOffset(FixedOffset):
+    def __init__(self, offset=None, name=None, dstoffset=None):
+        FixedOffset.__init__(self, offset, name, dstoffset)
+
+class TestTZInfo(unittest.TestCase):
+
+    def test_non_abstractness(self):
+        # In order to allow subclasses to get pickled, the C implementation
+        # wasn't able to get away with having __init__ raise
+        # NotImplementedError.
+        useless = tzinfo()
+        dt = datetime.max
+        self.assertRaises(NotImplementedError, useless.tzname, dt)
+        self.assertRaises(NotImplementedError, useless.utcoffset, dt)
+        self.assertRaises(NotImplementedError, useless.dst, dt)
+
+    def test_subclass_must_override(self):
+        class NotEnough(tzinfo):
+            def __init__(self, offset, name):
+                self.__offset = offset
+                self.__name = name
+        self.failUnless(issubclass(NotEnough, tzinfo))
+        ne = NotEnough(3, "NotByALongShot")
+        self.failUnless(isinstance(ne, tzinfo))
+
+        dt = datetime.now()
+        self.assertRaises(NotImplementedError, ne.tzname, dt)
+        self.assertRaises(NotImplementedError, ne.utcoffset, dt)
+        self.assertRaises(NotImplementedError, ne.dst, dt)
+
+    def test_normal(self):
+        fo = FixedOffset(3, "Three")
+        self.failUnless(isinstance(fo, tzinfo))
+        for dt in datetime.now(), None:
+            self.assertEqual(fo.utcoffset(dt), timedelta(minutes=3))
+            self.assertEqual(fo.tzname(dt), "Three")
+            self.assertEqual(fo.dst(dt), timedelta(minutes=42))
+
+    def test_pickling_base(self):
+        # There's no point to pickling tzinfo objects on their own (they
+        # carry no data), but they need to be picklable anyway else
+        # concrete subclasses can't be pickled.
+        orig = tzinfo.__new__(tzinfo)
+        self.failUnless(type(orig) is tzinfo)
+        for pickler, unpickler, proto in pickle_choices:
+            green = pickler.dumps(orig, proto)
+            derived = unpickler.loads(green)
+            self.failUnless(type(derived) is tzinfo)
+
+    def test_pickling_subclass(self):
+        # Make sure we can pickle/unpickle an instance of a subclass.
+        offset = timedelta(minutes=-300)
+        orig = PicklableFixedOffset(offset, 'cookie')
+        self.failUnless(isinstance(orig, tzinfo))
+        self.failUnless(type(orig) is PicklableFixedOffset)
+        self.assertEqual(orig.utcoffset(None), offset)
+        self.assertEqual(orig.tzname(None), 'cookie')
+        for pickler, unpickler, proto in pickle_choices:
+            green = pickler.dumps(orig, proto)
+            derived = unpickler.loads(green)
+            self.failUnless(isinstance(derived, tzinfo))
+            self.failUnless(type(derived) is PicklableFixedOffset)
+            self.assertEqual(derived.utcoffset(None), offset)
+            self.assertEqual(derived.tzname(None), 'cookie')
+
+#############################################################################
+# Base clase for testing a particular aspect of timedelta, time, date and
+# datetime comparisons.
+
+class HarmlessMixedComparison:
+    # Test that __eq__ and __ne__ don't complain for mixed-type comparisons.
+
+    # Subclasses must define 'theclass', and theclass(1, 1, 1) must be a
+    # legit constructor.
+
+    def test_harmless_mixed_comparison(self):
+        me = self.theclass(1, 1, 1)
+
+        self.failIf(me == ())
+        self.failUnless(me != ())
+        self.failIf(() == me)
+        self.failUnless(() != me)
+
+        self.failUnless(me in [1, 20L, [], me])
+        self.failIf(me not in [1, 20L, [], me])
+
+        self.failUnless([] in [me, 1, 20L, []])
+        self.failIf([] not in [me, 1, 20L, []])
+
+    def test_harmful_mixed_comparison(self):
+        me = self.theclass(1, 1, 1)
+
+        self.assertRaises(TypeError, lambda: me < ())
+        self.assertRaises(TypeError, lambda: me <= ())
+        self.assertRaises(TypeError, lambda: me > ())
+        self.assertRaises(TypeError, lambda: me >= ())
+
+        self.assertRaises(TypeError, lambda: () < me)
+        self.assertRaises(TypeError, lambda: () <= me)
+        self.assertRaises(TypeError, lambda: () > me)
+        self.assertRaises(TypeError, lambda: () >= me)
+
+        self.assertRaises(TypeError, cmp, (), me)
+        self.assertRaises(TypeError, cmp, me, ())
+
+#############################################################################
+# timedelta tests
+
+class TestTimeDelta(HarmlessMixedComparison, unittest.TestCase):
+
+    theclass = timedelta
+
+    def test_constructor(self):
+        eq = self.assertEqual
+        td = timedelta
+
+        # Check keyword args to constructor
+        eq(td(), td(weeks=0, days=0, hours=0, minutes=0, seconds=0,
+                    milliseconds=0, microseconds=0))
+        eq(td(1), td(days=1))
+        eq(td(0, 1), td(seconds=1))
+        eq(td(0, 0, 1), td(microseconds=1))
+        eq(td(weeks=1), td(days=7))
+        eq(td(days=1), td(hours=24))
+        eq(td(hours=1), td(minutes=60))
+        eq(td(minutes=1), td(seconds=60))
+        eq(td(seconds=1), td(milliseconds=1000))
+        eq(td(milliseconds=1), td(microseconds=1000))
+
+        # Check float args to constructor
+        eq(td(weeks=1.0/7), td(days=1))
+        eq(td(days=1.0/24), td(hours=1))
+        eq(td(hours=1.0/60), td(minutes=1))
+        eq(td(minutes=1.0/60), td(seconds=1))
+        eq(td(seconds=0.001), td(milliseconds=1))
+        eq(td(milliseconds=0.001), td(microseconds=1))
+
+    def test_computations(self):
+        eq = self.assertEqual
+        td = timedelta
+
+        a = td(7) # One week
+        b = td(0, 60) # One minute
+        c = td(0, 0, 1000) # One millisecond
+        eq(a+b+c, td(7, 60, 1000))
+        eq(a-b, td(6, 24*3600 - 60))
+        eq(-a, td(-7))
+        eq(+a, td(7))
+        eq(-b, td(-1, 24*3600 - 60))
+        eq(-c, td(-1, 24*3600 - 1, 999000))
+        eq(abs(a), a)
+        eq(abs(-a), a)
+        eq(td(6, 24*3600), a)
+        eq(td(0, 0, 60*1000000), b)
+        eq(a*10, td(70))
+        eq(a*10, 10*a)
+        eq(a*10L, 10*a)
+        eq(b*10, td(0, 600))
+        eq(10*b, td(0, 600))
+        eq(b*10L, td(0, 600))
+        eq(c*10, td(0, 0, 10000))
+        eq(10*c, td(0, 0, 10000))
+        eq(c*10L, td(0, 0, 10000))
+        eq(a*-1, -a)
+        eq(b*-2, -b-b)
+        eq(c*-2, -c+-c)
+        eq(b*(60*24), (b*60)*24)
+        eq(b*(60*24), (60*b)*24)
+        eq(c*1000, td(0, 1))
+        eq(1000*c, td(0, 1))
+        eq(a//7, td(1))
+        eq(b//10, td(0, 6))
+        eq(c//1000, td(0, 0, 1))
+        eq(a//10, td(0, 7*24*360))
+        eq(a//3600000, td(0, 0, 7*24*1000))
+
+    def test_disallowed_computations(self):
+        a = timedelta(42)
+
+        # Add/sub ints, longs, floats should be illegal
+        for i in 1, 1L, 1.0:
+            self.assertRaises(TypeError, lambda: a+i)
+            self.assertRaises(TypeError, lambda: a-i)
+            self.assertRaises(TypeError, lambda: i+a)
+            self.assertRaises(TypeError, lambda: i-a)
+
+        # Mul/div by float isn't supported.
+        x = 2.3
+        self.assertRaises(TypeError, lambda: a*x)
+        self.assertRaises(TypeError, lambda: x*a)
+        self.assertRaises(TypeError, lambda: a/x)
+        self.assertRaises(TypeError, lambda: x/a)
+        self.assertRaises(TypeError, lambda: a // x)
+        self.assertRaises(TypeError, lambda: x // a)
+
+        # Division of int by timedelta doesn't make sense.
+        # Division by zero doesn't make sense.
+        for zero in 0, 0L:
+            self.assertRaises(TypeError, lambda: zero // a)
+            self.assertRaises(ZeroDivisionError, lambda: a // zero)
+
+    def test_basic_attributes(self):
+        days, seconds, us = 1, 7, 31
+        td = timedelta(days, seconds, us)
+        self.assertEqual(td.days, days)
+        self.assertEqual(td.seconds, seconds)
+        self.assertEqual(td.microseconds, us)
+
+    def test_carries(self):
+        t1 = timedelta(days=100,
+                       weeks=-7,
+                       hours=-24*(100-49),
+                       minutes=-3,
+                       seconds=12,
+                       microseconds=(3*60 - 12) * 1e6 + 1)
+        t2 = timedelta(microseconds=1)
+        self.assertEqual(t1, t2)
+
+    def test_hash_equality(self):
+        t1 = timedelta(days=100,
+                       weeks=-7,
+                       hours=-24*(100-49),
+                       minutes=-3,
+                       seconds=12,
+                       microseconds=(3*60 - 12) * 1000000)
+        t2 = timedelta()
+        self.assertEqual(hash(t1), hash(t2))
+
+        t1 += timedelta(weeks=7)
+        t2 += timedelta(days=7*7)
+        self.assertEqual(t1, t2)
+        self.assertEqual(hash(t1), hash(t2))
+
+        d = {t1: 1}
+        d[t2] = 2
+        self.assertEqual(len(d), 1)
+        self.assertEqual(d[t1], 2)
+
+    def test_pickling(self):
+        args = 12, 34, 56
+        orig = timedelta(*args)
+        for pickler, unpickler, proto in pickle_choices:
+            green = pickler.dumps(orig, proto)
+            derived = unpickler.loads(green)
+            self.assertEqual(orig, derived)
+
+    def test_compare(self):
+        t1 = timedelta(2, 3, 4)
+        t2 = timedelta(2, 3, 4)
+        self.failUnless(t1 == t2)
+        self.failUnless(t1 <= t2)
+        self.failUnless(t1 >= t2)
+        self.failUnless(not t1 != t2)
+        self.failUnless(not t1 < t2)
+        self.failUnless(not t1 > t2)
+        self.assertEqual(cmp(t1, t2), 0)
+        self.assertEqual(cmp(t2, t1), 0)
+
+        for args in (3, 3, 3), (2, 4, 4), (2, 3, 5):
+            t2 = timedelta(*args)   # this is larger than t1
+            self.failUnless(t1 < t2)
+            self.failUnless(t2 > t1)
+            self.failUnless(t1 <= t2)
+            self.failUnless(t2 >= t1)
+            self.failUnless(t1 != t2)
+            self.failUnless(t2 != t1)
+            self.failUnless(not t1 == t2)
+            self.failUnless(not t2 == t1)
+            self.failUnless(not t1 > t2)
+            self.failUnless(not t2 < t1)
+            self.failUnless(not t1 >= t2)
+            self.failUnless(not t2 <= t1)
+            self.assertEqual(cmp(t1, t2), -1)
+            self.assertEqual(cmp(t2, t1), 1)
+
+        for badarg in OTHERSTUFF:
+            self.assertEqual(t1 == badarg, False)
+            self.assertEqual(t1 != badarg, True)
+            self.assertEqual(badarg == t1, False)
+            self.assertEqual(badarg != t1, True)
+
+            self.assertRaises(TypeError, lambda: t1 <= badarg)
+            self.assertRaises(TypeError, lambda: t1 < badarg)
+            self.assertRaises(TypeError, lambda: t1 > badarg)
+            self.assertRaises(TypeError, lambda: t1 >= badarg)
+            self.assertRaises(TypeError, lambda: badarg <= t1)
+            self.assertRaises(TypeError, lambda: badarg < t1)
+            self.assertRaises(TypeError, lambda: badarg > t1)
+            self.assertRaises(TypeError, lambda: badarg >= t1)
+
+    def test_str(self):
+        td = timedelta
+        eq = self.assertEqual
+
+        eq(str(td(1)), "1 day, 0:00:00")
+        eq(str(td(-1)), "-1 day, 0:00:00")
+        eq(str(td(2)), "2 days, 0:00:00")
+        eq(str(td(-2)), "-2 days, 0:00:00")
+
+        eq(str(td(hours=12, minutes=58, seconds=59)), "12:58:59")
+        eq(str(td(hours=2, minutes=3, seconds=4)), "2:03:04")
+        eq(str(td(weeks=-30, hours=23, minutes=12, seconds=34)),
+           "-210 days, 23:12:34")
+
+        eq(str(td(milliseconds=1)), "0:00:00.001000")
+        eq(str(td(microseconds=3)), "0:00:00.000003")
+
+        eq(str(td(days=999999999, hours=23, minutes=59, seconds=59,
+                   microseconds=999999)),
+           "999999999 days, 23:59:59.999999")
+
+    def test_roundtrip(self):
+        for td in (timedelta(days=999999999, hours=23, minutes=59,
+                             seconds=59, microseconds=999999),
+                   timedelta(days=-999999999),
+                   timedelta(days=1, seconds=2, microseconds=3)):
+
+            # Verify td -> string -> td identity.
+            s = repr(td)
+            self.failUnless(s.startswith('datetime.'))
+            s = s[9:]
+            td2 = eval(s)
+            self.assertEqual(td, td2)
+
+            # Verify identity via reconstructing from pieces.
+            td2 = timedelta(td.days, td.seconds, td.microseconds)
+            self.assertEqual(td, td2)
+
+    def test_resolution_info(self):
+        self.assert_(isinstance(timedelta.min, timedelta))
+        self.assert_(isinstance(timedelta.max, timedelta))
+        self.assert_(isinstance(timedelta.resolution, timedelta))
+        self.assert_(timedelta.max > timedelta.min)
+        self.assertEqual(timedelta.min, timedelta(-999999999))
+        self.assertEqual(timedelta.max, timedelta(999999999, 24*3600-1, 1e6-1))
+        self.assertEqual(timedelta.resolution, timedelta(0, 0, 1))
+
+    def test_overflow(self):
+        tiny = timedelta.resolution
+
+        td = timedelta.min + tiny
+        td -= tiny  # no problem
+        self.assertRaises(OverflowError, td.__sub__, tiny)
+        self.assertRaises(OverflowError, td.__add__, -tiny)
+
+        td = timedelta.max - tiny
+        td += tiny  # no problem
+        self.assertRaises(OverflowError, td.__add__, tiny)
+        self.assertRaises(OverflowError, td.__sub__, -tiny)
+
+        self.assertRaises(OverflowError, lambda: -timedelta.max)
+
+    def test_microsecond_rounding(self):
+        td = timedelta
+        eq = self.assertEqual
+
+        # Single-field rounding.
+        eq(td(milliseconds=0.4/1000), td(0))    # rounds to 0
+        eq(td(milliseconds=-0.4/1000), td(0))    # rounds to 0
+        eq(td(milliseconds=0.6/1000), td(microseconds=1))
+        eq(td(milliseconds=-0.6/1000), td(microseconds=-1))
+
+        # Rounding due to contributions from more than one field.
+        us_per_hour = 3600e6
+        us_per_day = us_per_hour * 24
+        eq(td(days=.4/us_per_day), td(0))
+        eq(td(hours=.2/us_per_hour), td(0))
+        eq(td(days=.4/us_per_day, hours=.2/us_per_hour), td(microseconds=1))
+
+        eq(td(days=-.4/us_per_day), td(0))
+        eq(td(hours=-.2/us_per_hour), td(0))
+        eq(td(days=-.4/us_per_day, hours=-.2/us_per_hour), td(microseconds=-1))
+
+    def test_massive_normalization(self):
+        td = timedelta(microseconds=-1)
+        self.assertEqual((td.days, td.seconds, td.microseconds),
+                         (-1, 24*3600-1, 999999))
+
+    def test_bool(self):
+        self.failUnless(timedelta(1))
+        self.failUnless(timedelta(0, 1))
+        self.failUnless(timedelta(0, 0, 1))
+        self.failUnless(timedelta(microseconds=1))
+        self.failUnless(not timedelta(0))
+
+    def test_subclass_timedelta(self):
+
+        class T(timedelta):
+            @staticmethod
+            def from_td(td):
+                return T(td.days, td.seconds, td.microseconds)
+
+            def as_hours(self):
+                sum = (self.days * 24 +
+                       self.seconds / 3600.0 +
+                       self.microseconds / 3600e6)
+                return round(sum)
+
+        t1 = T(days=1)
+        self.assert_(type(t1) is T)
+        self.assertEqual(t1.as_hours(), 24)
+
+        t2 = T(days=-1, seconds=-3600)
+        self.assert_(type(t2) is T)
+        self.assertEqual(t2.as_hours(), -25)
+
+        t3 = t1 + t2
+        self.assert_(type(t3) is timedelta)
+        t4 = T.from_td(t3)
+        self.assert_(type(t4) is T)
+        self.assertEqual(t3.days, t4.days)
+        self.assertEqual(t3.seconds, t4.seconds)
+        self.assertEqual(t3.microseconds, t4.microseconds)
+        self.assertEqual(str(t3), str(t4))
+        self.assertEqual(t4.as_hours(), -1)
+
+#############################################################################
+# date tests
+
+class TestDateOnly(unittest.TestCase):
+    # Tests here won't pass if also run on datetime objects, so don't
+    # subclass this to test datetimes too.
+
+    def test_delta_non_days_ignored(self):
+        dt = date(2000, 1, 2)
+        delta = timedelta(days=1, hours=2, minutes=3, seconds=4,
+                          microseconds=5)
+        days = timedelta(delta.days)
+        self.assertEqual(days, timedelta(1))
+
+        dt2 = dt + delta
+        self.assertEqual(dt2, dt + days)
+
+        dt2 = delta + dt
+        self.assertEqual(dt2, dt + days)
+
+        dt2 = dt - delta
+        self.assertEqual(dt2, dt - days)
+
+        delta = -delta
+        days = timedelta(delta.days)
+        self.assertEqual(days, timedelta(-2))
+
+        dt2 = dt + delta
+        self.assertEqual(dt2, dt + days)
+
+        dt2 = delta + dt
+        self.assertEqual(dt2, dt + days)
+
+        dt2 = dt - delta
+        self.assertEqual(dt2, dt - days)
+
+class SubclassDate(date):
+    sub_var = 1
+
+class TestDate(HarmlessMixedComparison, unittest.TestCase):
+    # Tests here should pass for both dates and datetimes, except for a
+    # few tests that TestDateTime overrides.
+
+    theclass = date
+
+    def test_basic_attributes(self):
+        dt = self.theclass(2002, 3, 1)
+        self.assertEqual(dt.year, 2002)
+        self.assertEqual(dt.month, 3)
+        self.assertEqual(dt.day, 1)
+
+    def test_roundtrip(self):
+        for dt in (self.theclass(1, 2, 3),
+                   self.theclass.today()):
+            # Verify dt -> string -> date identity.
+            s = repr(dt)
+            self.failUnless(s.startswith('datetime.'))
+            s = s[9:]
+            dt2 = eval(s)
+            self.assertEqual(dt, dt2)
+
+            # Verify identity via reconstructing from pieces.
+            dt2 = self.theclass(dt.year, dt.month, dt.day)
+            self.assertEqual(dt, dt2)
+
+    def test_ordinal_conversions(self):
+        # Check some fixed values.
+        for y, m, d, n in [(1, 1, 1, 1),      # calendar origin
+                           (1, 12, 31, 365),
+                           (2, 1, 1, 366),
+                           # first example from "Calendrical Calculations"
+                           (1945, 11, 12, 710347)]:
+            d = self.theclass(y, m, d)
+            self.assertEqual(n, d.toordinal())
+            fromord = self.theclass.fromordinal(n)
+            self.assertEqual(d, fromord)
+            if hasattr(fromord, "hour"):
+            # if we're checking something fancier than a date, verify
+            # the extra fields have been zeroed out
+                self.assertEqual(fromord.hour, 0)
+                self.assertEqual(fromord.minute, 0)
+                self.assertEqual(fromord.second, 0)
+                self.assertEqual(fromord.microsecond, 0)
+
+        # Check first and last days of year spottily across the whole
+        # range of years supported.
+        for year in xrange(MINYEAR, MAXYEAR+1, 7):
+            # Verify (year, 1, 1) -> ordinal -> y, m, d is identity.
+            d = self.theclass(year, 1, 1)
+            n = d.toordinal()
+            d2 = self.theclass.fromordinal(n)
+            self.assertEqual(d, d2)
+            # Verify that moving back a day gets to the end of year-1.
+            if year > 1:
+                d = self.theclass.fromordinal(n-1)
+                d2 = self.theclass(year-1, 12, 31)
+                self.assertEqual(d, d2)
+                self.assertEqual(d2.toordinal(), n-1)
+
+        # Test every day in a leap-year and a non-leap year.
+        dim = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+        for year, isleap in (2000, True), (2002, False):
+            n = self.theclass(year, 1, 1).toordinal()
+            for month, maxday in zip(range(1, 13), dim):
+                if month == 2 and isleap:
+                    maxday += 1
+                for day in range(1, maxday+1):
+                    d = self.theclass(year, month, day)
+                    self.assertEqual(d.toordinal(), n)
+                    self.assertEqual(d, self.theclass.fromordinal(n))
+                    n += 1
+
+    def test_extreme_ordinals(self):
+        a = self.theclass.min
+        a = self.theclass(a.year, a.month, a.day)  # get rid of time parts
+        aord = a.toordinal()
+        b = a.fromordinal(aord)
+        self.assertEqual(a, b)
+
+        self.assertRaises(ValueError, lambda: a.fromordinal(aord - 1))
+
+        b = a + timedelta(days=1)
+        self.assertEqual(b.toordinal(), aord + 1)
+        self.assertEqual(b, self.theclass.fromordinal(aord + 1))
+
+        a = self.theclass.max
+        a = self.theclass(a.year, a.month, a.day)  # get rid of time parts
+        aord = a.toordinal()
+        b = a.fromordinal(aord)
+        self.assertEqual(a, b)
+
+        self.assertRaises(ValueError, lambda: a.fromordinal(aord + 1))
+
+        b = a - timedelta(days=1)
+        self.assertEqual(b.toordinal(), aord - 1)
+        self.assertEqual(b, self.theclass.fromordinal(aord - 1))
+
+    def test_bad_constructor_arguments(self):
+        # bad years
+        self.theclass(MINYEAR, 1, 1)  # no exception
+        self.theclass(MAXYEAR, 1, 1)  # no exception
+        self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1)
+        self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1)
+        # bad months
+        self.theclass(2000, 1, 1)    # no exception
+        self.theclass(2000, 12, 1)   # no exception
+        self.assertRaises(ValueError, self.theclass, 2000, 0, 1)
+        self.assertRaises(ValueError, self.theclass, 2000, 13, 1)
+        # bad days
+        self.theclass(2000, 2, 29)   # no exception
+        self.theclass(2004, 2, 29)   # no exception
+        self.theclass(2400, 2, 29)   # no exception
+        self.assertRaises(ValueError, self.theclass, 2000, 2, 30)
+        self.assertRaises(ValueError, self.theclass, 2001, 2, 29)
+        self.assertRaises(ValueError, self.theclass, 2100, 2, 29)
+        self.assertRaises(ValueError, self.theclass, 1900, 2, 29)
+        self.assertRaises(ValueError, self.theclass, 2000, 1, 0)
+        self.assertRaises(ValueError, self.theclass, 2000, 1, 32)
+
+    def test_hash_equality(self):
+        d = self.theclass(2000, 12, 31)
+        # same thing
+        e = self.theclass(2000, 12, 31)
+        self.assertEqual(d, e)
+        self.assertEqual(hash(d), hash(e))
+
+        dic = {d: 1}
+        dic[e] = 2
+        self.assertEqual(len(dic), 1)
+        self.assertEqual(dic[d], 2)
+        self.assertEqual(dic[e], 2)
+
+        d = self.theclass(2001,  1,  1)
+        # same thing
+        e = self.theclass(2001,  1,  1)
+        self.assertEqual(d, e)
+        self.assertEqual(hash(d), hash(e))
+
+        dic = {d: 1}
+        dic[e] = 2
+        self.assertEqual(len(dic), 1)
+        self.assertEqual(dic[d], 2)
+        self.assertEqual(dic[e], 2)
+
+    def test_computations(self):
+        a = self.theclass(2002, 1, 31)
+        b = self.theclass(1956, 1, 31)
+
+        diff = a-b
+        self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4)))
+        self.assertEqual(diff.seconds, 0)
+        self.assertEqual(diff.microseconds, 0)
+
+        day = timedelta(1)
+        week = timedelta(7)
+        a = self.theclass(2002, 3, 2)
+        self.assertEqual(a + day, self.theclass(2002, 3, 3))
+        self.assertEqual(day + a, self.theclass(2002, 3, 3))
+        self.assertEqual(a - day, self.theclass(2002, 3, 1))
+        self.assertEqual(-day + a, self.theclass(2002, 3, 1))
+        self.assertEqual(a + week, self.theclass(2002, 3, 9))
+        self.assertEqual(a - week, self.theclass(2002, 2, 23))
+        self.assertEqual(a + 52*week, self.theclass(2003, 3, 1))
+        self.assertEqual(a - 52*week, self.theclass(2001, 3, 3))
+        self.assertEqual((a + week) - a, week)
+        self.assertEqual((a + day) - a, day)
+        self.assertEqual((a - week) - a, -week)
+        self.assertEqual((a - day) - a, -day)
+        self.assertEqual(a - (a + week), -week)
+        self.assertEqual(a - (a + day), -day)
+        self.assertEqual(a - (a - week), week)
+        self.assertEqual(a - (a - day), day)
+
+        # Add/sub ints, longs, floats should be illegal
+        for i in 1, 1L, 1.0:
+            self.assertRaises(TypeError, lambda: a+i)
+            self.assertRaises(TypeError, lambda: a-i)
+            self.assertRaises(TypeError, lambda: i+a)
+            self.assertRaises(TypeError, lambda: i-a)
+
+        # delta - date is senseless.
+        self.assertRaises(TypeError, lambda: day - a)
+        # mixing date and (delta or date) via * or // is senseless
+        self.assertRaises(TypeError, lambda: day * a)
+        self.assertRaises(TypeError, lambda: a * day)
+        self.assertRaises(TypeError, lambda: day // a)
+        self.assertRaises(TypeError, lambda: a // day)
+        self.assertRaises(TypeError, lambda: a * a)
+        self.assertRaises(TypeError, lambda: a // a)
+        # date + date is senseless
+        self.assertRaises(TypeError, lambda: a + a)
+
+    def test_overflow(self):
+        tiny = self.theclass.resolution
+
+        for delta in [tiny, timedelta(1), timedelta(2)]:
+            dt = self.theclass.min + delta
+            dt -= delta  # no problem
+            self.assertRaises(OverflowError, dt.__sub__, delta)
+            self.assertRaises(OverflowError, dt.__add__, -delta)
+
+            dt = self.theclass.max - delta
+            dt += delta  # no problem
+            self.assertRaises(OverflowError, dt.__add__, delta)
+            self.assertRaises(OverflowError, dt.__sub__, -delta)
+
+    def test_fromtimestamp(self):
+        import time
+
+        # Try an arbitrary fixed value.
+        year, month, day = 1999, 9, 19
+        ts = time.mktime((year, month, day, 0, 0, 0, 0, 0, -1))
+        d = self.theclass.fromtimestamp(ts)
+        self.assertEqual(d.year, year)
+        self.assertEqual(d.month, month)
+        self.assertEqual(d.day, day)
+
+    def test_insane_fromtimestamp(self):
+        # It's possible that some platform maps time_t to double,
+        # and that this test will fail there.  This test should
+        # exempt such platforms (provided they return reasonable
+        # results!).
+        for insane in -1e200, 1e200:
+            self.assertRaises(ValueError, self.theclass.fromtimestamp,
+                              insane)
+
+    def test_today(self):
+        import time
+
+        # We claim that today() is like fromtimestamp(time.time()), so
+        # prove it.
+        for dummy in range(3):
+            today = self.theclass.today()
+            ts = time.time()
+            todayagain = self.theclass.fromtimestamp(ts)
+            if today == todayagain:
+                break
+            # There are several legit reasons that could fail:
+            # 1. It recently became midnight, between the today() and the
+            #    time() calls.
+            # 2. The platform time() has such fine resolution that we'll
+            #    never get the same value twice.
+            # 3. The platform time() has poor resolution, and we just
+            #    happened to call today() right before a resolution quantum
+            #    boundary.
+            # 4. The system clock got fiddled between calls.
+            # In any case, wait a little while and try again.
+            time.sleep(0.1)
+
+        # It worked or it didn't.  If it didn't, assume it's reason #2, and
+        # let the test pass if they're within half a second of each other.
+        self.failUnless(today == todayagain or
+                        abs(todayagain - today) < timedelta(seconds=0.5))
+
+    def test_weekday(self):
+        for i in range(7):
+            # March 4, 2002 is a Monday
+            self.assertEqual(self.theclass(2002, 3, 4+i).weekday(), i)
+            self.assertEqual(self.theclass(2002, 3, 4+i).isoweekday(), i+1)
+            # January 2, 1956 is a Monday
+            self.assertEqual(self.theclass(1956, 1, 2+i).weekday(), i)
+            self.assertEqual(self.theclass(1956, 1, 2+i).isoweekday(), i+1)
+
+    def test_isocalendar(self):
+        # Check examples from
+        # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
+        for i in range(7):
+            d = self.theclass(2003, 12, 22+i)
+            self.assertEqual(d.isocalendar(), (2003, 52, i+1))
+            d = self.theclass(2003, 12, 29) + timedelta(i)
+            self.assertEqual(d.isocalendar(), (2004, 1, i+1))
+            d = self.theclass(2004, 1, 5+i)
+            self.assertEqual(d.isocalendar(), (2004, 2, i+1))
+            d = self.theclass(2009, 12, 21+i)
+            self.assertEqual(d.isocalendar(), (2009, 52, i+1))
+            d = self.theclass(2009, 12, 28) + timedelta(i)
+            self.assertEqual(d.isocalendar(), (2009, 53, i+1))
+            d = self.theclass(2010, 1, 4+i)
+            self.assertEqual(d.isocalendar(), (2010, 1, i+1))
+
+    def test_iso_long_years(self):
+        # Calculate long ISO years and compare to table from
+        # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
+        ISO_LONG_YEARS_TABLE = """
+              4   32   60   88
+              9   37   65   93
+             15   43   71   99
+             20   48   76
+             26   54   82
+
+            105  133  161  189
+            111  139  167  195
+            116  144  172
+            122  150  178
+            128  156  184
+
+            201  229  257  285
+            207  235  263  291
+            212  240  268  296
+            218  246  274
+            224  252  280
+
+            303  331  359  387
+            308  336  364  392
+            314  342  370  398
+            320  348  376
+            325  353  381
+        """
+        iso_long_years = map(int, ISO_LONG_YEARS_TABLE.split())
+        iso_long_years.sort()
+        L = []
+        for i in range(400):
+            d = self.theclass(2000+i, 12, 31)
+            d1 = self.theclass(1600+i, 12, 31)
+            self.assertEqual(d.isocalendar()[1:], d1.isocalendar()[1:])
+            if d.isocalendar()[1] == 53:
+                L.append(i)
+        self.assertEqual(L, iso_long_years)
+
+    def test_isoformat(self):
+        t = self.theclass(2, 3, 2)
+        self.assertEqual(t.isoformat(), "0002-03-02")
+
+    def test_ctime(self):
+        t = self.theclass(2002, 3, 2)
+        self.assertEqual(t.ctime(), "Sat Mar  2 00:00:00 2002")
+
+    def test_strftime(self):
+        t = self.theclass(2005, 3, 2)
+        self.assertEqual(t.strftime("m:%m d:%d y:%y"), "m:03 d:02 y:05")
+        self.assertEqual(t.strftime(""), "") # SF bug #761337
+        self.assertEqual(t.strftime('x'*1000), 'x'*1000) # SF bug #1556784
+
+        self.assertRaises(TypeError, t.strftime) # needs an arg
+        self.assertRaises(TypeError, t.strftime, "one", "two") # too many args
+        self.assertRaises(TypeError, t.strftime, 42) # arg wrong type
+
+        # test that unicode input is allowed (issue 2782)
+        self.assertEqual(t.strftime(u"%m"), "03")
+
+        # A naive object replaces %z and %Z w/ empty strings.
+        self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''")
+
+        #make sure that invalid format specifiers are handled correctly
+        #self.assertRaises(ValueError, t.strftime, "%e")
+        #self.assertRaises(ValueError, t.strftime, "%")
+        #self.assertRaises(ValueError, t.strftime, "%#")
+
+        #oh well, some systems just ignore those invalid ones.
+        #at least, excercise them to make sure that no crashes
+        #are generated
+        for f in ["%e", "%", "%#"]:
+            try:
+                t.strftime(f)
+            except ValueError:
+                pass
+
+        #check that this standard extension works
+        t.strftime("%f")
+
+
+    def test_format(self):
+        dt = self.theclass(2007, 9, 10)
+        self.assertEqual(dt.__format__(''), str(dt))
+
+        # check that a derived class's __str__() gets called
+        class A(self.theclass):
+            def __str__(self):
+                return 'A'
+        a = A(2007, 9, 10)
+        self.assertEqual(a.__format__(''), 'A')
+
+        # check that a derived class's strftime gets called
+        class B(self.theclass):
+            def strftime(self, format_spec):
+                return 'B'
+        b = B(2007, 9, 10)
+        self.assertEqual(b.__format__(''), str(dt))
+
+        for fmt in ["m:%m d:%d y:%y",
+                    "m:%m d:%d y:%y H:%H M:%M S:%S",
+                    "%z %Z",
+                    ]:
+            self.assertEqual(dt.__format__(fmt), dt.strftime(fmt))
+            self.assertEqual(a.__format__(fmt), dt.strftime(fmt))
+            self.assertEqual(b.__format__(fmt), 'B')
+
+    def test_resolution_info(self):
+        self.assert_(isinstance(self.theclass.min, self.theclass))
+        self.assert_(isinstance(self.theclass.max, self.theclass))
+        self.assert_(isinstance(self.theclass.resolution, timedelta))
+        self.assert_(self.theclass.max > self.theclass.min)
+
+    def test_extreme_timedelta(self):
+        big = self.theclass.max - self.theclass.min
+        # 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds
+        n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds
+        # n == 315537897599999999 ~= 2**58.13
+        justasbig = timedelta(0, 0, n)
+        self.assertEqual(big, justasbig)
+        self.assertEqual(self.theclass.min + big, self.theclass.max)
+        self.assertEqual(self.theclass.max - big, self.theclass.min)
+
+    def test_timetuple(self):
+        for i in range(7):
+            # January 2, 1956 is a Monday (0)
+            d = self.theclass(1956, 1, 2+i)
+            t = d.timetuple()
+            self.assertEqual(t, (1956, 1, 2+i, 0, 0, 0, i, 2+i, -1))
+            # February 1, 1956 is a Wednesday (2)
+            d = self.theclass(1956, 2, 1+i)
+            t = d.timetuple()
+            self.assertEqual(t, (1956, 2, 1+i, 0, 0, 0, (2+i)%7, 32+i, -1))
+            # March 1, 1956 is a Thursday (3), and is the 31+29+1 = 61st day
+            # of the year.
+            d = self.theclass(1956, 3, 1+i)
+            t = d.timetuple()
+            self.assertEqual(t, (1956, 3, 1+i, 0, 0, 0, (3+i)%7, 61+i, -1))
+            self.assertEqual(t.tm_year, 1956)
+            self.assertEqual(t.tm_mon, 3)
+            self.assertEqual(t.tm_mday, 1+i)
+            self.assertEqual(t.tm_hour, 0)
+            self.assertEqual(t.tm_min, 0)
+            self.assertEqual(t.tm_sec, 0)
+            self.assertEqual(t.tm_wday, (3+i)%7)
+            self.assertEqual(t.tm_yday, 61+i)
+            self.assertEqual(t.tm_isdst, -1)
+
+    def test_pickling(self):
+        args = 6, 7, 23
+        orig = self.theclass(*args)
+        for pickler, unpickler, proto in pickle_choices:
+            green = pickler.dumps(orig, proto)
+            derived = unpickler.loads(green)
+            self.assertEqual(orig, derived)
+
+    def test_compare(self):
+        t1 = self.theclass(2, 3, 4)
+        t2 = self.theclass(2, 3, 4)
+        self.failUnless(t1 == t2)
+        self.failUnless(t1 <= t2)
+        self.failUnless(t1 >= t2)
+        self.failUnless(not t1 != t2)
+        self.failUnless(not t1 < t2)
+        self.failUnless(not t1 > t2)
+        self.assertEqual(cmp(t1, t2), 0)
+        self.assertEqual(cmp(t2, t1), 0)
+
+        for args in (3, 3, 3), (2, 4, 4), (2, 3, 5):
+            t2 = self.theclass(*args)   # this is larger than t1
+            self.failUnless(t1 < t2)
+            self.failUnless(t2 > t1)
+            self.failUnless(t1 <= t2)
+            self.failUnless(t2 >= t1)
+            self.failUnless(t1 != t2)
+            self.failUnless(t2 != t1)
+            self.failUnless(not t1 == t2)
+            self.failUnless(not t2 == t1)
+            self.failUnless(not t1 > t2)
+            self.failUnless(not t2 < t1)
+            self.failUnless(not t1 >= t2)
+            self.failUnless(not t2 <= t1)
+            self.assertEqual(cmp(t1, t2), -1)
+            self.assertEqual(cmp(t2, t1), 1)
+
+        for badarg in OTHERSTUFF:
+            self.assertEqual(t1 == badarg, False)
+            self.assertEqual(t1 != badarg, True)
+            self.assertEqual(badarg == t1, False)
+            self.assertEqual(badarg != t1, True)
+
+            self.assertRaises(TypeError, lambda: t1 < badarg)
+            self.assertRaises(TypeError, lambda: t1 > badarg)
+            self.assertRaises(TypeError, lambda: t1 >= badarg)
+            self.assertRaises(TypeError, lambda: badarg <= t1)
+            self.assertRaises(TypeError, lambda: badarg < t1)
+            self.assertRaises(TypeError, lambda: badarg > t1)
+            self.assertRaises(TypeError, lambda: badarg >= t1)
+
+    def test_mixed_compare(self):
+        our = self.theclass(2000, 4, 5)
+        self.assertRaises(TypeError, cmp, our, 1)
+        self.assertRaises(TypeError, cmp, 1, our)
+
+        class AnotherDateTimeClass(object):
+            def __cmp__(self, other):
+                # Return "equal" so calling this can't be confused with
+                # compare-by-address (which never says "equal" for distinct
+                # objects).
+                return 0
+            __hash__ = None # Silence Py3k warning
+
+        # This still errors, because date and datetime comparison raise
+        # TypeError instead of NotImplemented when they don't know what to
+        # do, in order to stop comparison from falling back to the default
+        # compare-by-address.
+        their = AnotherDateTimeClass()
+        self.assertRaises(TypeError, cmp, our, their)
+        # Oops:  The next stab raises TypeError in the C implementation,
+        # but not in the Python implementation of datetime.  The difference
+        # is due to that the Python implementation defines __cmp__ but
+        # the C implementation defines tp_richcompare.  This is more pain
+        # to fix than it's worth, so commenting out the test.
+        # self.assertEqual(cmp(their, our), 0)
+
+        # But date and datetime comparison return NotImplemented instead if the
+        # other object has a timetuple attr.  This gives the other object a
+        # chance to do the comparison.
+        class Comparable(AnotherDateTimeClass):
+            def timetuple(self):
+                return ()
+
+        their = Comparable()
+        self.assertEqual(cmp(our, their), 0)
+        self.assertEqual(cmp(their, our), 0)
+        self.failUnless(our == their)
+        self.failUnless(their == our)
+
+    def test_bool(self):
+        # All dates are considered true.
+        self.failUnless(self.theclass.min)
+        self.failUnless(self.theclass.max)
+
+    def test_strftime_out_of_range(self):
+        # For nasty technical reasons, we can't handle years before 1900.
+        cls = self.theclass
+        self.assertEqual(cls(1900, 1, 1).strftime("%Y"), "1900")
+        for y in 1, 49, 51, 99, 100, 1000, 1899:
+            self.assertRaises(ValueError, cls(y, 1, 1).strftime, "%Y")
+
+    def test_replace(self):
+        cls = self.theclass
+        args = [1, 2, 3]
+        base = cls(*args)
+        self.assertEqual(base, base.replace())
+
+        i = 0
+        for name, newval in (("year", 2),
+                             ("month", 3),
+                             ("day", 4)):
+            newargs = args[:]
+            newargs[i] = newval
+            expected = cls(*newargs)
+            got = base.replace(**{name: newval})
+            self.assertEqual(expected, got)
+            i += 1
+
+        # Out of bounds.
+        base = cls(2000, 2, 29)
+        self.assertRaises(ValueError, base.replace, year=2001)
+
+    def test_subclass_date(self):
+
+        class C(self.theclass):
+            theAnswer = 42
+
+            def __new__(cls, *args, **kws):
+                temp = kws.copy()
+                extra = temp.pop('extra')
+                result = self.theclass.__new__(cls, *args, **temp)
+                result.extra = extra
+                return result
+
+            def newmeth(self, start):
+                return start + self.year + self.month
+
+        args = 2003, 4, 14
+
+        dt1 = self.theclass(*args)
+        dt2 = C(*args, **{'extra': 7})
+
+        self.assertEqual(dt2.__class__, C)
+        self.assertEqual(dt2.theAnswer, 42)
+        self.assertEqual(dt2.extra, 7)
+        self.assertEqual(dt1.toordinal(), dt2.toordinal())
+        self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month - 7)
+
+    def test_pickling_subclass_date(self):
+
+        args = 6, 7, 23
+        orig = SubclassDate(*args)
+        for pickler, unpickler, proto in pickle_choices:
+            green = pickler.dumps(orig, proto)
+            derived = unpickler.loads(green)
+            self.assertEqual(orig, derived)
+
+    def test_backdoor_resistance(self):
+        # For fast unpickling, the constructor accepts a pickle string.
+        # This is a low-overhead backdoor.  A user can (by intent or
+        # mistake) pass a string directly, which (if it's the right length)
+        # will get treated like a pickle, and bypass the normal sanity
+        # checks in the constructor.  This can create insane objects.
+        # The constructor doesn't want to burn the time to validate all
+        # fields, but does check the month field.  This stops, e.g.,
+        # datetime.datetime('1995-03-25') from yielding an insane object.
+        base = '1995-03-25'
+        if not issubclass(self.theclass, datetime):
+            base = base[:4]
+        for month_byte in '9', chr(0), chr(13), '\xff':
+            self.assertRaises(TypeError, self.theclass,
+                                         base[:2] + month_byte + base[3:])
+        for ord_byte in range(1, 13):
+            # This shouldn't blow up because of the month byte alone.  If
+            # the implementation changes to do more-careful checking, it may
+            # blow up because other fields are insane.
+            self.theclass(base[:2] + chr(ord_byte) + base[3:])
+
+#############################################################################
+# datetime tests
+
+class SubclassDatetime(datetime):
+    sub_var = 1
+
+class TestDateTime(TestDate):
+
+    theclass = datetime
+
+    def test_basic_attributes(self):
+        dt = self.theclass(2002, 3, 1, 12, 0)
+        self.assertEqual(dt.year, 2002)
+        self.assertEqual(dt.month, 3)
+        self.assertEqual(dt.day, 1)
+        self.assertEqual(dt.hour, 12)
+        self.assertEqual(dt.minute, 0)
+        self.assertEqual(dt.second, 0)
+        self.assertEqual(dt.microsecond, 0)
+
+    def test_basic_attributes_nonzero(self):
+        # Make sure all attributes are non-zero so bugs in
+        # bit-shifting access show up.
+        dt = self.theclass(2002, 3, 1, 12, 59, 59, 8000)
+        self.assertEqual(dt.year, 2002)
+        self.assertEqual(dt.month, 3)
+        self.assertEqual(dt.day, 1)
+        self.assertEqual(dt.hour, 12)
+        self.assertEqual(dt.minute, 59)
+        self.assertEqual(dt.second, 59)
+        self.assertEqual(dt.microsecond, 8000)
+
+    def test_roundtrip(self):
+        for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7),
+                   self.theclass.now()):
+            # Verify dt -> string -> datetime identity.
+            s = repr(dt)
+            self.failUnless(s.startswith('datetime.'))
+            s = s[9:]
+            dt2 = eval(s)
+            self.assertEqual(dt, dt2)
+
+            # Verify identity via reconstructing from pieces.
+            dt2 = self.theclass(dt.year, dt.month, dt.day,
+                                dt.hour, dt.minute, dt.second,
+                                dt.microsecond)
+            self.assertEqual(dt, dt2)
+
+    def test_isoformat(self):
+        t = self.theclass(2, 3, 2, 4, 5, 1, 123)
+        self.assertEqual(t.isoformat(),    "0002-03-02T04:05:01.000123")
+        self.assertEqual(t.isoformat('T'), "0002-03-02T04:05:01.000123")
+        self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123")
+        self.assertEqual(t.isoformat('\x00'), "0002-03-02\x0004:05:01.000123")
+        # str is ISO format with the separator forced to a blank.
+        self.assertEqual(str(t), "0002-03-02 04:05:01.000123")
+
+        t = self.theclass(2, 3, 2)
+        self.assertEqual(t.isoformat(),    "0002-03-02T00:00:00")
+        self.assertEqual(t.isoformat('T'), "0002-03-02T00:00:00")
+        self.assertEqual(t.isoformat(' '), "0002-03-02 00:00:00")
+        # str is ISO format with the separator forced to a blank.
+        self.assertEqual(str(t), "0002-03-02 00:00:00")
+
+    def test_format(self):
+        dt = self.theclass(2007, 9, 10, 4, 5, 1, 123)
+        self.assertEqual(dt.__format__(''), str(dt))
+
+        # check that a derived class's __str__() gets called
+        class A(self.theclass):
+            def __str__(self):
+                return 'A'
+        a = A(2007, 9, 10, 4, 5, 1, 123)
+        self.assertEqual(a.__format__(''), 'A')
+
+        # check that a derived class's strftime gets called
+        class B(self.theclass):
+            def strftime(self, format_spec):
+                return 'B'
+        b = B(2007, 9, 10, 4, 5, 1, 123)
+        self.assertEqual(b.__format__(''), str(dt))
+
+        for fmt in ["m:%m d:%d y:%y",
+                    "m:%m d:%d y:%y H:%H M:%M S:%S",
+                    "%z %Z",
+                    ]:
+            self.assertEqual(dt.__format__(fmt), dt.strftime(fmt))
+            self.assertEqual(a.__format__(fmt), dt.strftime(fmt))
+            self.assertEqual(b.__format__(fmt), 'B')
+
+    def test_more_ctime(self):
+        # Test fields that TestDate doesn't touch.
+        import time
+
+        t = self.theclass(2002, 3, 2, 18, 3, 5, 123)
+        self.assertEqual(t.ctime(), "Sat Mar  2 18:03:05 2002")
+        # Oops!  The next line fails on Win2K under MSVC 6, so it's commented
+        # out.  The difference is that t.ctime() produces " 2" for the day,
+        # but platform ctime() produces "02" for the day.  According to
+        # C99, t.ctime() is correct here.
+        # self.assertEqual(t.ctime(), time.ctime(time.mktime(t.timetuple())))
+
+        # So test a case where that difference doesn't matter.
+        t = self.theclass(2002, 3, 22, 18, 3, 5, 123)
+        self.assertEqual(t.ctime(), time.ctime(time.mktime(t.timetuple())))
+
+    def test_tz_independent_comparing(self):
+        dt1 = self.theclass(2002, 3, 1, 9, 0, 0)
+        dt2 = self.theclass(2002, 3, 1, 10, 0, 0)
+        dt3 = self.theclass(2002, 3, 1, 9, 0, 0)
+        self.assertEqual(dt1, dt3)
+        self.assert_(dt2 > dt3)
+
+        # Make sure comparison doesn't forget microseconds, and isn't done
+        # via comparing a float timestamp (an IEEE double doesn't have enough
+        # precision to span microsecond resolution across years 1 thru 9999,
+        # so comparing via timestamp necessarily calls some distinct values
+        # equal).
+        dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998)
+        us = timedelta(microseconds=1)
+        dt2 = dt1 + us
+        self.assertEqual(dt2 - dt1, us)
+        self.assert_(dt1 < dt2)
+
+    def test_strftime_with_bad_tzname_replace(self):
+        # verify ok if tzinfo.tzname().replace() returns a non-string
+        class MyTzInfo(FixedOffset):
+            def tzname(self, dt):
+                class MyStr(str):
+                    def replace(self, *args):
+                        return None
+                return MyStr('name')
+        t = self.theclass(2005, 3, 2, 0, 0, 0, 0, MyTzInfo(3, 'name'))
+        self.assertRaises(TypeError, t.strftime, '%Z')
+
+    def test_bad_constructor_arguments(self):
+        # bad years
+        self.theclass(MINYEAR, 1, 1)  # no exception
+        self.theclass(MAXYEAR, 1, 1)  # no exception
+        self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1)
+        self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1)
+        # bad months
+        self.theclass(2000, 1, 1)    # no exception
+        self.theclass(2000, 12, 1)   # no exception
+        self.assertRaises(ValueError, self.theclass, 2000, 0, 1)
+        self.assertRaises(ValueError, self.theclass, 2000, 13, 1)
+        # bad days
+        self.theclass(2000, 2, 29)   # no exception
+        self.theclass(2004, 2, 29)   # no exception
+        self.theclass(2400, 2, 29)   # no exception
+        self.assertRaises(ValueError, self.theclass, 2000, 2, 30)
+        self.assertRaises(ValueError, self.theclass, 2001, 2, 29)
+        self.assertRaises(ValueError, self.theclass, 2100, 2, 29)
+        self.assertRaises(ValueError, self.theclass, 1900, 2, 29)
+        self.assertRaises(ValueError, self.theclass, 2000, 1, 0)
+        self.assertRaises(ValueError, self.theclass, 2000, 1, 32)
+        # bad hours
+        self.theclass(2000, 1, 31, 0)    # no exception
+        self.theclass(2000, 1, 31, 23)   # no exception
+        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, -1)
+        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 24)
+        # bad minutes
+        self.theclass(2000, 1, 31, 23, 0)    # no exception
+        self.theclass(2000, 1, 31, 23, 59)   # no exception
+        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, -1)
+        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 60)
+        # bad seconds
+        self.theclass(2000, 1, 31, 23, 59, 0)    # no exception
+        self.theclass(2000, 1, 31, 23, 59, 59)   # no exception
+        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, -1)
+        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, 60)
+        # bad microseconds
+        self.theclass(2000, 1, 31, 23, 59, 59, 0)    # no exception
+        self.theclass(2000, 1, 31, 23, 59, 59, 999999)   # no exception
+        self.assertRaises(ValueError, self.theclass,
+                          2000, 1, 31, 23, 59, 59, -1)
+        self.assertRaises(ValueError, self.theclass,
+                          2000, 1, 31, 23, 59, 59,
+                          1000000)
+
+    def test_hash_equality(self):
+        d = self.theclass(2000, 12, 31, 23, 30, 17)
+        e = self.theclass(2000, 12, 31, 23, 30, 17)
+        self.assertEqual(d, e)
+        self.assertEqual(hash(d), hash(e))
+
+        dic = {d: 1}
+        dic[e] = 2
+        self.assertEqual(len(dic), 1)
+        self.assertEqual(dic[d], 2)
+        self.assertEqual(dic[e], 2)
+
+        d = self.theclass(2001,  1,  1,  0,  5, 17)
+        e = self.theclass(2001,  1,  1,  0,  5, 17)
+        self.assertEqual(d, e)
+        self.assertEqual(hash(d), hash(e))
+
+        dic = {d: 1}
+        dic[e] = 2
+        self.assertEqual(len(dic), 1)
+        self.assertEqual(dic[d], 2)
+        self.assertEqual(dic[e], 2)
+
+    def test_computations(self):
+        a = self.theclass(2002, 1, 31)
+        b = self.theclass(1956, 1, 31)
+        diff = a-b
+        self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4)))
+        self.assertEqual(diff.seconds, 0)
+        self.assertEqual(diff.microseconds, 0)
+        a = self.theclass(2002, 3, 2, 17, 6)
+        millisec = timedelta(0, 0, 1000)
+        hour = timedelta(0, 3600)
+        day = timedelta(1)
+        week = timedelta(7)
+        self.assertEqual(a + hour, self.theclass(2002, 3, 2, 18, 6))
+        self.assertEqual(hour + a, self.theclass(2002, 3, 2, 18, 6))
+        self.assertEqual(a + 10*hour, self.theclass(2002, 3, 3, 3, 6))
+        self.assertEqual(a - hour, self.theclass(2002, 3, 2, 16, 6))
+        self.assertEqual(-hour + a, self.theclass(2002, 3, 2, 16, 6))
+        self.assertEqual(a - hour, a + -hour)
+        self.assertEqual(a - 20*hour, self.theclass(2002, 3, 1, 21, 6))
+        self.assertEqual(a + day, self.theclass(2002, 3, 3, 17, 6))
+        self.assertEqual(a - day, self.theclass(2002, 3, 1, 17, 6))
+        self.assertEqual(a + week, self.theclass(2002, 3, 9, 17, 6))
+        self.assertEqual(a - week, self.theclass(2002, 2, 23, 17, 6))
+        self.assertEqual(a + 52*week, self.theclass(2003, 3, 1, 17, 6))
+        self.assertEqual(a - 52*week, self.theclass(2001, 3, 3, 17, 6))
+        self.assertEqual((a + week) - a, week)
+        self.assertEqual((a + day) - a, day)
+        self.assertEqual((a + hour) - a, hour)
+        self.assertEqual((a + millisec) - a, millisec)
+        self.assertEqual((a - week) - a, -week)
+        self.assertEqual((a - day) - a, -day)
+        self.assertEqual((a - hour) - a, -hour)
+        self.assertEqual((a - millisec) - a, -millisec)
+        self.assertEqual(a - (a + week), -week)
+        self.assertEqual(a - (a + day), -day)
+        self.assertEqual(a - (a + hour), -hour)
+        self.assertEqual(a - (a + millisec), -millisec)
+        self.assertEqual(a - (a - week), week)
+        self.assertEqual(a - (a - day), day)
+        self.assertEqual(a - (a - hour), hour)
+        self.assertEqual(a - (a - millisec), millisec)
+        self.assertEqual(a + (week + day + hour + millisec),
+                         self.theclass(2002, 3, 10, 18, 6, 0, 1000))
+        self.assertEqual(a + (week + day + hour + millisec),
+                         (((a + week) + day) + hour) + millisec)
+        self.assertEqual(a - (week + day + hour + millisec),
+                         self.theclass(2002, 2, 22, 16, 5, 59, 999000))
+        self.assertEqual(a - (week + day + hour + millisec),
+                         (((a - week) - day) - hour) - millisec)
+        # Add/sub ints, longs, floats should be illegal
+        for i in 1, 1L, 1.0:
+            self.assertRaises(TypeError, lambda: a+i)
+            self.assertRaises(TypeError, lambda: a-i)
+            self.assertRaises(TypeError, lambda: i+a)
+            self.assertRaises(TypeError, lambda: i-a)
+
+        # delta - datetime is senseless.
+        self.assertRaises(TypeError, lambda: day - a)
+        # mixing datetime and (delta or datetime) via * or // is senseless
+        self.assertRaises(TypeError, lambda: day * a)
+        self.assertRaises(TypeError, lambda: a * day)
+        self.assertRaises(TypeError, lambda: day // a)
+        self.assertRaises(TypeError, lambda: a // day)
+        self.assertRaises(TypeError, lambda: a * a)
+        self.assertRaises(TypeError, lambda: a // a)
+        # datetime + datetime is senseless
+        self.assertRaises(TypeError, lambda: a + a)
+
+    def test_pickling(self):
+        args = 6, 7, 23, 20, 59, 1, 64**2
+        orig = self.theclass(*args)
+        for pickler, unpickler, proto in pickle_choices:
+            green = pickler.dumps(orig, proto)
+            derived = unpickler.loads(green)
+            self.assertEqual(orig, derived)
+
+    def test_more_pickling(self):
+        a = self.theclass(2003, 2, 7, 16, 48, 37, 444116)
+        s = pickle.dumps(a)
+        b = pickle.loads(s)
+        self.assertEqual(b.year, 2003)
+        self.assertEqual(b.month, 2)
+        self.assertEqual(b.day, 7)
+
+    def test_pickling_subclass_datetime(self):
+        args = 6, 7, 23, 20, 59, 1, 64**2
+        orig = SubclassDatetime(*args)
+        for pickler, unpickler, proto in pickle_choices:
+            green = pickler.dumps(orig, proto)
+            derived = unpickler.loads(green)
+            self.assertEqual(orig, derived)
+
+    def test_more_compare(self):
+        # The test_compare() inherited from TestDate covers the error cases.
+        # We just want to test lexicographic ordering on the members datetime
+        # has that date lacks.
+        args = [2000, 11, 29, 20, 58, 16, 999998]
+        t1 = self.theclass(*args)
+        t2 = self.theclass(*args)
+        self.failUnless(t1 == t2)
+        self.failUnless(t1 <= t2)
+        self.failUnless(t1 >= t2)
+        self.failUnless(not t1 != t2)
+        self.failUnless(not t1 < t2)
+        self.failUnless(not t1 > t2)
+        self.assertEqual(cmp(t1, t2), 0)
+        self.assertEqual(cmp(t2, t1), 0)
+
+        for i in range(len(args)):
+            newargs = args[:]
+            newargs[i] = args[i] + 1
+            t2 = self.theclass(*newargs)   # this is larger than t1
+            self.failUnless(t1 < t2)
+            self.failUnless(t2 > t1)
+            self.failUnless(t1 <= t2)
+            self.failUnless(t2 >= t1)
+            self.failUnless(t1 != t2)
+            self.failUnless(t2 != t1)
+            self.failUnless(not t1 == t2)
+            self.failUnless(not t2 == t1)
+            self.failUnless(not t1 > t2)
+            self.failUnless(not t2 < t1)
+            self.failUnless(not t1 >= t2)
+            self.failUnless(not t2 <= t1)
+            self.assertEqual(cmp(t1, t2), -1)
+            self.assertEqual(cmp(t2, t1), 1)
+
+
+    # A helper for timestamp constructor tests.
+    def verify_field_equality(self, expected, got):
+        self.assertEqual(expected.tm_year, got.year)
+        self.assertEqual(expected.tm_mon, got.month)
+        self.assertEqual(expected.tm_mday, got.day)
+        self.assertEqual(expected.tm_hour, got.hour)
+        self.assertEqual(expected.tm_min, got.minute)
+        self.assertEqual(expected.tm_sec, got.second)
+
+    def test_fromtimestamp(self):
+        import time
+
+        ts = time.time()
+        expected = time.localtime(ts)
+        got = self.theclass.fromtimestamp(ts)
+        self.verify_field_equality(expected, got)
+
+    def test_utcfromtimestamp(self):
+        import time
+
+        ts = time.time()
+        expected = time.gmtime(ts)
+        got = self.theclass.utcfromtimestamp(ts)
+        self.verify_field_equality(expected, got)
+
+    def test_microsecond_rounding(self):
+        # Test whether fromtimestamp "rounds up" floats that are less
+        # than one microsecond smaller than an integer.
+        self.assertEquals(self.theclass.fromtimestamp(0.9999999),
+                          self.theclass.fromtimestamp(1))
+
+    def test_insane_fromtimestamp(self):
+        # It's possible that some platform maps time_t to double,
+        # and that this test will fail there.  This test should
+        # exempt such platforms (provided they return reasonable
+        # results!).
+        for insane in -1e200, 1e200:
+            self.assertRaises(ValueError, self.theclass.fromtimestamp,
+                              insane)
+
+    def test_insane_utcfromtimestamp(self):
+        # It's possible that some platform maps time_t to double,
+        # and that this test will fail there.  This test should
+        # exempt such platforms (provided they return reasonable
+        # results!).
+        for insane in -1e200, 1e200:
+            self.assertRaises(ValueError, self.theclass.utcfromtimestamp,
+                              insane)
+
+    def test_negative_float_fromtimestamp(self):
+        # Windows doesn't accept negative timestamps
+        if sys.platform == "win32":
+            return
+        # The result is tz-dependent; at least test that this doesn't
+        # fail (like it did before bug 1646728 was fixed).
+        self.theclass.fromtimestamp(-1.05)
+
+    def test_negative_float_utcfromtimestamp(self):
+        # Windows doesn't accept negative timestamps
+        if sys.platform == "win32":
+            return
+        d = self.theclass.utcfromtimestamp(-1.05)
+        self.assertEquals(d, self.theclass(1969, 12, 31, 23, 59, 58, 950000))
+
+    def test_utcnow(self):
+        import time
+
+        # Call it a success if utcnow() and utcfromtimestamp() are within
+        # a second of each other.
+        tolerance = timedelta(seconds=1)
+        for dummy in range(3):
+            from_now = self.theclass.utcnow()
+            from_timestamp = self.theclass.utcfromtimestamp(time.time())
+            if abs(from_timestamp - from_now) <= tolerance:
+                break
+            # Else try again a few times.
+        self.failUnless(abs(from_timestamp - from_now) <= tolerance)
+
+    def test_strptime(self):
+        import _strptime
+
+        string = '2004-12-01 13:02:47.197'
+        format = '%Y-%m-%d %H:%M:%S.%f'
+        result, frac = _strptime._strptime(string, format)
+        expected = self.theclass(*(result[0:6]+(frac,)))
+        got = self.theclass.strptime(string, format)
+        self.assertEqual(expected, got)
+
+    def test_more_timetuple(self):
+        # This tests fields beyond those tested by the TestDate.test_timetuple.
+        t = self.theclass(2004, 12, 31, 6, 22, 33)
+        self.assertEqual(t.timetuple(), (2004, 12, 31, 6, 22, 33, 4, 366, -1))
+        self.assertEqual(t.timetuple(),
+                         (t.year, t.month, t.day,
+                          t.hour, t.minute, t.second,
+                          t.weekday(),
+                          t.toordinal() - date(t.year, 1, 1).toordinal() + 1,
+                          -1))
+        tt = t.timetuple()
+        self.assertEqual(tt.tm_year, t.year)
+        self.assertEqual(tt.tm_mon, t.month)
+        self.assertEqual(tt.tm_mday, t.day)
+        self.assertEqual(tt.tm_hour, t.hour)
+        self.assertEqual(tt.tm_min, t.minute)
+        self.assertEqual(tt.tm_sec, t.second)
+        self.assertEqual(tt.tm_wday, t.weekday())
+        self.assertEqual(tt.tm_yday, t.toordinal() -
+                                     date(t.year, 1, 1).toordinal() + 1)
+        self.assertEqual(tt.tm_isdst, -1)
+
+    def test_more_strftime(self):
+        # This tests fields beyond those tested by the TestDate.test_strftime.
+        t = self.theclass(2004, 12, 31, 6, 22, 33, 47)
+        self.assertEqual(t.strftime("%m %d %y %f %S %M %H %j"),
+                                    "12 31 04 000047 33 22 06 366")
+
+    def test_extract(self):
+        dt = self.theclass(2002, 3, 4, 18, 45, 3, 1234)
+        self.assertEqual(dt.date(), date(2002, 3, 4))
+        self.assertEqual(dt.time(), time(18, 45, 3, 1234))
+
+    def test_combine(self):
+        d = date(2002, 3, 4)
+        t = time(18, 45, 3, 1234)
+        expected = self.theclass(2002, 3, 4, 18, 45, 3, 1234)
+        combine = self.theclass.combine
+        dt = combine(d, t)
+        self.assertEqual(dt, expected)
+
+        dt = combine(time=t, date=d)
+        self.assertEqual(dt, expected)
+
+        self.assertEqual(d, dt.date())
+        self.assertEqual(t, dt.time())
+        self.assertEqual(dt, combine(dt.date(), dt.time()))
+
+        self.assertRaises(TypeError, combine) # need an arg
+        self.assertRaises(TypeError, combine, d) # need two args
+        self.assertRaises(TypeError, combine, t, d) # args reversed
+        self.assertRaises(TypeError, combine, d, t, 1) # too many args
+        self.assertRaises(TypeError, combine, "date", "time") # wrong types
+
+    def test_replace(self):
+        cls = self.theclass
+        args = [1, 2, 3, 4, 5, 6, 7]
+        base = cls(*args)
+        self.assertEqual(base, base.replace())
+
+        i = 0
+        for name, newval in (("year", 2),
+                             ("month", 3),
+                             ("day", 4),
+                             ("hour", 5),
+                             ("minute", 6),
+                             ("second", 7),
+                             ("microsecond", 8)):
+            newargs = args[:]
+            newargs[i] = newval
+            expected = cls(*newargs)
+            got = base.replace(**{name: newval})
+            self.assertEqual(expected, got)
+            i += 1
+
+        # Out of bounds.
+        base = cls(2000, 2, 29)
+        self.assertRaises(ValueError, base.replace, year=2001)
+
+    def test_astimezone(self):
+        # Pretty boring!  The TZ test is more interesting here.  astimezone()
+        # simply can't be applied to a naive object.
+        dt = self.theclass.now()
+        f = FixedOffset(44, "")
+        self.assertRaises(TypeError, dt.astimezone) # not enough args
+        self.assertRaises(TypeError, dt.astimezone, f, f) # too many args
+        self.assertRaises(TypeError, dt.astimezone, dt) # arg wrong type
+        self.assertRaises(ValueError, dt.astimezone, f) # naive
+        self.assertRaises(ValueError, dt.astimezone, tz=f)  # naive
+
+        class Bogus(tzinfo):
+            def utcoffset(self, dt): return None
+            def dst(self, dt): return timedelta(0)
+        bog = Bogus()
+        self.assertRaises(ValueError, dt.astimezone, bog)   # naive
+
+        class AlsoBogus(tzinfo):
+            def utcoffset(self, dt): return timedelta(0)
+            def dst(self, dt): return None
+        alsobog = AlsoBogus()
+        self.assertRaises(ValueError, dt.astimezone, alsobog) # also naive
+
+    def test_subclass_datetime(self):
+
+        class C(self.theclass):
+            theAnswer = 42
+
+            def __new__(cls, *args, **kws):
+                temp = kws.copy()
+                extra = temp.pop('extra')
+                result = self.theclass.__new__(cls, *args, **temp)
+                result.extra = extra
+                return result
+
+            def newmeth(self, start):
+                return start + self.year + self.month + self.second
+
+        args = 2003, 4, 14, 12, 13, 41
+
+        dt1 = self.theclass(*args)
+        dt2 = C(*args, **{'extra': 7})
+
+        self.assertEqual(dt2.__class__, C)
+        self.assertEqual(dt2.theAnswer, 42)
+        self.assertEqual(dt2.extra, 7)
+        self.assertEqual(dt1.toordinal(), dt2.toordinal())
+        self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month +
+                                          dt1.second - 7)
+
+class SubclassTime(time):
+    sub_var = 1
+
+class TestTime(HarmlessMixedComparison, unittest.TestCase):
+
+    theclass = time
+
+    def test_basic_attributes(self):
+        t = self.theclass(12, 0)
+        self.assertEqual(t.hour, 12)
+        self.assertEqual(t.minute, 0)
+        self.assertEqual(t.second, 0)
+        self.assertEqual(t.microsecond, 0)
+
+    def test_basic_attributes_nonzero(self):
+        # Make sure all attributes are non-zero so bugs in
+        # bit-shifting access show up.
+        t = self.theclass(12, 59, 59, 8000)
+        self.assertEqual(t.hour, 12)
+        self.assertEqual(t.minute, 59)
+        self.assertEqual(t.second, 59)
+        self.assertEqual(t.microsecond, 8000)
+
+    def test_roundtrip(self):
+        t = self.theclass(1, 2, 3, 4)
+
+        # Verify t -> string -> time identity.
+        s = repr(t)
+        self.failUnless(s.startswith('datetime.'))
+        s = s[9:]
+        t2 = eval(s)
+        self.assertEqual(t, t2)
+
+        # Verify identity via reconstructing from pieces.
+        t2 = self.theclass(t.hour, t.minute, t.second,
+                           t.microsecond)
+        self.assertEqual(t, t2)
+
+    def test_comparing(self):
+        args = [1, 2, 3, 4]
+        t1 = self.theclass(*args)
+        t2 = self.theclass(*args)
+        self.failUnless(t1 == t2)
+        self.failUnless(t1 <= t2)
+        self.failUnless(t1 >= t2)
+        self.failUnless(not t1 != t2)
+        self.failUnless(not t1 < t2)
+        self.failUnless(not t1 > t2)
+        self.assertEqual(cmp(t1, t2), 0)
+        self.assertEqual(cmp(t2, t1), 0)
+
+        for i in range(len(args)):
+            newargs = args[:]
+            newargs[i] = args[i] + 1
+            t2 = self.theclass(*newargs)   # this is larger than t1
+            self.failUnless(t1 < t2)
+            self.failUnless(t2 > t1)
+            self.failUnless(t1 <= t2)
+            self.failUnless(t2 >= t1)
+            self.failUnless(t1 != t2)
+            self.failUnless(t2 != t1)
+            self.failUnless(not t1 == t2)
+            self.failUnless(not t2 == t1)
+            self.failUnless(not t1 > t2)
+            self.failUnless(not t2 < t1)
+            self.failUnless(not t1 >= t2)
+            self.failUnless(not t2 <= t1)
+            self.assertEqual(cmp(t1, t2), -1)
+            self.assertEqual(cmp(t2, t1), 1)
+
+        for badarg in OTHERSTUFF:
+            self.assertEqual(t1 == badarg, False)
+            self.assertEqual(t1 != badarg, True)
+            self.assertEqual(badarg == t1, False)
+            self.assertEqual(badarg != t1, True)
+
+            self.assertRaises(TypeError, lambda: t1 <= badarg)
+            self.assertRaises(TypeError, lambda: t1 < badarg)
+            self.assertRaises(TypeError, lambda: t1 > badarg)
+            self.assertRaises(TypeError, lambda: t1 >= badarg)
+            self.assertRaises(TypeError, lambda: badarg <= t1)
+            self.assertRaises(TypeError, lambda: badarg < t1)
+            self.assertRaises(TypeError, lambda: badarg > t1)
+            self.assertRaises(TypeError, lambda: badarg >= t1)
+
+    def test_bad_constructor_arguments(self):
+        # bad hours
+        self.theclass(0, 0)    # no exception
+        self.theclass(23, 0)   # no exception
+        self.assertRaises(ValueError, self.theclass, -1, 0)
+        self.assertRaises(ValueError, self.theclass, 24, 0)
+        # bad minutes
+        self.theclass(23, 0)    # no exception
+        self.theclass(23, 59)   # no exception
+        self.assertRaises(ValueError, self.theclass, 23, -1)
+        self.assertRaises(ValueError, self.theclass, 23, 60)
+        # bad seconds
+        self.theclass(23, 59, 0)    # no exception
+        self.theclass(23, 59, 59)   # no exception
+        self.assertRaises(ValueError, self.theclass, 23, 59, -1)
+        self.assertRaises(ValueError, self.theclass, 23, 59, 60)
+        # bad microseconds
+        self.theclass(23, 59, 59, 0)        # no exception
+        self.theclass(23, 59, 59, 999999)   # no exception
+        self.assertRaises(ValueError, self.theclass, 23, 59, 59, -1)
+        self.assertRaises(ValueError, self.theclass, 23, 59, 59, 1000000)
+
+    def test_hash_equality(self):
+        d = self.theclass(23, 30, 17)
+        e = self.theclass(23, 30, 17)
+        self.assertEqual(d, e)
+        self.assertEqual(hash(d), hash(e))
+
+        dic = {d: 1}
+        dic[e] = 2
+        self.assertEqual(len(dic), 1)
+        self.assertEqual(dic[d], 2)
+        self.assertEqual(dic[e], 2)
+
+        d = self.theclass(0,  5, 17)
+        e = self.theclass(0,  5, 17)
+        self.assertEqual(d, e)
+        self.assertEqual(hash(d), hash(e))
+
+        dic = {d: 1}
+        dic[e] = 2
+        self.assertEqual(len(dic), 1)
+        self.assertEqual(dic[d], 2)
+        self.assertEqual(dic[e], 2)
+
+    def test_isoformat(self):
+        t = self.theclass(4, 5, 1, 123)
+        self.assertEqual(t.isoformat(), "04:05:01.000123")
+        self.assertEqual(t.isoformat(), str(t))
+
+        t = self.theclass()
+        self.assertEqual(t.isoformat(), "00:00:00")
+        self.assertEqual(t.isoformat(), str(t))
+
+        t = self.theclass(microsecond=1)
+        self.assertEqual(t.isoformat(), "00:00:00.000001")
+        self.assertEqual(t.isoformat(), str(t))
+
+        t = self.theclass(microsecond=10)
+        self.assertEqual(t.isoformat(), "00:00:00.000010")
+        self.assertEqual(t.isoformat(), str(t))
+
+        t = self.theclass(microsecond=100)
+        self.assertEqual(t.isoformat(), "00:00:00.000100")
+        self.assertEqual(t.isoformat(), str(t))
+
+        t = self.theclass(microsecond=1000)
+        self.assertEqual(t.isoformat(), "00:00:00.001000")
+        self.assertEqual(t.isoformat(), str(t))
+
+        t = self.theclass(microsecond=10000)
+        self.assertEqual(t.isoformat(), "00:00:00.010000")
+        self.assertEqual(t.isoformat(), str(t))
+
+        t = self.theclass(microsecond=100000)
+        self.assertEqual(t.isoformat(), "00:00:00.100000")
+        self.assertEqual(t.isoformat(), str(t))
+
+    def test_1653736(self):
+        # verify it doesn't accept extra keyword arguments
+        t = self.theclass(second=1)
+        self.assertRaises(TypeError, t.isoformat, foo=3)
+
+    def test_strftime(self):
+        t = self.theclass(1, 2, 3, 4)
+        self.assertEqual(t.strftime('%H %M %S %f'), "01 02 03 000004")
+        # A naive object replaces %z and %Z with empty strings.
+        self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''")
+
+    def test_format(self):
+        t = self.theclass(1, 2, 3, 4)
+        self.assertEqual(t.__format__(''), str(t))
+
+        # check that a derived class's __str__() gets called
+        class A(self.theclass):
+            def __str__(self):
+                return 'A'
+        a = A(1, 2, 3, 4)
+        self.assertEqual(a.__format__(''), 'A')
+
+        # check that a derived class's strftime gets called
+        class B(self.theclass):
+            def strftime(self, format_spec):
+                return 'B'
+        b = B(1, 2, 3, 4)
+        self.assertEqual(b.__format__(''), str(t))
+
+        for fmt in ['%H %M %S',
+                    ]:
+            self.assertEqual(t.__format__(fmt), t.strftime(fmt))
+            self.assertEqual(a.__format__(fmt), t.strftime(fmt))
+            self.assertEqual(b.__format__(fmt), 'B')
+
+    def test_str(self):
+        self.assertEqual(str(self.theclass(1, 2, 3, 4)), "01:02:03.000004")
+        self.assertEqual(str(self.theclass(10, 2, 3, 4000)), "10:02:03.004000")
+        self.assertEqual(str(self.theclass(0, 2, 3, 400000)), "00:02:03.400000")
+        self.assertEqual(str(self.theclass(12, 2, 3, 0)), "12:02:03")
+        self.assertEqual(str(self.theclass(23, 15, 0, 0)), "23:15:00")
+
+    def test_repr(self):
+        name = 'datetime.' + self.theclass.__name__
+        self.assertEqual(repr(self.theclass(1, 2, 3, 4)),
+                         "%s(1, 2, 3, 4)" % name)
+        self.assertEqual(repr(self.theclass(10, 2, 3, 4000)),
+                         "%s(10, 2, 3, 4000)" % name)
+        self.assertEqual(repr(self.theclass(0, 2, 3, 400000)),
+                         "%s(0, 2, 3, 400000)" % name)
+        self.assertEqual(repr(self.theclass(12, 2, 3, 0)),
+                         "%s(12, 2, 3)" % name)
+        self.assertEqual(repr(self.theclass(23, 15, 0, 0)),
+                         "%s(23, 15)" % name)
+
+    def test_resolution_info(self):
+        self.assert_(isinstance(self.theclass.min, self.theclass))
+        self.assert_(isinstance(self.theclass.max, self.theclass))
+        self.assert_(isinstance(self.theclass.resolution, timedelta))
+        self.assert_(self.theclass.max > self.theclass.min)
+
+    def test_pickling(self):
+        args = 20, 59, 16, 64**2
+        orig = self.theclass(*args)
+        for pickler, unpickler, proto in pickle_choices:
+            green = pickler.dumps(orig, proto)
+            derived = unpickler.loads(green)
+            self.assertEqual(orig, derived)
+
+    def test_pickling_subclass_time(self):
+        args = 20, 59, 16, 64**2
+        orig = SubclassTime(*args)
+        for pickler, unpickler, proto in pickle_choices:
+            green = pickler.dumps(orig, proto)
+            derived = unpickler.loads(green)
+            self.assertEqual(orig, derived)
+
+    def test_bool(self):
+        cls = self.theclass
+        self.failUnless(cls(1))
+        self.failUnless(cls(0, 1))
+        self.failUnless(cls(0, 0, 1))
+        self.failUnless(cls(0, 0, 0, 1))
+        self.failUnless(not cls(0))
+        self.failUnless(not cls())
+
+    def test_replace(self):
+        cls = self.theclass
+        args = [1, 2, 3, 4]
+        base = cls(*args)
+        self.assertEqual(base, base.replace())
+
+        i = 0
+        for name, newval in (("hour", 5),
+                             ("minute", 6),
+                             ("second", 7),
+                             ("microsecond", 8)):
+            newargs = args[:]
+            newargs[i] = newval
+            expected = cls(*newargs)
+            got = base.replace(**{name: newval})
+            self.assertEqual(expected, got)
+            i += 1
+
+        # Out of bounds.
+        base = cls(1)
+        self.assertRaises(ValueError, base.replace, hour=24)
+        self.assertRaises(ValueError, base.replace, minute=-1)
+        self.assertRaises(ValueError, base.replace, second=100)
+        self.assertRaises(ValueError, base.replace, microsecond=1000000)
+
+    def test_subclass_time(self):
+
+        class C(self.theclass):
+            theAnswer = 42
+
+            def __new__(cls, *args, **kws):
+                temp = kws.copy()
+                extra = temp.pop('extra')
+                result = self.theclass.__new__(cls, *args, **temp)
+                result.extra = extra
+                return result
+
+            def newmeth(self, start):
+                return start + self.hour + self.second
+
+        args = 4, 5, 6
+
+        dt1 = self.theclass(*args)
+        dt2 = C(*args, **{'extra': 7})
+
+        self.assertEqual(dt2.__class__, C)
+        self.assertEqual(dt2.theAnswer, 42)
+        self.assertEqual(dt2.extra, 7)
+        self.assertEqual(dt1.isoformat(), dt2.isoformat())
+        self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.second - 7)
+
+    def test_backdoor_resistance(self):

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.

------------------------------------------------------------------------------
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d