[Python-checkins] cpython (merge default -> default): merge heads

senthil.kumaran python-checkins at python.org
Tue Mar 13 08:17:28 CET 2012


http://hg.python.org/cpython/rev/3184e2d52ac5
changeset:   75575:3184e2d52ac5
parent:      75574:c5833f277258
parent:      75570:7e576ad85663
user:        Senthil Kumaran <senthil at uthcode.com>
date:        Tue Mar 13 00:14:25 2012 -0700
summary:
  merge heads

files:
  Lib/aifc.py                                     |   12 +-
  Lib/pickle.py                                   |    8 +
  Lib/test/pickletester.py                        |   12 +
  Lib/test/test_aifc.py                           |  158 +++++++++-
  Lib/test/test_ast.py                            |    9 +-
  Lib/test/test_re.py                             |   30 +
  Lib/test/test_sys.py                            |    2 +-
  Lib/test/test_unicode.py                        |   15 +-
  Lib/test/test_zipimport.py                      |    4 +
  Lib/tkinter/__init__.py                         |   36 +-
  Lib/tkinter/test/test_tkinter/test_variables.py |  165 ++++++++++
  Lib/unittest/main.py                            |   80 ++--
  Lib/unittest/test/test_program.py               |   17 -
  Misc/ACKS                                       |    3 +
  Misc/NEWS                                       |   14 +
  Modules/_pickle.c                               |   26 +
  Modules/_sre.c                                  |   16 +-
  Modules/timemodule.c                            |   18 +-
  Parser/asdl_c.py                                |   18 +-
  Python/Python-ast.c                             |   18 +-
  Python/ast.c                                    |   10 +-
  21 files changed, 548 insertions(+), 123 deletions(-)


diff --git a/Lib/aifc.py b/Lib/aifc.py
--- a/Lib/aifc.py
+++ b/Lib/aifc.py
@@ -136,6 +136,7 @@
 
 import struct
 import builtins
+import warnings
 
 __all__ = ["Error", "open", "openfp"]
 
@@ -440,7 +441,7 @@
             kludge = 0
             if chunk.chunksize == 18:
                 kludge = 1
-                print('Warning: bad COMM chunk size')
+                warnings.warn('Warning: bad COMM chunk size')
                 chunk.chunksize = 23
             #DEBUG end
             self._comptype = chunk.read(4)
@@ -484,11 +485,10 @@
                     # a position 0 and name ''
                     self._markers.append((id, pos, name))
         except EOFError:
-            print('Warning: MARK chunk contains only', end=' ')
-            print(len(self._markers), end=' ')
-            if len(self._markers) == 1: print('marker', end=' ')
-            else: print('markers', end=' ')
-            print('instead of', nmarkers)
+            w = ('Warning: MARK chunk contains only %s marker%s instead of %s' %
+                 (len(self._markers), '' if len(self._markers) == 1 else 's',
+                  nmarkers))
+            warnings.warn(w)
 
 class Aifc_write:
     # Variables used in this class:
diff --git a/Lib/pickle.py b/Lib/pickle.py
--- a/Lib/pickle.py
+++ b/Lib/pickle.py
@@ -438,6 +438,14 @@
         self.write(NONE)
     dispatch[type(None)] = save_none
 
+    def save_ellipsis(self, obj):
+        self.save_global(Ellipsis, 'Ellipsis')
+    dispatch[type(Ellipsis)] = save_ellipsis
+
+    def save_notimplemented(self, obj):
+        self.save_global(NotImplemented, 'NotImplemented')
+    dispatch[type(NotImplemented)] = save_notimplemented
+
     def save_bool(self, obj):
         if self.proto >= 2:
             self.write(obj and NEWTRUE or NEWFALSE)
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -743,6 +743,18 @@
                 u = self.loads(s)
                 self.assertEqual(t, u)
 
+    def test_ellipsis(self):
+        for proto in protocols:
+            s = self.dumps(..., proto)
+            u = self.loads(s)
+            self.assertEqual(..., u)
+
+    def test_notimplemented(self):
+        for proto in protocols:
+            s = self.dumps(NotImplemented, proto)
+            u = self.loads(s)
+            self.assertEqual(NotImplemented, u)
+
     # Tests for protocol 2
 
     def test_proto(self):
diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py
--- a/Lib/test/test_aifc.py
+++ b/Lib/test/test_aifc.py
@@ -1,7 +1,8 @@
-from test.support import findfile, run_unittest, TESTFN
+from test.support import findfile, run_unittest, TESTFN, unlink
 import unittest
 import os
 import io
+import struct
 
 import aifc
 
@@ -20,10 +21,8 @@
                 self.fout.close()
             except (aifc.Error, AttributeError):
                 pass
-        try:
-            os.remove(TESTFN)
-        except OSError:
-            pass
+        unlink(TESTFN)
+        unlink(TESTFN + '.aiff')
 
     def test_skipunknown(self):
         #Issue 2245
@@ -32,6 +31,7 @@
 
     def test_params(self):
         f = self.f = aifc.open(self.sndfilepath)
+        self.assertEqual(f.getfp().name, self.sndfilepath)
         self.assertEqual(f.getnchannels(), 2)
         self.assertEqual(f.getsampwidth(), 2)
         self.assertEqual(f.getframerate(), 48000)
@@ -45,6 +45,7 @@
 
     def test_read(self):
         f = self.f = aifc.open(self.sndfilepath)
+        self.assertEqual(f.readframes(0), b'')
         self.assertEqual(f.tell(), 0)
         self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4')
         f.rewind()
@@ -58,6 +59,10 @@
         self.assertEqual(f.readframes(2), b'\x17t\x17t"\xad"\xad')
         f.setpos(pos0)
         self.assertEqual(f.readframes(2), b'\x00\x00\x00\x00\x0b\xd4\x0b\xd4')
+        with self.assertRaises(aifc.Error):
+            f.setpos(-1)
+        with self.assertRaises(aifc.Error):
+            f.setpos(f.getnframes() + 1)
 
     def test_write(self):
         f = self.f = aifc.open(self.sndfilepath)
@@ -92,8 +97,6 @@
         self.assertEqual(f.getparams()[0:3], fout.getparams()[0:3])
         self.assertEqual(fout.getcomptype(), b'ULAW')
         self.assertEqual(fout.getcompname(), b'foo')
-        # XXX: this test fails, not sure if it should succeed or not
-        # self.assertEqual(f.readframes(5), fout.readframes(5))
 
     def test_close(self):
         class Wrapfile(object):
@@ -112,7 +115,7 @@
 
     def test_write_header_comptype_sampwidth(self):
         for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
-            fout = self.fout = aifc.open(io.BytesIO(), 'wb')
+            fout = aifc.open(io.BytesIO(), 'wb')
             fout.setnchannels(1)
             fout.setframerate(1)
             fout.setcomptype(comptype, b'')
@@ -121,7 +124,7 @@
             fout.initfp(None)
 
     def test_write_markers_values(self):
-        fout = self.fout = aifc.open(io.BytesIO(), 'wb')
+        fout = aifc.open(io.BytesIO(), 'wb')
         self.assertEqual(fout.getmarkers(), None)
         fout.setmark(1, 0, b'foo1')
         fout.setmark(1, 1, b'foo2')
@@ -179,6 +182,143 @@
         with self.assertRaises(ValueError):
             aifc._write_string(f, b'too long' * 255)
 
+    def test_wrong_open_mode(self):
+        with self.assertRaises(aifc.Error):
+            aifc.open(TESTFN, 'wrong_mode')
+
+    def test_read_wrong_form(self):
+        b1 = io.BytesIO(b'WRNG' + struct.pack('>L', 0))
+        b2 = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'WRNG')
+        self.assertRaises(aifc.Error, aifc.open, b1)
+        self.assertRaises(aifc.Error, aifc.open, b2)
+
+    def test_read_no_comm_chunk(self):
+        b = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'AIFF')
+        self.assertRaises(aifc.Error, aifc.open, b)
+
+    def test_read_wrong_compression_type(self):
+        b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
+        b += b'COMM' + struct.pack('>LhlhhLL', 23, 0, 0, 0, 0, 0, 0)
+        b += b'WRNG' + struct.pack('B', 0)
+        self.assertRaises(aifc.Error, aifc.open, io.BytesIO(b))
+
+    def test_read_wrong_marks(self):
+        b = b'FORM' + struct.pack('>L', 4) + b'AIFF'
+        b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
+        b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
+        b += b'MARK' + struct.pack('>LhB', 3, 1, 1)
+        with self.assertWarns(UserWarning):
+            f = aifc.open(io.BytesIO(b))
+        self.assertEqual(f.getmarkers(), None)
+
+    def test_read_comm_kludge_compname_even(self):
+        b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
+        b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
+        b += b'NONE' + struct.pack('B', 4) + b'even' + b'\x00'
+        b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
+        with self.assertWarns(UserWarning):
+            f = aifc.open(io.BytesIO(b))
+        self.assertEqual(f.getcompname(), b'even')
+
+    def test_read_comm_kludge_compname_odd(self):
+        b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
+        b += b'COMM' + struct.pack('>LhlhhLL', 18, 0, 0, 0, 0, 0, 0)
+        b += b'NONE' + struct.pack('B', 3) + b'odd'
+        b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
+        with self.assertWarns(UserWarning):
+            f = aifc.open(io.BytesIO(b))
+        self.assertEqual(f.getcompname(), b'odd')
+
+    def test_write_params_raises(self):
+        fout = aifc.open(io.BytesIO(), 'wb')
+        wrong_params = (0, 0, 0, 0, b'WRNG', '')
+        self.assertRaises(aifc.Error, fout.setparams, wrong_params)
+        self.assertRaises(aifc.Error, fout.getparams)
+        self.assertRaises(aifc.Error, fout.setnchannels, 0)
+        self.assertRaises(aifc.Error, fout.getnchannels)
+        self.assertRaises(aifc.Error, fout.setsampwidth, 0)
+        self.assertRaises(aifc.Error, fout.getsampwidth)
+        self.assertRaises(aifc.Error, fout.setframerate, 0)
+        self.assertRaises(aifc.Error, fout.getframerate)
+        self.assertRaises(aifc.Error, fout.setcomptype, b'WRNG', '')
+        fout.aiff()
+        fout.setnchannels(1)
+        fout.setsampwidth(1)
+        fout.setframerate(1)
+        fout.setnframes(1)
+        fout.writeframes(b'\x00')
+        self.assertRaises(aifc.Error, fout.setparams, (1, 1, 1, 1, 1, 1))
+        self.assertRaises(aifc.Error, fout.setnchannels, 1)
+        self.assertRaises(aifc.Error, fout.setsampwidth, 1)
+        self.assertRaises(aifc.Error, fout.setframerate, 1)
+        self.assertRaises(aifc.Error, fout.setnframes, 1)
+        self.assertRaises(aifc.Error, fout.setcomptype, b'NONE', '')
+        self.assertRaises(aifc.Error, fout.aiff)
+        self.assertRaises(aifc.Error, fout.aifc)
+
+    def test_write_params_singles(self):
+        fout = aifc.open(io.BytesIO(), 'wb')
+        fout.aifc()
+        fout.setnchannels(1)
+        fout.setsampwidth(2)
+        fout.setframerate(3)
+        fout.setnframes(4)
+        fout.setcomptype(b'NONE', b'name')
+        self.assertEqual(fout.getnchannels(), 1)
+        self.assertEqual(fout.getsampwidth(), 2)
+        self.assertEqual(fout.getframerate(), 3)
+        self.assertEqual(fout.getnframes(), 0)
+        self.assertEqual(fout.tell(), 0)
+        self.assertEqual(fout.getcomptype(), b'NONE')
+        self.assertEqual(fout.getcompname(), b'name')
+        fout.writeframes(b'\x00' * 4 * fout.getsampwidth() * fout.getnchannels())
+        self.assertEqual(fout.getnframes(), 4)
+        self.assertEqual(fout.tell(), 4)
+
+    def test_write_params_bunch(self):
+        fout = aifc.open(io.BytesIO(), 'wb')
+        fout.aifc()
+        p = (1, 2, 3, 4, b'NONE', b'name')
+        fout.setparams(p)
+        self.assertEqual(fout.getparams(), p)
+        fout.initfp(None)
+
+    def test_write_header_raises(self):
+        fout = aifc.open(io.BytesIO(), 'wb')
+        self.assertRaises(aifc.Error, fout.close)
+        fout.setnchannels(1)
+        self.assertRaises(aifc.Error, fout.close)
+        fout.setsampwidth(1)
+        self.assertRaises(aifc.Error, fout.close)
+        fout.initfp(None)
+
+    def test_write_header_comptype_raises(self):
+        for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
+            fout = aifc.open(io.BytesIO(), 'wb')
+            fout.setsampwidth(1)
+            fout.setcomptype(comptype, b'')
+            self.assertRaises(aifc.Error, fout.close)
+            fout.initfp(None)
+
+    def test_write_markers_raises(self):
+        fout = aifc.open(io.BytesIO(), 'wb')
+        self.assertRaises(aifc.Error, fout.setmark, 0, 0, b'')
+        self.assertRaises(aifc.Error, fout.setmark, 1, -1, b'')
+        self.assertRaises(aifc.Error, fout.setmark, 1, 0, None)
+        self.assertRaises(aifc.Error, fout.getmark, 1)
+        fout.initfp(None)
+
+    def test_write_aiff_by_extension(self):
+        sampwidth = 2
+        fout = self.fout = aifc.open(TESTFN + '.aiff', 'wb')
+        fout.setparams((1, sampwidth, 1, 1, b'ULAW', b''))
+        frames = b'\x00' * fout.getnchannels() * sampwidth
+        fout.writeframes(frames)
+        fout.close()
+        f = self.f = aifc.open(TESTFN + '.aiff', 'rb')
+        self.assertEqual(f.getcomptype(), b'NONE')
+        f.close()
+
 
 def test_main():
     run_unittest(AIFCTest)
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -196,16 +196,13 @@
     def test_AST_objects(self):
         x = ast.AST()
         self.assertEqual(x._fields, ())
+        x.foobar = 42
+        self.assertEqual(x.foobar, 42)
+        self.assertEqual(x.__dict__["foobar"], 42)
 
         with self.assertRaises(AttributeError):
             x.vararg
 
-        with self.assertRaises(AttributeError):
-            x.foobar = 21
-
-        with self.assertRaises(AttributeError):
-            ast.AST(lineno=2)
-
         with self.assertRaises(TypeError):
             # "_ast.AST constructor takes 0 positional arguments"
             ast.AST(2)
diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py
--- a/Lib/test/test_re.py
+++ b/Lib/test/test_re.py
@@ -652,6 +652,26 @@
         self.assertEqual([item.group(0) for item in iter],
                          [":", "::", ":::"])
 
+        pat = re.compile(r":+")
+        iter = pat.finditer("a:b::c:::d", 1, 10)
+        self.assertEqual([item.group(0) for item in iter],
+                         [":", "::", ":::"])
+
+        pat = re.compile(r":+")
+        iter = pat.finditer("a:b::c:::d", pos=1, endpos=10)
+        self.assertEqual([item.group(0) for item in iter],
+                         [":", "::", ":::"])
+
+        pat = re.compile(r":+")
+        iter = pat.finditer("a:b::c:::d", endpos=10, pos=1)
+        self.assertEqual([item.group(0) for item in iter],
+                         [":", "::", ":::"])
+
+        pat = re.compile(r":+")
+        iter = pat.finditer("a:b::c:::d", pos=3, endpos=8)
+        self.assertEqual([item.group(0) for item in iter],
+                         ["::", "::"])
+
     def test_bug_926075(self):
         self.assertTrue(re.compile('bug_926075') is not
                      re.compile(b'bug_926075'))
@@ -825,6 +845,16 @@
         self.assertIsNotNone(re.search("123.*-", '123\U0010ffff-'))
         self.assertIsNotNone(re.search("123.*-", '123\xe9\u20ac\U0010ffff-'))
 
+    def test_compile(self):
+        # Test return value when given string and pattern as parameter
+        pattern = re.compile('random pattern')
+        self.assertIsInstance(pattern, re._pattern_type)
+        same_pattern = re.compile(pattern)
+        self.assertIsInstance(same_pattern, re._pattern_type)
+        self.assertIs(same_pattern, pattern)
+        # Test behaviour when not given a string or pattern as parameter
+        self.assertRaises(TypeError, re.compile, 0)
+
 def run_re_tests():
     from test.re_tests import tests, SUCCEED, FAIL, SYNTAX_ERROR
     if verbose:
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -882,7 +882,7 @@
         check = self.check_sizeof
         # _ast.AST
         import _ast
-        check(_ast.AST(), size(h + ''))
+        check(_ast.AST(), size(h + 'P'))
         # imp.NullImporter
         import imp
         check(imp.NullImporter(self.file.name), size(h + ''))
diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py
--- a/Lib/test/test_unicode.py
+++ b/Lib/test/test_unicode.py
@@ -957,12 +957,15 @@
         self.assertEqual('{foo._x}'.format_map({'foo': C(20)}), '20')
 
         # test various errors
-        self.assertRaises(TypeError, '{'.format_map)
-        self.assertRaises(TypeError, '}'.format_map)
-        self.assertRaises(TypeError, 'a{'.format_map)
-        self.assertRaises(TypeError, 'a}'.format_map)
-        self.assertRaises(TypeError, '{a'.format_map)
-        self.assertRaises(TypeError, '}a'.format_map)
+        self.assertRaises(TypeError, ''.format_map)
+        self.assertRaises(TypeError, 'a'.format_map)
+
+        self.assertRaises(ValueError, '{'.format_map, {})
+        self.assertRaises(ValueError, '}'.format_map, {})
+        self.assertRaises(ValueError, 'a{'.format_map, {})
+        self.assertRaises(ValueError, 'a}'.format_map, {})
+        self.assertRaises(ValueError, '{a'.format_map, {})
+        self.assertRaises(ValueError, '}a'.format_map, {})
 
         # issue #12579: can't supply positional params to format_map
         self.assertRaises(ValueError, '{}'.format_map, {'a' : 2})
diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py
--- a/Lib/test/test_zipimport.py
+++ b/Lib/test/test_zipimport.py
@@ -205,6 +205,10 @@
             mod = zi.load_module(TESTPACK)
             self.assertEqual(zi.get_filename(TESTPACK), mod.__file__)
 
+            existing_pack_path = __import__(TESTPACK).__path__[0]
+            expected_path_path = os.path.join(TEMP_ZIP, TESTPACK)
+            self.assertEqual(existing_pack_path, expected_path_path)
+
             self.assertEqual(zi.is_package(packdir + '__init__'), False)
             self.assertEqual(zi.is_package(packdir + TESTPACK2), True)
             self.assertEqual(zi.is_package(packdir2 + TESTMOD), False)
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -155,6 +155,7 @@
     Subclasses StringVar, IntVar, DoubleVar, BooleanVar are specializations
     that constrain the type of the value returned from get()."""
     _default = ""
+    _tk = None
     def __init__(self, master=None, value=None, name=None):
         """Construct a variable
 
@@ -165,6 +166,11 @@
         If NAME matches an existing variable and VALUE is omitted
         then the existing value is retained.
         """
+        # check for type of NAME parameter to override weird error message
+        # raised from Modules/_tkinter.c:SetVar like:
+        # TypeError: setvar() takes exactly 3 arguments (2 given)
+        if name is not None and not isinstance(name, str):
+            raise TypeError("name must be a string")
         global _varnum
         if not master:
             master = _default_root
@@ -176,18 +182,21 @@
             self._name = 'PY_VAR' + repr(_varnum)
             _varnum += 1
         if value is not None:
-            self.set(value)
+            self.initialize(value)
         elif not self._tk.call("info", "exists", self._name):
-            self.set(self._default)
+            self.initialize(self._default)
     def __del__(self):
         """Unset the variable in Tcl."""
-        self._tk.globalunsetvar(self._name)
+        if (self._tk is not None and self._tk.call("info", "exists",
+                                                   self._name)):
+            self._tk.globalunsetvar(self._name)
     def __str__(self):
         """Return the name of the variable in Tcl."""
         return self._name
     def set(self, value):
         """Set the variable to VALUE."""
         return self._tk.globalsetvar(self._name, value)
+    initialize = set
     def get(self):
         """Return value of variable."""
         return self._tk.globalgetvar(self._name)
@@ -262,12 +271,6 @@
         """
         Variable.__init__(self, master, value, name)
 
-    def set(self, value):
-        """Set the variable to value, converting booleans to integers."""
-        if isinstance(value, bool):
-            value = int(value)
-        return Variable.set(self, value)
-
     def get(self):
         """Return the value of the variable as an integer."""
         return getint(self._tk.globalgetvar(self._name))
@@ -308,7 +311,10 @@
 
     def get(self):
         """Return the value of the variable as a bool."""
-        return self._tk.getboolean(self._tk.globalgetvar(self._name))
+        try:
+            return self._tk.getboolean(self._tk.globalgetvar(self._name))
+        except TclError:
+            raise ValueError("invalid literal for getboolean()")
 
 def mainloop(n=0):
     """Run the main loop of Tcl."""
@@ -320,7 +326,10 @@
 
 def getboolean(s):
     """Convert true and false to integer values 1 and 0."""
-    return _default_root.tk.getboolean(s)
+    try:
+        return _default_root.tk.getboolean(s)
+    except TclError:
+        raise ValueError("invalid literal for getboolean()")
 
 # Methods defined on both toplevel and interior widgets
 class Misc:
@@ -410,7 +419,10 @@
     getdouble = float
     def getboolean(self, s):
         """Return a boolean value for Tcl boolean values true and false given as parameter."""
-        return self.tk.getboolean(s)
+        try:
+            return self.tk.getboolean(s)
+        except TclError:
+            raise ValueError("invalid literal for getboolean()")
     def focus_set(self):
         """Direct input focus to this widget.
 
diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py
new file mode 100644
--- /dev/null
+++ b/Lib/tkinter/test/test_tkinter/test_variables.py
@@ -0,0 +1,165 @@
+import unittest
+
+from tkinter import Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tk
+
+
+class Var(Variable):
+
+    _default = "default"
+    side_effect = False
+
+    def set(self, value):
+        self.side_effect = True
+        super().set(value)
+
+
+class TestBase(unittest.TestCase):
+
+    def setUp(self):
+        self.root = Tk()
+
+    def tearDown(self):
+        self.root.destroy()
+
+
+class TestVariable(TestBase):
+
+    def test_default(self):
+        v = Variable(self.root)
+        self.assertEqual("", v.get())
+        self.assertRegex(str(v), r"^PY_VAR(\d+)$")
+
+    def test_name_and_value(self):
+        v = Variable(self.root, "sample string", "varname")
+        self.assertEqual("sample string", v.get())
+        self.assertEqual("varname", str(v))
+
+    def test___del__(self):
+        self.assertFalse(self.root.call("info", "exists", "varname"))
+        v = Variable(self.root, "sample string", "varname")
+        self.assertTrue(self.root.call("info", "exists", "varname"))
+        del v
+        self.assertFalse(self.root.call("info", "exists", "varname"))
+
+    def test_dont_unset_not_existing(self):
+        self.assertFalse(self.root.call("info", "exists", "varname"))
+        v1 = Variable(self.root, name="name")
+        v2 = Variable(self.root, name="name")
+        del v1
+        self.assertFalse(self.root.call("info", "exists", "name"))
+        # shouldn't raise exception
+        del v2
+        self.assertFalse(self.root.call("info", "exists", "name"))
+
+    def test___eq__(self):
+        # values doesn't matter, only class and name are checked
+        v1 = Variable(self.root, name="abc")
+        v2 = Variable(self.root, name="abc")
+        self.assertEqual(v1, v2)
+
+        v3 = Variable(self.root, name="abc")
+        v4 = StringVar(self.root, name="abc")
+        self.assertNotEqual(v3, v4)
+
+    def test_invalid_name(self):
+        with self.assertRaises(TypeError):
+            Variable(self.root, name=123)
+
+    def test_initialize(self):
+        v = Var()
+        self.assertFalse(v.side_effect)
+        v.set("value")
+        self.assertTrue(v.side_effect)
+
+
+class TestStringVar(TestBase):
+
+    def test_default(self):
+        v = StringVar(self.root)
+        self.assertEqual("", v.get())
+
+    def test_get(self):
+        v = StringVar(self.root, "abc", "name")
+        self.assertEqual("abc", v.get())
+        self.root.globalsetvar("name", True)
+        self.assertEqual("1", v.get())
+
+
+class TestIntVar(TestBase):
+
+    def test_default(self):
+        v = IntVar(self.root)
+        self.assertEqual(0, v.get())
+
+    def test_get(self):
+        v = IntVar(self.root, 123, "name")
+        self.assertEqual(123, v.get())
+        self.root.globalsetvar("name", "345")
+        self.assertEqual(345, v.get())
+
+    def test_invalid_value(self):
+        v = IntVar(self.root, name="name")
+        self.root.globalsetvar("name", "value")
+        with self.assertRaises(ValueError):
+            v.get()
+        self.root.globalsetvar("name", "345.0")
+        with self.assertRaises(ValueError):
+            v.get()
+
+
+class TestDoubleVar(TestBase):
+
+    def test_default(self):
+        v = DoubleVar(self.root)
+        self.assertEqual(0.0, v.get())
+
+    def test_get(self):
+        v = DoubleVar(self.root, 1.23, "name")
+        self.assertAlmostEqual(1.23, v.get())
+        self.root.globalsetvar("name", "3.45")
+        self.assertAlmostEqual(3.45, v.get())
+
+    def test_get_from_int(self):
+        v = DoubleVar(self.root, 1.23, "name")
+        self.assertAlmostEqual(1.23, v.get())
+        self.root.globalsetvar("name", "3.45")
+        self.assertAlmostEqual(3.45, v.get())
+        self.root.globalsetvar("name", "456")
+        self.assertAlmostEqual(456, v.get())
+
+    def test_invalid_value(self):
+        v = DoubleVar(self.root, name="name")
+        self.root.globalsetvar("name", "value")
+        with self.assertRaises(ValueError):
+            v.get()
+
+
+class TestBooleanVar(TestBase):
+
+    def test_default(self):
+        v = BooleanVar(self.root)
+        self.assertEqual(False, v.get())
+
+    def test_get(self):
+        v = BooleanVar(self.root, True, "name")
+        self.assertAlmostEqual(True, v.get())
+        self.root.globalsetvar("name", "0")
+        self.assertAlmostEqual(False, v.get())
+
+    def test_invalid_value_domain(self):
+        v = BooleanVar(self.root, name="name")
+        self.root.globalsetvar("name", "value")
+        with self.assertRaises(ValueError):
+            v.get()
+        self.root.globalsetvar("name", "1.0")
+        with self.assertRaises(ValueError):
+            v.get()
+
+
+tests_gui = (TestVariable, TestStringVar, TestIntVar,
+             TestDoubleVar, TestBooleanVar)
+
+
+if __name__ == "__main__":
+    from test.support import run_unittest
+    run_unittest(*tests_gui)
diff --git a/Lib/unittest/main.py b/Lib/unittest/main.py
--- a/Lib/unittest/main.py
+++ b/Lib/unittest/main.py
@@ -1,6 +1,7 @@
 """Unittest main program"""
 
 import sys
+import optparse
 import os
 
 from . import loader, runner
@@ -76,6 +77,7 @@
 def _convert_names(names):
     return [_convert_name(name) for name in names]
 
+
 class TestProgram(object):
     """A command-line program that runs a set of tests; this is primarily
        for making test modules conveniently executable.
@@ -142,33 +144,9 @@
             self._do_discovery(argv[2:])
             return
 
-        import getopt
-        long_opts = ['help', 'verbose', 'quiet', 'failfast', 'catch', 'buffer']
-        try:
-            options, args = getopt.getopt(argv[1:], 'hHvqfcb', long_opts)
-        except getopt.error as msg:
-            self.usageExit(msg)
-            return
-
-        for opt, value in options:
-            if opt in ('-h','-H','--help'):
-                self.usageExit()
-            if opt in ('-q','--quiet'):
-                self.verbosity = 0
-            if opt in ('-v','--verbose'):
-                self.verbosity = 2
-            if opt in ('-f','--failfast'):
-                if self.failfast is None:
-                    self.failfast = True
-                # Should this raise an exception if -f is not valid?
-            if opt in ('-c','--catch'):
-                if self.catchbreak is None:
-                    self.catchbreak = True
-                # Should this raise an exception if -c is not valid?
-            if opt in ('-b','--buffer'):
-                if self.buffer is None:
-                    self.buffer = True
-                # Should this raise an exception if -b is not valid?
+        parser = self._getOptParser()
+        options, args = parser.parse_args(argv[1:])
+        self._setAttributesFromOptions(options)
 
         if len(args) == 0 and self.module is None:
             # this allows "python -m unittest -v" to still work for
@@ -196,14 +174,14 @@
             self.test = self.testLoader.loadTestsFromNames(self.testNames,
                                                            self.module)
 
-    def _do_discovery(self, argv, Loader=loader.TestLoader):
-        # handle command line args for test discovery
-        self.progName = '%s discover' % self.progName
-        import optparse
+    def _getOptParser(self):
         parser = optparse.OptionParser()
         parser.prog = self.progName
         parser.add_option('-v', '--verbose', dest='verbose', default=False,
                           help='Verbose output', action='store_true')
+        parser.add_option('-q', '--quiet', dest='quiet', default=False,
+                          help='Quiet output', action='store_true')
+
         if self.failfast != False:
             parser.add_option('-f', '--failfast', dest='failfast', default=False,
                               help='Stop on first fail or error',
@@ -216,20 +194,9 @@
             parser.add_option('-b', '--buffer', dest='buffer', default=False,
                               help='Buffer stdout and stderr during tests',
                               action='store_true')
-        parser.add_option('-s', '--start-directory', dest='start', default='.',
-                          help="Directory to start discovery ('.' default)")
-        parser.add_option('-p', '--pattern', dest='pattern', default='test*.py',
-                          help="Pattern to match tests ('test*.py' default)")
-        parser.add_option('-t', '--top-level-directory', dest='top', default=None,
-                          help='Top level directory of project (defaults to start directory)')
+        return parser
 
-        options, args = parser.parse_args(argv)
-        if len(args) > 3:
-            self.usageExit()
-
-        for name, value in zip(('start', 'pattern', 'top'), args):
-            setattr(options, name, value)
-
+    def _setAttributesFromOptions(self, options):
         # only set options from the parsing here
         # if they weren't set explicitly in the constructor
         if self.failfast is None:
@@ -241,6 +208,31 @@
 
         if options.verbose:
             self.verbosity = 2
+        elif options.quiet:
+            self.verbosity = 0
+
+    def _addDiscoveryOptions(self, parser):
+        parser.add_option('-s', '--start-directory', dest='start', default='.',
+                          help="Directory to start discovery ('.' default)")
+        parser.add_option('-p', '--pattern', dest='pattern', default='test*.py',
+                          help="Pattern to match tests ('test*.py' default)")
+        parser.add_option('-t', '--top-level-directory', dest='top', default=None,
+                          help='Top level directory of project (defaults to start directory)')
+
+    def _do_discovery(self, argv, Loader=loader.TestLoader):
+        # handle command line args for test discovery
+        self.progName = '%s discover' % self.progName
+        parser = self._getOptParser()
+        self._addDiscoveryOptions(parser)
+
+        options, args = parser.parse_args(argv)
+        if len(args) > 3:
+            self.usageExit()
+
+        for name, value in zip(('start', 'pattern', 'top'), args):
+            setattr(options, name, value)
+
+        self._setAttributesFromOptions(options)
 
         start_dir = options.start
         pattern = options.pattern
diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py
--- a/Lib/unittest/test/test_program.py
+++ b/Lib/unittest/test/test_program.py
@@ -131,23 +131,6 @@
         FakeRunner.test = None
         FakeRunner.raiseError = False
 
-    def testHelpAndUnknown(self):
-        program = self.program
-        def usageExit(msg=None):
-            program.msg = msg
-            program.exit = True
-        program.usageExit = usageExit
-
-        for opt in '-h', '-H', '--help':
-            program.exit = False
-            program.parseArgs([None, opt])
-            self.assertTrue(program.exit)
-            self.assertIsNone(program.msg)
-
-        program.parseArgs([None, '-$'])
-        self.assertTrue(program.exit)
-        self.assertIsNotNone(program.msg)
-
     def testVerbosity(self):
         program = self.program
 
diff --git a/Misc/ACKS b/Misc/ACKS
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -602,6 +602,7 @@
 Alain Leufroy
 Mark Levinson
 William Lewis
+Akira Li
 Xuanji Li
 Robert van Liere
 Ross Light
@@ -686,6 +687,7 @@
 Dom Mitchell
 Dustin J. Mitchell
 Zubin Mithra
+Florian Mladitsch
 Doug Moen
 The Dragon De Monsyne
 Skip Montanaro
@@ -883,6 +885,7 @@
 Rich Salz
 Kevin Samborn
 Adrian Sampson
+James Sanders
 Ilya Sandler
 Mark Sapiro
 Ty Sarna
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@
 Core and Builtins
 -----------------
 
+- Give the ast.AST class a __dict__.
+
 - Issue #1469629: Allow cycles through an object's __dict__ slot to be
   collected. (For example if ``x.__dict__ is x``).
 
@@ -22,6 +24,15 @@
 Library
 -------
 
+- Issue #1178863: Separate initialisation from setting when initializing
+  Tkinter.Variables; harmonize exceptions to ValueError; only delete variables
+  that have not been deleted; assert that variable names are strings.
+
+- Issue #14104: Implement time.monotonic() on Mac OS X, patch written by
+  Nicholas Riley.
+
+- Issue #13394: the aifc module now uses warnings.warn() to signal warnings.
+
 - Issue #14252: Fix subprocess.Popen.terminate() to not raise an error under
   Windows when the child process has already exited.
 
@@ -49,6 +60,9 @@
 - Issue #14212: The re module didn't retain a reference to buffers it was
   scanning, resulting in segfaults.
 
+- Issue #14259: The finditer() method of re objects did not take any
+  keyword arguments, contrary to the documentation.
+
 
 What's New in Python 3.3.0 Alpha 1?
 ===================================
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -2812,6 +2812,24 @@
 }
 
 static int
+save_ellipsis(PicklerObject *self, PyObject *obj)
+{
+    PyObject *str = PyUnicode_FromString("Ellipsis");
+    if (str == NULL)
+        return -1;
+    return save_global(self, Py_Ellipsis, str);
+}
+
+static int
+save_notimplemented(PicklerObject *self, PyObject *obj)
+{
+    PyObject *str = PyUnicode_FromString("NotImplemented");
+    if (str == NULL)
+        return -1;
+    return save_global(self, Py_NotImplemented, str);
+}
+
+static int
 save_pers(PicklerObject *self, PyObject *obj, PyObject *func)
 {
     PyObject *pid = NULL;
@@ -3114,6 +3132,14 @@
         status = save_none(self, obj);
         goto done;
     }
+    else if (obj == Py_Ellipsis) {
+        status = save_ellipsis(self, obj);
+        goto done;
+    }
+    else if (obj == Py_NotImplemented) {
+        status = save_notimplemented(self, obj);
+        goto done;
+    }
     else if (obj == Py_False || obj == Py_True) {
         status = save_bool(self, obj);
         goto done;
diff --git a/Modules/_sre.c b/Modules/_sre.c
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -1596,7 +1596,7 @@
 
 /* see sre.h for object declarations */
 static PyObject*pattern_new_match(PatternObject*, SRE_STATE*, int);
-static PyObject*pattern_scanner(PatternObject*, PyObject*);
+static PyObject*pattern_scanner(PatternObject*, PyObject*, PyObject* kw);
 
 static int
 sre_literal_template(int charsize, char* ptr, Py_ssize_t len)
@@ -2132,13 +2132,13 @@
 
 #if PY_VERSION_HEX >= 0x02020000
 static PyObject*
-pattern_finditer(PatternObject* pattern, PyObject* args)
+pattern_finditer(PatternObject* pattern, PyObject* args, PyObject* kw)
 {
     PyObject* scanner;
     PyObject* search;
     PyObject* iterator;
 
-    scanner = pattern_scanner(pattern, args);
+    scanner = pattern_scanner(pattern, args, kw);
     if (!scanner)
         return NULL;
 
@@ -2576,10 +2576,10 @@
     {"findall", (PyCFunction) pattern_findall, METH_VARARGS|METH_KEYWORDS,
         pattern_findall_doc},
 #if PY_VERSION_HEX >= 0x02020000
-    {"finditer", (PyCFunction) pattern_finditer, METH_VARARGS,
+    {"finditer", (PyCFunction) pattern_finditer, METH_VARARGS|METH_KEYWORDS,
         pattern_finditer_doc},
 #endif
-    {"scanner", (PyCFunction) pattern_scanner, METH_VARARGS},
+    {"scanner", (PyCFunction) pattern_scanner, METH_VARARGS|METH_KEYWORDS},
     {"__copy__", (PyCFunction) pattern_copy, METH_NOARGS},
     {"__deepcopy__", (PyCFunction) pattern_deepcopy, METH_O},
     {NULL, NULL}
@@ -3822,7 +3822,7 @@
 };
 
 static PyObject*
-pattern_scanner(PatternObject* pattern, PyObject* args)
+pattern_scanner(PatternObject* pattern, PyObject* args, PyObject* kw)
 {
     /* create search state object */
 
@@ -3831,7 +3831,9 @@
     PyObject* string;
     Py_ssize_t start = 0;
     Py_ssize_t end = PY_SSIZE_T_MAX;
-    if (!PyArg_ParseTuple(args, "O|nn:scanner", &string, &start, &end))
+    static char* kwlist[] = { "source", "pos", "endpos", NULL };
+    if (!PyArg_ParseTupleAndKeywords(args, kw, "O|nn:scanner", kwlist,
+                                     &string, &start, &end))
         return NULL;
 
     /* create scanner object */
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -40,6 +40,10 @@
 #include <sys/time.h>
 #endif
 
+#if defined(__APPLE__)
+#include <mach/mach_time.h>
+#endif
+
 /* Forward declarations */
 static int floatsleep(double);
 static double floattime(void);
@@ -816,7 +820,8 @@
 calls is valid.");
 
 #if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) \
-    || (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC))
+    || (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)) \
+    || (defined(__APPLE__))
 #  define HAVE_PYTIME_MONOTONIC
 #endif
 
@@ -826,6 +831,17 @@
 {
 #if defined(MS_WINDOWS) && !defined(__BORLANDC__)
     return win32_clock(0);
+#elif defined(__APPLE__)
+    uint64_t time = mach_absolute_time();
+    double secs;
+
+    static mach_timebase_info_data_t timebase;
+    if (timebase.denom == 0)
+      mach_timebase_info(&timebase);
+
+    secs = (double)time * timebase.numer / timebase.denom * 1e-9;
+
+    return PyFloat_FromDouble(secs);
 #else
     static int clk_index = 0;
     clockid_t clk_ids[] = {
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py
--- a/Parser/asdl_c.py
+++ b/Parser/asdl_c.py
@@ -603,6 +603,11 @@
 
     def visitModule(self, mod):
         self.emit("""
+typedef struct {
+    PyObject_HEAD
+    PyObject *dict;
+} AST_object;
+
 static int
 ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
 {
@@ -681,10 +686,15 @@
     {NULL}
 };
 
+static PyGetSetDef ast_type_getsets[] = {
+    {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
+    {NULL}
+};
+
 static PyTypeObject AST_type = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     "_ast.AST",
-    sizeof(PyObject),
+    sizeof(AST_object),
     0,
     0,                       /* tp_dealloc */
     0,                       /* tp_print */
@@ -711,12 +721,12 @@
     0,                       /* tp_iternext */
     ast_type_methods,        /* tp_methods */
     0,                       /* tp_members */
-    0,                       /* tp_getset */
+    ast_type_getsets,        /* tp_getset */
     0,                       /* tp_base */
     0,                       /* tp_dict */
     0,                       /* tp_descr_get */
     0,                       /* tp_descr_set */
-    0,                       /* tp_dictoffset */
+    offsetof(AST_object, dict),/* tp_dictoffset */
     (initproc)ast_type_init, /* tp_init */
     PyType_GenericAlloc,     /* tp_alloc */
     PyType_GenericNew,       /* tp_new */
@@ -1185,6 +1195,8 @@
         p = os.path.join(SRC_DIR, str(mod.name) + "-ast.c")
         f = open(p, "w")
         f.write(auto_gen_msg)
+        f.write('#include <stddef.h>\n')
+        f.write('\n')
         f.write('#include "Python.h"\n')
         f.write('#include "%s-ast.h"\n' % mod.name)
         f.write('\n')
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
--- a/Python/Python-ast.c
+++ b/Python/Python-ast.c
@@ -1,5 +1,7 @@
 /* File automatically generated by Parser/asdl_c.py. */
 
+#include <stddef.h>
+
 #include "Python.h"
 #include "Python-ast.h"
 
@@ -453,6 +455,11 @@
 };
 
 
+typedef struct {
+    PyObject_HEAD
+    PyObject *dict;
+} AST_object;
+
 static int
 ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
 {
@@ -531,10 +538,15 @@
     {NULL}
 };
 
+static PyGetSetDef ast_type_getsets[] = {
+    {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
+    {NULL}
+};
+
 static PyTypeObject AST_type = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     "_ast.AST",
-    sizeof(PyObject),
+    sizeof(AST_object),
     0,
     0,                       /* tp_dealloc */
     0,                       /* tp_print */
@@ -561,12 +573,12 @@
     0,                       /* tp_iternext */
     ast_type_methods,        /* tp_methods */
     0,                       /* tp_members */
-    0,                       /* tp_getset */
+    ast_type_getsets,        /* tp_getset */
     0,                       /* tp_base */
     0,                       /* tp_dict */
     0,                       /* tp_descr_get */
     0,                       /* tp_descr_set */
-    0,                       /* tp_dictoffset */
+    offsetof(AST_object, dict),/* tp_dictoffset */
     (initproc)ast_type_init, /* tp_init */
     PyType_GenericAlloc,     /* tp_alloc */
     PyType_GenericNew,       /* tp_new */
diff --git a/Python/ast.c b/Python/ast.c
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -1153,7 +1153,7 @@
 }
 
 static arg_ty
-compiler_arg(struct compiling *c, const node *n)
+ast_for_arg(struct compiling *c, const node *n)
 {
     identifier name;
     expr_ty annotation = NULL;
@@ -1174,12 +1174,6 @@
     }
 
     return arg(name, annotation, c->c_arena);
-#if 0
-    result = Tuple(args, Store, LINENO(n), n->n_col_offset, c->c_arena);
-    if (!set_context(c, result, Store, n))
-        return NULL;
-    return result;
-#endif
 }
 
 /* returns -1 if failed to handle keyword only arguments
@@ -1367,7 +1361,7 @@
                              "non-default argument follows default argument");
                     return NULL;
                 }
-                arg = compiler_arg(c, ch);
+                arg = ast_for_arg(c, ch);
                 if (!arg)
                     return NULL;
                 asdl_seq_SET(posargs, k++, arg);

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list