From python-3000-checkins at python.org Tue Mar 6 20:16:22 2007 From: python-3000-checkins at python.org (georg.brandl) Date: Tue, 6 Mar 2007 20:16:22 +0100 (CET) Subject: [Python-3000-checkins] r54179 - python/branches/p3yk/Lib/test/string_tests.py python/branches/p3yk/Lib/test/test_bytes.py Message-ID: <20070306191622.23AC71E400D@bag.python.org> Author: georg.brandl Date: Tue Mar 6 20:16:20 2007 New Revision: 54179 Modified: python/branches/p3yk/Lib/test/string_tests.py python/branches/p3yk/Lib/test/test_bytes.py Log: Addendum of patch #1669633: additional tests for bytes methods. Modified: python/branches/p3yk/Lib/test/string_tests.py ============================================================================== --- python/branches/p3yk/Lib/test/string_tests.py (original) +++ python/branches/p3yk/Lib/test/string_tests.py Tue Mar 6 20:16:20 2007 @@ -18,10 +18,10 @@ def __init__(self): self.seq = ['a', 'b', 'c'] def __len__(self): return 8 -class CommonTest(unittest.TestCase): - # This testcase contains test that can be used in all - # stringlike classes. Currently this is str, unicode - # UserString and the string module. +class BaseTest(unittest.TestCase): + # These tests are for buffers of values (bytes) and not + # specific to character interpretation, used for bytes objects + # and various string implementations # The type to be tested # Change in subclasses to change the behaviour of fixtesttype() @@ -80,24 +80,6 @@ args = self.fixtype(args) getattr(object, methodname)(*args) - def test_hash(self): - # SF bug 1054139: += optimization was not invalidating cached hash value - a = self.type2test('DNSSEC') - b = self.type2test('') - for c in a: - b += c - hash(b) - self.assertEqual(hash(a), hash(b)) - - def test_capitalize(self): - self.checkequal(' hello ', ' hello ', 'capitalize') - self.checkequal('Hello ', 'Hello ','capitalize') - self.checkequal('Hello ', 'hello ','capitalize') - self.checkequal('Aaaa', 'aaaa', 'capitalize') - self.checkequal('Aaaa', 'AaAa', 'capitalize') - - self.checkraises(TypeError, 'hello', 'capitalize', 42) - def test_count(self): self.checkequal(3, 'aaa', 'count', 'a') self.checkequal(0, 'aaa', 'count', 'b') @@ -229,55 +211,7 @@ self.checkraises(TypeError, 'hello', 'rindex') self.checkraises(TypeError, 'hello', 'rindex', 42) - def test_lower(self): - self.checkequal('hello', 'HeLLo', 'lower') - self.checkequal('hello', 'hello', 'lower') - self.checkraises(TypeError, 'hello', 'lower', 42) - - def test_upper(self): - self.checkequal('HELLO', 'HeLLo', 'upper') - self.checkequal('HELLO', 'HELLO', 'upper') - self.checkraises(TypeError, 'hello', 'upper', 42) - - def test_expandtabs(self): - self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs') - self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs', 8) - self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs', 4) - self.checkequal('abc\r\nab def\ng hi', 'abc\r\nab\tdef\ng\thi', 'expandtabs', 4) - self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs') - self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs', 8) - self.checkequal('abc\r\nab\r\ndef\ng\r\nhi', 'abc\r\nab\r\ndef\ng\r\nhi', 'expandtabs', 4) - - self.checkraises(TypeError, 'hello', 'expandtabs', 42, 42) - def test_split(self): - self.checkequal(['this', 'is', 'the', 'split', 'function'], - 'this is the split function', 'split') - - # by whitespace - self.checkequal(['a', 'b', 'c', 'd'], 'a b c d ', 'split') - self.checkequal(['a', 'b c d'], 'a b c d', 'split', None, 1) - self.checkequal(['a', 'b', 'c d'], 'a b c d', 'split', None, 2) - self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None, 3) - self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None, 4) - self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None, - sys.maxint-1) - self.checkequal(['a b c d'], 'a b c d', 'split', None, 0) - self.checkequal(['a b c d'], ' a b c d', 'split', None, 0) - self.checkequal(['a', 'b', 'c d'], 'a b c d', 'split', None, 2) - - self.checkequal([], ' ', 'split') - self.checkequal(['a'], ' a ', 'split') - self.checkequal(['a', 'b'], ' a b ', 'split') - self.checkequal(['a', 'b '], ' a b ', 'split', None, 1) - self.checkequal(['a', 'b c '], ' a b c ', 'split', None, 1) - self.checkequal(['a', 'b', 'c '], ' a b c ', 'split', None, 2) - self.checkequal(['a', 'b'], '\n\ta \t\r b \v ', 'split') - aaa = ' a '*20 - self.checkequal(['a']*20, aaa, 'split') - self.checkequal(['a'] + [aaa[4:]], aaa, 'split', None, 1) - self.checkequal(['a']*19 + ['a '], aaa, 'split', None, 19) - # by a char self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|') self.checkequal(['a|b|c|d'], 'a|b|c|d', 'split', '|', 0) @@ -327,9 +261,6 @@ self.checkequal(['a']*18 + ['aBLAHa'], ('aBLAH'*20)[:-4], 'split', 'BLAH', 18) - # mixed use of str and unicode - self.checkequal([u'a', u'b', u'c d'], 'a b c d', 'split', u' ', 2) - # argument type self.checkraises(TypeError, 'hello', 'split', 42, 42, 42) @@ -338,36 +269,6 @@ self.checkraises(ValueError, 'hello', 'split', '', 0) def test_rsplit(self): - self.checkequal(['this', 'is', 'the', 'rsplit', 'function'], - 'this is the rsplit function', 'rsplit') - - # by whitespace - self.checkequal(['a', 'b', 'c', 'd'], 'a b c d ', 'rsplit') - self.checkequal(['a b c', 'd'], 'a b c d', 'rsplit', None, 1) - self.checkequal(['a b', 'c', 'd'], 'a b c d', 'rsplit', None, 2) - self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None, 3) - self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None, 4) - self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None, - sys.maxint-20) - self.checkequal(['a b c d'], 'a b c d', 'rsplit', None, 0) - self.checkequal(['a b c d'], 'a b c d ', 'rsplit', None, 0) - self.checkequal(['a b', 'c', 'd'], 'a b c d', 'rsplit', None, 2) - - self.checkequal([], ' ', 'rsplit') - self.checkequal(['a'], ' a ', 'rsplit') - self.checkequal(['a', 'b'], ' a b ', 'rsplit') - self.checkequal([' a', 'b'], ' a b ', 'rsplit', None, 1) - self.checkequal([' a b','c'], ' a b c ', 'rsplit', - None, 1) - self.checkequal([' a', 'b', 'c'], ' a b c ', 'rsplit', - None, 2) - self.checkequal(['a', 'b'], '\n\ta \t\r b \v ', 'rsplit', None, 88) - aaa = ' a '*20 - self.checkequal(['a']*20, aaa, 'rsplit') - self.checkequal([aaa[:-4]] + ['a'], aaa, 'rsplit', None, 1) - self.checkequal([' a a'] + ['a']*18, aaa, 'rsplit', None, 18) - - # by a char self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'rsplit', '|') self.checkequal(['a|b|c', 'd'], 'a|b|c|d', 'rsplit', '|', 1) @@ -417,9 +318,6 @@ self.checkequal(['aBLAHa'] + ['a']*18, ('aBLAH'*20)[:-4], 'rsplit', 'BLAH', 18) - # mixed use of str and unicode - self.checkequal([u'a b', u'c', u'd'], 'a b c d', 'rsplit', u' ', 2) - # argument type self.checkraises(TypeError, 'hello', 'rsplit', 42, 42, 42) @@ -427,68 +325,6 @@ self.checkraises(ValueError, 'hello', 'rsplit', '') self.checkraises(ValueError, 'hello', 'rsplit', '', 0) - def test_strip(self): - self.checkequal('hello', ' hello ', 'strip') - self.checkequal('hello ', ' hello ', 'lstrip') - self.checkequal(' hello', ' hello ', 'rstrip') - self.checkequal('hello', 'hello', 'strip') - - # strip/lstrip/rstrip with None arg - self.checkequal('hello', ' hello ', 'strip', None) - self.checkequal('hello ', ' hello ', 'lstrip', None) - self.checkequal(' hello', ' hello ', 'rstrip', None) - self.checkequal('hello', 'hello', 'strip', None) - - # strip/lstrip/rstrip with str arg - self.checkequal('hello', 'xyzzyhelloxyzzy', 'strip', 'xyz') - self.checkequal('helloxyzzy', 'xyzzyhelloxyzzy', 'lstrip', 'xyz') - self.checkequal('xyzzyhello', 'xyzzyhelloxyzzy', 'rstrip', 'xyz') - self.checkequal('hello', 'hello', 'strip', 'xyz') - - # strip/lstrip/rstrip with unicode arg - if test_support.have_unicode: - self.checkequal(unicode('hello', 'ascii'), 'xyzzyhelloxyzzy', - 'strip', unicode('xyz', 'ascii')) - self.checkequal(unicode('helloxyzzy', 'ascii'), 'xyzzyhelloxyzzy', - 'lstrip', unicode('xyz', 'ascii')) - self.checkequal(unicode('xyzzyhello', 'ascii'), 'xyzzyhelloxyzzy', - 'rstrip', unicode('xyz', 'ascii')) - self.checkequal(unicode('hello', 'ascii'), 'hello', - 'strip', unicode('xyz', 'ascii')) - - self.checkraises(TypeError, 'hello', 'strip', 42, 42) - self.checkraises(TypeError, 'hello', 'lstrip', 42, 42) - self.checkraises(TypeError, 'hello', 'rstrip', 42, 42) - - def test_ljust(self): - self.checkequal('abc ', 'abc', 'ljust', 10) - self.checkequal('abc ', 'abc', 'ljust', 6) - self.checkequal('abc', 'abc', 'ljust', 3) - self.checkequal('abc', 'abc', 'ljust', 2) - self.checkequal('abc*******', 'abc', 'ljust', 10, '*') - self.checkraises(TypeError, 'abc', 'ljust') - - def test_rjust(self): - self.checkequal(' abc', 'abc', 'rjust', 10) - self.checkequal(' abc', 'abc', 'rjust', 6) - self.checkequal('abc', 'abc', 'rjust', 3) - self.checkequal('abc', 'abc', 'rjust', 2) - self.checkequal('*******abc', 'abc', 'rjust', 10, '*') - self.checkraises(TypeError, 'abc', 'rjust') - - def test_center(self): - self.checkequal(' abc ', 'abc', 'center', 10) - self.checkequal(' abc ', 'abc', 'center', 6) - self.checkequal('abc', 'abc', 'center', 3) - self.checkequal('abc', 'abc', 'center', 2) - self.checkequal('***abc****', 'abc', 'center', 10, '*') - self.checkraises(TypeError, 'abc', 'center') - - def test_swapcase(self): - self.checkequal('hEllO CoMPuTErS', 'HeLLo cOmpUteRs', 'swapcase') - - self.checkraises(TypeError, 'hello', 'swapcase', 42) - def test_replace(self): EQ = self.checkequal @@ -678,6 +514,178 @@ self.checkraises(OverflowError, A2_16, "replace", "A", A2_16) self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16) + + +class CommonTest(BaseTest): + # This testcase contains test that can be used in all + # stringlike classes. Currently this is str, unicode + # UserString and the string module. + + def test_hash(self): + # SF bug 1054139: += optimization was not invalidating cached hash value + a = self.type2test('DNSSEC') + b = self.type2test('') + for c in a: + b += c + hash(b) + self.assertEqual(hash(a), hash(b)) + + def test_capitalize(self): + self.checkequal(' hello ', ' hello ', 'capitalize') + self.checkequal('Hello ', 'Hello ','capitalize') + self.checkequal('Hello ', 'hello ','capitalize') + self.checkequal('Aaaa', 'aaaa', 'capitalize') + self.checkequal('Aaaa', 'AaAa', 'capitalize') + + self.checkraises(TypeError, 'hello', 'capitalize', 42) + + def test_lower(self): + self.checkequal('hello', 'HeLLo', 'lower') + self.checkequal('hello', 'hello', 'lower') + self.checkraises(TypeError, 'hello', 'lower', 42) + + def test_upper(self): + self.checkequal('HELLO', 'HeLLo', 'upper') + self.checkequal('HELLO', 'HELLO', 'upper') + self.checkraises(TypeError, 'hello', 'upper', 42) + + def test_expandtabs(self): + self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs') + self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs', 8) + self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs', 4) + self.checkequal('abc\r\nab def\ng hi', 'abc\r\nab\tdef\ng\thi', 'expandtabs', 4) + self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs') + self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs', 8) + self.checkequal('abc\r\nab\r\ndef\ng\r\nhi', 'abc\r\nab\r\ndef\ng\r\nhi', 'expandtabs', 4) + + self.checkraises(TypeError, 'hello', 'expandtabs', 42, 42) + + def test_additional_split(self): + self.checkequal(['this', 'is', 'the', 'split', 'function'], + 'this is the split function', 'split') + + # by whitespace + self.checkequal(['a', 'b', 'c', 'd'], 'a b c d ', 'split') + self.checkequal(['a', 'b c d'], 'a b c d', 'split', None, 1) + self.checkequal(['a', 'b', 'c d'], 'a b c d', 'split', None, 2) + self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None, 3) + self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None, 4) + self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None, + sys.maxint-1) + self.checkequal(['a b c d'], 'a b c d', 'split', None, 0) + self.checkequal(['a b c d'], ' a b c d', 'split', None, 0) + self.checkequal(['a', 'b', 'c d'], 'a b c d', 'split', None, 2) + + self.checkequal([], ' ', 'split') + self.checkequal(['a'], ' a ', 'split') + self.checkequal(['a', 'b'], ' a b ', 'split') + self.checkequal(['a', 'b '], ' a b ', 'split', None, 1) + self.checkequal(['a', 'b c '], ' a b c ', 'split', None, 1) + self.checkequal(['a', 'b', 'c '], ' a b c ', 'split', None, 2) + self.checkequal(['a', 'b'], '\n\ta \t\r b \v ', 'split') + aaa = ' a '*20 + self.checkequal(['a']*20, aaa, 'split') + self.checkequal(['a'] + [aaa[4:]], aaa, 'split', None, 1) + self.checkequal(['a']*19 + ['a '], aaa, 'split', None, 19) + + # mixed use of str and unicode + self.checkequal([u'a', u'b', u'c d'], 'a b c d', 'split', u' ', 2) + + def test_additional_rsplit(self): + self.checkequal(['this', 'is', 'the', 'rsplit', 'function'], + 'this is the rsplit function', 'rsplit') + + # by whitespace + self.checkequal(['a', 'b', 'c', 'd'], 'a b c d ', 'rsplit') + self.checkequal(['a b c', 'd'], 'a b c d', 'rsplit', None, 1) + self.checkequal(['a b', 'c', 'd'], 'a b c d', 'rsplit', None, 2) + self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None, 3) + self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None, 4) + self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None, + sys.maxint-20) + self.checkequal(['a b c d'], 'a b c d', 'rsplit', None, 0) + self.checkequal(['a b c d'], 'a b c d ', 'rsplit', None, 0) + self.checkequal(['a b', 'c', 'd'], 'a b c d', 'rsplit', None, 2) + + self.checkequal([], ' ', 'rsplit') + self.checkequal(['a'], ' a ', 'rsplit') + self.checkequal(['a', 'b'], ' a b ', 'rsplit') + self.checkequal([' a', 'b'], ' a b ', 'rsplit', None, 1) + self.checkequal([' a b','c'], ' a b c ', 'rsplit', + None, 1) + self.checkequal([' a', 'b', 'c'], ' a b c ', 'rsplit', + None, 2) + self.checkequal(['a', 'b'], '\n\ta \t\r b \v ', 'rsplit', None, 88) + aaa = ' a '*20 + self.checkequal(['a']*20, aaa, 'rsplit') + self.checkequal([aaa[:-4]] + ['a'], aaa, 'rsplit', None, 1) + self.checkequal([' a a'] + ['a']*18, aaa, 'rsplit', None, 18) + + # mixed use of str and unicode + self.checkequal([u'a b', u'c', u'd'], 'a b c d', 'rsplit', u' ', 2) + + def test_strip(self): + self.checkequal('hello', ' hello ', 'strip') + self.checkequal('hello ', ' hello ', 'lstrip') + self.checkequal(' hello', ' hello ', 'rstrip') + self.checkequal('hello', 'hello', 'strip') + + # strip/lstrip/rstrip with None arg + self.checkequal('hello', ' hello ', 'strip', None) + self.checkequal('hello ', ' hello ', 'lstrip', None) + self.checkequal(' hello', ' hello ', 'rstrip', None) + self.checkequal('hello', 'hello', 'strip', None) + + # strip/lstrip/rstrip with str arg + self.checkequal('hello', 'xyzzyhelloxyzzy', 'strip', 'xyz') + self.checkequal('helloxyzzy', 'xyzzyhelloxyzzy', 'lstrip', 'xyz') + self.checkequal('xyzzyhello', 'xyzzyhelloxyzzy', 'rstrip', 'xyz') + self.checkequal('hello', 'hello', 'strip', 'xyz') + + # strip/lstrip/rstrip with unicode arg + if test_support.have_unicode: + self.checkequal(unicode('hello', 'ascii'), 'xyzzyhelloxyzzy', + 'strip', unicode('xyz', 'ascii')) + self.checkequal(unicode('helloxyzzy', 'ascii'), 'xyzzyhelloxyzzy', + 'lstrip', unicode('xyz', 'ascii')) + self.checkequal(unicode('xyzzyhello', 'ascii'), 'xyzzyhelloxyzzy', + 'rstrip', unicode('xyz', 'ascii')) + self.checkequal(unicode('hello', 'ascii'), 'hello', + 'strip', unicode('xyz', 'ascii')) + + self.checkraises(TypeError, 'hello', 'strip', 42, 42) + self.checkraises(TypeError, 'hello', 'lstrip', 42, 42) + self.checkraises(TypeError, 'hello', 'rstrip', 42, 42) + + def test_ljust(self): + self.checkequal('abc ', 'abc', 'ljust', 10) + self.checkequal('abc ', 'abc', 'ljust', 6) + self.checkequal('abc', 'abc', 'ljust', 3) + self.checkequal('abc', 'abc', 'ljust', 2) + self.checkequal('abc*******', 'abc', 'ljust', 10, '*') + self.checkraises(TypeError, 'abc', 'ljust') + + def test_rjust(self): + self.checkequal(' abc', 'abc', 'rjust', 10) + self.checkequal(' abc', 'abc', 'rjust', 6) + self.checkequal('abc', 'abc', 'rjust', 3) + self.checkequal('abc', 'abc', 'rjust', 2) + self.checkequal('*******abc', 'abc', 'rjust', 10, '*') + self.checkraises(TypeError, 'abc', 'rjust') + + def test_center(self): + self.checkequal(' abc ', 'abc', 'center', 10) + self.checkequal(' abc ', 'abc', 'center', 6) + self.checkequal('abc', 'abc', 'center', 3) + self.checkequal('abc', 'abc', 'center', 2) + self.checkequal('***abc****', 'abc', 'center', 10, '*') + self.checkraises(TypeError, 'abc', 'center') + + def test_swapcase(self): + self.checkequal('hEllO CoMPuTErS', 'HeLLo cOmpUteRs', 'swapcase') + + self.checkraises(TypeError, 'hello', 'swapcase', 42) + def test_zfill(self): self.checkequal('123', '123', 'zfill', 2) self.checkequal('123', '123', 'zfill', 3) Modified: python/branches/p3yk/Lib/test/test_bytes.py ============================================================================== --- python/branches/p3yk/Lib/test/test_bytes.py (original) +++ python/branches/p3yk/Lib/test/test_bytes.py Tue Mar 6 20:16:20 2007 @@ -6,6 +6,7 @@ import tempfile import unittest import test.test_support +import test.string_tests class BytesTest(unittest.TestCase): @@ -612,8 +613,38 @@ # are not appropriate for bytes +class BytesAsStringTest(test.string_tests.BaseTest): + type2test = bytes + + def checkequal(self, result, object, methodname, *args): + object = bytes(object) + realresult = getattr(bytes, methodname)(object, *args) + self.assertEqual( + self.fixtype(result), + realresult + ) + + def checkraises(self, exc, object, methodname, *args): + object = bytes(object) + self.assertRaises( + exc, + getattr(bytes, methodname), + object, + *args + ) + + # Currently the bytes containment testing uses a single integer + # value. This may not be the final design, but until then the + # bytes section with in a bytes containment not valid + def test_contains(self): + pass + def test_find(self): + pass + + def test_main(): test.test_support.run_unittest(BytesTest) + test.test_support.run_unittest(BytesAsStringTest) if __name__ == "__main__": From python-3000-checkins at python.org Wed Mar 7 02:00:18 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 7 Mar 2007 02:00:18 +0100 (CET) Subject: [Python-3000-checkins] r54190 - in python/branches/p3yk/Lib: io.py test/test_io.py Message-ID: <20070307010018.630221E4015@bag.python.org> Author: guido.van.rossum Date: Wed Mar 7 02:00:12 2007 New Revision: 54190 Modified: python/branches/p3yk/Lib/io.py python/branches/p3yk/Lib/test/test_io.py Log: New version from Mike Verdone (sat in my inbox since 2/27). I cleaned up whitespace but otherwise didn't change it. This will need work to reflect the tentative decision to drop nonblocking I/O support from the buffering layers. Modified: python/branches/p3yk/Lib/io.py ============================================================================== --- python/branches/p3yk/Lib/io.py (original) +++ python/branches/p3yk/Lib/io.py Wed Mar 7 02:00:12 2007 @@ -10,12 +10,21 @@ "Mike Verdone ") __all__ = ["open", "RawIOBase", "FileIO", "SocketIO", "BytesIO", - "BufferedReader", "BufferedWriter", "BufferedRWPair", "EOF"] + "BufferedReader", "BufferedWriter", "BufferedRWPair", + "BufferedRandom", "EOF"] import os DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes -EOF = b"" +DEFAULT_MAX_BUFFER_SIZE = 16 * 1024 # bytes +EOF = b'' + + +class BlockingIO(IOError): + def __init__(self, errno, strerror, characters_written): + IOError.__init__(self, errno, strerror) + self.characters_written = characters_written + def open(filename, mode="r", buffering=None, *, encoding=None): """Replacement for the built-in open function. @@ -117,6 +126,11 @@ # XXX Add individual method docstrings def read(self, n): + """Read and return up to n bytes. + + Returns an empty bytes array on EOF, or None if the object is + set not to block and has no data to read. + """ b = bytes(n.__index__()) self.readinto(b) return b @@ -125,6 +139,10 @@ raise IOError(".readinto() not supported") def write(self, b): + """Write the given buffer to the IO stream. + + Returns the number of bytes written. + """ raise IOError(".write() not supported") def seek(self, pos, whence=0): @@ -324,111 +342,210 @@ return True +class BufferedIOBase(RawIOBase): + + """Base class for buffered IO objects.""" + + def flush(self): + """Flush the buffer to the underlying raw IO object.""" + raise IOError(".flush() unsupported") + + class BufferedReader(BufferedIOBase): - """Buffered reader. + """Buffer for a readable sequential RawIO object. - Buffer for a readable sequential RawIO object. Does not allow - random access (seek, tell). + Does not allow random access (seek, tell). """ def __init__(self, raw): - """ - Create a new buffered reader using the given readable raw IO object. + """Create a new buffered reader using the given readable raw IO object. """ assert raw.readable() self.raw = raw - self._read_buf = b'' + self._read_buf = b"" if hasattr(raw, 'fileno'): self.fileno = raw.fileno def read(self, n=None): + """Read n bytes. + + Returns exactly n bytes of data unless the underlying raw IO + stream reaches EOF of if the call would block in non-blocking + mode. If n is None, read until EOF or until read() would + block. """ - Read n bytes. Returns exactly n bytes of data unless the underlying - raw IO stream reaches EOF of if the call would block in non-blocking - mode. If n is None, read until EOF or until read() would block. - """ + assert n is None or n > 0 nodata_val = EOF while (len(self._read_buf) < n) if (n is not None) else True: current = self.raw.read(n) if current in (EOF, None): nodata_val = current break - self._read_buf += current # XXX using += is bad - read = self._read_buf[:n] - if (not self._read_buf): - return nodata_val - self._read_buf = self._read_buf[n if n else 0:] - return read - - def write(self, b): - raise IOError(".write() unsupported") + self._read_buf += current + if self._read_buf: + if n is None: + n = len(self._read_buf) + out = self._read_buf[:n] + self._read_buf = self._read_buf[n:] + else: + out = nodata_val + return out def readable(self): return True + def fileno(self): + return self.raw.fileno() + def flush(self): # Flush is a no-op pass + def close(self): + self.raw.close() -class BufferedWriter(BufferedIOBase): - - """Buffered writer. - XXX More docs. - """ +class BufferedWriter(BufferedIOBase): - def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): - assert raw.writeable() + def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE, + max_buffer_size=DEFAULT_MAX_BUFFER_SIZE): + assert raw.writable() self.raw = raw self.buffer_size = buffer_size - self._write_buf_stack = [] - self._write_buf_size = 0 - if hasattr(raw, 'fileno'): - self.fileno = raw.fileno - - def read(self, n=None): - raise IOError(".read() not supported") + self.max_buffer_size = max_buffer_size + self._write_buf = b'' def write(self, b): + # XXX we can implement some more tricks to try and avoid partial writes assert issubclass(type(b), bytes) - self._write_buf_stack.append(b) - self._write_buf_size += len(b) - if (self._write_buf_size > self.buffer_size): - self.flush() + if len(self._write_buf) > self.buffer_size: + # We're full, so let's pre-flush the buffer + try: + self.flush() + except BlockingIO as e: + # We can't accept anything else. + raise BlockingIO(e.errno, e.strerror, 0) + self._write_buf += b + if (len(self._write_buf) > self.buffer_size): + try: + self.flush() + except BlockingIO as e: + if (len(self._write_buf) > self.max_buffer_size): + # We've hit max_buffer_size. We have to accept a partial + # write and cut back our buffer. + overage = len(self._write_buf) - self.max_buffer_size + self._write_buf = self._write_buf[:self.max_buffer_size] + raise BlockingIO(e.errno, e.strerror, overage) - def writeable(self): + def writable(self): return True def flush(self): - buf = b''.join(self._write_buf_stack) - while len(buf): - buf = buf[self.raw.write(buf):] - self._write_buf_stack = [] - self._write_buf_size = 0 + try: + while len(self._write_buf): + self._write_buf = self._write_buf[ + self.raw.write(self._write_buf):] + except BlockingIO as e: + self._write_buf[e.characters_written:] + raise + + def fileno(self): + return self.raw.fileno() + + def close(self): + self.raw.close() - # XXX support flushing buffer on close, del + def __del__(self): + # XXX flush buffers before dying. Is there a nicer way to do this? + if self._write_buf: + self.flush() class BufferedRWPair(BufferedReader, BufferedWriter): - """Buffered Read/Write Pair. + """A buffered reader and writer object together. A buffered reader object and buffered writer object put together to form a sequential IO object that can read and write. """ - def __init__(self, bufferedReader, bufferedWriter): - assert bufferedReader.readable() - assert bufferedWriter.writeable() - self.bufferedReader = bufferedReader - self.bufferedWriter = bufferedWriter - self.read = bufferedReader.read - self.write = bufferedWriter.write - self.flush = bufferedWriter.flush - self.readable = bufferedReader.readable - self.writeable = bufferedWriter.writeable + def __init__(self, reader, writer, buffer_size=DEFAULT_BUFFER_SIZE, + max_buffer_size=DEFAULT_MAX_BUFFER_SIZE): + assert reader.readable() + assert writer.writable() + BufferedReader.__init__(self, reader) + BufferedWriter.__init__(self, writer, buffer_size, max_buffer_size) + self.reader = reader + self.writer = writer + + def read(self, n=None): + return self.reader.read(n) + + def write(self, b): + return self.writer.write(b) + + def readable(self): + return self.reader.readable() + + def writable(self): + return self.writer.writable() + + def flush(self): + return self.writer.flush() def seekable(self): return False + + def fileno(self): + # XXX whose fileno do we return? Reader's? Writer's? Unsupported? + raise IOError(".fileno() unsupported") + + def close(self): + self.reader.close() + self.writer.close() + + +class BufferedRandom(BufferedReader, BufferedWriter): + + def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE, + max_buffer_size=DEFAULT_MAX_BUFFER_SIZE): + assert raw.seekable() + BufferedReader.__init__(self, raw) + BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size) + + def seekable(self): + return self.raw.seekable() + + def readable(self): + return self.raw.readable() + + def writable(self): + return self.raw.writable() + + def seek(self, pos, whence=0): + self.flush() + self._read_buf = b"" + self.raw.seek(pos, whence) + # XXX I suppose we could implement some magic here to move through the + # existing read buffer in the case of seek(, 1) + + def tell(self): + if (self._write_buf): + return self.raw.tell() + len(self._write_buf) + else: + return self.raw.tell() - len(self._read_buf) + + def read(self, n=None): + self.flush() + return BufferedReader.read(self, n) + + def write(self, b): + self._read_buf = b"" + return BufferedWriter.write(self, b) + + def flush(self): + BufferedWriter.flush(self) + + def close(self): + self.raw.close() Modified: python/branches/p3yk/Lib/test/test_io.py ============================================================================== --- python/branches/p3yk/Lib/test/test_io.py (original) +++ python/branches/p3yk/Lib/test/test_io.py Wed Mar 7 02:00:12 2007 @@ -5,10 +5,10 @@ import io - -class MockReadIO(io.RawIOBase): - def __init__(self, readStack): +class MockIO(io.RawIOBase): + def __init__(self, readStack=()): self._readStack = list(readStack) + self._writeStack = [] def read(self, n=None): try: @@ -16,27 +16,41 @@ except: return io.EOF + def write(self, b): + self._writeStack.append(b) + return len(b) + + def writable(self): + return True + def fileno(self): return 42 def readable(self): return True - -class MockWriteIO(io.RawIOBase): - def __init__(self): - self._writeStack = [] - - def write(self, b): - self._writeStack.append(b) - return len(b) - - def writeable(self): + def seekable(self): return True - def fileno(self): + def seek(self, pos, whence): + pass + + def tell(self): return 42 +class MockNonBlockWriterIO(io.RawIOBase): + def __init__(self, blockingScript): + self.bs = list(blockingScript) + self._write_stack = [] + def write(self, b): + self._write_stack.append(b) + n = self.bs.pop(0) + if (n < 0): + raise io.BlockingIO(0, "test blocking", -n) + else: + return n + def writable(self): + return True class IOTest(unittest.TestCase): @@ -90,9 +104,7 @@ f = io.BytesIO(data) self.read_ops(f) - class BytesIOTest(unittest.TestCase): - def testInit(self): buf = b"1234567890" bytesIo = io.BytesIO(buf) @@ -134,44 +146,51 @@ bytesIo.seek(10000) self.assertEquals(10000, bytesIo.tell()) - class BufferedReaderTest(unittest.TestCase): - def testRead(self): - rawIo = MockReadIO((b"abc", b"d", b"efg")) + rawIo = MockIO((b"abc", b"d", b"efg")) bufIo = io.BufferedReader(rawIo) self.assertEquals(b"abcdef", bufIo.read(6)) + def testReadNonBlocking(self): + # Inject some None's in there to simulate EWOULDBLOCK + rawIo = MockIO((b"abc", b"d", None, b"efg", None, None)) + bufIo = io.BufferedReader(rawIo) + + self.assertEquals(b"abcd", bufIo.read(6)) + self.assertEquals(b"e", bufIo.read(1)) + self.assertEquals(b"fg", bufIo.read()) + self.assert_(None is bufIo.read()) + self.assertEquals(io.EOF, bufIo.read()) + def testReadToEof(self): - rawIo = MockReadIO((b"abc", b"d", b"efg")) + rawIo = MockIO((b"abc", b"d", b"efg")) bufIo = io.BufferedReader(rawIo) self.assertEquals(b"abcdefg", bufIo.read(9000)) def testReadNoArgs(self): - rawIo = MockReadIO((b"abc", b"d", b"efg")) + rawIo = MockIO((b"abc", b"d", b"efg")) bufIo = io.BufferedReader(rawIo) self.assertEquals(b"abcdefg", bufIo.read()) def testFileno(self): - rawIo = MockReadIO((b"abc", b"d", b"efg")) + rawIo = MockIO((b"abc", b"d", b"efg")) bufIo = io.BufferedReader(rawIo) self.assertEquals(42, bufIo.fileno()) def testFilenoNoFileno(self): - # TODO will we always have fileno() function? If so, kill + # XXX will we always have fileno() function? If so, kill # this test. Else, write it. pass - class BufferedWriterTest(unittest.TestCase): - def testWrite(self): # Write to the buffered IO but don't overflow the buffer. - writer = MockWriteIO() + writer = MockIO() bufIo = io.BufferedWriter(writer, 8) bufIo.write(b"abc") @@ -179,7 +198,7 @@ self.assertFalse(writer._writeStack) def testWriteOverflow(self): - writer = MockWriteIO() + writer = MockIO() bufIo = io.BufferedWriter(writer, 8) bufIo.write(b"abc") @@ -187,8 +206,33 @@ self.assertEquals(b"abcdefghijkl", writer._writeStack[0]) + def testWriteNonBlocking(self): + raw = MockNonBlockWriterIO((9, 2, 22, -6, 10, 12, 12)) + bufIo = io.BufferedWriter(raw, 8, 16) + + bufIo.write(b"asdf") + bufIo.write(b"asdfa") + self.assertEquals(b"asdfasdfa", raw._write_stack[0]) + + bufIo.write(b"asdfasdfasdf") + self.assertEquals(b"asdfasdfasdf", raw._write_stack[1]) + bufIo.write(b"asdfasdfasdf") + self.assertEquals(b"dfasdfasdf", raw._write_stack[2]) + self.assertEquals(b"asdfasdfasdf", raw._write_stack[3]) + + bufIo.write(b"asdfasdfasdf") + + # XXX I don't like this test. It relies too heavily on how the algorithm + # actually works, which we might change. Refactor later. + + def testFileno(self): + rawIo = MockIO((b"abc", b"d", b"efg")) + bufIo = io.BufferedWriter(rawIo) + + self.assertEquals(42, bufIo.fileno()) + def testFlush(self): - writer = MockWriteIO() + writer = MockIO() bufIo = io.BufferedWriter(writer, 8) bufIo.write(b"abc") @@ -196,11 +240,51 @@ self.assertEquals(b"abc", writer._writeStack[0]) -# TODO. Tests for open() +class BufferedRWPairTest(unittest.TestCase): + def testRWPair(self): + r = MockIO(()) + w = MockIO() + pair = io.BufferedRWPair(r, w) + + # XXX need implementation + +class BufferedRandom(unittest.TestCase): + def testReadAndWrite(self): + raw = MockIO((b"asdf", b"ghjk")) + rw = io.BufferedRandom(raw, 8, 12) + + self.assertEqual(b"as", rw.read(2)) + rw.write(b"ddd") + rw.write(b"eee") + self.assertFalse(raw._writeStack) # Buffer writes + self.assertEqual(b"ghjk", rw.read()) # This read forces write flush + self.assertEquals(b"dddeee", raw._writeStack[0]) + + def testSeekAndTell(self): + raw = io.BytesIO(b"asdfghjkl") + rw = io.BufferedRandom(raw) + + self.assertEquals(b"as", rw.read(2)) + self.assertEquals(2, rw.tell()) + rw.seek(0, 0) + self.assertEquals(b"asdf", rw.read(4)) + + rw.write(b"asdf") + rw.seek(0, 0) + self.assertEquals(b"asdfasdfl", rw.read()) + self.assertEquals(9, rw.tell()) + rw.seek(-4, 2) + self.assertEquals(5, rw.tell()) + rw.seek(2, 1) + self.assertEquals(7, rw.tell()) + self.assertEquals(b"fl", rw.read(11)) + +# XXX Tests for open() def test_main(): test_support.run_unittest(IOTest, BytesIOTest, BufferedReaderTest, - BufferedWriterTest) + BufferedWriterTest, BufferedRWPairTest, + BufferedRandom) if __name__ == "__main__": test_main() From python-3000-checkins at python.org Wed Mar 7 06:23:26 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 7 Mar 2007 06:23:26 +0100 (CET) Subject: [Python-3000-checkins] r54194 - in python/branches/p3yk/Lib: io.py test/test_io.py Message-ID: <20070307052326.C01511E4003@bag.python.org> Author: guido.van.rossum Date: Wed Mar 7 06:23:25 2007 New Revision: 54194 Modified: python/branches/p3yk/Lib/io.py python/branches/p3yk/Lib/test/test_io.py Log: Change the specs for readinto() -- it should *not* shorten the buffer to the amount of data read. Modified: python/branches/p3yk/Lib/io.py ============================================================================== --- python/branches/p3yk/Lib/io.py (original) +++ python/branches/p3yk/Lib/io.py Wed Mar 7 06:23:25 2007 @@ -132,7 +132,8 @@ set not to block and has no data to read. """ b = bytes(n.__index__()) - self.readinto(b) + n = self.readinto(b) + del b[n:] return b def readinto(self, b): @@ -200,8 +201,10 @@ def readinto(self, b): # XXX We really should have os.readinto() - b[:] = os.read(self._fd, len(b)) - return len(b) + tmp = os.read(self._fd, len(b)) + n = len(tmp) + b[:n] = tmp + return n def write(self, b): return os.write(self._fd, b) @@ -303,7 +306,10 @@ return b def readinto(self, b): - b[:] = self.read(len(b)) + tmp = self.read(len(b)) + n = len(tmp) + b[:n] = tmp + return n def write(self, b): n = len(b) Modified: python/branches/p3yk/Lib/test/test_io.py ============================================================================== --- python/branches/p3yk/Lib/test/test_io.py (original) +++ python/branches/p3yk/Lib/test/test_io.py Wed Mar 7 06:23:25 2007 @@ -70,10 +70,13 @@ def read_ops(self, f): data = f.read(5) self.assertEqual(data, b"hello") - f.readinto(data) + n = f.readinto(data) + self.assertEqual(n, 5) self.assertEqual(data, b" worl") - f.readinto(data) - self.assertEqual(data, b"d\n") + n = f.readinto(data) + self.assertEqual(n, 2) + self.assertEqual(len(data), 5) + self.assertEqual(data[:2], b"d\n") f.seek(0) self.assertEqual(f.read(20), b"hello world\n") f.seek(-6, 2) From python-3000-checkins at python.org Wed Mar 7 23:59:41 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 7 Mar 2007 23:59:41 +0100 (CET) Subject: [Python-3000-checkins] r54213 - python/branches/p3yk/Lib/test/test_io.py Message-ID: <20070307225941.3F97D1E4002@bag.python.org> Author: guido.van.rossum Date: Wed Mar 7 23:59:39 2007 New Revision: 54213 Modified: python/branches/p3yk/Lib/test/test_io.py Log: Delete TESTFN after the test. Modified: python/branches/p3yk/Lib/test/test_io.py ============================================================================== --- python/branches/p3yk/Lib/test/test_io.py (original) +++ python/branches/p3yk/Lib/test/test_io.py Wed Mar 7 23:59:39 2007 @@ -54,6 +54,9 @@ class IOTest(unittest.TestCase): + def tearDown(self): + test_support.unlink(test_support.TESTFN) + def write_ops(self, f): f.write(b"blah.") f.seek(0) From python-3000-checkins at python.org Thu Mar 8 01:43:54 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Thu, 8 Mar 2007 01:43:54 +0100 (CET) Subject: [Python-3000-checkins] r54214 - in python/branches/p3yk: Lib/io.py Lib/test/test_fileio.py Lib/test/test_io.py Modules/_fileio.c setup.py Message-ID: <20070308004354.66CFB1E4004@bag.python.org> Author: guido.van.rossum Date: Thu Mar 8 01:43:48 2007 New Revision: 54214 Added: python/branches/p3yk/Lib/test/test_fileio.py (contents, props changed) python/branches/p3yk/Modules/_fileio.c (contents, props changed) Modified: python/branches/p3yk/Lib/io.py python/branches/p3yk/Lib/test/test_io.py python/branches/p3yk/setup.py Log: Check in Daniel Stutzbach's _fileio.c and test_fileio.py (see SF#1671314) with small tweaks. The io module now uses this instead of its own implementation of the FileIO class, if it can import _fileio. Modified: python/branches/p3yk/Lib/io.py ============================================================================== --- python/branches/p3yk/Lib/io.py (original) +++ python/branches/p3yk/Lib/io.py Thu Mar 8 01:43:48 2007 @@ -177,7 +177,7 @@ raise IOError(".fileno() not supported") -class FileIO(RawIOBase): +class _PyFileIO(RawIOBase): """Raw I/O implementation for OS files.""" @@ -243,6 +243,18 @@ return self._fd +try: + import _fileio +except ImportError: + # Let's use the Python version + FileIO = _PyFileIO +else: + # Create a trivial subclass with the proper inheritance structure + class FileIO(_fileio._FileIO, RawIOBase): + """Raw I/O implementation for OS files.""" + # XXX More docs + + class SocketIO(RawIOBase): """Raw I/O implementation for stream sockets.""" Added: python/branches/p3yk/Lib/test/test_fileio.py ============================================================================== --- (empty file) +++ python/branches/p3yk/Lib/test/test_fileio.py Thu Mar 8 01:43:48 2007 @@ -0,0 +1,227 @@ +/* Adapted from test_file.py by Daniel Stutzbach */ + +import sys +import os +import unittest +from array import array +from weakref import proxy + +from test.test_support import TESTFN, findfile, run_unittest +from UserList import UserList + +import _fileio + +class AutoFileTests(unittest.TestCase): + # file tests for which a test file is automatically set up + + def setUp(self): + self.f = _fileio._FileIO(TESTFN, 'w') + + def tearDown(self): + if self.f: + self.f.close() + os.remove(TESTFN) + + def testWeakRefs(self): + # verify weak references + p = proxy(self.f) + p.write(bytes(range(10))) + self.assertEquals(self.f.tell(), p.tell()) + self.f.close() + self.f = None + self.assertRaises(ReferenceError, getattr, p, 'tell') + + def testSeekTell(self): + self.f.write(bytes(range(20))) + self.assertEquals(self.f.tell(), 20) + self.f.seek(0) + self.assertEquals(self.f.tell(), 0) + self.f.seek(10) + self.assertEquals(self.f.tell(), 10) + self.f.seek(5, 1) + self.assertEquals(self.f.tell(), 15) + self.f.seek(-5, 1) + self.assertEquals(self.f.tell(), 10) + self.f.seek(-5, 2) + self.assertEquals(self.f.tell(), 15) + + def testAttributes(self): + # verify expected attributes exist + f = self.f + # XXX do we want these? + #f.name # merely shouldn't blow up + #f.mode # ditto + #f.closed # ditto + + # verify the others aren't + for attr in 'name', 'mode', 'closed': + self.assertRaises((AttributeError, TypeError), setattr, f, attr, 'oops') + + def testReadinto(self): + # verify readinto + self.f.write(bytes([1, 2])) + self.f.close() + a = array('b', 'x'*10) + self.f = _fileio._FileIO(TESTFN, 'r') + n = self.f.readinto(a) + self.assertEquals(array('b', [1, 2]), a[:n]) + + def testRepr(self): + # verify repr works + return # XXX doesn't work yet + self.assert_(repr(self.f).startswith(" + # "file.truncate fault on windows" + f = _fileio._FileIO(TESTFN, 'w') + f.write(bytes(range(11))) + f.close() + + f = _fileio._FileIO(TESTFN,'r+') + data = f.read(5) + if data != bytes(range(5)): + self.fail("Read on file opened for update failed %r" % data) + if f.tell() != 5: + self.fail("File pos after read wrong %d" % f.tell()) + + f.truncate() + if f.tell() != 5: + self.fail("File pos after ftruncate wrong %d" % f.tell()) + + f.close() + size = os.path.getsize(TESTFN) + if size != 5: + self.fail("File size after ftruncate wrong %d" % size) + + try: + bug801631() + finally: + os.unlink(TESTFN) + +def test_main(): + # Historically, these tests have been sloppy about removing TESTFN. + # So get rid of it no matter what. + try: + run_unittest(AutoFileTests, OtherFileTests) + finally: + if os.path.exists(TESTFN): + os.unlink(TESTFN) + +if __name__ == '__main__': + test_main() Modified: python/branches/p3yk/Lib/test/test_io.py ============================================================================== --- python/branches/p3yk/Lib/test/test_io.py (original) +++ python/branches/p3yk/Lib/test/test_io.py Thu Mar 8 01:43:48 2007 @@ -5,7 +5,9 @@ import io + class MockIO(io.RawIOBase): + def __init__(self, readStack=()): self._readStack = list(readStack) self._writeStack = [] @@ -38,10 +40,13 @@ def tell(self): return 42 + class MockNonBlockWriterIO(io.RawIOBase): + def __init__(self, blockingScript): self.bs = list(blockingScript) self._write_stack = [] + def write(self, b): self._write_stack.append(b) n = self.bs.pop(0) @@ -49,9 +54,11 @@ raise io.BlockingIO(0, "test blocking", -n) else: return n + def writable(self): return True + class IOTest(unittest.TestCase): def tearDown(self): @@ -110,7 +117,38 @@ f = io.BytesIO(data) self.read_ops(f) + def test_fileio_FileIO(self): + import _fileio + f = _fileio._FileIO(test_support.TESTFN, "w") + self.assertEqual(f.readable(), False) + self.assertEqual(f.writable(), True) + self.assertEqual(f.seekable(), True) + self.write_ops(f) + f.close() + f = _fileio._FileIO(test_support.TESTFN, "r") + self.assertEqual(f.readable(), True) + self.assertEqual(f.writable(), False) + self.assertEqual(f.seekable(), True) + self.read_ops(f) + f.close() + + def test_PyFileIO(self): + f = io._PyFileIO(test_support.TESTFN, "w") + self.assertEqual(f.readable(), False) + self.assertEqual(f.writable(), True) + self.assertEqual(f.seekable(), True) + self.write_ops(f) + f.close() + f = io._PyFileIO(test_support.TESTFN, "r") + self.assertEqual(f.readable(), True) + self.assertEqual(f.writable(), False) + self.assertEqual(f.seekable(), True) + self.read_ops(f) + f.close() + + class BytesIOTest(unittest.TestCase): + def testInit(self): buf = b"1234567890" bytesIo = io.BytesIO(buf) @@ -152,7 +190,9 @@ bytesIo.seek(10000) self.assertEquals(10000, bytesIo.tell()) + class BufferedReaderTest(unittest.TestCase): + def testRead(self): rawIo = MockIO((b"abc", b"d", b"efg")) bufIo = io.BufferedReader(rawIo) @@ -193,7 +233,9 @@ # this test. Else, write it. pass + class BufferedWriterTest(unittest.TestCase): + def testWrite(self): # Write to the buffered IO but don't overflow the buffer. writer = MockIO() @@ -246,7 +288,9 @@ self.assertEquals(b"abc", writer._writeStack[0]) + class BufferedRWPairTest(unittest.TestCase): + def testRWPair(self): r = MockIO(()) w = MockIO() @@ -254,7 +298,9 @@ # XXX need implementation + class BufferedRandom(unittest.TestCase): + def testReadAndWrite(self): raw = MockIO((b"asdf", b"ghjk")) rw = io.BufferedRandom(raw, 8, 12) Added: python/branches/p3yk/Modules/_fileio.c ============================================================================== --- (empty file) +++ python/branches/p3yk/Modules/_fileio.c Thu Mar 8 01:43:48 2007 @@ -0,0 +1,713 @@ +/* Author: Daniel Stutzbach */ + +#define PY_SSIZE_T_CLEAN +#include "Python.h" +#include +#include +#include +#include /* For offsetof */ + +/* + * Known likely problems: + * + * - Files larger then 2**32-1 + * - Files with unicode filenames + * - Passing numbers greater than 2**32-1 when an integer is expected + * - Making it work on Windows and other oddball platforms + * + * To Do: + * + * - autoconfify header file inclusion + * - Make the ABC RawIO type and inherit from it. + * + * Unanswered questions: + * + * - Add mode, name, and closed properties a la Python 2 file objects? + * - Do we need a (*close)() in the struct like Python 2 file objects, + * for not-quite-ordinary-file objects? + */ + +#ifdef MS_WINDOWS +/* can simulate truncate with Win32 API functions; see file_truncate */ +#define HAVE_FTRUNCATE +#define WIN32_LEAN_AND_MEAN +#include +#endif + +typedef struct { + PyObject_HEAD + int fd; + int own_fd; /* 1 means we should close fd */ + int readable; + int writable; + int seekable; /* -1 means unknown */ + PyObject *weakreflist; +} PyFileIOObject; + +#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type)) + +/* Note: if this function is changed so that it can return a true value, + * then we need a separate function for __exit__ + */ +static PyObject * +fileio_close(PyFileIOObject *self) +{ + if (self->fd >= 0) { + Py_BEGIN_ALLOW_THREADS + errno = 0; + close(self->fd); + Py_END_ALLOW_THREADS + if (errno < 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + self->fd = -1; + } + + Py_RETURN_NONE; +} + +static PyObject * +fileio_new(PyTypeObject *type, PyObject *args, PyObject *kews) +{ + PyFileIOObject *self; + + assert(type != NULL && type->tp_alloc != NULL); + + self = (PyFileIOObject *) type->tp_alloc(type, 0); + if (self != NULL) { + self->fd = -1; + self->weakreflist = NULL; + self->own_fd = 1; + self->seekable = -1; + } + + return (PyObject *) self; +} + +/* On Unix, open will succeed for directories. + In Python, there should be no file objects referring to + directories, so we need a check. */ + +static int +dircheck(PyFileIOObject* self) +{ +#if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR) + struct stat buf; + if (self->fd < 0) + return 0; + if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) { +#ifdef HAVE_STRERROR + char *msg = strerror(EISDIR); +#else + char *msg = "Is a directory"; +#endif + PyObject *exc; + PyObject *closeresult = fileio_close(self); + Py_DECREF(closeresult); + + exc = PyObject_CallFunction(PyExc_IOError, "(is)", + EISDIR, msg); + PyErr_SetObject(PyExc_IOError, exc); + Py_XDECREF(exc); + return -1; + } +#endif + return 0; +} + + +static int +fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) +{ + PyFileIOObject *self = (PyFileIOObject *) oself; + static char *kwlist[] = {"filename", "mode", NULL}; + char *name = NULL; + char *mode = "r"; + char *s; + int wideargument = 0; + int ret = 0; + int rwa = 0, plus = 0, append = 0; + int flags = 0; + + assert(PyFileIO_Check(oself)); + if (self->fd >= 0) + { + /* Have to close the existing file first. */ + PyObject *closeresult = fileio_close(self); + if (closeresult == NULL) + return -1; + Py_DECREF(closeresult); + } + +#ifdef Py_WIN_WIDE_FILENAMES + if (GetVersion() < 0x80000000) { /* On NT, so wide API available */ + PyObject *po; + if (PyArg_ParseTupleAndKeywords(args, kwds, "U|s:fileio", + kwlist, &po, &mode)) { + wideargument = 1; + } else { + /* Drop the argument parsing error as narrow + strings are also valid. */ + PyErr_Clear(); + } + + PyErr_SetString(PyExc_NotImplementedError, + "Windows wide filenames are not yet supported"); + goto error; + } +#endif + + if (!wideargument) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|s:fileio", + kwlist, + Py_FileSystemDefaultEncoding, + &name, &mode)) + goto error; + } + + self->readable = self->writable = 0; + s = mode; + while (*s) { + switch (*s++) { + case 'r': + if (rwa) { + bad_mode: + PyErr_SetString(PyExc_ValueError, + "Must have exactly one of read/write/append mode"); + goto error; + } + rwa = 1; + self->readable = 1; + break; + case 'w': + if (rwa) + goto bad_mode; + rwa = 1; + self->writable = 1; + flags |= O_CREAT | O_TRUNC; + break; + case 'a': + if (rwa) + goto bad_mode; + rwa = 1; + self->writable = 1; + flags |= O_CREAT; + append = 1; + break; + case '+': + if (plus) + goto bad_mode; + self->readable = self->writable = 1; + plus = 1; + break; + default: + PyErr_Format(PyExc_ValueError, + "invalid mode: %.200s", mode); + goto error; + } + } + + if (!rwa) + goto bad_mode; + + if (self->readable && self->writable) + flags |= O_RDWR; + else if (self->readable) + flags |= O_RDONLY; + else + flags |= O_WRONLY; + +#ifdef O_BINARY + flags |= O_BINARY; +#endif + + Py_BEGIN_ALLOW_THREADS + errno = 0; + self->fd = open(name, flags, 0666); + Py_END_ALLOW_THREADS + if (self->fd < 0 || dircheck(self) < 0) { + PyErr_SetFromErrnoWithFilename(PyExc_IOError, name); + goto error; + } + + goto done; + + error: + ret = -1; + + done: + PyMem_Free(name); + return ret; +} + +static void +fileio_dealloc(PyFileIOObject *self) +{ + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) self); + + if (self->fd >= 0 && self->own_fd) { + PyObject *closeresult = fileio_close(self); + if (closeresult == NULL) { +#ifdef HAVE_STRERROR + PySys_WriteStderr("close failed: [Errno %d] %s\n", errno, strerror(errno)); +#else + PySys_WriteStderr("close failed: [Errno %d]\n", errno); +#endif + } else + Py_DECREF(closeresult); + } + + self->ob_type->tp_free((PyObject *)self); +} + +static PyObject * +err_closed(void) +{ + PyErr_SetString(PyExc_ValueError, "I/O operation on closed file"); + return NULL; +} + +static PyObject * +fileio_fileno(PyFileIOObject *self) +{ + if (self->fd < 0) + return err_closed(); + return PyInt_FromLong((long) self->fd); +} + +static PyObject * +fileio_readable(PyFileIOObject *self) +{ + if (self->fd < 0) + return err_closed(); + return PyInt_FromLong((long) self->readable); +} + +static PyObject * +fileio_writable(PyFileIOObject *self) +{ + if (self->fd < 0) + return err_closed(); + return PyInt_FromLong((long) self->writable); +} + +static PyObject * +fileio_seekable(PyFileIOObject *self) +{ + if (self->fd < 0) + return err_closed(); + if (self->seekable < 0) { + int ret; + Py_BEGIN_ALLOW_THREADS + ret = lseek(self->fd, 0, SEEK_CUR); + Py_END_ALLOW_THREADS + if (ret < 0) + self->seekable = 0; + else + self->seekable = 1; + } + return PyInt_FromLong((long) self->seekable); +} + +static PyObject * +fileio_readinto(PyFileIOObject *self, PyObject *args) +{ + char *ptr; + Py_ssize_t n; + + if (self->fd < 0) + return err_closed(); + if (!PyArg_ParseTuple(args, "w#", &ptr, &n)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + errno = 0; + n = read(self->fd, ptr, n); + Py_END_ALLOW_THREADS + if (n < 0) { + if (errno == EAGAIN) + Py_RETURN_NONE; + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + + return PyInt_FromLong(n); +} + +static PyObject * +fileio_read(PyFileIOObject *self, PyObject *args) +{ + char *ptr; + Py_ssize_t n, size; + PyObject *bytes; + + if (self->fd < 0) + return err_closed(); + + if (!PyArg_ParseTuple(args, "i", &size)) + return NULL; + + bytes = PyBytes_FromStringAndSize(NULL, size); + if (bytes == NULL) + return NULL; + ptr = PyBytes_AsString(bytes); + + Py_BEGIN_ALLOW_THREADS + errno = 0; + n = read(self->fd, ptr, size); + Py_END_ALLOW_THREADS + + if (n < 0) { + if (errno == EAGAIN) + Py_RETURN_NONE; + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + + if (n != size) { + if (PyBytes_Resize(bytes, n) < 0) { + Py_DECREF(bytes); + return NULL; + } + } + + return (PyObject *) bytes; +} + +static PyObject * +fileio_write(PyFileIOObject *self, PyObject *args) +{ + Py_ssize_t n; + char *ptr; + + if (self->fd < 0) + return err_closed(); + if (!PyArg_ParseTuple(args, "s#", &ptr, &n)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + errno = 0; + n = write(self->fd, ptr, n); + Py_END_ALLOW_THREADS + + if (n < 0) { + if (errno == EAGAIN) + Py_RETURN_NONE; + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + + return PyInt_FromLong(n); +} + +static PyObject * +fileio_seek(PyFileIOObject *self, PyObject *args) +{ + Py_ssize_t offset; + Py_ssize_t whence = 0; + + if (self->fd < 0) + return err_closed(); + + if (!PyArg_ParseTuple(args, "i|i", &offset, &whence)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + errno = 0; + offset = lseek(self->fd, offset, whence); + Py_END_ALLOW_THREADS + + if (offset < 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + + Py_RETURN_NONE; +} + +static PyObject * +fileio_tell(PyFileIOObject *self, PyObject *args) +{ + Py_ssize_t offset; + + if (self->fd < 0) + return err_closed(); + + Py_BEGIN_ALLOW_THREADS + errno = 0; + offset = lseek(self->fd, 0, SEEK_CUR); + Py_END_ALLOW_THREADS + + if (offset < 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + + return PyInt_FromLong(offset); +} + +#ifdef HAVE_FTRUNCATE +static PyObject * +fileio_truncate(PyFileIOObject *self, PyObject *args) +{ + Py_ssize_t length; + int ret; + + if (self->fd < 0) + return err_closed(); + + /* Setup default value */ + Py_BEGIN_ALLOW_THREADS + errno = 0; + length = lseek(self->fd, 0, SEEK_CUR); + Py_END_ALLOW_THREADS + + if (length < 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + + if (!PyArg_ParseTuple(args, "|i", &length)) + return NULL; + +#ifdef MS_WINDOWS + /* MS _chsize doesn't work if newsize doesn't fit in 32 bits, + so don't even try using it. */ + { + HANDLE hFile; + Py_ssize_t initialpos; + + /* Have to move current pos to desired endpoint on Windows. */ + Py_BEGIN_ALLOW_THREADS + errno = 0; + ret = _portable_fseek(f->f_fp, newsize, SEEK_SET) != 0; + Py_END_ALLOW_THREADS + if (ret) + goto onioerror; + + /* Truncate. Note that this may grow the file! */ + Py_BEGIN_ALLOW_THREADS + errno = 0; + hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp)); + ret = hFile == (HANDLE)-1; + if (ret == 0) { + ret = SetEndOfFile(hFile) == 0; + if (ret) + errno = EACCES; + } + Py_END_ALLOW_THREADS + if (ret) + goto onioerror; + } +#else + Py_BEGIN_ALLOW_THREADS + errno = 0; + ret = ftruncate(self->fd, length); + Py_END_ALLOW_THREADS +#endif /* !MS_WINDOWS */ + + if (ret < 0) { + onioerror: + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + + /* Return to initial position */ + Py_BEGIN_ALLOW_THREADS + errno = 0; + ret = lseek(self->fd, length, SEEK_SET); + Py_END_ALLOW_THREADS + if (ret < 0) + goto onioerror; + + Py_RETURN_NONE; +} +#endif + +static PyObject * +fileio_repr(PyFileIOObject *self) +{ + PyObject *ret = NULL; + + ret = PyString_FromFormat("<%s file at %p>", + self->fd < 0 ? "closed" : "open", + self); + return ret; +} + +static PyObject * +fileio_isatty(PyFileIOObject *self) +{ + long res; + + if (self->fd < 0) + return err_closed(); + Py_BEGIN_ALLOW_THREADS + res = isatty(self->fd); + Py_END_ALLOW_THREADS + return PyBool_FromLong(res); +} + +static PyObject * +fileio_self(PyFileIOObject *self) +{ + if (self->fd < 0) + return err_closed(); + Py_INCREF(self); + return (PyObject *)self; +} + +PyDoc_STRVAR(fileio_doc, +"file(name: str[, mode: str]) -> file IO object\n" +"\n" +"Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n" +"writing or appending. The file will be created if it doesn't exist\n" +"when opened for writing or appending; it will be truncated when\n" +"opened for writing. Add a '+' to the mode to allow simultaneous\n" +"reading and writing."); + +PyDoc_STRVAR(read_doc, +"read(size: int) -> bytes. read at most size bytes, returned as bytes.\n" +"\n" +"Only makes one system call, so less data may be returned than requested\n" +"In non-blocking mode, returns None if no data is available. On\n" +"end-of-file, returns 0."); + +PyDoc_STRVAR(write_doc, +"write(b: bytes) -> int. Write bytes b to file, return number written.\n" +"\n" +"Only makes one system call, so not all of the data may be written.\n" +"The number of bytes actually written is returned."); + +PyDoc_STRVAR(fileno_doc, +"fileno() -> int. \"file descriptor\".\n" +"\n" +"This is needed for lower-level file interfaces, such the fcntl module."); + +PyDoc_STRVAR(seek_doc, +"seek(offset: int[, whence: int]) -> None. Move to new file position.\n" +"\n" +"Argument offset is a byte count. Optional argument whence defaults to\n" +"0 (offset from start of file, offset should be >= 0); other values are 1\n" +"(move relative to current position, positive or negative), and 2 (move\n" +"relative to end of file, usually negative, although many platforms allow\n" +"seeking beyond the end of a file)." +"\n" +"Note that not all file objects are seekable."); + +PyDoc_STRVAR(truncate_doc, +"truncate([size: int]) -> None. Truncate the file to at most size bytes.\n" +"\n" +"Size defaults to the current file position, as returned by tell()."); + +PyDoc_STRVAR(tell_doc, +"tell() -> int. Current file position"); + +PyDoc_STRVAR(readinto_doc, +"readinto() -> Undocumented. Don't use this; it may go away."); + +PyDoc_STRVAR(close_doc, +"close() -> None. Close the file.\n" +"\n" +"A closed file cannot be used for further I/O operations. close() may be\n" +"called more than once without error. Changes the fileno to -1."); + +PyDoc_STRVAR(isatty_doc, +"isatty() -> bool. True if the file is connected to a tty device."); + +PyDoc_STRVAR(enter_doc, +"__enter__() -> self."); + +PyDoc_STRVAR(exit_doc, +"__exit__(*excinfo) -> None. Closes the file."); + +PyDoc_STRVAR(seekable_doc, +"seekable() -> bool. True if file supports random-access."); + +PyDoc_STRVAR(readable_doc, +"readable() -> bool. True if file was opened in a read mode."); + +PyDoc_STRVAR(writable_doc, +"writable() -> bool. True if file was opened in a write mode."); + +static PyMethodDef fileio_methods[] = { + {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc}, + {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc}, + {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc}, + {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc}, + {"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc}, + {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc}, + {"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc}, + {"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc}, + {"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc}, + {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc}, + {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc}, + {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc}, + {"__enter__",(PyCFunction)fileio_self, METH_NOARGS, enter_doc}, + {"__exit__", (PyCFunction)fileio_close, METH_VARARGS, exit_doc}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject PyFileIO_Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "FileIO", + sizeof(PyFileIOObject), + 0, + (destructor)fileio_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)fileio_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + fileio_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + offsetof(PyFileIOObject, weakreflist), /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + fileio_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + fileio_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + fileio_new, /* tp_new */ + PyObject_Del, /* tp_free */ +}; + +static PyMethodDef module_methods[] = { + {NULL, NULL} +}; + +PyMODINIT_FUNC +init_fileio(void) +{ + PyObject *m; /* a module object */ + + m = Py_InitModule3("_fileio", module_methods, + "Fast implementation of io.FileIO."); + if (m == NULL) + return; + if (PyType_Ready(&PyFileIO_Type) < 0) + return; + Py_INCREF(&PyFileIO_Type); + PyModule_AddObject(m, "_FileIO", (PyObject *) &PyFileIO_Type); +} Modified: python/branches/p3yk/setup.py ============================================================================== --- python/branches/p3yk/setup.py (original) +++ python/branches/p3yk/setup.py Thu Mar 8 01:43:48 2007 @@ -1037,6 +1037,9 @@ # Thomas Heller's _ctypes module self.detect_ctypes(inc_dirs, lib_dirs) + # _fileio -- supposedly cross platform + exts.append(Extension('_fileio', ['_fileio.c'])) + # Platform-specific libraries if platform == 'linux2': # Linux-specific modules From python-3000-checkins at python.org Thu Mar 8 02:02:05 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Thu, 8 Mar 2007 02:02:05 +0100 (CET) Subject: [Python-3000-checkins] r54215 - python/branches/p3yk/Lib/test/test_fileio.py Message-ID: <20070308010205.9C1E21E4002@bag.python.org> Author: guido.van.rossum Date: Thu Mar 8 02:02:00 2007 New Revision: 54215 Modified: python/branches/p3yk/Lib/test/test_fileio.py Log: Fix embarrassing syntax mix. Modified: python/branches/p3yk/Lib/test/test_fileio.py ============================================================================== --- python/branches/p3yk/Lib/test/test_fileio.py (original) +++ python/branches/p3yk/Lib/test/test_fileio.py Thu Mar 8 02:02:00 2007 @@ -1,4 +1,4 @@ -/* Adapted from test_file.py by Daniel Stutzbach */ +# Adapted from test_file.py by Daniel Stutzbach import sys import os From python-3000-checkins at python.org Thu Mar 8 02:17:52 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Thu, 8 Mar 2007 02:17:52 +0100 (CET) Subject: [Python-3000-checkins] r54216 - python/branches/p3yk/Lib/test/test_anydbm.py Message-ID: <20070308011752.EC87D1E4002@bag.python.org> Author: guido.van.rossum Date: Thu Mar 8 02:17:51 2007 New Revision: 54216 Modified: python/branches/p3yk/Lib/test/test_anydbm.py Log: Fix another unittest that broke due to dict views (more precisely, due to the cowboy way they are currently hacked in). Modified: python/branches/p3yk/Lib/test/test_anydbm.py ============================================================================== --- python/branches/p3yk/Lib/test/test_anydbm.py (original) +++ python/branches/p3yk/Lib/test/test_anydbm.py Thu Mar 8 02:17:51 2007 @@ -35,7 +35,7 @@ def test_anydbm_creation(self): f = anydbm.open(_fname, 'c') - self.assertEqual(f.keys(), []) + self.assertEqual(list(f.keys()), []) for key in self._dict: f[key] = self._dict[key] self.read_helper(f) From python-3000-checkins at python.org Thu Mar 8 20:54:45 2007 From: python-3000-checkins at python.org (collin.winter) Date: Thu, 8 Mar 2007 20:54:45 +0100 (CET) Subject: [Python-3000-checkins] r54226 - python/branches/p3yk/Lib/test/regrtest.py Message-ID: <20070308195445.651161E4002@bag.python.org> Author: collin.winter Date: Thu Mar 8 20:54:43 2007 New Revision: 54226 Modified: python/branches/p3yk/Lib/test/regrtest.py Log: Move test_unittest, test_doctest and test_doctest2 higher up in the test order Modified: python/branches/p3yk/Lib/test/regrtest.py ============================================================================== --- python/branches/p3yk/Lib/test/regrtest.py (original) +++ python/branches/p3yk/Lib/test/regrtest.py Thu Mar 8 20:54:43 2007 @@ -478,6 +478,9 @@ 'test_builtin', 'test_exceptions', 'test_types', + 'test_unittest', + 'test_doctest', + 'test_doctest2', ] NOTTESTS = [ From python-3000-checkins at python.org Thu Mar 8 22:46:18 2007 From: python-3000-checkins at python.org (collin.winter) Date: Thu, 8 Mar 2007 22:46:18 +0100 (CET) Subject: [Python-3000-checkins] r54231 - python/branches/p3yk/Modules/_fileio.c Message-ID: <20070308214618.D19511E4004@bag.python.org> Author: collin.winter Date: Thu Mar 8 22:46:15 2007 New Revision: 54231 Modified: python/branches/p3yk/Modules/_fileio.c Log: Add a missing forward declaration for PyFileIO_Type. The _fileio module now compiles with --with-pydebug. Modified: python/branches/p3yk/Modules/_fileio.c ============================================================================== --- python/branches/p3yk/Modules/_fileio.c (original) +++ python/branches/p3yk/Modules/_fileio.c Thu Mar 8 22:46:15 2007 @@ -44,6 +44,8 @@ PyObject *weakreflist; } PyFileIOObject; +PyTypeObject PyFileIO_Type; + #define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type)) /* Note: if this function is changed so that it can return a true value, From guido at python.org Fri Mar 9 00:55:54 2007 From: guido at python.org (Guido van Rossum) Date: Thu, 8 Mar 2007 15:55:54 -0800 Subject: [Python-3000-checkins] r54226 - python/branches/p3yk/Lib/test/regrtest.py In-Reply-To: <20070308195445.651161E4002@bag.python.org> References: <20070308195445.651161E4002@bag.python.org> Message-ID: I've missed something perhaps -- why is this? On 3/8/07, collin.winter wrote: > Author: collin.winter > Date: Thu Mar 8 20:54:43 2007 > New Revision: 54226 > > Modified: > python/branches/p3yk/Lib/test/regrtest.py > Log: > Move test_unittest, test_doctest and test_doctest2 higher up in the test order > > Modified: python/branches/p3yk/Lib/test/regrtest.py > ============================================================================== > --- python/branches/p3yk/Lib/test/regrtest.py (original) > +++ python/branches/p3yk/Lib/test/regrtest.py Thu Mar 8 20:54:43 2007 > @@ -478,6 +478,9 @@ > 'test_builtin', > 'test_exceptions', > 'test_types', > + 'test_unittest', > + 'test_doctest', > + 'test_doctest2', > ] > > NOTTESTS = [ > _______________________________________________ > Python-3000-checkins mailing list > Python-3000-checkins at python.org > http://mail.python.org/mailman/listinfo/python-3000-checkins > -- --Guido van Rossum (home page: http://www.python.org/~guido/) From brett at python.org Fri Mar 9 02:56:57 2007 From: brett at python.org (Brett Cannon) Date: Thu, 8 Mar 2007 17:56:57 -0800 Subject: [Python-3000-checkins] r54226 - python/branches/p3yk/Lib/test/regrtest.py In-Reply-To: References: <20070308195445.651161E4002@bag.python.org> Message-ID: On 3/8/07, Guido van Rossum wrote: > I've missed something perhaps -- why is this? > Because they are so crucial to the entire regression test suite that if they fail there is no real point in running the rest of the unit tests. -Brett > On 3/8/07, collin.winter wrote: > > Author: collin.winter > > Date: Thu Mar 8 20:54:43 2007 > > New Revision: 54226 > > > > Modified: > > python/branches/p3yk/Lib/test/regrtest.py > > Log: > > Move test_unittest, test_doctest and test_doctest2 higher up in the test order > > > > Modified: python/branches/p3yk/Lib/test/regrtest.py > > ============================================================================== > > --- python/branches/p3yk/Lib/test/regrtest.py (original) > > +++ python/branches/p3yk/Lib/test/regrtest.py Thu Mar 8 20:54:43 2007 > > @@ -478,6 +478,9 @@ > > 'test_builtin', > > 'test_exceptions', > > 'test_types', > > + 'test_unittest', > > + 'test_doctest', > > + 'test_doctest2', > > ] > > > > NOTTESTS = [ > > _______________________________________________ > > Python-3000-checkins mailing list > > Python-3000-checkins at python.org > > http://mail.python.org/mailman/listinfo/python-3000-checkins > > > > > -- > --Guido van Rossum (home page: http://www.python.org/~guido/) > _______________________________________________ > Python-3000-checkins mailing list > Python-3000-checkins at python.org > http://mail.python.org/mailman/listinfo/python-3000-checkins > From python-3000-checkins at python.org Sat Mar 10 23:13:29 2007 From: python-3000-checkins at python.org (georg.brandl) Date: Sat, 10 Mar 2007 23:13:29 +0100 (CET) Subject: [Python-3000-checkins] r54265 - in python/branches/p3yk: Doc/lib/libfuncs.tex Lib/test/test_builtin.py Misc/NEWS Objects/object.c Python/bltinmodule.c Message-ID: <20070310221329.54DBB1E4002@bag.python.org> Author: georg.brandl Date: Sat Mar 10 23:13:27 2007 New Revision: 54265 Modified: python/branches/p3yk/Doc/lib/libfuncs.tex python/branches/p3yk/Lib/test/test_builtin.py python/branches/p3yk/Misc/NEWS python/branches/p3yk/Objects/object.c python/branches/p3yk/Python/bltinmodule.c Log: Patch #1591665: implement the __dir__() special function lookup in PyObject_Dir. Modified: python/branches/p3yk/Doc/lib/libfuncs.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libfuncs.tex (original) +++ python/branches/p3yk/Doc/lib/libfuncs.tex Sat Mar 10 23:13:27 2007 @@ -274,21 +274,34 @@ \end{funcdesc} \begin{funcdesc}{dir}{\optional{object}} - Without arguments, return the list of names in the current local - symbol table. With an argument, attempts to return a list of valid - attributes for that object. This information is gleaned from the - object's \member{__dict__} attribute, if defined, and from the class - or type object. The list is not necessarily complete. - If the object is a module object, the list contains the names of the - module's attributes. - If the object is a type or class object, - the list contains the names of its attributes, - and recursively of the attributes of its bases. - Otherwise, the list contains the object's attributes' names, - the names of its class's attributes, - and recursively of the attributes of its class's base classes. - The resulting list is sorted alphabetically. - For example: + Without arguments, return the list of names in the current local scope. With + an argument, attempt to return a list of valid attributes for that object. + + If the object has a method named \method{__dir__()}, this method will be + called and must return the list of attributes. This allows objects that + implement a custom \function{__getattr__()} or \function{__getattribute__()} + function to customize the way \function{dir()} reports their attributes. + + If the object does not provide \method{__dir__()}, the function tries its best + to gather information from the object's \member{__dict__} attribute, if + defined, and from its type object. The resulting list is not necessarily + complete, and may be inaccurate when the object has a custom + \function{__getattr__()}. + + The default \function{dir()} mechanism behaves differently with different + types of objects, as it attempts to produce the most relevant, rather than + complete, information: + \begin{itemize} + \item If the object is a module object, the list contains the names of the + module's attributes. + \item If the object is a type or class object, the list contains the names of + its attributes, and recursively of the attributes of its bases. + \item Otherwise, the list contains the object's attributes' names, the names + of its class's attributes, and recursively of the attributes of its class's + base classes. + \end{itemize} + + The resulting list is sorted alphabetically. For example: \begin{verbatim} >>> import struct @@ -296,13 +309,19 @@ ['__builtins__', '__doc__', '__name__', 'struct'] >>> dir(struct) ['__doc__', '__name__', 'calcsize', 'error', 'pack', 'unpack'] +>>> class Foo(object): +... def __dir__(self): +... return ["kan", "ga", "roo"] +... +>>> f = Foo() +>>> dir(f) +['ga', 'kan', 'roo'] \end{verbatim} - \note{Because \function{dir()} is supplied primarily as a convenience - for use at an interactive prompt, - it tries to supply an interesting set of names more than it tries to - supply a rigorously or consistently defined set of names, - and its detailed behavior may change across releases.} + \note{Because \function{dir()} is supplied primarily as a convenience for use + at an interactive prompt, it tries to supply an interesting set of names + more than it tries to supply a rigorously or consistently defined set of + names, and its detailed behavior may change across releases.} \end{funcdesc} \begin{funcdesc}{divmod}{a, b} Modified: python/branches/p3yk/Lib/test/test_builtin.py ============================================================================== --- python/branches/p3yk/Lib/test/test_builtin.py (original) +++ python/branches/p3yk/Lib/test/test_builtin.py Sat Mar 10 23:13:27 2007 @@ -223,12 +223,67 @@ self.assertRaises(TypeError, delattr) def test_dir(self): - x = 1 - self.assert_('x' in dir()) - import sys - self.assert_('modules' in dir(sys)) + # dir(wrong number of arguments) self.assertRaises(TypeError, dir, 42, 42) + # dir() - local scope + local_var = 1 + self.assert_('local_var' in dir()) + + # dir(module) + import sys + self.assert_('exit' in dir(sys)) + + # dir(module_with_invalid__dict__) + import types + class Foo(types.ModuleType): + __dict__ = 8 + f = Foo("foo") + self.assertRaises(TypeError, dir, f) + + # dir(type) + self.assert_("strip" in dir(str)) + self.assert_("__mro__" not in dir(str)) + + # dir(obj) + class Foo(object): + def __init__(self): + self.x = 7 + self.y = 8 + self.z = 9 + f = Foo() + self.assert_("y" in dir(f)) + + # dir(obj_no__dict__) + class Foo(object): + __slots__ = [] + f = Foo() + self.assert_("__repr__" in dir(f)) + + # dir(obj_no__class__with__dict__) + # (an ugly trick to cause getattr(f, "__class__") to fail) + class Foo(object): + __slots__ = ["__class__", "__dict__"] + def __init__(self): + self.bar = "wow" + f = Foo() + self.assert_("__repr__" not in dir(f)) + self.assert_("bar" in dir(f)) + + # dir(obj_using __dir__) + class Foo(object): + def __dir__(self): + return ["kan", "ga", "roo"] + f = Foo() + self.assert_(dir(f) == ["ga", "kan", "roo"]) + + # dir(obj__dir__not_list) + class Foo(object): + def __dir__(self): + return 7 + f = Foo() + self.assertRaises(TypeError, dir, f) + def test_divmod(self): self.assertEqual(divmod(12, 7), (1, 5)) self.assertEqual(divmod(-12, 7), (-2, 2)) Modified: python/branches/p3yk/Misc/NEWS ============================================================================== --- python/branches/p3yk/Misc/NEWS (original) +++ python/branches/p3yk/Misc/NEWS Sat Mar 10 23:13:27 2007 @@ -28,11 +28,15 @@ Core and Builtins ----------------- -- Removing indexing/slicing on BaseException. +- The dir() function has been extended to call the __dir__() method on + its argument, if it exists. If not, it will work like before. This allows + customizing the output of dir() in the presence of a __getattr__(). -- Remove the exceptions module, all the exceptions are already builtin. +- Removed indexing/slicing on BaseException. -- input() becomes raw_input(): the name input() now implements the +- Removed the exceptions module, all the exceptions are already builtin. + +- input() became raw_input(): the name input() now implements the functionality formerly known as raw_input(); the name raw_input() is no longer defined. Modified: python/branches/p3yk/Objects/object.c ============================================================================== --- python/branches/p3yk/Objects/object.c (original) +++ python/branches/p3yk/Objects/object.c Sat Mar 10 23:13:27 2007 @@ -1284,6 +1284,8 @@ return x->ob_type->tp_call != NULL; } +/* ------------------------- PyObject_Dir() helpers ------------------------- */ + /* Helper for PyObject_Dir. Merge the __dict__ of aclass into dict, and recursively also all the __dict__s of aclass's base classes. The order of merging isn't @@ -1343,158 +1345,174 @@ return 0; } -/* Helper for PyObject_Dir. - If obj has an attr named attrname that's a list, merge its string - elements into keys of dict. - Return 0 on success, -1 on error. Errors due to not finding the attr, - or the attr not being a list, are suppressed. -*/ +/* Helper for PyObject_Dir without arguments: returns the local scope. */ +static PyObject * +_dir_locals() +{ + PyObject *locals = PyEval_GetLocals(); -static int -merge_list_attr(PyObject* dict, PyObject* obj, const char *attrname) + if (locals == NULL) { + PyErr_SetString(PyExc_SystemError, "frame does not exist"); + return NULL; + } + + /* the locals don't need to be DECREF'd */ + return PyMapping_Keys(locals); +} + +/* Helper for PyObject_Dir of type objects: returns __dict__ and __bases__. + We deliberately don't suck up its __class__, as methods belonging to the + metaclass would probably be more confusing than helpful. +*/ +static PyObject * +_specialized_dir_type(PyObject *obj) { - PyObject *list; - int result = 0; + PyObject *result = NULL; + PyObject *dict = PyDict_New(); - assert(PyDict_Check(dict)); - assert(obj); - assert(attrname); + if (dict != NULL && merge_class_dict(dict, obj) == 0) + result = PyDict_Keys(dict); - list = PyObject_GetAttrString(obj, attrname); - if (list == NULL) - PyErr_Clear(); + Py_XDECREF(dict); + return result; +} - else if (PyList_Check(list)) { - int i; - for (i = 0; i < PyList_GET_SIZE(list); ++i) { - PyObject *item = PyList_GET_ITEM(list, i); - if (PyString_Check(item)) { - result = PyDict_SetItem(dict, item, Py_None); - if (result < 0) - break; - } +/* Helper for PyObject_Dir of module objects: returns the module's __dict__. */ +static PyObject * +_specialized_dir_module(PyObject *obj) +{ + PyObject *result = NULL; + PyObject *dict = PyObject_GetAttrString(obj, "__dict__"); + + if (dict != NULL) { + if (PyDict_Check(dict)) + result = PyDict_Keys(dict); + else { + PyErr_Format(PyExc_TypeError, + "%.200s.__dict__ is not a dictionary", + PyModule_GetName(obj)); } } - Py_XDECREF(list); + Py_XDECREF(dict); return result; } -/* Like __builtin__.dir(arg). See bltinmodule.c's builtin_dir for the - docstring, which should be kept in synch with this implementation. */ - -PyObject * -PyObject_Dir(PyObject *arg) +/* Helper for PyObject_Dir of generic objects: returns __dict__, __class__, + and recursively up the __class__.__bases__ chain. +*/ +static PyObject * +_generic_dir(PyObject *obj) { - /* Set exactly one of these non-NULL before the end. */ - PyObject *result = NULL; /* result list */ - PyObject *masterdict = NULL; /* result is masterdict.keys() */ - - /* If NULL arg, return the locals. */ - if (arg == NULL) { - PyObject *locals = PyEval_GetLocals(); - if (locals == NULL) - goto error; - result = PyMapping_Keys(locals); - if (result == NULL) - goto error; + PyObject *result = NULL; + PyObject *dict = NULL; + PyObject *itsclass = NULL; + + /* Get __dict__ (which may or may not be a real dict...) */ + dict = PyObject_GetAttrString(obj, "__dict__"); + if (dict == NULL) { + PyErr_Clear(); + dict = PyDict_New(); } - - /* Elif this is some form of module, we only want its dict. */ - else if (PyModule_Check(arg)) { - masterdict = PyObject_GetAttrString(arg, "__dict__"); - if (masterdict == NULL) - goto error; - if (!PyDict_Check(masterdict)) { - PyErr_SetString(PyExc_TypeError, - "module.__dict__ is not a dictionary"); - goto error; - } + else if (!PyDict_Check(dict)) { + Py_DECREF(dict); + dict = PyDict_New(); } - - /* Elif some form of type or class, grab its dict and its bases. - We deliberately don't suck up its __class__, as methods belonging - to the metaclass would probably be more confusing than helpful. */ - else if (PyType_Check(arg)) { - masterdict = PyDict_New(); - if (masterdict == NULL) - goto error; - if (merge_class_dict(masterdict, arg) < 0) - goto error; + else { + /* Copy __dict__ to avoid mutating it. */ + PyObject *temp = PyDict_Copy(dict); + Py_DECREF(dict); + dict = temp; } - /* Else look at its dict, and the attrs reachable from its class. */ + if (dict == NULL) + goto error; + + /* Merge in attrs reachable from its class. */ + itsclass = PyObject_GetAttrString(obj, "__class__"); + if (itsclass == NULL) + /* XXX(tomer): Perhaps fall back to obj->ob_type if no + __class__ exists? */ + PyErr_Clear(); else { - PyObject *itsclass; - /* Create a dict to start with. CAUTION: Not everything - responding to __dict__ returns a dict! */ - masterdict = PyObject_GetAttrString(arg, "__dict__"); - if (masterdict == NULL) { - PyErr_Clear(); - masterdict = PyDict_New(); - } - else if (!PyDict_Check(masterdict)) { - Py_DECREF(masterdict); - masterdict = PyDict_New(); - } - else { - /* The object may have returned a reference to its - dict, so copy it to avoid mutating it. */ - PyObject *temp = PyDict_Copy(masterdict); - Py_DECREF(masterdict); - masterdict = temp; - } - if (masterdict == NULL) + if (merge_class_dict(dict, itsclass) != 0) goto error; + } - /* Merge in __members__ and __methods__ (if any). - XXX Would like this to go away someday; for now, it's - XXX needed to get at im_self etc of method objects. */ - if (merge_list_attr(masterdict, arg, "__members__") < 0) - goto error; - if (merge_list_attr(masterdict, arg, "__methods__") < 0) - goto error; + result = PyDict_Keys(dict); + /* fall through */ +error: + Py_XDECREF(itsclass); + Py_XDECREF(dict); + return result; +} - /* Merge in attrs reachable from its class. - CAUTION: Not all objects have a __class__ attr. */ - itsclass = PyObject_GetAttrString(arg, "__class__"); - if (itsclass == NULL) - PyErr_Clear(); - else { - int status = merge_class_dict(masterdict, itsclass); - Py_DECREF(itsclass); - if (status < 0) - goto error; - } - } +/* Helper for PyObject_Dir: object introspection. + This calls one of the above specialized versions if no __dir__ method + exists. */ +static PyObject * +_dir_object(PyObject *obj) +{ + PyObject * result = NULL; + PyObject * dirfunc = PyObject_GetAttrString((PyObject*)obj->ob_type, + "__dir__"); - assert((result == NULL) ^ (masterdict == NULL)); - if (masterdict != NULL) { - /* The result comes from its keys. */ - assert(result == NULL); - result = PyDict_Keys(masterdict); - if (result == NULL) - goto error; + assert(obj); + if (dirfunc == NULL) { + /* use default implementation */ + PyErr_Clear(); + if (PyModule_Check(obj)) + result = _specialized_dir_module(obj); + else if (PyType_Check(obj)) + result = _specialized_dir_type(obj); + else + result = _generic_dir(obj); } + else { + /* use __dir__ */ + result = PyObject_CallFunctionObjArgs(dirfunc, obj, NULL); + Py_DECREF(dirfunc); + if (result == NULL) + return NULL; - assert(result); - if (!PyList_Check(result)) { - PyErr_Format(PyExc_TypeError, - "Expected keys() to be a list, not '%.200s'", - result->ob_type->tp_name); - goto error; + /* result must be a list */ + /* XXX(gbrandl): could also check if all items are strings */ + if (!PyList_Check(result)) { + PyErr_Format(PyExc_TypeError, + "__dir__() must return a list, not %.200s", + result->ob_type->tp_name); + Py_DECREF(result); + result = NULL; + } } - if (PyList_Sort(result) != 0) - goto error; + + return result; +} + +/* Implementation of dir() -- if obj is NULL, returns the names in the current + (local) scope. Otherwise, performs introspection of the object: returns a + sorted list of attribute names (supposedly) accessible from the object +*/ +PyObject * +PyObject_Dir(PyObject *obj) +{ + PyObject * result; + + if (obj == NULL) + /* no object -- introspect the locals */ + result = _dir_locals(); else - goto normal_return; + /* object -- introspect the object */ + result = _dir_object(obj); - error: - Py_XDECREF(result); - result = NULL; - /* fall through */ - normal_return: - Py_XDECREF(masterdict); + assert(result == NULL || PyList_Check(result)); + + if (result != NULL && PyList_Sort(result) != 0) { + /* sorting the list failed */ + Py_DECREF(result); + result = NULL; + } + return result; } Modified: python/branches/p3yk/Python/bltinmodule.c ============================================================================== --- python/branches/p3yk/Python/bltinmodule.c (original) +++ python/branches/p3yk/Python/bltinmodule.c Sat Mar 10 23:13:27 2007 @@ -427,15 +427,16 @@ PyDoc_STRVAR(dir_doc, "dir([object]) -> list of strings\n" "\n" -"Return an alphabetized list of names comprising (some of) the attributes\n" -"of the given object, and of attributes reachable from it:\n" -"\n" -"No argument: the names in the current scope.\n" -"Module object: the module attributes.\n" -"Type or class object: its attributes, and recursively the attributes of\n" -" its bases.\n" -"Otherwise: its attributes, its class's attributes, and recursively the\n" -" attributes of its class's base classes."); +"If called without an argument, return the names in the current scope.\n" +"Else, return an alphabetized list of names comprising (some of) the attributes\n" +"of the given object, and of attributes reachable from it.\n" +"If the object supplies a method named __dir__, it will be used; otherwise\n" +"the default dir() logic is used and returns:\n" +" for a module object: the module's attributes.\n" +" for a class object: its attributes, and recursively the attributes\n" +" of its bases.\n" +" for an other object: its attributes, its class's attributes, and\n" +" recursively the attributes of its class's base classes."); static PyObject * builtin_divmod(PyObject *self, PyObject *args) From python-3000-checkins at python.org Mon Mar 12 14:15:18 2007 From: python-3000-checkins at python.org (georg.brandl) Date: Mon, 12 Mar 2007 14:15:18 +0100 (CET) Subject: [Python-3000-checkins] r54286 - python/branches/p3yk/Objects/object.c Message-ID: <20070312131518.8036A1E400B@bag.python.org> Author: georg.brandl Date: Mon Mar 12 14:15:14 2007 New Revision: 54286 Modified: python/branches/p3yk/Objects/object.c Log: Check the keys of the locals dict -- they need not be a list. Modified: python/branches/p3yk/Objects/object.c ============================================================================== --- python/branches/p3yk/Objects/object.c (original) +++ python/branches/p3yk/Objects/object.c Mon Mar 12 14:15:14 2007 @@ -1349,6 +1349,7 @@ static PyObject * _dir_locals() { + PyObject *names; PyObject *locals = PyEval_GetLocals(); if (locals == NULL) { @@ -1356,8 +1357,18 @@ return NULL; } + names = PyMapping_Keys(locals); + if (!names) + return NULL; + if (!PyList_Check(names)) { + PyErr_Format(PyExc_TypeError, + "dir(): expected keys() of locals to be a list, " + "not '%.200s'", names->ob_type->tp_name); + Py_DECREF(names); + return NULL; + } /* the locals don't need to be DECREF'd */ - return PyMapping_Keys(locals); + return names; } /* Helper for PyObject_Dir of type objects: returns __dict__ and __bases__. From nnorwitz at gmail.com Tue Mar 13 06:52:16 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Mon, 12 Mar 2007 21:52:16 -0800 Subject: [Python-3000-checkins] r54265 - in python/branches/p3yk: Doc/lib/libfuncs.tex Lib/test/test_builtin.py Misc/NEWS Objects/object.c Python/bltinmodule.c In-Reply-To: <20070310221329.54DBB1E4002@bag.python.org> References: <20070310221329.54DBB1E4002@bag.python.org> Message-ID: I assume this is not the desired behaviour? >>> class F: ... def __dir__(self): ... return [5] ... >>> dir(F()) [5] >>> f = F() >>> dir(f) [5] >>> def __dir__(): return [10] ... >>> f.__dir__ = __dir__ >>> dir(f) [5] I think the problem is in _dir_object() + PyObject * dirfunc = PyObject_GetAttrString((PyObject*)obj->ob_type, + "__dir__"); Shouldn't the first arg just be obj, not obj->ob_type? > Modified: python/branches/p3yk/Python/bltinmodule.c > ============================================================================== > --- python/branches/p3yk/Python/bltinmodule.c (original) > +++ python/branches/p3yk/Python/bltinmodule.c Sat Mar 10 23:13:27 2007 > @@ -427,15 +427,16 @@ > PyDoc_STRVAR(dir_doc, > "dir([object]) -> list of strings\n" > "\n" > -"Return an alphabetized list of names comprising (some of) the attributes\n" > -"of the given object, and of attributes reachable from it:\n" > -"\n" > -"No argument: the names in the current scope.\n" > -"Module object: the module attributes.\n" > -"Type or class object: its attributes, and recursively the attributes of\n" > -" its bases.\n" > -"Otherwise: its attributes, its class's attributes, and recursively the\n" > -" attributes of its class's base classes."); > +"If called without an argument, return the names in the current scope.\n" > +"Else, return an alphabetized list of names comprising (some of) the attributes\n" > +"of the given object, and of attributes reachable from it.\n" > +"If the object supplies a method named __dir__, it will be used; otherwise\n" > +"the default dir() logic is used and returns:\n" > +" for a module object: the module's attributes.\n" > +" for a class object: its attributes, and recursively the attributes\n" > +" of its bases.\n" > +" for an other object: its attributes, its class's attributes, and\n" > +" recursively the attributes of its class's base classes."); 'for an other object' should that be for *any* other object? There might have been other stuff, this patch was too hard to read. n From nnorwitz at gmail.com Tue Mar 13 06:53:35 2007 From: nnorwitz at gmail.com (Neal Norwitz) Date: Mon, 12 Mar 2007 21:53:35 -0800 Subject: [Python-3000-checkins] r54265 - in python/branches/p3yk: Doc/lib/libfuncs.tex Lib/test/test_builtin.py Misc/NEWS Objects/object.c Python/bltinmodule.c In-Reply-To: References: <20070310221329.54DBB1E4002@bag.python.org> Message-ID: Whoops, pulled the trigger too soon. I also wanted to point out that in the example below__dir__() is returning non-strings. Is that ok, even though attributes must be strings? n -- On 3/12/07, Neal Norwitz wrote: > I assume this is not the desired behaviour? > > >>> class F: > ... def __dir__(self): > ... return [5] > ... > >>> dir(F()) > [5] > >>> f = F() > >>> dir(f) > [5] > >>> def __dir__(): return [10] > ... > >>> f.__dir__ = __dir__ > >>> dir(f) > [5] > > I think the problem is in _dir_object() > > + PyObject * dirfunc = PyObject_GetAttrString((PyObject*)obj->ob_type, > + "__dir__"); > > Shouldn't the first arg just be obj, not obj->ob_type? > > > Modified: python/branches/p3yk/Python/bltinmodule.c > > ============================================================================== > > --- python/branches/p3yk/Python/bltinmodule.c (original) > > +++ python/branches/p3yk/Python/bltinmodule.c Sat Mar 10 23:13:27 2007 > > @@ -427,15 +427,16 @@ > > PyDoc_STRVAR(dir_doc, > > "dir([object]) -> list of strings\n" > > "\n" > > -"Return an alphabetized list of names comprising (some of) the attributes\n" > > -"of the given object, and of attributes reachable from it:\n" > > -"\n" > > -"No argument: the names in the current scope.\n" > > -"Module object: the module attributes.\n" > > -"Type or class object: its attributes, and recursively the attributes of\n" > > -" its bases.\n" > > -"Otherwise: its attributes, its class's attributes, and recursively the\n" > > -" attributes of its class's base classes."); > > +"If called without an argument, return the names in the current scope.\n" > > +"Else, return an alphabetized list of names comprising (some of) the attributes\n" > > +"of the given object, and of attributes reachable from it.\n" > > +"If the object supplies a method named __dir__, it will be used; otherwise\n" > > +"the default dir() logic is used and returns:\n" > > +" for a module object: the module's attributes.\n" > > +" for a class object: its attributes, and recursively the attributes\n" > > +" of its bases.\n" > > +" for an other object: its attributes, its class's attributes, and\n" > > +" recursively the attributes of its class's base classes."); > > 'for an other object' should that be for *any* other object? There > might have been other stuff, this patch was too hard to read. > > n > From g.brandl at gmx.net Tue Mar 13 08:22:04 2007 From: g.brandl at gmx.net (Georg Brandl) Date: Tue, 13 Mar 2007 08:22:04 +0100 Subject: [Python-3000-checkins] r54265 - in python/branches/p3yk: Doc/lib/libfuncs.tex Lib/test/test_builtin.py Misc/NEWS Objects/object.c Python/bltinmodule.c In-Reply-To: References: <20070310221329.54DBB1E4002@bag.python.org> Message-ID: Neal Norwitz schrieb: > I assume this is not the desired behaviour? > >>>> class F: > ... def __dir__(self): > ... return [5] > ... >>>> dir(F()) > [5] >>>> f = F() >>>> dir(f) > [5] >>>> def __dir__(): return [10] > ... >>>> f.__dir__ = __dir__ >>>> dir(f) > [5] > > I think the problem is in _dir_object() > > + PyObject * dirfunc = PyObject_GetAttrString((PyObject*)obj->ob_type, > + "__dir__"); > > Shouldn't the first arg just be obj, not obj->ob_type? This is modeled after the principle that for new-style objects, __special__ methods are looked up on the type, not the instance. > I also wanted to point out that in the example below__dir__() is > returning non-strings. Is that ok, even though attributes must be > strings? Yes, I have already put an XXX in the code asking if the returned list should be checked for string-only entries. I wasn't sure whether it is worth the effort. >> +" for an other object: its attributes, its class's attributes, and\n" >> +" recursively the attributes of its class's base classes."); > > 'for an other object' should that be for *any* other object? There > might have been other stuff, this patch was too hard to read. Fixed, thanks. Georg From python-3000-checkins at python.org Thu Mar 15 19:09:47 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Thu, 15 Mar 2007 19:09:47 +0100 (CET) Subject: [Python-3000-checkins] r54400 - python/branches/p3yk/Misc/ACKS Message-ID: <20070315180947.88FB51E400D@bag.python.org> Author: guido.van.rossum Date: Thu Mar 15 19:09:35 2007 New Revision: 54400 Modified: python/branches/p3yk/Misc/ACKS Log: Add Mike Verdone (co-author of io.py and PEP 3116). Daniel Stutzbach (already in) is main author of _fileio.c. Modified: python/branches/p3yk/Misc/ACKS ============================================================================== --- python/branches/p3yk/Misc/ACKS (original) +++ python/branches/p3yk/Misc/ACKS Thu Mar 15 19:09:35 2007 @@ -642,6 +642,7 @@ Hector Urtubia Dmitry Vasiliev Frank Vercruesse +Mike Verdone Jaap Vermeulen Al Vezza Jacques A. Vidrine From python-3000-checkins at python.org Thu Mar 15 19:59:36 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Thu, 15 Mar 2007 19:59:36 +0100 (CET) Subject: [Python-3000-checkins] r54401 - python/branches/p3yk/Lib/io.py Message-ID: <20070315185936.6C35D1E400D@bag.python.org> Author: guido.van.rossum Date: Thu Mar 15 19:59:31 2007 New Revision: 54401 Modified: python/branches/p3yk/Lib/io.py Log: Add some XXX comments and fix BufferedReader signature. Modified: python/branches/p3yk/Lib/io.py ============================================================================== --- python/branches/p3yk/Lib/io.py (original) +++ python/branches/p3yk/Lib/io.py Thu Mar 15 19:59:31 2007 @@ -4,6 +4,10 @@ reimplemented in C and the rest may be turned into a package. See PEP XXX; for now: http://docs.google.com/Doc?id=dfksfvqd_1cn5g5m + +XXX need to default buffer size to 1 if isatty() +XXX need to support 1 meaning line-buffered +XXX change behavior of blocking I/O """ __author__ = ("Guido van Rossum , " @@ -17,7 +21,7 @@ DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes DEFAULT_MAX_BUFFER_SIZE = 16 * 1024 # bytes -EOF = b'' +EOF = b'' # XXX This is wrong because it's mutable class BlockingIO(IOError): @@ -376,7 +380,7 @@ Does not allow random access (seek, tell). """ - def __init__(self, raw): + def __init__(self, raw, unused_buffer_size=None): """Create a new buffered reader using the given readable raw IO object. """ assert raw.readable() From python-3000-checkins at python.org Sun Mar 18 04:36:37 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Sun, 18 Mar 2007 04:36:37 +0100 (CET) Subject: [Python-3000-checkins] r54424 - python/branches/p3yk/Lib/io.py Message-ID: <20070318033637.0C8B41E400A@bag.python.org> Author: guido.van.rossum Date: Sun Mar 18 04:36:28 2007 New Revision: 54424 Modified: python/branches/p3yk/Lib/io.py Log: Bug 1679498: unset variable 'bs'. Modified: python/branches/p3yk/Lib/io.py ============================================================================== --- python/branches/p3yk/Lib/io.py (original) +++ python/branches/p3yk/Lib/io.py Sun Mar 18 04:36:28 2007 @@ -91,6 +91,8 @@ try: bs = os.fstat(raw.fileno()).st_blksize except (os.error, AttributeError): + pass + else: if bs > 1: buffering = bs if buffering < 0: From python-3000-checkins at python.org Sun Mar 18 04:42:16 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Sun, 18 Mar 2007 04:42:16 +0100 (CET) Subject: [Python-3000-checkins] r54425 - python/branches/p3yk/Lib/io.py Message-ID: <20070318034216.533CB1E400A@bag.python.org> Author: guido.van.rossum Date: Sun Mar 18 04:42:15 2007 New Revision: 54425 Modified: python/branches/p3yk/Lib/io.py Log: Bug 1679498: remove unused instance variables _readable, _writable and _seekable. Modified: python/branches/p3yk/Lib/io.py ============================================================================== --- python/branches/p3yk/Lib/io.py (original) +++ python/branches/p3yk/Lib/io.py Sun Mar 18 04:42:15 2007 @@ -196,7 +196,6 @@ flags = os.O_RDONLY elif mode == "w": flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC - self._writable = True elif mode == "r+": flags = os.O_RDWR else: @@ -271,9 +270,6 @@ assert mode in ("r", "w", "rw") self._sock = sock self._mode = mode - self._readable = "r" in mode - self._writable = "w" in mode - self._seekable = False def readinto(self, b): return self._sock.recv_into(b) From python-3000-checkins at python.org Sun Mar 18 16:42:12 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Sun, 18 Mar 2007 16:42:12 +0100 (CET) Subject: [Python-3000-checkins] r54428 - in python/branches/p3yk: Grammar/Grammar Include/Python-ast.h Include/opcode.h Lib/build_class.py Lib/ctypes/_endian.py Lib/opcode.py Lib/string.py Lib/test/crashers/modify_dict_attr.py Lib/test/leakers/test_selftype.py Lib/test/pickletester.py Lib/test/test_ast.py Lib/test/test_copy.py Lib/test/test_descr.py Lib/test/test_metaclass.py Lib/unittest.py Modules/_bsddb.c Parser/Python.asdl Python/Python-ast.c Python/ast.c Python/bltinmodule.c Python/ceval.c Python/compile.c Python/graminit.c Python/import.c Python/symtable.c Message-ID: <20070318154212.917E41E400A@bag.python.org> Author: guido.van.rossum Date: Sun Mar 18 16:41:51 2007 New Revision: 54428 Added: python/branches/p3yk/Lib/build_class.py (contents, props changed) python/branches/p3yk/Lib/test/test_metaclass.py (contents, props changed) Modified: python/branches/p3yk/Grammar/Grammar python/branches/p3yk/Include/Python-ast.h python/branches/p3yk/Include/opcode.h python/branches/p3yk/Lib/ctypes/_endian.py python/branches/p3yk/Lib/opcode.py python/branches/p3yk/Lib/string.py python/branches/p3yk/Lib/test/crashers/modify_dict_attr.py python/branches/p3yk/Lib/test/leakers/test_selftype.py python/branches/p3yk/Lib/test/pickletester.py python/branches/p3yk/Lib/test/test_ast.py python/branches/p3yk/Lib/test/test_copy.py python/branches/p3yk/Lib/test/test_descr.py python/branches/p3yk/Lib/unittest.py python/branches/p3yk/Modules/_bsddb.c python/branches/p3yk/Parser/Python.asdl python/branches/p3yk/Python/Python-ast.c python/branches/p3yk/Python/ast.c python/branches/p3yk/Python/bltinmodule.c python/branches/p3yk/Python/ceval.c python/branches/p3yk/Python/compile.c python/branches/p3yk/Python/graminit.c python/branches/p3yk/Python/import.c python/branches/p3yk/Python/symtable.c Log: Implement PEP 3115 -- new metaclass syntax and semantics. The compiler package hasn't been updated yet; test_compiler.py fails. Otherwise all tests seem to be passing now. There are no occurrences of __metaclass__ left in the standard library. Docs have not been updated. Modified: python/branches/p3yk/Grammar/Grammar ============================================================================== --- python/branches/p3yk/Grammar/Grammar (original) +++ python/branches/p3yk/Grammar/Grammar Sun Mar 18 16:41:51 2007 @@ -119,7 +119,7 @@ testlist: test (',' test)* [','] dictsetmaker: (test ':' test (',' test ':' test)* [',']) | (test (',' test)* [',']) -classdef: 'class' NAME ['(' [testlist] ')'] ':' suite +classdef: 'class' NAME ['(' [arglist] ')'] ':' suite arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) argument: test [gen_for] | test '=' test # Really [keyword '='] test Modified: python/branches/p3yk/Include/Python-ast.h ============================================================================== --- python/branches/p3yk/Include/Python-ast.h (original) +++ python/branches/p3yk/Include/Python-ast.h Sun Mar 18 16:41:51 2007 @@ -82,6 +82,9 @@ struct { identifier name; asdl_seq *bases; + asdl_seq *keywords; + expr_ty starargs; + expr_ty kwargs; asdl_seq *body; } ClassDef; @@ -380,8 +383,9 @@ stmt_ty _Py_FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * decorators, expr_ty returns, int lineno, int col_offset, PyArena *arena); -#define ClassDef(a0, a1, a2, a3, a4, a5) _Py_ClassDef(a0, a1, a2, a3, a4, a5) -stmt_ty _Py_ClassDef(identifier name, asdl_seq * bases, asdl_seq * body, int +#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) +stmt_ty _Py_ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, + expr_ty starargs, expr_ty kwargs, asdl_seq * body, int lineno, int col_offset, PyArena *arena); #define Return(a0, a1, a2, a3) _Py_Return(a0, a1, a2, a3) stmt_ty _Py_Return(expr_ty value, int lineno, int col_offset, PyArena *arena); Modified: python/branches/p3yk/Include/opcode.h ============================================================================== --- python/branches/p3yk/Include/opcode.h (original) +++ python/branches/p3yk/Include/opcode.h Sun Mar 18 16:41:51 2007 @@ -59,8 +59,9 @@ #define BINARY_OR 66 #define INPLACE_POWER 67 #define GET_ITER 68 - +#define STORE_LOCALS 69 #define PRINT_EXPR 70 +#define LOAD_BUILD_CLASS 71 #define INPLACE_LSHIFT 75 #define INPLACE_RSHIFT 76 @@ -69,14 +70,13 @@ #define INPLACE_OR 79 #define BREAK_LOOP 80 #define WITH_CLEANUP 81 -#define LOAD_LOCALS 82 + #define RETURN_VALUE 83 #define IMPORT_STAR 84 #define MAKE_BYTES 85 #define YIELD_VALUE 86 #define POP_BLOCK 87 #define END_FINALLY 88 -#define BUILD_CLASS 89 #define HAVE_ARGUMENT 90 /* Opcodes from here have an argument: */ @@ -120,10 +120,10 @@ #define RAISE_VARARGS 130 /* Number of raise arguments (1, 2 or 3) */ /* CALL_FUNCTION_XXX opcodes defined below depend on this definition */ #define CALL_FUNCTION 131 /* #args + (#kwargs<<8) */ -#define MAKE_FUNCTION 132 /* #defaults */ +#define MAKE_FUNCTION 132 /* #defaults + #kwdefaults<<8 + #annotations<<16 */ #define BUILD_SLICE 133 /* Number of items */ -#define MAKE_CLOSURE 134 /* #free vars */ +#define MAKE_CLOSURE 134 /* same as MAKE_FUNCTION */ #define LOAD_CLOSURE 135 /* Load free variable from closure */ #define LOAD_DEREF 136 /* Load and dereference from closure cell */ #define STORE_DEREF 137 /* Store into cell */ Added: python/branches/p3yk/Lib/build_class.py ============================================================================== Modified: python/branches/p3yk/Lib/ctypes/_endian.py ============================================================================== --- python/branches/p3yk/Lib/ctypes/_endian.py (original) +++ python/branches/p3yk/Lib/ctypes/_endian.py Sun Mar 18 16:41:51 2007 @@ -42,18 +42,16 @@ LittleEndianStructure = Structure - class BigEndianStructure(Structure): + class BigEndianStructure(Structure, metaclass=_swapped_meta): """Structure with big endian byte order""" - __metaclass__ = _swapped_meta _swappedbytes_ = None elif sys.byteorder == "big": _OTHER_ENDIAN = "__ctype_le__" BigEndianStructure = Structure - class LittleEndianStructure(Structure): + class LittleEndianStructure(Structure, metaclass=_swapped_meta): """Structure with little endian byte order""" - __metaclass__ = _swapped_meta _swappedbytes_ = None else: Modified: python/branches/p3yk/Lib/opcode.py ============================================================================== --- python/branches/p3yk/Lib/opcode.py (original) +++ python/branches/p3yk/Lib/opcode.py Sun Mar 18 16:41:51 2007 @@ -98,8 +98,10 @@ def_op('BINARY_OR', 66) def_op('INPLACE_POWER', 67) def_op('GET_ITER', 68) +def_op('STORE_LOCALS', 69) def_op('PRINT_EXPR', 70) +def_op('LOAD_BUILD_CLASS', 71) def_op('INPLACE_LSHIFT', 75) def_op('INPLACE_RSHIFT', 76) @@ -108,14 +110,13 @@ def_op('INPLACE_OR', 79) def_op('BREAK_LOOP', 80) def_op('WITH_CLEANUP', 81) -def_op('LOAD_LOCALS', 82) + def_op('RETURN_VALUE', 83) def_op('IMPORT_STAR', 84) def_op('MAKE_BYTES', 85) def_op('YIELD_VALUE', 86) def_op('POP_BLOCK', 87) def_op('END_FINALLY', 88) -def_op('BUILD_CLASS', 89) HAVE_ARGUMENT = 90 # Opcodes from here have an argument: Modified: python/branches/p3yk/Lib/string.py ============================================================================== --- python/branches/p3yk/Lib/string.py (original) +++ python/branches/p3yk/Lib/string.py Sun Mar 18 16:41:51 2007 @@ -119,9 +119,8 @@ cls.pattern = _re.compile(pattern, _re.IGNORECASE | _re.VERBOSE) -class Template: +class Template(metaclass=_TemplateMetaclass): """A string class for supporting $-substitutions.""" - __metaclass__ = _TemplateMetaclass delimiter = '$' idpattern = r'[_a-z][_a-z0-9]*' Modified: python/branches/p3yk/Lib/test/crashers/modify_dict_attr.py ============================================================================== --- python/branches/p3yk/Lib/test/crashers/modify_dict_attr.py (original) +++ python/branches/p3yk/Lib/test/crashers/modify_dict_attr.py Sun Mar 18 16:41:51 2007 @@ -7,11 +7,10 @@ class type_with_modifiable_dict(Y, type): pass -class MyClass(object): +class MyClass(object, metaclass=type_with_modifiable_dict): """This class has its __dict__ attribute completely exposed: user code can read, reassign and even delete it. """ - __metaclass__ = type_with_modifiable_dict if __name__ == '__main__': Modified: python/branches/p3yk/Lib/test/leakers/test_selftype.py ============================================================================== --- python/branches/p3yk/Lib/test/leakers/test_selftype.py (original) +++ python/branches/p3yk/Lib/test/leakers/test_selftype.py Sun Mar 18 16:41:51 2007 @@ -6,8 +6,8 @@ def leak(): class T(type): pass - class U(type): - __metaclass__ = T + class U(type, metaclass=T): + pass U.__class__ = U del U gc.collect(); gc.collect(); gc.collect() Modified: python/branches/p3yk/Lib/test/pickletester.py ============================================================================== --- python/branches/p3yk/Lib/test/pickletester.py (original) +++ python/branches/p3yk/Lib/test/pickletester.py Sun Mar 18 16:41:51 2007 @@ -88,8 +88,8 @@ class metaclass(type): pass -class use_metaclass(object): - __metaclass__ = metaclass +class use_metaclass(object, metaclass=metaclass): + pass # DATA0 .. DATA2 are the pickles we expect under the various protocols, for # the object returned by create_data(). Modified: python/branches/p3yk/Lib/test/test_ast.py ============================================================================== --- python/branches/p3yk/Lib/test/test_ast.py (original) +++ python/branches/p3yk/Lib/test/test_ast.py Sun Mar 18 16:41:51 2007 @@ -144,13 +144,19 @@ (eval_tests, eval_results, "eval")): for i, o in itertools.izip(input, output): ast_tree = compile(i, "?", kind, 0x400) + if to_tuple(ast_tree) != o: + print("i=", i) + print("o=", o) + print("kind=", kind) + print("tree=", ast_tree) + print("tuple=", to_tuple(ast_tree)) assert to_tuple(ast_tree) == o test_order(ast_tree, (0, 0)) #### EVERYTHING BELOW IS GENERATED ##### exec_results = [ ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, [], None, None, [], []), [('Pass', (1, 9))], [], None)]), -('Module', [('ClassDef', (1, 0), 'C', [], [('Pass', (1, 8))])]), +('Module', [('ClassDef', (1, 0), 'C', [], [], None, None, [('Pass', (1, 8))])]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, [], None, None, [], []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None)]), ('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]), ('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]), Modified: python/branches/p3yk/Lib/test/test_copy.py ============================================================================== --- python/branches/p3yk/Lib/test/test_copy.py (original) +++ python/branches/p3yk/Lib/test/test_copy.py Sun Mar 18 16:41:51 2007 @@ -191,8 +191,8 @@ # type. class Meta(type): pass - class C: - __metaclass__ = Meta + class C(metaclass=Meta): + pass self.assertEqual(copy.deepcopy(C), C) def test_deepcopy_deepcopy(self): Modified: python/branches/p3yk/Lib/test/test_descr.py ============================================================================== --- python/branches/p3yk/Lib/test/test_descr.py (original) +++ python/branches/p3yk/Lib/test/test_descr.py Sun Mar 18 16:41:51 2007 @@ -616,9 +616,8 @@ vereq(a[100:200], (100,200)) def metaclass(): - if verbose: print("Testing __metaclass__...") - class C: - __metaclass__ = type + if verbose: print("Testing metaclass...") + class C(metaclass=type): def __init__(self): self.__state = 0 def getstate(self): @@ -629,9 +628,10 @@ vereq(a.getstate(), 0) a.setstate(10) vereq(a.getstate(), 10) - class D: - class __metaclass__(type): - def myself(cls): return cls + class _metaclass(type): + def myself(cls): return cls + class D(metaclass=_metaclass): + pass vereq(D.myself(), D) d = D() verify(d.__class__ is D) @@ -639,8 +639,8 @@ def __new__(cls, name, bases, dict): dict['__spam__'] = 1 return type.__new__(cls, name, bases, dict) - class C: - __metaclass__ = M1 + class C(metaclass=M1): + pass vereq(C.__spam__, 1) c = C() vereq(c.__spam__, 1) @@ -663,8 +663,7 @@ continue setattr(it, key, self.dict[key].__get__(it, self)) return it - class C: - __metaclass__ = M2 + class C(metaclass=M2): def spam(self): return 42 vereq(C.name, 'C') @@ -690,8 +689,7 @@ name = "__super" setattr(cls, name, super(cls)) return cls - class A: - __metaclass__ = autosuper + class A(metaclass=autosuper): def meth(self): return "A" class B(A): @@ -729,8 +727,7 @@ dict[key] = property(get, set) return super(autoproperty, metaclass).__new__(metaclass, name, bases, dict) - class A: - __metaclass__ = autoproperty + class A(metaclass=autoproperty): def _get_x(self): return -self.__x def _set_x(self, x): @@ -744,8 +741,7 @@ class multimetaclass(autoproperty, autosuper): # Merge of multiple cooperating metaclasses pass - class A: - __metaclass__ = multimetaclass + class A(metaclass=multimetaclass): def _get_x(self): return "A" class B(A): @@ -764,8 +760,8 @@ counter = 0 def __init__(self, *args): T.counter += 1 - class C: - __metaclass__ = T + class C(metaclass=T): + pass vereq(T.counter, 1) a = C() vereq(type(a), C) @@ -1273,8 +1269,8 @@ # Test comparison of classes with dynamic metaclasses class dynamicmetaclass(type): pass - class someclass: - __metaclass__ = dynamicmetaclass + class someclass(metaclass=dynamicmetaclass): + pass verify(someclass != object) def errors(): @@ -1505,36 +1501,39 @@ L = type.mro(cls) L.reverse() return L - class X(D,B,C,A): - __metaclass__ = PerverseMetaType + class X(D,B,C,A, metaclass=PerverseMetaType): + pass vereq(X.__mro__, (object, A, C, B, D, X)) vereq(X().f(), "A") try: - class X(object): - class __metaclass__(type): - def mro(self): - return [self, dict, object] + class _metaclass(type): + def mro(self): + return [self, dict, object] + class X(object, metaclass=_metaclass): + pass except TypeError: pass else: raise TestFailed, "devious mro() return not caught" try: - class X(object): - class __metaclass__(type): - def mro(self): - return [1] + class _metaclass(type): + def mro(self): + return [1] + class X(object, metaclass=_metaclass): + pass except TypeError: pass else: raise TestFailed, "non-class mro() return not caught" try: - class X(object): - class __metaclass__(type): - def mro(self): - return 1 + class _metaclass(type): + def mro(self): + return 1 + class X(object, metaclass=_metaclass): + pass except TypeError: pass else: @@ -3575,11 +3574,11 @@ class E(D): pass - class F(D): - __metaclass__ = WorkOnce + class F(D, metaclass=WorkOnce): + pass - class G(D): - __metaclass__ = WorkAlways + class G(D, metaclass=WorkAlways): + pass # Immediate subclasses have their mro's adjusted in alphabetical # order, so E's will get adjusted before adjusting F's fails. We @@ -3690,15 +3689,15 @@ def dict_type_with_metaclass(): if verbose: - print("Testing type of __dict__ when __metaclass__ set...") + print("Testing type of __dict__ when metaclass set...") class B(object): pass class M(type): pass - class C: + class C(metaclass=M): # In 2.3a1, C.__dict__ was a real dict rather than a dict proxy - __metaclass__ = M + pass veris(type(C.__dict__), type(B.__dict__)) def meth_class_get(): Added: python/branches/p3yk/Lib/test/test_metaclass.py ============================================================================== --- (empty file) +++ python/branches/p3yk/Lib/test/test_metaclass.py Sun Mar 18 16:41:51 2007 @@ -0,0 +1,218 @@ +doctests = """ + +Basic class construction. + + >>> class C: + ... def meth(self): print("Hello") + ... + >>> C.__class__ is type + True + >>> a = C() + >>> a.__class__ is C + True + >>> a.meth() + Hello + >>> + +Use *args notation for the bases. + + >>> class A: pass + >>> class B: pass + >>> bases = (A, B) + >>> class C(*bases): pass + >>> C.__bases__ == bases + True + >>> + +Use a trivial metaclass. + + >>> class M(type): + ... pass + ... + >>> class C(metaclass=M): + ... def meth(self): print("Hello") + ... + >>> C.__class__ is M + True + >>> a = C() + >>> a.__class__ is C + True + >>> a.meth() + Hello + >>> + +Use **kwds notation for the metaclass keyword. + + >>> kwds = {'metaclass': M} + >>> class C(**kwds): pass + ... + >>> C.__class__ is M + True + >>> a = C() + >>> a.__class__ is C + True + >>> + +Use a metaclass with a __prepare__ static method. + + >>> class M(type): + ... @staticmethod + ... def __prepare__(*args, **kwds): + ... print("Prepare called:", args, kwds) + ... return dict() + ... def __new__(cls, name, bases, namespace, **kwds): + ... print("New called:", kwds) + ... return type.__new__(cls, name, bases, namespace) + ... + >>> class C(metaclass=M): + ... def meth(self): print("Hello") + ... + Prepare called: ('C', ()) {} + New called: {} + >>> + +Also pass another keyword. + + >>> class C(object, metaclass=M, other="haha"): + ... pass + ... + Prepare called: ('C', (,)) {'other': 'haha'} + New called: {'other': 'haha'} + >>> C.__class__ is M + True + >>> C.__bases__ == (object,) + True + >>> a = C() + >>> a.__class__ is C + True + >>> + +Check that build_class doesn't mutate the kwds dict. + + >>> kwds = {'metaclass': type} + >>> class C(**kwds): pass + ... + >>> kwds == {'metaclass': type} + True + >>> + +Use various combinations of explicit keywords and **kwds. + + >>> bases = (object,) + >>> kwds = {'metaclass': M, 'other': 'haha'} + >>> class C(*bases, **kwds): pass + ... + Prepare called: ('C', (,)) {'other': 'haha'} + New called: {'other': 'haha'} + >>> C.__class__ is M + True + >>> C.__bases__ == (object,) + True + >>> class B: pass + >>> kwds = {'other': 'haha'} + >>> class C(B, metaclass=M, *bases, **kwds): pass + ... + Prepare called: ('C', (, )) {'other': 'haha'} + New called: {'other': 'haha'} + >>> C.__class__ is M + True + >>> C.__bases__ == (B, object) + True + >>> + +Check for duplicate keywords. + + >>> class C(metaclass=type, metaclass=type): pass + ... + Traceback (most recent call last): + [...] + TypeError: __build_class__() got multiple values for keyword argument 'metaclass' + >>> + +Another way. + + >>> kwds = {'metaclass': type} + >>> class C(metaclass=type, **kwds): pass + ... + Traceback (most recent call last): + [...] + TypeError: __build_class__() got multiple values for keyword argument 'metaclass' + >>> + +Use a __prepare__ method that returns an instrumented dict. + + >>> class LoggingDict(dict): + ... def __setitem__(self, key, value): + ... print("d[%r] = %r" % (key, value)) + ... dict.__setitem__(self, key, value) + ... + >>> class Meta(type): + ... @staticmethod + ... def __prepare__(name, bases): + ... return LoggingDict() + ... + >>> class C(metaclass=Meta): + ... foo = 2+2 + ... foo = 42 + ... bar = 123 + ... + d['__module__'] = 'test.test_metaclass' + d['foo'] = 4 + d['foo'] = 42 + d['bar'] = 123 + >>> + +Use a metaclass that doesn't derive from type. + + >>> def meta(name, bases, namespace, **kwds): + ... print("meta:", name, bases) + ... print("ns:", sorted(namespace.items())) + ... print("kw:", sorted(kwds.items())) + ... return namespace + ... + >>> class C(metaclass=meta): + ... a = 42 + ... b = 24 + ... + meta: C () + ns: [('__module__', 'test.test_metaclass'), ('a', 42), ('b', 24)] + kw: [] + >>> type(C) is dict + True + >>> print(sorted(C.items())) + [('__module__', 'test.test_metaclass'), ('a', 42), ('b', 24)] + >>> + +And again, with a __prepare__ attribute. + + >>> def prepare(name, bases, **kwds): + ... print("prepare:", name, bases, sorted(kwds.items())) + ... return LoggingDict() + ... + >>> meta.__prepare__ = prepare + >>> class C(metaclass=meta, other="booh"): + ... a = 1 + ... a = 2 + ... b = 3 + ... + prepare: C () [('other', 'booh')] + d['__module__'] = 'test.test_metaclass' + d['a'] = 1 + d['a'] = 2 + d['b'] = 3 + meta: C () + ns: [('__module__', 'test.test_metaclass'), ('a', 2), ('b', 3)] + kw: [('other', 'booh')] + >>> + +""" + +__test__ = {'doctests' : doctests} + +def test_main(verbose=False): + from test import test_support + from test import test_metaclass + test_support.run_doctest(test_metaclass, verbose) + +if __name__ == "__main__": + test_main(verbose=True) Modified: python/branches/p3yk/Lib/unittest.py ============================================================================== --- python/branches/p3yk/Lib/unittest.py (original) +++ python/branches/p3yk/Lib/unittest.py Sun Mar 18 16:41:51 2007 @@ -84,9 +84,6 @@ # Test framework core ############################################################################## -# All classes defined herein are 'new-style' classes, allowing use of 'super()' -__metaclass__ = type - def _strclass(cls): return "%s.%s" % (cls.__module__, cls.__name__) Modified: python/branches/p3yk/Modules/_bsddb.c ============================================================================== --- python/branches/p3yk/Modules/_bsddb.c (original) +++ python/branches/p3yk/Modules/_bsddb.c Sun Mar 18 16:41:51 2007 @@ -5991,6 +5991,10 @@ * from both DBError and KeyError, since the API only supports * using one base class. */ PyDict_SetItemString(d, "KeyError", PyExc_KeyError); + { + PyObject *builtin_mod = PyImport_ImportModule("__builtin__"); + PyDict_SetItemString(d, "__builtins__", builtin_mod); + } PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n" "class DBKeyEmptyError(DBError, KeyError): pass", Py_file_input, d, d); Modified: python/branches/p3yk/Parser/Python.asdl ============================================================================== --- python/branches/p3yk/Parser/Python.asdl (original) +++ python/branches/p3yk/Parser/Python.asdl Sun Mar 18 16:41:51 2007 @@ -11,7 +11,12 @@ stmt = FunctionDef(identifier name, arguments args, stmt* body, expr* decorators, expr? returns) - | ClassDef(identifier name, expr* bases, stmt* body) + | ClassDef(identifier name, + expr* bases, + keyword* keywords, + expr? starargs, + expr? kwargs, + stmt* body) | Return(expr? value) | Delete(expr* targets) Modified: python/branches/p3yk/Python/Python-ast.c ============================================================================== --- python/branches/p3yk/Python/Python-ast.c (original) +++ python/branches/p3yk/Python/Python-ast.c Sun Mar 18 16:41:51 2007 @@ -49,6 +49,9 @@ static char *ClassDef_fields[]={ "name", "bases", + "keywords", + "starargs", + "kwargs", "body", }; static PyTypeObject *Return_type; @@ -477,7 +480,7 @@ FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields, 5); if (!FunctionDef_type) return 0; - ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 3); + ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 6); if (!ClassDef_type) return 0; Return_type = make_type("Return", stmt_type, Return_fields, 1); if (!Return_type) return 0; @@ -835,8 +838,9 @@ } stmt_ty -ClassDef(identifier name, asdl_seq * bases, asdl_seq * body, int lineno, int - col_offset, PyArena *arena) +ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, expr_ty + starargs, expr_ty kwargs, asdl_seq * body, int lineno, int col_offset, + PyArena *arena) { stmt_ty p; if (!name) { @@ -850,6 +854,9 @@ p->kind = ClassDef_kind; p->v.ClassDef.name = name; p->v.ClassDef.bases = bases; + p->v.ClassDef.keywords = keywords; + p->v.ClassDef.starargs = starargs; + p->v.ClassDef.kwargs = kwargs; p->v.ClassDef.body = body; p->lineno = lineno; p->col_offset = col_offset; @@ -1974,6 +1981,21 @@ if (PyObject_SetAttrString(result, "bases", value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_list(o->v.ClassDef.keywords, ast2obj_keyword); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "keywords", value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(o->v.ClassDef.starargs); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "starargs", value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(o->v.ClassDef.kwargs); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "kwargs", value) == -1) + goto failed; + Py_DECREF(value); value = ast2obj_list(o->v.ClassDef.body, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttrString(result, "body", value) == -1) Modified: python/branches/p3yk/Python/ast.c ============================================================================== --- python/branches/p3yk/Python/ast.c (original) +++ python/branches/p3yk/Python/ast.c Sun Mar 18 16:41:51 2007 @@ -2092,28 +2092,6 @@ return ast_for_testlist(c, n); } -/* like ast_for_testlist() but returns a sequence */ -static asdl_seq* -ast_for_class_bases(struct compiling *c, const node* n) -{ - /* testlist: test (',' test)* [','] */ - assert(NCH(n) > 0); - REQ(n, testlist); - if (NCH(n) == 1) { - expr_ty base; - asdl_seq *bases = asdl_seq_new(1, c->c_arena); - if (!bases) - return NULL; - base = ast_for_expr(c, CHILD(n, 0)); - if (!base) - return NULL; - asdl_seq_SET(bases, 0, base); - return bases; - } - - return seq_for_testlist(c, n); -} - static stmt_ty ast_for_expr_stmt(struct compiling *c, const node *n) { @@ -3032,9 +3010,10 @@ static stmt_ty ast_for_classdef(struct compiling *c, const node *n) { - /* classdef: 'class' NAME ['(' testlist ')'] ':' suite */ - asdl_seq *bases, *s; - + /* classdef: 'class' NAME ['(' arglist ')'] ':' suite */ + asdl_seq *s; + expr_ty call, dummy; + REQ(n, classdef); if (!strcmp(STR(CHILD(n, 1)), "None")) { @@ -3042,32 +3021,36 @@ return NULL; } - if (NCH(n) == 4) { + if (NCH(n) == 4) { /* class NAME ':' suite */ s = ast_for_suite(c, CHILD(n, 3)); if (!s) return NULL; - return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), NULL, s, LINENO(n), - n->n_col_offset, c->c_arena); + return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), NULL, NULL, NULL, NULL, s, + LINENO(n), n->n_col_offset, c->c_arena); } - /* check for empty base list */ - if (TYPE(CHILD(n,3)) == RPAR) { + + if (TYPE(CHILD(n, 3)) == RPAR) { /* class NAME '(' ')' ':' suite */ s = ast_for_suite(c, CHILD(n,5)); if (!s) return NULL; - return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), NULL, s, LINENO(n), - n->n_col_offset, c->c_arena); + return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), NULL, NULL, NULL, NULL, s, + LINENO(n), n->n_col_offset, c->c_arena); } - /* else handle the base class list */ - bases = ast_for_class_bases(c, CHILD(n, 3)); - if (!bases) + /* class NAME '(' arglist ')' ':' suite */ + /* build up a fake Call node so we can extract its pieces */ + dummy = Name(NEW_IDENTIFIER(CHILD(n, 1)), Load, LINENO(n), n->n_col_offset, c->c_arena); + call = ast_for_call(c, CHILD(n, 3), dummy); + if (!call) return NULL; - s = ast_for_suite(c, CHILD(n, 6)); if (!s) return NULL; - return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), bases, s, LINENO(n), - n->n_col_offset, c->c_arena); + + return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), + call->v.Call.args, call->v.Call.keywords, + call->v.Call.starargs, call->v.Call.kwargs, s, + LINENO(n), n->n_col_offset, c->c_arena); } static stmt_ty Modified: python/branches/p3yk/Python/bltinmodule.c ============================================================================== --- python/branches/p3yk/Python/bltinmodule.c (original) +++ python/branches/p3yk/Python/bltinmodule.c Sun Mar 18 16:41:51 2007 @@ -31,6 +31,113 @@ static PyObject *filtertuple (PyObject *, PyObject *); static PyObject * +builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *func, *name, *bases, *mkw, *meta, *prep, *ns, *res; + Py_ssize_t nargs, nbases; + + assert(args != NULL); + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_TypeError, + "__build_class__: args is not a tuple"); + return NULL; + } + nargs = PyTuple_GET_SIZE(args); + if (nargs < 2) { + PyErr_SetString(PyExc_TypeError, + "__build_class__: not enough arguments"); + return NULL; + } + func = PyTuple_GET_ITEM(args, 0); /* Better be callable */ + name = PyTuple_GET_ITEM(args, 1); + if (!PyString_Check(name)) { + PyErr_SetString(PyExc_TypeError, + "__build_class__: name is not a string"); + return NULL; + } + bases = PyTuple_GetSlice(args, 2, nargs); + if (bases == NULL) + return NULL; + nbases = nargs - 2; + + if (kwds == NULL) { + meta = NULL; + mkw = NULL; + } + else { + mkw = PyDict_Copy(kwds); /* Don't modify kwds passed in! */ + if (mkw == NULL) { + Py_DECREF(bases); + return NULL; + } + meta = PyDict_GetItemString(mkw, "metaclass"); + if (meta != NULL) { + Py_INCREF(meta); + if (PyDict_DelItemString(mkw, "metaclass") < 0) { + Py_DECREF(meta); + Py_DECREF(mkw); + Py_DECREF(bases); + return NULL; + } + } + } + if (meta == NULL) { + if (PyTuple_GET_SIZE(bases) == 0) + meta = (PyObject *) (&PyType_Type); + else { + PyObject *base0 = PyTuple_GET_ITEM(bases, 0); + meta = (PyObject *) (base0->ob_type); + } + Py_INCREF(meta); + } + prep = PyObject_GetAttrString(meta, "__prepare__"); + if (prep == NULL) { + PyErr_Clear(); + ns = PyDict_New(); + } + else { + PyObject *pargs = Py_BuildValue("OO", name, bases); + if (pargs == NULL) { + Py_DECREF(prep); + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return NULL; + } + ns = PyEval_CallObjectWithKeywords(prep, pargs, mkw); + Py_DECREF(pargs); + Py_DECREF(prep); + if (ns == NULL) { + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return NULL; + } + } + res = PyObject_CallFunctionObjArgs(func, ns, NULL); + if (res != NULL) { + PyObject *margs; + Py_DECREF(res); + res = NULL; + margs = Py_BuildValue("OOO", name, bases, ns); + if (margs != NULL) { + res = PyEval_CallObjectWithKeywords(meta, margs, mkw); + Py_DECREF(margs); + } + } + Py_DECREF(ns); + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return res; +} + +PyDoc_STRVAR(build_class_doc, +"__build_class__(func, name, *bases, metaclass=None, **kwds) -> class\n\ +\n\ +Internal helper function used by the class statement."); + +static PyObject * builtin___import__(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"name", "globals", "locals", "fromlist", @@ -2103,6 +2210,8 @@ static PyMethodDef builtin_methods[] = { + {"__build_class__", (PyCFunction)builtin___build_class__, + METH_VARARGS | METH_KEYWORDS, build_class_doc}, {"__import__", (PyCFunction)builtin___import__, METH_VARARGS | METH_KEYWORDS, import_doc}, {"abs", builtin_abs, METH_O, abs_doc}, {"all", builtin_all, METH_O, all_doc}, Modified: python/branches/p3yk/Python/ceval.c ============================================================================== --- python/branches/p3yk/Python/ceval.c (original) +++ python/branches/p3yk/Python/ceval.c Sun Mar 18 16:41:51 2007 @@ -117,7 +117,6 @@ static PyObject * cmp_outcome(int, PyObject *, PyObject *); static PyObject * import_from(PyObject *, PyObject *); static int import_all_from(PyObject *, PyObject *); -static PyObject * build_class(PyObject *, PyObject *, PyObject *); static void set_exc_info(PyThreadState *, PyObject *, PyObject *, PyObject *); static void reset_exc_info(PyThreadState *); static void format_exc_check_arg(PyObject *, char *, PyObject *); @@ -1532,14 +1531,12 @@ } break; - case LOAD_LOCALS: - if ((x = f->f_locals) != NULL) { - Py_INCREF(x); - PUSH(x); - continue; - } - PyErr_SetString(PyExc_SystemError, "no locals"); - break; + case STORE_LOCALS: + x = POP(); + v = f->f_locals; + Py_XDECREF(v); + f->f_locals = x; + continue; case RETURN_VALUE: retval = POP(); @@ -1586,16 +1583,16 @@ Py_DECREF(v); break; - case BUILD_CLASS: - u = TOP(); - v = SECOND(); - w = THIRD(); - STACKADJ(-2); - x = build_class(u, v, w); - SET_TOP(x); - Py_DECREF(u); - Py_DECREF(v); - Py_DECREF(w); + case LOAD_BUILD_CLASS: + x = PyDict_GetItemString(f->f_builtins, + "__build_class__"); + if (x == NULL) { + PyErr_SetString(PyExc_ImportError, + "__build_class__ not found"); + break; + } + Py_INCREF(x); + PUSH(x); break; case STORE_NAME: @@ -4023,60 +4020,6 @@ return err; } -static PyObject * -build_class(PyObject *methods, PyObject *bases, PyObject *name) -{ - PyObject *metaclass = NULL, *result, *base; - - if (PyDict_Check(methods)) - metaclass = PyDict_GetItemString(methods, "__metaclass__"); - if (metaclass != NULL) - Py_INCREF(metaclass); - else if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) { - base = PyTuple_GET_ITEM(bases, 0); - metaclass = PyObject_GetAttrString(base, "__class__"); - if (metaclass == NULL) { - PyErr_Clear(); - metaclass = (PyObject *)base->ob_type; - Py_INCREF(metaclass); - } - } - else { - PyObject *g = PyEval_GetGlobals(); - if (g != NULL && PyDict_Check(g)) - metaclass = PyDict_GetItemString(g, "__metaclass__"); - if (metaclass == NULL) - metaclass = (PyObject *) &PyType_Type; - Py_INCREF(metaclass); - } - result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods, - NULL); - Py_DECREF(metaclass); - if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) { - /* A type error here likely means that the user passed - in a base that was not a class (such the random module - instead of the random.random type). Help them out with - by augmenting the error message with more information.*/ - - PyObject *ptype, *pvalue, *ptraceback; - - PyErr_Fetch(&ptype, &pvalue, &ptraceback); - if (PyString_Check(pvalue)) { - PyObject *newmsg; - newmsg = PyString_FromFormat( - "Error when calling the metaclass bases\n" - " %s", - PyString_AS_STRING(pvalue)); - if (newmsg != NULL) { - Py_DECREF(pvalue); - pvalue = newmsg; - } - } - PyErr_Restore(ptype, pvalue, ptraceback); - } - return result; -} - static void format_exc_check_arg(PyObject *exc, char *format_str, PyObject *obj) { Modified: python/branches/p3yk/Python/compile.c ============================================================================== --- python/branches/p3yk/Python/compile.c (original) +++ python/branches/p3yk/Python/compile.c Sun Mar 18 16:41:51 2007 @@ -176,6 +176,11 @@ static int expr_constant(expr_ty e); static int compiler_with(struct compiler *, stmt_ty); +static int compiler_call_helper(struct compiler *c, int n, + asdl_seq *args, + asdl_seq *keywords, + expr_ty starargs, + expr_ty kwargs); static PyCodeObject *assemble(struct compiler *, int addNone); static PyObject *__doc__; @@ -734,6 +739,8 @@ case PRINT_EXPR: return -1; + case LOAD_BUILD_CLASS: + return 1; case INPLACE_LSHIFT: case INPLACE_RSHIFT: case INPLACE_AND: @@ -744,8 +751,8 @@ return 0; case WITH_CLEANUP: return -1; /* XXX Sometimes more */ - case LOAD_LOCALS: - return 1; + case STORE_LOCALS: + return -1; case RETURN_VALUE: return -1; case IMPORT_STAR: @@ -757,8 +764,6 @@ return 0; case END_FINALLY: return -1; /* or -2 or -3 if exception occurred */ - case BUILD_CLASS: - return -2; case STORE_NAME: return -1; @@ -1509,54 +1514,107 @@ static int compiler_class(struct compiler *c, stmt_ty s) { - int n; + static PyObject *build_class = NULL; + static PyObject *locals = NULL; PyCodeObject *co; PyObject *str; - /* push class name on stack, needed by BUILD_CLASS */ - ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts); - /* push the tuple of base classes on the stack */ - n = asdl_seq_LEN(s->v.ClassDef.bases); - if (n > 0) - VISIT_SEQ(c, expr, s->v.ClassDef.bases); - ADDOP_I(c, BUILD_TUPLE, n); - if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, - s->lineno)) - return 0; - c->u->u_private = s->v.ClassDef.name; - Py_INCREF(c->u->u_private); - str = PyString_InternFromString("__name__"); - if (!str || !compiler_nameop(c, str, Load)) { - Py_XDECREF(str); - compiler_exit_scope(c); - return 0; + PySTEntryObject *ste; + + /* initialize statics */ + if (build_class == NULL) { + build_class = PyString_FromString("__build_class__"); + if (build_class == NULL) + return 0; } - - Py_DECREF(str); - str = PyString_InternFromString("__module__"); - if (!str || !compiler_nameop(c, str, Store)) { - Py_XDECREF(str); - compiler_exit_scope(c); - return 0; + if (locals == NULL) { + locals = PyString_FromString("__locals__"); + if (locals == NULL) + return 0; } - Py_DECREF(str); - if (!compiler_body(c, s->v.ClassDef.body)) { - compiler_exit_scope(c); - return 0; - } + /* ultimately generate code for: + = __build_class__(, , *, **) + where: + is a function/closure created from the class body + is the class name + is the positional arguments and *varargs argument + is the keyword arguments and **kwds argument + This borrows from compiler_call. + */ - ADDOP_IN_SCOPE(c, LOAD_LOCALS); - ADDOP_IN_SCOPE(c, RETURN_VALUE); - co = assemble(c, 1); + /* 0. Create a fake variable named __locals__ */ + ste = PySymtable_Lookup(c->c_st, s); + if (ste == NULL) + return 0; + assert(PyList_Check(ste->ste_varnames)); + if (PyList_Append(ste->ste_varnames, locals) < 0) + return 0; + + /* 1. compile the class body into a code object */ + if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, s->lineno)) + return 0; + /* this block represents what we do in the new scope */ + { + /* use the class name for name mangling */ + Py_INCREF(s->v.ClassDef.name); + c->u->u_private = s->v.ClassDef.name; + /* force it to have one mandatory argument */ + c->u->u_argcount = 1; + /* load the first argument ... */ + ADDOP_I(c, LOAD_FAST, 0); + /* ... and store it into f_locals */ + ADDOP_IN_SCOPE(c, STORE_LOCALS); + /* load __name__ ... */ + str = PyString_InternFromString("__name__"); + if (!str || !compiler_nameop(c, str, Load)) { + Py_XDECREF(str); + compiler_exit_scope(c); + return 0; + } + Py_DECREF(str); + /* ... and store it as __module__ */ + str = PyString_InternFromString("__module__"); + if (!str || !compiler_nameop(c, str, Store)) { + Py_XDECREF(str); + compiler_exit_scope(c); + return 0; + } + Py_DECREF(str); + /* compile the body proper */ + if (!compiler_body(c, s->v.ClassDef.body)) { + compiler_exit_scope(c); + return 0; + } + /* return None */ + ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP_IN_SCOPE(c, RETURN_VALUE); + /* create the code object */ + co = assemble(c, 1); + } + /* leave the new scope */ compiler_exit_scope(c); if (co == NULL) return 0; + /* 2. load the 'build_class' function */ + ADDOP(c, LOAD_BUILD_CLASS); + + /* 3. load a function (or closure) made from the code object */ compiler_make_closure(c, co, 0); Py_DECREF(co); - ADDOP_I(c, CALL_FUNCTION, 0); - ADDOP(c, BUILD_CLASS); + /* 4. load class name */ + ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts); + + /* 5. generate the rest of the code for the call */ + if (!compiler_call_helper(c, 2, + s->v.ClassDef.bases, + s->v.ClassDef.keywords, + s->v.ClassDef.starargs, + s->v.ClassDef.kwargs)) + return 0; + + /* 6. store into */ if (!compiler_nameop(c, s->v.ClassDef.name, Store)) return 0; return 1; @@ -2613,21 +2671,37 @@ static int compiler_call(struct compiler *c, expr_ty e) { - int n, code = 0; - VISIT(c, expr, e->v.Call.func); - n = asdl_seq_LEN(e->v.Call.args); - VISIT_SEQ(c, expr, e->v.Call.args); - if (e->v.Call.keywords) { - VISIT_SEQ(c, keyword, e->v.Call.keywords); - n |= asdl_seq_LEN(e->v.Call.keywords) << 8; + return compiler_call_helper(c, 0, + e->v.Call.args, + e->v.Call.keywords, + e->v.Call.starargs, + e->v.Call.kwargs); +} + +/* shared code between compiler_call and compiler_class */ +static int +compiler_call_helper(struct compiler *c, + int n, /* Args already pushed */ + asdl_seq *args, + asdl_seq *keywords, + expr_ty starargs, + expr_ty kwargs) +{ + int code = 0; + + n += asdl_seq_LEN(args); + VISIT_SEQ(c, expr, args); + if (keywords) { + VISIT_SEQ(c, keyword, keywords); + n |= asdl_seq_LEN(keywords) << 8; } - if (e->v.Call.starargs) { - VISIT(c, expr, e->v.Call.starargs); + if (starargs) { + VISIT(c, expr, starargs); code |= 1; } - if (e->v.Call.kwargs) { - VISIT(c, expr, e->v.Call.kwargs); + if (kwargs) { + VISIT(c, expr, kwargs); code |= 2; } switch (code) { Modified: python/branches/p3yk/Python/graminit.c ============================================================================== --- python/branches/p3yk/Python/graminit.c (original) +++ python/branches/p3yk/Python/graminit.c Sun Mar 18 16:41:51 2007 @@ -1635,7 +1635,7 @@ {23, 4}, }; static arc arcs_76_3[2] = { - {9, 5}, + {14, 5}, {15, 6}, }; static arc arcs_76_4[1] = { Modified: python/branches/p3yk/Python/import.c ============================================================================== --- python/branches/p3yk/Python/import.c (original) +++ python/branches/p3yk/Python/import.c Sun Mar 18 16:41:51 2007 @@ -72,9 +72,10 @@ 3030 (added keyword-only parameters) 3040 (added signature annotations) 3050 (print becomes a function) + 3060 (PEP 3115 metaclass syntax) . */ -#define MAGIC (3050 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (3060 | ((long)'\r'<<16) | ((long)'\n'<<24)) /* Magic word as global; note that _PyImport_Init() can change the value of this global to accommodate for alterations of how the Modified: python/branches/p3yk/Python/symtable.c ============================================================================== --- python/branches/p3yk/Python/symtable.c (original) +++ python/branches/p3yk/Python/symtable.c Sun Mar 18 16:41:51 2007 @@ -983,6 +983,11 @@ if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL)) return 0; VISIT_SEQ(st, expr, s->v.ClassDef.bases); + VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); + if (s->v.ClassDef.starargs) + VISIT(st, expr, s->v.ClassDef.starargs); + if (s->v.ClassDef.kwargs) + VISIT(st, expr, s->v.ClassDef.kwargs); if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, (void *)s, s->lineno)) return 0; From python-3000-checkins at python.org Sun Mar 18 17:10:37 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Sun, 18 Mar 2007 17:10:37 +0100 (CET) Subject: [Python-3000-checkins] r54430 - python/branches/p3yk/Python/Python-ast.c Message-ID: <20070318161037.CC4941E400A@bag.python.org> Author: guido.van.rossum Date: Sun Mar 18 17:10:35 2007 New Revision: 54430 Modified: python/branches/p3yk/Python/Python-ast.c Log: Update the silly version number. Modified: python/branches/p3yk/Python/Python-ast.c ============================================================================== --- python/branches/p3yk/Python/Python-ast.c (original) +++ python/branches/p3yk/Python/Python-ast.c Sun Mar 18 17:10:35 2007 @@ -2,7 +2,7 @@ /* - __version__ 53986. + __version__ 54428. This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -3060,7 +3060,7 @@ if (PyDict_SetItemString(d, "AST", (PyObject*)AST_type) < 0) return; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return; - if (PyModule_AddStringConstant(m, "__version__", "53986") < 0) + if (PyModule_AddStringConstant(m, "__version__", "54428") < 0) return; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return; if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0) From python-3000-checkins at python.org Sun Mar 18 19:35:20 2007 From: python-3000-checkins at python.org (georg.brandl) Date: Sun, 18 Mar 2007 19:35:20 +0100 (CET) Subject: [Python-3000-checkins] r54433 - in python/branches/p3yk: Doc/api/concrete.tex Doc/api/refcounts.dat Include/floatobject.h Misc/NEWS Objects/abstract.c Objects/floatobject.c Message-ID: <20070318183520.70D471E400A@bag.python.org> Author: georg.brandl Date: Sun Mar 18 19:35:15 2007 New Revision: 54433 Modified: python/branches/p3yk/Doc/api/concrete.tex python/branches/p3yk/Doc/api/refcounts.dat python/branches/p3yk/Include/floatobject.h python/branches/p3yk/Misc/NEWS python/branches/p3yk/Objects/abstract.c python/branches/p3yk/Objects/floatobject.c Log: Remove the deprecated and useless "pend" argument from PyFloat_FromString. (fixes bug #1650903) Modified: python/branches/p3yk/Doc/api/concrete.tex ============================================================================== --- python/branches/p3yk/Doc/api/concrete.tex (original) +++ python/branches/p3yk/Doc/api/concrete.tex Sun Mar 18 19:35:15 2007 @@ -430,10 +430,9 @@ \versionadded{2.2} \end{cfuncdesc} -\begin{cfuncdesc}{PyObject*}{PyFloat_FromString}{PyObject *str, char **pend} +\begin{cfuncdesc}{PyObject*}{PyFloat_FromString}{PyObject *str} Create a \ctype{PyFloatObject} object based on the string value in - \var{str}, or \NULL{} on failure. The \var{pend} argument is ignored. It - remains only for backward compatibility. + \var{str}, or \NULL{} on failure. \end{cfuncdesc} \begin{cfuncdesc}{PyObject*}{PyFloat_FromDouble}{double v} Modified: python/branches/p3yk/Doc/api/refcounts.dat ============================================================================== --- python/branches/p3yk/Doc/api/refcounts.dat (original) +++ python/branches/p3yk/Doc/api/refcounts.dat Sun Mar 18 19:35:15 2007 @@ -385,7 +385,6 @@ PyFloat_FromString:PyObject*::+1: PyFloat_FromString:PyObject*:str:0: -PyFloat_FromString:char**:pend:0:ignored PyFrozenSet_New:PyObject*::+1: PyFrozenSet_New:PyObject*:iterable:0: Modified: python/branches/p3yk/Include/floatobject.h ============================================================================== --- python/branches/p3yk/Include/floatobject.h (original) +++ python/branches/p3yk/Include/floatobject.h Sun Mar 18 19:35:15 2007 @@ -21,10 +21,8 @@ #define PyFloat_Check(op) PyObject_TypeCheck(op, &PyFloat_Type) #define PyFloat_CheckExact(op) ((op)->ob_type == &PyFloat_Type) -/* Return Python float from string PyObject. Second argument ignored on - input, and, if non-NULL, NULL is stored into *junk (this tried to serve a - purpose once but can't be made to work as intended). */ -PyAPI_FUNC(PyObject *) PyFloat_FromString(PyObject*, char** junk); +/* Return Python float from string PyObject. */ +PyAPI_FUNC(PyObject *) PyFloat_FromString(PyObject*); /* Return Python float from C double. */ PyAPI_FUNC(PyObject *) PyFloat_FromDouble(double); Modified: python/branches/p3yk/Misc/NEWS ============================================================================== --- python/branches/p3yk/Misc/NEWS (original) +++ python/branches/p3yk/Misc/NEWS Sun Mar 18 19:35:15 2007 @@ -28,6 +28,9 @@ Core and Builtins ----------------- +- The long-deprecated argument "pend" of PyFloat_FromString() has been + removed. + - The dir() function has been extended to call the __dir__() method on its argument, if it exists. If not, it will work like before. This allows customizing the output of dir() in the presence of a __getattr__(). Modified: python/branches/p3yk/Objects/abstract.c ============================================================================== --- python/branches/p3yk/Objects/abstract.c (original) +++ python/branches/p3yk/Objects/abstract.c Sun Mar 18 19:35:15 2007 @@ -968,7 +968,7 @@ PyFloatObject *po = (PyFloatObject *)o; return PyFloat_FromDouble(po->ob_fval); } - return PyFloat_FromString(o, NULL); + return PyFloat_FromString(o); } /* Operations on sequences */ Modified: python/branches/p3yk/Objects/floatobject.c ============================================================================== --- python/branches/p3yk/Objects/floatobject.c (original) +++ python/branches/p3yk/Objects/floatobject.c Sun Mar 18 19:35:15 2007 @@ -62,24 +62,8 @@ return (PyObject *) op; } -/************************************************************************** -RED_FLAG 22-Sep-2000 tim -PyFloat_FromString's pend argument is braindead. Prior to this RED_FLAG, - -1. If v was a regular string, *pend was set to point to its terminating - null byte. That's useless (the caller can find that without any - help from this function!). - -2. If v was a Unicode string, or an object convertible to a character - buffer, *pend was set to point into stack trash (the auto temp - vector holding the character buffer). That was downright dangerous. - -Since we can't change the interface of a public API function, pend is -still supported but now *officially* useless: if pend is not NULL, -*pend is set to NULL. -**************************************************************************/ PyObject * -PyFloat_FromString(PyObject *v, char **pend) +PyFloat_FromString(PyObject *v) { const char *s, *last, *end; double x; @@ -89,8 +73,6 @@ #endif Py_ssize_t len; - if (pend) - *pend = NULL; if (PyString_Check(v)) { s = PyString_AS_STRING(v); len = PyString_GET_SIZE(v); @@ -852,7 +834,7 @@ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x)) return NULL; if (PyString_Check(x)) - return PyFloat_FromString(x, NULL); + return PyFloat_FromString(x); return PyNumber_Float(x); } From python-3000-checkins at python.org Sun Mar 18 20:01:59 2007 From: python-3000-checkins at python.org (georg.brandl) Date: Sun, 18 Mar 2007 20:01:59 +0100 (CET) Subject: [Python-3000-checkins] r54434 - in python/branches/p3yk: Grammar/Grammar Include/token.h Lib/compiler/transformer.py Lib/test/test_grammar.py Lib/token.py Lib/tokenize.py Parser/tokenizer.c Python/ast.c Python/graminit.c Message-ID: <20070318190159.A5D251E400D@bag.python.org> Author: georg.brandl Date: Sun Mar 18 20:01:53 2007 New Revision: 54434 Modified: python/branches/p3yk/Grammar/Grammar python/branches/p3yk/Include/token.h python/branches/p3yk/Lib/compiler/transformer.py python/branches/p3yk/Lib/test/test_grammar.py python/branches/p3yk/Lib/token.py python/branches/p3yk/Lib/tokenize.py python/branches/p3yk/Parser/tokenizer.c python/branches/p3yk/Python/ast.c python/branches/p3yk/Python/graminit.c Log: Make ELLIPSIS a separate token. This makes it a syntax error to write ". . ." for Ellipsis. Modified: python/branches/p3yk/Grammar/Grammar ============================================================================== --- python/branches/p3yk/Grammar/Grammar (original) +++ python/branches/p3yk/Grammar/Grammar Sun Mar 18 20:01:53 2007 @@ -107,7 +107,7 @@ atom: ('(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']' | '{' [dictsetmaker] '}' | - NAME | NUMBER | STRING+ | '.' '.' '.') + NAME | NUMBER | STRING+ | '...') listmaker: test ( list_for | (',' test)* [','] ) testlist_gexp: test ( gen_for | (',' test)* [','] ) lambdef: 'lambda' [varargslist] ':' test Modified: python/branches/p3yk/Include/token.h ============================================================================== --- python/branches/p3yk/Include/token.h (original) +++ python/branches/p3yk/Include/token.h Sun Mar 18 20:01:53 2007 @@ -59,10 +59,11 @@ #define DOUBLESLASHEQUAL 49 #define AT 50 #define RARROW 51 +#define ELLIPSIS 52 /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */ -#define OP 52 -#define ERRORTOKEN 53 -#define N_TOKENS 54 +#define OP 53 +#define ERRORTOKEN 54 +#define N_TOKENS 55 /* Special definitions for cooperation with parser */ Modified: python/branches/p3yk/Lib/compiler/transformer.py ============================================================================== --- python/branches/p3yk/Lib/compiler/transformer.py (original) +++ python/branches/p3yk/Lib/compiler/transformer.py Sun Mar 18 20:01:53 2007 @@ -113,7 +113,7 @@ token.LBRACE: self.atom_lbrace, token.NUMBER: self.atom_number, token.STRING: self.atom_string, - token.DOT: self.atom_ellipsis, + token.ELLIPSIS: self.atom_ellipsis, token.NAME: self.atom_name, } self.encoding = None Modified: python/branches/p3yk/Lib/test/test_grammar.py ============================================================================== --- python/branches/p3yk/Lib/test/test_grammar.py (original) +++ python/branches/p3yk/Lib/test/test_grammar.py Sun Mar 18 20:01:53 2007 @@ -121,6 +121,7 @@ def testEllipsis(self): x = ... self.assert_(x is Ellipsis) + self.assertRaises(SyntaxError, eval, ".. .") class GrammarTests(unittest.TestCase): Modified: python/branches/p3yk/Lib/token.py ============================================================================== --- python/branches/p3yk/Lib/token.py (original) +++ python/branches/p3yk/Lib/token.py Sun Mar 18 20:01:53 2007 @@ -61,9 +61,10 @@ DOUBLESLASHEQUAL = 49 AT = 50 RARROW = 51 -OP = 52 -ERRORTOKEN = 53 -N_TOKENS = 54 +ELLIPSIS = 52 +OP = 53 +ERRORTOKEN = 54 +N_TOKENS = 55 NT_OFFSET = 256 #--end constants-- Modified: python/branches/p3yk/Lib/tokenize.py ============================================================================== --- python/branches/p3yk/Lib/tokenize.py (original) +++ python/branches/p3yk/Lib/tokenize.py Sun Mar 18 20:01:53 2007 @@ -83,7 +83,7 @@ r"~") Bracket = '[][(){}]' -Special = group(r'\r?\n', r'[:;.,@]') +Special = group(r'\r?\n', r'\.\.\.', r'[:;.,@]') Funny = group(Operator, Bracket, Special) PlainToken = group(Number, Funny, String, Name) @@ -334,8 +334,8 @@ spos, epos, pos = (lnum, start), (lnum, end), end token, initial = line[start:end], line[start] - if initial in numchars or \ - (initial == '.' and token != '.'): # ordinary number + if (initial in numchars or # ordinary number + (initial == '.' and token != '.' and token != '...')): yield (NUMBER, token, spos, epos, line) elif initial in '\r\n': yield (NL if parenlev > 0 else NEWLINE, Modified: python/branches/p3yk/Parser/tokenizer.c ============================================================================== --- python/branches/p3yk/Parser/tokenizer.c (original) +++ python/branches/p3yk/Parser/tokenizer.c Sun Mar 18 20:01:53 2007 @@ -93,6 +93,7 @@ "DOUBLESLASHEQUAL", "AT", "RARROW", + "ELLIPSIS", /* This table must match the #defines in token.h! */ "OP", "", @@ -1082,6 +1083,16 @@ break; } break; + case '.': + switch (c2) { + case '.': + switch (c3) { + case '.': + return ELLIPSIS; + } + break; + } + break; } return OP; } @@ -1278,13 +1289,22 @@ c = tok_nextc(tok); if (isdigit(c)) { goto fraction; - } - else { + } else if (c == '.') { + c = tok_nextc(tok); + if (c == '.') { + *p_start = tok->start; + *p_end = tok->cur; + return ELLIPSIS; + } else { + tok_backup(tok, c); + } + tok_backup(tok, '.'); + } else { tok_backup(tok, c); - *p_start = tok->start; - *p_end = tok->cur; - return DOT; } + *p_start = tok->start; + *p_end = tok->cur; + return DOT; } /* Number */ Modified: python/branches/p3yk/Python/ast.c ============================================================================== --- python/branches/p3yk/Python/ast.c (original) +++ python/branches/p3yk/Python/ast.c Sun Mar 18 20:01:53 2007 @@ -1410,7 +1410,7 @@ PyArena_AddPyObject(c->c_arena, pynum); return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena); } - case DOT: /* Ellipsis */ + case ELLIPSIS: /* Ellipsis */ return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena); case LPAR: /* some parenthesized expressions */ ch = CHILD(n, 1); Modified: python/branches/p3yk/Python/graminit.c ============================================================================== --- python/branches/p3yk/Python/graminit.c (original) +++ python/branches/p3yk/Python/graminit.c Sun Mar 18 20:01:53 2007 @@ -1336,19 +1336,19 @@ {19, 4}, {154, 4}, {155, 5}, - {78, 6}, + {156, 4}, }; static arc arcs_65_1[3] = { - {48, 7}, - {147, 7}, + {48, 6}, + {147, 6}, {15, 4}, }; static arc arcs_65_2[2] = { - {149, 8}, + {149, 7}, {150, 4}, }; static arc arcs_65_3[2] = { - {152, 9}, + {152, 8}, {153, 4}, }; static arc arcs_65_4[1] = { @@ -1359,21 +1359,15 @@ {0, 5}, }; static arc arcs_65_6[1] = { - {78, 10}, -}; -static arc arcs_65_7[1] = { {15, 4}, }; -static arc arcs_65_8[1] = { +static arc arcs_65_7[1] = { {150, 4}, }; -static arc arcs_65_9[1] = { +static arc arcs_65_8[1] = { {153, 4}, }; -static arc arcs_65_10[1] = { - {78, 4}, -}; -static state states_65[11] = { +static state states_65[9] = { {7, arcs_65_0}, {3, arcs_65_1}, {2, arcs_65_2}, @@ -1383,14 +1377,12 @@ {1, arcs_65_6}, {1, arcs_65_7}, {1, arcs_65_8}, - {1, arcs_65_9}, - {1, arcs_65_10}, }; static arc arcs_66_0[1] = { {22, 1}, }; static arc arcs_66_1[3] = { - {156, 2}, + {157, 2}, {28, 3}, {0, 1}, }; @@ -1416,7 +1408,7 @@ {22, 1}, }; static arc arcs_67_1[3] = { - {157, 2}, + {158, 2}, {28, 3}, {0, 1}, }; @@ -1471,7 +1463,7 @@ {15, 5}, }; static arc arcs_69_2[1] = { - {158, 6}, + {159, 6}, }; static arc arcs_69_3[1] = { {19, 5}, @@ -1495,14 +1487,14 @@ {1, arcs_69_6}, }; static arc arcs_70_0[1] = { - {159, 1}, + {160, 1}, }; static arc arcs_70_1[2] = { {28, 2}, {0, 1}, }; static arc arcs_70_2[2] = { - {159, 1}, + {160, 1}, {0, 2}, }; static state states_70[3] = { @@ -1520,11 +1512,11 @@ }; static arc arcs_71_2[3] = { {22, 3}, - {160, 4}, + {161, 4}, {0, 2}, }; static arc arcs_71_3[2] = { - {160, 4}, + {161, 4}, {0, 3}, }; static arc arcs_71_4[1] = { @@ -1625,7 +1617,7 @@ {1, arcs_75_7}, }; static arc arcs_76_0[1] = { - {161, 1}, + {162, 1}, }; static arc arcs_76_1[1] = { {19, 2}, @@ -1661,7 +1653,7 @@ {1, arcs_76_7}, }; static arc arcs_77_0[3] = { - {162, 1}, + {163, 1}, {29, 2}, {31, 3}, }; @@ -1676,7 +1668,7 @@ {22, 6}, }; static arc arcs_77_4[4] = { - {162, 1}, + {163, 1}, {29, 2}, {31, 3}, {0, 4}, @@ -1705,7 +1697,7 @@ {22, 1}, }; static arc arcs_78_1[3] = { - {157, 2}, + {158, 2}, {27, 3}, {0, 1}, }; @@ -1722,8 +1714,8 @@ {1, arcs_78_3}, }; static arc arcs_79_0[2] = { - {156, 1}, - {164, 1}, + {157, 1}, + {165, 1}, }; static arc arcs_79_1[1] = { {0, 1}, @@ -1745,7 +1737,7 @@ {107, 4}, }; static arc arcs_80_4[2] = { - {163, 5}, + {164, 5}, {0, 4}, }; static arc arcs_80_5[1] = { @@ -1766,7 +1758,7 @@ {108, 2}, }; static arc arcs_81_2[2] = { - {163, 3}, + {164, 3}, {0, 2}, }; static arc arcs_81_3[1] = { @@ -1779,8 +1771,8 @@ {1, arcs_81_3}, }; static arc arcs_82_0[2] = { - {157, 1}, - {166, 1}, + {158, 1}, + {167, 1}, }; static arc arcs_82_1[1] = { {0, 1}, @@ -1802,7 +1794,7 @@ {109, 4}, }; static arc arcs_83_4[2] = { - {165, 5}, + {166, 5}, {0, 4}, }; static arc arcs_83_5[1] = { @@ -1823,7 +1815,7 @@ {108, 2}, }; static arc arcs_84_2[2] = { - {165, 3}, + {166, 3}, {0, 2}, }; static arc arcs_84_3[1] = { @@ -1857,7 +1849,7 @@ {1, arcs_86_1}, }; static arc arcs_87_0[1] = { - {169, 1}, + {170, 1}, }; static arc arcs_87_1[2] = { {9, 2}, @@ -1873,11 +1865,11 @@ }; static dfa dfas[88] = { {256, "single_input", 0, 3, states_0, - "\004\050\014\000\000\000\000\240\340\151\070\220\045\200\040\000\000\206\220\014\002\002"}, + "\004\050\014\000\000\000\000\240\340\051\070\220\045\200\040\000\000\206\220\034\004\004"}, {257, "file_input", 0, 2, states_1, - "\204\050\014\000\000\000\000\240\340\151\070\220\045\200\040\000\000\206\220\014\002\002"}, + "\204\050\014\000\000\000\000\240\340\051\070\220\045\200\040\000\000\206\220\034\004\004"}, {258, "eval_input", 0, 3, states_2, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {259, "decorator", 0, 7, states_3, "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {260, "decorators", 0, 2, states_4, @@ -1903,13 +1895,13 @@ {270, "vfplist", 0, 3, states_14, "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {271, "stmt", 0, 2, states_15, - "\000\050\014\000\000\000\000\240\340\151\070\220\045\200\040\000\000\206\220\014\002\002"}, + "\000\050\014\000\000\000\000\240\340\051\070\220\045\200\040\000\000\206\220\034\004\004"}, {272, "simple_stmt", 0, 4, states_16, - "\000\040\010\000\000\000\000\240\340\151\070\000\000\200\040\000\000\206\220\014\000\002"}, + "\000\040\010\000\000\000\000\240\340\051\070\000\000\200\040\000\000\206\220\034\000\004"}, {273, "small_stmt", 0, 2, states_17, - "\000\040\010\000\000\000\000\240\340\151\070\000\000\200\040\000\000\206\220\014\000\002"}, + "\000\040\010\000\000\000\000\240\340\051\070\000\000\200\040\000\000\206\220\034\000\004"}, {274, "expr_stmt", 0, 6, states_18, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {275, "augassign", 0, 2, states_19, "\000\000\000\000\000\000\376\037\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {276, "del_stmt", 0, 3, states_20, @@ -1917,7 +1909,7 @@ {277, "pass_stmt", 0, 2, states_21, "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {278, "flow_stmt", 0, 2, states_22, - "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\000\002"}, + "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\000\004"}, {279, "break_stmt", 0, 2, states_23, "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {280, "continue_stmt", 0, 2, states_24, @@ -1925,7 +1917,7 @@ {281, "return_stmt", 0, 3, states_25, "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {282, "yield_stmt", 0, 2, states_26, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"}, {283, "raise_stmt", 0, 7, states_27, "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000"}, {284, "import_stmt", 0, 2, states_28, @@ -1951,7 +1943,7 @@ {294, "assert_stmt", 0, 5, states_38, "\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000"}, {295, "compound_stmt", 0, 2, states_39, - "\000\010\004\000\000\000\000\000\000\000\000\220\045\000\000\000\000\000\000\000\002\000"}, + "\000\010\004\000\000\000\000\000\000\000\000\220\045\000\000\000\000\000\000\000\004\000"}, {296, "if_stmt", 0, 8, states_40, "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, {297, "while_stmt", 0, 8, states_41, @@ -1967,69 +1959,69 @@ {302, "except_clause", 0, 5, states_46, "\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, {303, "suite", 0, 5, states_47, - "\004\040\010\000\000\000\000\240\340\151\070\000\000\200\040\000\000\206\220\014\000\002"}, + "\004\040\010\000\000\000\000\240\340\051\070\000\000\200\040\000\000\206\220\034\000\004"}, {304, "testlist_safe", 0, 5, states_48, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {305, "old_test", 0, 2, states_49, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {306, "old_lambdef", 0, 5, states_50, "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000"}, {307, "test", 0, 6, states_51, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {308, "or_test", 0, 2, states_52, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\040\000\000\206\220\034\000\000"}, {309, "and_test", 0, 2, states_53, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\040\000\000\206\220\034\000\000"}, {310, "not_test", 0, 3, states_54, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\040\000\000\206\220\034\000\000"}, {311, "comparison", 0, 2, states_55, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, {312, "comp_op", 0, 4, states_56, "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\040\177\000\000\000\000\000\000"}, {313, "expr", 0, 2, states_57, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, {314, "xor_expr", 0, 2, states_58, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, {315, "and_expr", 0, 2, states_59, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, {316, "shift_expr", 0, 2, states_60, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, {317, "arith_expr", 0, 2, states_61, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, {318, "term", 0, 2, states_62, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, {319, "factor", 0, 3, states_63, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, {320, "power", 0, 4, states_64, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\220\014\000\000"}, - {321, "atom", 0, 11, states_65, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\220\034\000\000"}, + {321, "atom", 0, 9, states_65, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\220\034\000\000"}, {322, "listmaker", 0, 5, states_66, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {323, "testlist_gexp", 0, 5, states_67, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {324, "lambdef", 0, 5, states_68, "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000"}, {325, "trailer", 0, 7, states_69, "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\020\000\000\000"}, {326, "subscriptlist", 0, 3, states_70, - "\000\040\210\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\210\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {327, "subscript", 0, 5, states_71, - "\000\040\210\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\210\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {328, "sliceop", 0, 3, states_72, "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {329, "exprlist", 0, 3, states_73, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, {330, "testlist", 0, 3, states_74, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {331, "dictsetmaker", 0, 8, states_75, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {332, "classdef", 0, 8, states_76, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000"}, {333, "arglist", 0, 8, states_77, - "\000\040\010\240\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\240\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {334, "argument", 0, 4, states_78, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {335, "list_iter", 0, 2, states_79, "\000\000\000\000\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\000\000\000"}, {336, "list_for", 0, 6, states_80, @@ -2043,13 +2035,13 @@ {340, "gen_if", 0, 4, states_84, "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, {341, "testlist1", 0, 2, states_85, - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, {342, "encoding_decl", 0, 2, states_86, "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {343, "yield_expr", 0, 3, states_87, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"}, }; -static label labels[170] = { +static label labels[171] = { {0, "EMPTY"}, {256, 0}, {4, 0}, @@ -2206,6 +2198,7 @@ {27, 0}, {2, 0}, {3, 0}, + {52, 0}, {336, 0}, {339, 0}, {326, 0}, @@ -2224,6 +2217,6 @@ grammar _PyParser_Grammar = { 88, dfas, - {170, labels}, + {171, labels}, 256 }; From python-3000-checkins at python.org Sun Mar 18 20:52:26 2007 From: python-3000-checkins at python.org (georg.brandl) Date: Sun, 18 Mar 2007 20:52:26 +0100 (CET) Subject: [Python-3000-checkins] r54435 - python/branches/p3yk/Tools/compiler/astgen.py Message-ID: <20070318195226.472E71E400A@bag.python.org> Author: georg.brandl Date: Sun Mar 18 20:52:24 2007 New Revision: 54435 Modified: python/branches/p3yk/Tools/compiler/astgen.py Log: Refactor astgen.py with 2to3. Modified: python/branches/p3yk/Tools/compiler/astgen.py ============================================================================== --- python/branches/p3yk/Tools/compiler/astgen.py (original) +++ python/branches/p3yk/Tools/compiler/astgen.py Sun Mar 18 20:52:24 2007 @@ -93,90 +93,90 @@ def gen_source(self): buf = StringIO() - print >> buf, "class %s(Node):" % self.name + print("class %s(Node):" % self.name, file=buf) self._gen_init(buf) - print >> buf + print(file=buf) self._gen_getChildren(buf) - print >> buf + print(file=buf) self._gen_getChildNodes(buf) - print >> buf + print(file=buf) self._gen_repr(buf) buf.seek(0, 0) return buf.read() def _gen_init(self, buf): if self.args: - print >> buf, " def __init__(self, %s, lineno=None):" % self.args + print(" def __init__(self, %s, lineno=None):" % self.args, file=buf) else: - print >> buf, " def __init__(self, lineno=None):" + print(" def __init__(self, lineno=None):", file=buf) if self.argnames: for name in self.argnames: - print >> buf, " self.%s = %s" % (name, name) - print >> buf, " self.lineno = lineno" + print(" self.%s = %s" % (name, name), file=buf) + print(" self.lineno = lineno", file=buf) # Copy the lines in self.init, indented four spaces. The rstrip() # business is to get rid of the four spaces if line happens to be # empty, so that reindent.py is happy with the output. for line in self.init: - print >> buf, (" " + line).rstrip() + print((" " + line).rstrip(), file=buf) def _gen_getChildren(self, buf): - print >> buf, " def getChildren(self):" + print(" def getChildren(self):", file=buf) if len(self.argnames) == 0: - print >> buf, " return ()" + print(" return ()", file=buf) else: if self.hardest_arg < P_NESTED: clist = COMMA.join(["self.%s" % c for c in self.argnames]) if self.nargs == 1: - print >> buf, " return %s," % clist + print(" return %s," % clist, file=buf) else: - print >> buf, " return %s" % clist + print(" return %s" % clist, file=buf) else: if len(self.argnames) == 1: - print >> buf, " return tuple(flatten(self.%s))" % self.argnames[0] + print(" return tuple(flatten(self.%s))" % self.argnames[0], file=buf) else: - print >> buf, " children = []" + print(" children = []", file=buf) template = " children.%s(%sself.%s%s)" for name in self.argnames: if self.argprops[name] == P_NESTED: - print >> buf, template % ("extend", "flatten(", - name, ")") + print(template % ("extend", "flatten(", + name, ")"), file=buf) else: - print >> buf, template % ("append", "", name, "") - print >> buf, " return tuple(children)" + print(template % ("append", "", name, ""), file=buf) + print(" return tuple(children)", file=buf) def _gen_getChildNodes(self, buf): - print >> buf, " def getChildNodes(self):" + print(" def getChildNodes(self):", file=buf) if len(self.argnames) == 0: - print >> buf, " return ()" + print(" return ()", file=buf) else: if self.hardest_arg < P_NESTED: clist = ["self.%s" % c for c in self.argnames if self.argprops[c] == P_NODE] if len(clist) == 0: - print >> buf, " return ()" + print(" return ()", file=buf) elif len(clist) == 1: - print >> buf, " return %s," % clist[0] + print(" return %s," % clist[0], file=buf) else: - print >> buf, " return %s" % COMMA.join(clist) + print(" return %s" % COMMA.join(clist), file=buf) else: - print >> buf, " nodelist = []" + print(" nodelist = []", file=buf) template = " nodelist.%s(%sself.%s%s)" for name in self.argnames: if self.argprops[name] == P_NONE: tmp = (" if self.%s is not None:\n" " nodelist.append(self.%s)") - print >> buf, tmp % (name, name) + print(tmp % (name, name), file=buf) elif self.argprops[name] == P_NESTED: - print >> buf, template % ("extend", "flatten_nodes(", - name, ")") + print(template % ("extend", "flatten_nodes(", + name, ")"), file=buf) elif self.argprops[name] == P_NODE: - print >> buf, template % ("append", "", name, "") - print >> buf, " return tuple(nodelist)" + print(template % ("append", "", name, ""), file=buf) + print(" return tuple(nodelist)", file=buf) def _gen_repr(self, buf): - print >> buf, " def __repr__(self):" + print(" def __repr__(self):", file=buf) if self.argnames: fmt = COMMA.join(["%s"] * self.nargs) if '(' in self.args: @@ -185,10 +185,10 @@ vals = COMMA.join(vals) if self.nargs == 1: vals = vals + "," - print >> buf, ' return "%s(%s)" %% (%s)' % \ - (self.name, fmt, vals) + print(' return "%s(%s)" %% (%s)' % \ + (self.name, fmt, vals), file=buf) else: - print >> buf, ' return "%s()"' % self.name + print(' return "%s()"' % self.name, file=buf) rx_init = re.compile('init\((.*)\):') @@ -219,12 +219,12 @@ def main(): prologue, epilogue = load_boilerplate(sys.argv[-1]) - print prologue - print + print(prologue) + print() classes = parse_spec(SPEC) for info in classes: - print info.gen_source() - print epilogue + print(info.gen_source()) + print(epilogue) if __name__ == "__main__": main() From python-3000-checkins at python.org Sun Mar 18 21:18:34 2007 From: python-3000-checkins at python.org (georg.brandl) Date: Sun, 18 Mar 2007 21:18:34 +0100 (CET) Subject: [Python-3000-checkins] r54437 - python/branches/p3yk/Misc/NEWS Message-ID: <20070318201834.5220B1E400A@bag.python.org> Author: georg.brandl Date: Sun Mar 18 21:18:31 2007 New Revision: 54437 Modified: python/branches/p3yk/Misc/NEWS Log: NEWS item for PEP 3115. Modified: python/branches/p3yk/Misc/NEWS ============================================================================== --- python/branches/p3yk/Misc/NEWS (original) +++ python/branches/p3yk/Misc/NEWS Sun Mar 18 21:18:31 2007 @@ -28,6 +28,11 @@ Core and Builtins ----------------- +- PEP 3115: new metaclasses: the metaclass is now specified as a + keyword arg in the class statement, which can now use the full syntax of + a parameter list. Also, the metaclass can implement a __prepare__ function + which will be called to create the dictionary for the new class namespace. + - The long-deprecated argument "pend" of PyFloat_FromString() has been removed. From guido at python.org Sun Mar 18 23:12:06 2007 From: guido at python.org (Guido van Rossum) Date: Sun, 18 Mar 2007 15:12:06 -0700 Subject: [Python-3000-checkins] r54434 - in python/branches/p3yk: Grammar/Grammar Include/token.h Lib/compiler/transformer.py Lib/test/test_grammar.py Lib/token.py Lib/tokenize.py Parser/tokenizer.c Python/ast.c Python/graminit.c In-Reply-To: <20070318190159.A5D251E400D@bag.python.org> References: <20070318190159.A5D251E400D@bag.python.org> Message-ID: Cool. Do you think you can port this to the modified copy of tokenize.py in 2to3? (I wonder if this wouldn't be a candidate for 2.6 too.) --Guido On 3/18/07, georg.brandl wrote: > Author: georg.brandl > Date: Sun Mar 18 20:01:53 2007 > New Revision: 54434 > > Modified: > python/branches/p3yk/Grammar/Grammar > python/branches/p3yk/Include/token.h > python/branches/p3yk/Lib/compiler/transformer.py > python/branches/p3yk/Lib/test/test_grammar.py > python/branches/p3yk/Lib/token.py > python/branches/p3yk/Lib/tokenize.py > python/branches/p3yk/Parser/tokenizer.c > python/branches/p3yk/Python/ast.c > python/branches/p3yk/Python/graminit.c > Log: > Make ELLIPSIS a separate token. This makes it a syntax error to write ". . ." for Ellipsis. > > > Modified: python/branches/p3yk/Grammar/Grammar > ============================================================================== > --- python/branches/p3yk/Grammar/Grammar (original) > +++ python/branches/p3yk/Grammar/Grammar Sun Mar 18 20:01:53 2007 > @@ -107,7 +107,7 @@ > atom: ('(' [yield_expr|testlist_gexp] ')' | > '[' [listmaker] ']' | > '{' [dictsetmaker] '}' | > - NAME | NUMBER | STRING+ | '.' '.' '.') > + NAME | NUMBER | STRING+ | '...') > listmaker: test ( list_for | (',' test)* [','] ) > testlist_gexp: test ( gen_for | (',' test)* [','] ) > lambdef: 'lambda' [varargslist] ':' test > > Modified: python/branches/p3yk/Include/token.h > ============================================================================== > --- python/branches/p3yk/Include/token.h (original) > +++ python/branches/p3yk/Include/token.h Sun Mar 18 20:01:53 2007 > @@ -59,10 +59,11 @@ > #define DOUBLESLASHEQUAL 49 > #define AT 50 > #define RARROW 51 > +#define ELLIPSIS 52 > /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */ > -#define OP 52 > -#define ERRORTOKEN 53 > -#define N_TOKENS 54 > +#define OP 53 > +#define ERRORTOKEN 54 > +#define N_TOKENS 55 > > /* Special definitions for cooperation with parser */ > > > Modified: python/branches/p3yk/Lib/compiler/transformer.py > ============================================================================== > --- python/branches/p3yk/Lib/compiler/transformer.py (original) > +++ python/branches/p3yk/Lib/compiler/transformer.py Sun Mar 18 20:01:53 2007 > @@ -113,7 +113,7 @@ > token.LBRACE: self.atom_lbrace, > token.NUMBER: self.atom_number, > token.STRING: self.atom_string, > - token.DOT: self.atom_ellipsis, > + token.ELLIPSIS: self.atom_ellipsis, > token.NAME: self.atom_name, > } > self.encoding = None > > Modified: python/branches/p3yk/Lib/test/test_grammar.py > ============================================================================== > --- python/branches/p3yk/Lib/test/test_grammar.py (original) > +++ python/branches/p3yk/Lib/test/test_grammar.py Sun Mar 18 20:01:53 2007 > @@ -121,6 +121,7 @@ > def testEllipsis(self): > x = ... > self.assert_(x is Ellipsis) > + self.assertRaises(SyntaxError, eval, ".. .") > > class GrammarTests(unittest.TestCase): > > > Modified: python/branches/p3yk/Lib/token.py > ============================================================================== > --- python/branches/p3yk/Lib/token.py (original) > +++ python/branches/p3yk/Lib/token.py Sun Mar 18 20:01:53 2007 > @@ -61,9 +61,10 @@ > DOUBLESLASHEQUAL = 49 > AT = 50 > RARROW = 51 > -OP = 52 > -ERRORTOKEN = 53 > -N_TOKENS = 54 > +ELLIPSIS = 52 > +OP = 53 > +ERRORTOKEN = 54 > +N_TOKENS = 55 > NT_OFFSET = 256 > #--end constants-- > > > Modified: python/branches/p3yk/Lib/tokenize.py > ============================================================================== > --- python/branches/p3yk/Lib/tokenize.py (original) > +++ python/branches/p3yk/Lib/tokenize.py Sun Mar 18 20:01:53 2007 > @@ -83,7 +83,7 @@ > r"~") > > Bracket = '[][(){}]' > -Special = group(r'\r?\n', r'[:;.,@]') > +Special = group(r'\r?\n', r'\.\.\.', r'[:;.,@]') > Funny = group(Operator, Bracket, Special) > > PlainToken = group(Number, Funny, String, Name) > @@ -334,8 +334,8 @@ > spos, epos, pos = (lnum, start), (lnum, end), end > token, initial = line[start:end], line[start] > > - if initial in numchars or \ > - (initial == '.' and token != '.'): # ordinary number > + if (initial in numchars or # ordinary number > + (initial == '.' and token != '.' and token != '...')): > yield (NUMBER, token, spos, epos, line) > elif initial in '\r\n': > yield (NL if parenlev > 0 else NEWLINE, > > Modified: python/branches/p3yk/Parser/tokenizer.c > ============================================================================== > --- python/branches/p3yk/Parser/tokenizer.c (original) > +++ python/branches/p3yk/Parser/tokenizer.c Sun Mar 18 20:01:53 2007 > @@ -93,6 +93,7 @@ > "DOUBLESLASHEQUAL", > "AT", > "RARROW", > + "ELLIPSIS", > /* This table must match the #defines in token.h! */ > "OP", > "", > @@ -1082,6 +1083,16 @@ > break; > } > break; > + case '.': > + switch (c2) { > + case '.': > + switch (c3) { > + case '.': > + return ELLIPSIS; > + } > + break; > + } > + break; > } > return OP; > } > @@ -1278,13 +1289,22 @@ > c = tok_nextc(tok); > if (isdigit(c)) { > goto fraction; > - } > - else { > + } else if (c == '.') { > + c = tok_nextc(tok); > + if (c == '.') { > + *p_start = tok->start; > + *p_end = tok->cur; > + return ELLIPSIS; > + } else { > + tok_backup(tok, c); > + } > + tok_backup(tok, '.'); > + } else { > tok_backup(tok, c); > - *p_start = tok->start; > - *p_end = tok->cur; > - return DOT; > } > + *p_start = tok->start; > + *p_end = tok->cur; > + return DOT; > } > > /* Number */ > > Modified: python/branches/p3yk/Python/ast.c > ============================================================================== > --- python/branches/p3yk/Python/ast.c (original) > +++ python/branches/p3yk/Python/ast.c Sun Mar 18 20:01:53 2007 > @@ -1410,7 +1410,7 @@ > PyArena_AddPyObject(c->c_arena, pynum); > return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena); > } > - case DOT: /* Ellipsis */ > + case ELLIPSIS: /* Ellipsis */ > return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena); > case LPAR: /* some parenthesized expressions */ > ch = CHILD(n, 1); > > Modified: python/branches/p3yk/Python/graminit.c > ============================================================================== > --- python/branches/p3yk/Python/graminit.c (original) > +++ python/branches/p3yk/Python/graminit.c Sun Mar 18 20:01:53 2007 > @@ -1336,19 +1336,19 @@ > {19, 4}, > {154, 4}, > {155, 5}, > - {78, 6}, > + {156, 4}, > }; > static arc arcs_65_1[3] = { > - {48, 7}, > - {147, 7}, > + {48, 6}, > + {147, 6}, > {15, 4}, > }; > static arc arcs_65_2[2] = { > - {149, 8}, > + {149, 7}, > {150, 4}, > }; > static arc arcs_65_3[2] = { > - {152, 9}, > + {152, 8}, > {153, 4}, > }; > static arc arcs_65_4[1] = { > @@ -1359,21 +1359,15 @@ > {0, 5}, > }; > static arc arcs_65_6[1] = { > - {78, 10}, > -}; > -static arc arcs_65_7[1] = { > {15, 4}, > }; > -static arc arcs_65_8[1] = { > +static arc arcs_65_7[1] = { > {150, 4}, > }; > -static arc arcs_65_9[1] = { > +static arc arcs_65_8[1] = { > {153, 4}, > }; > -static arc arcs_65_10[1] = { > - {78, 4}, > -}; > -static state states_65[11] = { > +static state states_65[9] = { > {7, arcs_65_0}, > {3, arcs_65_1}, > {2, arcs_65_2}, > @@ -1383,14 +1377,12 @@ > {1, arcs_65_6}, > {1, arcs_65_7}, > {1, arcs_65_8}, > - {1, arcs_65_9}, > - {1, arcs_65_10}, > }; > static arc arcs_66_0[1] = { > {22, 1}, > }; > static arc arcs_66_1[3] = { > - {156, 2}, > + {157, 2}, > {28, 3}, > {0, 1}, > }; > @@ -1416,7 +1408,7 @@ > {22, 1}, > }; > static arc arcs_67_1[3] = { > - {157, 2}, > + {158, 2}, > {28, 3}, > {0, 1}, > }; > @@ -1471,7 +1463,7 @@ > {15, 5}, > }; > static arc arcs_69_2[1] = { > - {158, 6}, > + {159, 6}, > }; > static arc arcs_69_3[1] = { > {19, 5}, > @@ -1495,14 +1487,14 @@ > {1, arcs_69_6}, > }; > static arc arcs_70_0[1] = { > - {159, 1}, > + {160, 1}, > }; > static arc arcs_70_1[2] = { > {28, 2}, > {0, 1}, > }; > static arc arcs_70_2[2] = { > - {159, 1}, > + {160, 1}, > {0, 2}, > }; > static state states_70[3] = { > @@ -1520,11 +1512,11 @@ > }; > static arc arcs_71_2[3] = { > {22, 3}, > - {160, 4}, > + {161, 4}, > {0, 2}, > }; > static arc arcs_71_3[2] = { > - {160, 4}, > + {161, 4}, > {0, 3}, > }; > static arc arcs_71_4[1] = { > @@ -1625,7 +1617,7 @@ > {1, arcs_75_7}, > }; > static arc arcs_76_0[1] = { > - {161, 1}, > + {162, 1}, > }; > static arc arcs_76_1[1] = { > {19, 2}, > @@ -1661,7 +1653,7 @@ > {1, arcs_76_7}, > }; > static arc arcs_77_0[3] = { > - {162, 1}, > + {163, 1}, > {29, 2}, > {31, 3}, > }; > @@ -1676,7 +1668,7 @@ > {22, 6}, > }; > static arc arcs_77_4[4] = { > - {162, 1}, > + {163, 1}, > {29, 2}, > {31, 3}, > {0, 4}, > @@ -1705,7 +1697,7 @@ > {22, 1}, > }; > static arc arcs_78_1[3] = { > - {157, 2}, > + {158, 2}, > {27, 3}, > {0, 1}, > }; > @@ -1722,8 +1714,8 @@ > {1, arcs_78_3}, > }; > static arc arcs_79_0[2] = { > - {156, 1}, > - {164, 1}, > + {157, 1}, > + {165, 1}, > }; > static arc arcs_79_1[1] = { > {0, 1}, > @@ -1745,7 +1737,7 @@ > {107, 4}, > }; > static arc arcs_80_4[2] = { > - {163, 5}, > + {164, 5}, > {0, 4}, > }; > static arc arcs_80_5[1] = { > @@ -1766,7 +1758,7 @@ > {108, 2}, > }; > static arc arcs_81_2[2] = { > - {163, 3}, > + {164, 3}, > {0, 2}, > }; > static arc arcs_81_3[1] = { > @@ -1779,8 +1771,8 @@ > {1, arcs_81_3}, > }; > static arc arcs_82_0[2] = { > - {157, 1}, > - {166, 1}, > + {158, 1}, > + {167, 1}, > }; > static arc arcs_82_1[1] = { > {0, 1}, > @@ -1802,7 +1794,7 @@ > {109, 4}, > }; > static arc arcs_83_4[2] = { > - {165, 5}, > + {166, 5}, > {0, 4}, > }; > static arc arcs_83_5[1] = { > @@ -1823,7 +1815,7 @@ > {108, 2}, > }; > static arc arcs_84_2[2] = { > - {165, 3}, > + {166, 3}, > {0, 2}, > }; > static arc arcs_84_3[1] = { > @@ -1857,7 +1849,7 @@ > {1, arcs_86_1}, > }; > static arc arcs_87_0[1] = { > - {169, 1}, > + {170, 1}, > }; > static arc arcs_87_1[2] = { > {9, 2}, > @@ -1873,11 +1865,11 @@ > }; > static dfa dfas[88] = { > {256, "single_input", 0, 3, states_0, > - "\004\050\014\000\000\000\000\240\340\151\070\220\045\200\040\000\000\206\220\014\002\002"}, > + "\004\050\014\000\000\000\000\240\340\051\070\220\045\200\040\000\000\206\220\034\004\004"}, > {257, "file_input", 0, 2, states_1, > - "\204\050\014\000\000\000\000\240\340\151\070\220\045\200\040\000\000\206\220\014\002\002"}, > + "\204\050\014\000\000\000\000\240\340\051\070\220\045\200\040\000\000\206\220\034\004\004"}, > {258, "eval_input", 0, 3, states_2, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {259, "decorator", 0, 7, states_3, > "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, > {260, "decorators", 0, 2, states_4, > @@ -1903,13 +1895,13 @@ > {270, "vfplist", 0, 3, states_14, > "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, > {271, "stmt", 0, 2, states_15, > - "\000\050\014\000\000\000\000\240\340\151\070\220\045\200\040\000\000\206\220\014\002\002"}, > + "\000\050\014\000\000\000\000\240\340\051\070\220\045\200\040\000\000\206\220\034\004\004"}, > {272, "simple_stmt", 0, 4, states_16, > - "\000\040\010\000\000\000\000\240\340\151\070\000\000\200\040\000\000\206\220\014\000\002"}, > + "\000\040\010\000\000\000\000\240\340\051\070\000\000\200\040\000\000\206\220\034\000\004"}, > {273, "small_stmt", 0, 2, states_17, > - "\000\040\010\000\000\000\000\240\340\151\070\000\000\200\040\000\000\206\220\014\000\002"}, > + "\000\040\010\000\000\000\000\240\340\051\070\000\000\200\040\000\000\206\220\034\000\004"}, > {274, "expr_stmt", 0, 6, states_18, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {275, "augassign", 0, 2, states_19, > "\000\000\000\000\000\000\376\037\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, > {276, "del_stmt", 0, 3, states_20, > @@ -1917,7 +1909,7 @@ > {277, "pass_stmt", 0, 2, states_21, > "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, > {278, "flow_stmt", 0, 2, states_22, > - "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\000\002"}, > + "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\000\004"}, > {279, "break_stmt", 0, 2, states_23, > "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000"}, > {280, "continue_stmt", 0, 2, states_24, > @@ -1925,7 +1917,7 @@ > {281, "return_stmt", 0, 3, states_25, > "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"}, > {282, "yield_stmt", 0, 2, states_26, > - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002"}, > + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"}, > {283, "raise_stmt", 0, 7, states_27, > "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000"}, > {284, "import_stmt", 0, 2, states_28, > @@ -1951,7 +1943,7 @@ > {294, "assert_stmt", 0, 5, states_38, > "\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000"}, > {295, "compound_stmt", 0, 2, states_39, > - "\000\010\004\000\000\000\000\000\000\000\000\220\045\000\000\000\000\000\000\000\002\000"}, > + "\000\010\004\000\000\000\000\000\000\000\000\220\045\000\000\000\000\000\000\000\004\000"}, > {296, "if_stmt", 0, 8, states_40, > "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, > {297, "while_stmt", 0, 8, states_41, > @@ -1967,69 +1959,69 @@ > {302, "except_clause", 0, 5, states_46, > "\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, > {303, "suite", 0, 5, states_47, > - "\004\040\010\000\000\000\000\240\340\151\070\000\000\200\040\000\000\206\220\014\000\002"}, > + "\004\040\010\000\000\000\000\240\340\051\070\000\000\200\040\000\000\206\220\034\000\004"}, > {304, "testlist_safe", 0, 5, states_48, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {305, "old_test", 0, 2, states_49, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {306, "old_lambdef", 0, 5, states_50, > "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000"}, > {307, "test", 0, 6, states_51, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {308, "or_test", 0, 2, states_52, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\040\000\000\206\220\034\000\000"}, > {309, "and_test", 0, 2, states_53, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\040\000\000\206\220\034\000\000"}, > {310, "not_test", 0, 3, states_54, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\040\000\000\206\220\034\000\000"}, > {311, "comparison", 0, 2, states_55, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, > {312, "comp_op", 0, 4, states_56, > "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\040\177\000\000\000\000\000\000"}, > {313, "expr", 0, 2, states_57, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, > {314, "xor_expr", 0, 2, states_58, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, > {315, "and_expr", 0, 2, states_59, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, > {316, "shift_expr", 0, 2, states_60, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, > {317, "arith_expr", 0, 2, states_61, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, > {318, "term", 0, 2, states_62, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, > {319, "factor", 0, 3, states_63, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, > {320, "power", 0, 4, states_64, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\220\014\000\000"}, > - {321, "atom", 0, 11, states_65, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\220\034\000\000"}, > + {321, "atom", 0, 9, states_65, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\220\034\000\000"}, > {322, "listmaker", 0, 5, states_66, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {323, "testlist_gexp", 0, 5, states_67, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {324, "lambdef", 0, 5, states_68, > "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000"}, > {325, "trailer", 0, 7, states_69, > "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\020\000\000\000"}, > {326, "subscriptlist", 0, 3, states_70, > - "\000\040\210\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\210\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {327, "subscript", 0, 5, states_71, > - "\000\040\210\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\210\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {328, "sliceop", 0, 3, states_72, > "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, > {329, "exprlist", 0, 3, states_73, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\000\000\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, > {330, "testlist", 0, 3, states_74, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {331, "dictsetmaker", 0, 8, states_75, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {332, "classdef", 0, 8, states_76, > - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000"}, > + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000"}, > {333, "arglist", 0, 8, states_77, > - "\000\040\010\240\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\240\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {334, "argument", 0, 4, states_78, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {335, "list_iter", 0, 2, states_79, > "\000\000\000\000\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\000\000\000"}, > {336, "list_for", 0, 6, states_80, > @@ -2043,13 +2035,13 @@ > {340, "gen_if", 0, 4, states_84, > "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, > {341, "testlist1", 0, 2, states_85, > - "\000\040\010\000\000\000\000\000\000\100\000\000\000\200\040\000\000\206\220\014\000\000"}, > + "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, > {342, "encoding_decl", 0, 2, states_86, > "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, > {343, "yield_expr", 0, 3, states_87, > - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002"}, > + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"}, > }; > -static label labels[170] = { > +static label labels[171] = { > {0, "EMPTY"}, > {256, 0}, > {4, 0}, > @@ -2206,6 +2198,7 @@ > {27, 0}, > {2, 0}, > {3, 0}, > + {52, 0}, > {336, 0}, > {339, 0}, > {326, 0}, > @@ -2224,6 +2217,6 @@ > grammar _PyParser_Grammar = { > 88, > dfas, > - {170, labels}, > + {171, labels}, > 256 > }; > _______________________________________________ > Python-3000-checkins mailing list > Python-3000-checkins at python.org > http://mail.python.org/mailman/listinfo/python-3000-checkins > -- --Guido van Rossum (home page: http://www.python.org/~guido/) From g.brandl at gmx.net Mon Mar 19 16:32:11 2007 From: g.brandl at gmx.net (Georg Brandl) Date: Mon, 19 Mar 2007 16:32:11 +0100 Subject: [Python-3000-checkins] r54434 - in python/branches/p3yk: Grammar/Grammar Include/token.h Lib/compiler/transformer.py Lib/test/test_grammar.py Lib/token.py Lib/tokenize.py Parser/tokenizer.c Python/ast.c Python/graminit.c In-Reply-To: References: <20070318190159.A5D251E400D@bag.python.org> Message-ID: Guido van Rossum schrieb: > Cool. Do you think you can port this to the modified copy of > tokenize.py in 2to3? That is, recognize "..." and yield it as "OP"? > (I wonder if this wouldn't be a candidate for 2.6 too.) It would certainly be backportable. Since Thomas Wouters said he'd rather see no backports to the trunk at the moment, I'll put it on my to-do list. Georg From guido at python.org Mon Mar 19 17:52:21 2007 From: guido at python.org (Guido van Rossum) Date: Mon, 19 Mar 2007 09:52:21 -0700 Subject: [Python-3000-checkins] r54434 - in python/branches/p3yk: Grammar/Grammar Include/token.h Lib/compiler/transformer.py Lib/test/test_grammar.py Lib/token.py Lib/tokenize.py Parser/tokenizer.c Python/ast.c Python/graminit.c In-Reply-To: References: <20070318190159.A5D251E400D@bag.python.org> Message-ID: On 3/19/07, Georg Brandl wrote: > Guido van Rossum schrieb: > > Cool. Do you think you can port this to the modified copy of > > tokenize.py in 2to3? > > That is, recognize "..." and yield it as "OP"? Yes. (And modify the Grammar.txt file to match.) > > (I wonder if this wouldn't be a candidate for 2.6 too.) > > It would certainly be backportable. > > Since Thomas Wouters said he'd rather see no backports to the trunk at the > moment, I'll put it on my to-do list. Fair enough. -- --Guido van Rossum (home page: http://www.python.org/~guido/) From python-3000-checkins at python.org Mon Mar 19 18:56:08 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Mon, 19 Mar 2007 18:56:08 +0100 (CET) Subject: [Python-3000-checkins] r54438 - in python/branches/p3yk/Lib: compiler/ast.py compiler/pyassem.py compiler/pycodegen.py compiler/symbols.py compiler/transformer.py test/test_ast.py test/test_compiler.py Message-ID: <20070319175608.121F91E400B@bag.python.org> Author: guido.van.rossum Date: Mon Mar 19 18:56:01 2007 New Revision: 54438 Modified: python/branches/p3yk/Lib/compiler/ast.py python/branches/p3yk/Lib/compiler/pyassem.py python/branches/p3yk/Lib/compiler/pycodegen.py python/branches/p3yk/Lib/compiler/symbols.py python/branches/p3yk/Lib/compiler/transformer.py python/branches/p3yk/Lib/test/test_ast.py python/branches/p3yk/Lib/test/test_compiler.py Log: Fix the compiler package w.r.t. the new metaclass syntax. (It is still broken w.r.t. the new nonlocal keyword.) Remove a series of debug prints I accidentally left in test_ast.py. Modified: python/branches/p3yk/Lib/compiler/ast.py ============================================================================== --- python/branches/p3yk/Lib/compiler/ast.py (original) +++ python/branches/p3yk/Lib/compiler/ast.py Mon Mar 19 18:56:01 2007 @@ -311,9 +311,12 @@ return "CallFunc(%s, %s, %s, %s)" % (repr(self.node), repr(self.args), repr(self.star_args), repr(self.dstar_args)) class Class(Node): - def __init__(self, name, bases, doc, code, lineno=None): + def __init__(self, name, args, star_args, dstar_args, + doc, code, lineno=None): self.name = name - self.bases = bases + self.args = args + self.star_args = star_args + self.dstar_args = dstar_args self.doc = doc self.code = code self.lineno = lineno @@ -321,19 +324,30 @@ def getChildren(self): children = [] children.append(self.name) - children.extend(flatten(self.bases)) + children.extend(flatten(self.args)) + children.extend(self.star_args) + children.extend(self.dstar_args) children.append(self.doc) children.append(self.code) return tuple(children) def getChildNodes(self): nodelist = [] - nodelist.extend(flatten_nodes(self.bases)) + nodelist.extend(flatten_nodes(self.args)) + if self.star_args is not None: + nodelist.append(self.star_args) + if self.dstar_args is not None: + nodelist.append(self.dstar_args) nodelist.append(self.code) return tuple(nodelist) def __repr__(self): - return "Class(%s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code)) + return "Class(%r, %r, %r, %r, %r, %r)" % (self.name, + self.args, + self.star_args, + self.dstar_args, + self.doc, + self.code) class Compare(Node): def __init__(self, expr, ops, lineno=None): Modified: python/branches/p3yk/Lib/compiler/pyassem.py ============================================================================== --- python/branches/p3yk/Lib/compiler/pyassem.py (original) +++ python/branches/p3yk/Lib/compiler/pyassem.py Mon Mar 19 18:56:01 2007 @@ -786,7 +786,6 @@ 'PRINT_EXPR': -1, 'RETURN_VALUE': -1, 'YIELD_VALUE': -1, - 'BUILD_CLASS': -2, 'STORE_NAME': -1, 'STORE_ATTR': -2, 'DELETE_ATTR': -1, @@ -804,6 +803,8 @@ 'SETUP_FINALLY': 3, 'FOR_ITER': 1, 'WITH_CLEANUP': -1, + 'LOAD_BUILD_CLASS': 1, + 'STORE_LOCALS': -1, } # use pattern match patterns = [ Modified: python/branches/p3yk/Lib/compiler/pycodegen.py ============================================================================== --- python/branches/p3yk/Lib/compiler/pycodegen.py (original) +++ python/branches/p3yk/Lib/compiler/pycodegen.py Mon Mar 19 18:56:01 2007 @@ -435,13 +435,10 @@ walk(node.code, gen) gen.finish() self.set_lineno(node) - self.emit('LOAD_CONST', node.name) - for base in node.bases: - self.visit(base) - self.emit('BUILD_TUPLE', len(node.bases)) + self.emit('LOAD_BUILD_CLASS') self._makeClosure(gen, 0) - self.emit('CALL_FUNCTION', 0) - self.emit('BUILD_CLASS') + self.emit('LOAD_CONST', node.name) + self.finish_visit_call(node, 2) self.storeName(node.name) # The rest are standard visitor methods @@ -1115,10 +1112,11 @@ self.emit('STORE_SUBSCR') def visitCallFunc(self, node): - pos = 0 - kw = 0 self.set_lineno(node) self.visit(node.node) + self.finish_visit_call(node) + + def finish_visit_call(self, node, pos=0, kw=0): for arg in node.args: self.visit(arg) if isinstance(arg, ast.Keyword): @@ -1467,7 +1465,7 @@ def finish(self): self.graph.startExitBlock() - self.emit('LOAD_LOCALS') + self.emit('LOAD_CONST', None) self.emit('RETURN_VALUE') class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator): Modified: python/branches/p3yk/Lib/compiler/symbols.py ============================================================================== --- python/branches/p3yk/Lib/compiler/symbols.py (original) +++ python/branches/p3yk/Lib/compiler/symbols.py Mon Mar 19 18:56:01 2007 @@ -299,7 +299,7 @@ def visitClass(self, node, parent): parent.add_def(node.name) - for n in node.bases: + for n in node.args: self.visit(n, parent) scope = ClassScope(node.name, self.module) if parent.nested or isinstance(parent, FunctionScope): Modified: python/branches/p3yk/Lib/compiler/transformer.py ============================================================================== --- python/branches/p3yk/Lib/compiler/transformer.py (original) +++ python/branches/p3yk/Lib/compiler/transformer.py Mon Mar 19 18:56:01 2007 @@ -288,16 +288,16 @@ old_lambdef = lambdef def classdef(self, nodelist): - # classdef: 'class' NAME ['(' [testlist] ')'] ':' suite + # classdef: 'class' NAME ['(' [arglist] ')'] ':' suite name = nodelist[1][1] doc = self.get_docstring(nodelist[-1]) if nodelist[2][0] == token.COLON: - bases = [] + arglist = CallFunc(None, []) elif nodelist[3][0] == token.RPAR: - bases = [] + arglist = CallFunc(None, []) else: - bases = self.com_bases(nodelist[3]) + arglist = self.com_call_function(None, nodelist[3]) # code for class code = self.com_node(nodelist[-1]) @@ -307,7 +307,8 @@ assert isinstance(code.nodes[0], Discard) del code.nodes[0] - return Class(name, bases, doc, code, lineno=nodelist[1][2]) + return Class(name, arglist.args, arglist.star_args, arglist.dstar_args, + doc, code, lineno=nodelist[1][2]) def stmt(self, nodelist): return self.com_stmt(nodelist[0]) Modified: python/branches/p3yk/Lib/test/test_ast.py ============================================================================== --- python/branches/p3yk/Lib/test/test_ast.py (original) +++ python/branches/p3yk/Lib/test/test_ast.py Mon Mar 19 18:56:01 2007 @@ -144,13 +144,9 @@ (eval_tests, eval_results, "eval")): for i, o in itertools.izip(input, output): ast_tree = compile(i, "?", kind, 0x400) - if to_tuple(ast_tree) != o: - print("i=", i) - print("o=", o) - print("kind=", kind) - print("tree=", ast_tree) - print("tuple=", to_tuple(ast_tree)) - assert to_tuple(ast_tree) == o + tup = to_tuple(ast_tree) + assert tup == o, ("kind=%r\ninput=%r\nexpected=%r\ngot=%r" % + (kind, i, o, tup)) test_order(ast_tree, (0, 0)) #### EVERYTHING BELOW IS GENERATED ##### Modified: python/branches/p3yk/Lib/test/test_compiler.py ============================================================================== --- python/branches/p3yk/Lib/test/test_compiler.py (original) +++ python/branches/p3yk/Lib/test/test_compiler.py Mon Mar 19 18:56:01 2007 @@ -50,8 +50,8 @@ try: compiler.compile(buf, basename, "exec") except Exception as e: - args = list(e.args) - args[0] += "[in file %s]" % basename + args = list(e.args) or [""] + args[0] = "%s [in file %s]" % (args[0], basename) e.args = tuple(args) raise From guido at python.org Mon Mar 19 19:23:54 2007 From: guido at python.org (Guido van Rossum) Date: Mon, 19 Mar 2007 11:23:54 -0700 Subject: [Python-3000-checkins] r54434 - in python/branches/p3yk: Grammar/Grammar Include/token.h Lib/compiler/transformer.py Lib/test/test_grammar.py Lib/token.py Lib/tokenize.py Parser/tokenizer.c Python/ast.c Python/graminit.c In-Reply-To: <20070318190159.A5D251E400D@bag.python.org> References: <20070318190159.A5D251E400D@bag.python.org> Message-ID: Did you realize that this breaks test_modulefinder.py? It contains tests like from ... import something and the parser now returns an ellipsis token for the there dots instead of three '.' tokens. Since this is valid syntax (even though Thomas doesn't like it :-) we should fix this somehow. I guess the syntax should use ('.' | '...')+ where it currently uses '.'+ and ditto for '.'*. On 3/18/07, georg.brandl wrote: > Author: georg.brandl > Date: Sun Mar 18 20:01:53 2007 > New Revision: 54434 > > Modified: > python/branches/p3yk/Grammar/Grammar > python/branches/p3yk/Include/token.h > python/branches/p3yk/Lib/compiler/transformer.py > python/branches/p3yk/Lib/test/test_grammar.py > python/branches/p3yk/Lib/token.py > python/branches/p3yk/Lib/tokenize.py > python/branches/p3yk/Parser/tokenizer.c > python/branches/p3yk/Python/ast.c > python/branches/p3yk/Python/graminit.c > Log: > Make ELLIPSIS a separate token. This makes it a syntax error to write ". . ." for Ellipsis. -- --Guido van Rossum (home page: http://www.python.org/~guido/) From python-3000-checkins at python.org Mon Mar 19 19:56:53 2007 From: python-3000-checkins at python.org (georg.brandl) Date: Mon, 19 Mar 2007 19:56:53 +0100 (CET) Subject: [Python-3000-checkins] r54440 - in python/branches/p3yk: Grammar/Grammar Python/ast.c Message-ID: <20070319185653.2CB181E4003@bag.python.org> Author: georg.brandl Date: Mon Mar 19 19:56:50 2007 New Revision: 54440 Modified: python/branches/p3yk/Grammar/Grammar python/branches/p3yk/Python/ast.c Log: "from ... import x" should not be a syntax error... make import_stmt accept ELLIPSes and DOTs. Modified: python/branches/p3yk/Grammar/Grammar ============================================================================== --- python/branches/p3yk/Grammar/Grammar (original) +++ python/branches/p3yk/Grammar/Grammar Mon Mar 19 19:56:50 2007 @@ -55,7 +55,8 @@ raise_stmt: 'raise' [test [',' test [',' test]]] import_stmt: import_name | import_from import_name: 'import' dotted_as_names -import_from: ('from' ('.'* dotted_name | '.'+) +# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS +import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+) 'import' ('*' | '(' import_as_names ')' | import_as_names)) import_as_name: NAME ['as' NAME] dotted_as_name: dotted_name ['as' NAME] Modified: python/branches/p3yk/Python/ast.c ============================================================================== --- python/branches/p3yk/Python/ast.c (original) +++ python/branches/p3yk/Python/ast.c Mon Mar 19 19:56:50 2007 @@ -2406,8 +2406,8 @@ /* import_stmt: import_name | import_from import_name: 'import' dotted_as_names - import_from: 'from' ('.'* dotted_name | '.') 'import' - ('*' | '(' import_as_names ')' | import_as_names) + import_from: 'from' (('.' | '...')* dotted_name | ('.' | '...')+) + 'import' ('*' | '(' import_as_names ')' | import_as_names) */ int lineno; int col_offset; @@ -2445,6 +2445,10 @@ mod = alias_for_import_name(c, CHILD(n, idx)); idx++; break; + } else if (TYPE(CHILD(n, idx)) == ELLIPSIS) { + /* three consecutive dots are tokenized as one ELLIPSIS */ + ndots += 3; + continue; } else if (TYPE(CHILD(n, idx)) != DOT) { break; } From g.brandl at gmx.net Mon Mar 19 19:56:52 2007 From: g.brandl at gmx.net (Georg Brandl) Date: Mon, 19 Mar 2007 19:56:52 +0100 Subject: [Python-3000-checkins] r54434 - in python/branches/p3yk: Grammar/Grammar Include/token.h Lib/compiler/transformer.py Lib/test/test_grammar.py Lib/token.py Lib/tokenize.py Parser/tokenizer.c Python/ast.c Python/graminit.c In-Reply-To: References: <20070318190159.A5D251E400D@bag.python.org> Message-ID: Guido van Rossum schrieb: > Did you realize that this breaks test_modulefinder.py? It contains tests like > > from ... import something > > and the parser now returns an ellipsis token for the there dots > instead of three '.' tokens. Since this is valid syntax (even though > Thomas doesn't like it :-) we should fix this somehow. I guess the > syntax should use ('.' | '...')+ where it currently uses '.'+ and > ditto for '.'*. Argh, I saw the failure but decided it had nothing to do with my change... I'd never have thought of that new relative import syntax :) Should be fixed now. Georg From python-3000-checkins at python.org Mon Mar 19 23:24:00 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Mon, 19 Mar 2007 23:24:00 +0100 (CET) Subject: [Python-3000-checkins] r54451 - python/branches/p3yk/Lib/urllib.py Message-ID: <20070319222400.1DFAC1E4003@bag.python.org> Author: guido.van.rossum Date: Mon Mar 19 23:23:59 2007 New Revision: 54451 Modified: python/branches/p3yk/Lib/urllib.py Log: Use input() now that it is available. Modified: python/branches/p3yk/Lib/urllib.py ============================================================================== --- python/branches/p3yk/Lib/urllib.py (original) +++ python/branches/p3yk/Lib/urllib.py Mon Mar 19 23:23:59 2007 @@ -768,11 +768,9 @@ def prompt_user_passwd(self, host, realm): """Override this in a GUI environment!""" - import getpass, sys + import getpass try: - sys.stdout.write("Enter username for %s at %s: " % (realm, host)) - sys.stdout.flush() - user = sys.stdin.readline() + user = input("Enter username for %s at %s: " % (realm, host)) passwd = getpass.getpass("Enter password for %s in %s at %s: " % (user, realm, host)) return user, passwd From python-3000-checkins at python.org Mon Mar 19 23:26:29 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Mon, 19 Mar 2007 23:26:29 +0100 (CET) Subject: [Python-3000-checkins] r54452 - python/branches/p3yk/Lib/httplib.py Message-ID: <20070319222629.C9AE21E4011@bag.python.org> Author: guido.van.rossum Date: Mon Mar 19 23:26:27 2007 New Revision: 54452 Modified: python/branches/p3yk/Lib/httplib.py Log: Make test_socket_ssl.py pass by fixing some code that was incorrectly assuming that err.message was the Py3k way of writing err[0] in 2.x. The correct spelling is err.args[0]. Modified: python/branches/p3yk/Lib/httplib.py ============================================================================== --- python/branches/p3yk/Lib/httplib.py (original) +++ python/branches/p3yk/Lib/httplib.py Mon Mar 19 23:26:27 2007 @@ -714,7 +714,7 @@ else: self.sock.sendall(str) except socket.error as v: - if v[0] == 32: # Broken pipe + if v.args[0] == 32: # Broken pipe self.close() raise @@ -870,7 +870,7 @@ self._send_request(method, url, body, headers) except socket.error as v: # trap 'Broken pipe' if we're allowed to automatically reconnect - if v.message != 32 or not self.auto_open: + if v.args[0] != 32 or not self.auto_open: raise # try one more time self._send_request(method, url, body, headers) @@ -1020,7 +1020,7 @@ try: buf = self._ssl.read(self._bufsize) except socket.sslerror as err: - err_type = err.message + err_type = err.args[0] if (err_type == socket.SSL_ERROR_WANT_READ or err_type == socket.SSL_ERROR_WANT_WRITE): continue @@ -1029,7 +1029,7 @@ break raise except socket.error as err: - err_type = err.message + err_type = err.args[0] if err_type == errno.EINTR: continue if err_type == errno.EBADF: From python-3000-checkins at python.org Wed Mar 21 03:11:51 2007 From: python-3000-checkins at python.org (collin.winter) Date: Wed, 21 Mar 2007 03:11:51 +0100 (CET) Subject: [Python-3000-checkins] r54469 - in python/branches/p3yk/Doc/tools: buildindex.py custlib.py getversioninfo keywords.py listmodules.py mkackshtml mkhowto mkmodindex prechm.py refcounts.py sgmlconv/docfixer.py sgmlconv/esis2sgml.py sgmlconv/esistools.py sgmlconv/latex2esis.py undoc_symbols.py Message-ID: <20070321021151.881F91E4006@bag.python.org> Author: collin.winter Date: Wed Mar 21 03:11:39 2007 New Revision: 54469 Modified: python/branches/p3yk/Doc/tools/buildindex.py python/branches/p3yk/Doc/tools/custlib.py python/branches/p3yk/Doc/tools/getversioninfo python/branches/p3yk/Doc/tools/keywords.py python/branches/p3yk/Doc/tools/listmodules.py python/branches/p3yk/Doc/tools/mkackshtml python/branches/p3yk/Doc/tools/mkhowto python/branches/p3yk/Doc/tools/mkmodindex python/branches/p3yk/Doc/tools/prechm.py python/branches/p3yk/Doc/tools/refcounts.py python/branches/p3yk/Doc/tools/sgmlconv/docfixer.py python/branches/p3yk/Doc/tools/sgmlconv/esis2sgml.py python/branches/p3yk/Doc/tools/sgmlconv/esistools.py python/branches/p3yk/Doc/tools/sgmlconv/latex2esis.py python/branches/p3yk/Doc/tools/undoc_symbols.py Log: Run 2to3 over Doc/tools/. Modified: python/branches/p3yk/Doc/tools/buildindex.py ============================================================================== --- python/branches/p3yk/Doc/tools/buildindex.py (original) +++ python/branches/p3yk/Doc/tools/buildindex.py Wed Mar 21 03:11:39 2007 @@ -37,6 +37,15 @@ # build up the text self.text = split_entry_text(str) self.key = split_entry_key(str) + + def __eq__(self, other): + return cmp(self, other) == 0 + + def __lt__(self, other): + return cmp(self, other) == -1 + + def __gt__(self, other): + return cmp(self, other) == 1 def __cmp__(self, other): """Comparison operator includes sequence number, for use with @@ -380,8 +389,8 @@ sys.stderr.write("\n%s: %d index nodes" % (program, num_nodes)) else: open(ofn, "w").write(html) - print - print "%s: %d index nodes" % (program, num_nodes) + print() + print("%s: %d index nodes" % (program, num_nodes)) if __name__ == "__main__": Modified: python/branches/p3yk/Doc/tools/custlib.py ============================================================================== --- python/branches/p3yk/Doc/tools/custlib.py (original) +++ python/branches/p3yk/Doc/tools/custlib.py Wed Mar 21 03:11:39 2007 @@ -31,7 +31,7 @@ modules[base.lower()] = base # Minor oddity: the types module is documented in libtypes2.tex -if modules.has_key('types'): +if 'types' in modules: del modules['types'] modules['types2'] = None @@ -44,8 +44,8 @@ modname = file[3:-4] docs[modname] = modname -mlist = modules.keys() -mlist = filter(lambda x, docs=docs: docs.has_key(x), mlist) +mlist = list(modules.keys()) +mlist = filter(lambda x, docs=docs: x in docs, mlist) mlist.sort() mlist = map(lambda x, docs=docs: docs[x], mlist) @@ -55,7 +55,7 @@ # Write the boilerplate # XXX should be fancied up. -print """\documentstyle[twoside,11pt,myformat]{report} +print("""\documentstyle[twoside,11pt,myformat]{report} \\title{Python Library Reference} \\input{boilerplate} \\makeindex % tell \\index to actually write the .idx file @@ -68,11 +68,11 @@ \\end{abstract} \\pagebreak {\\parskip = 0mm \\tableofcontents} -\\pagebreak\\pagenumbering{arabic}""" +\\pagebreak\\pagenumbering{arabic}""") for modname in mlist: - print "\\input{lib%s}" % (modname,) + print("\\input{lib%s}" % (modname,)) # Write the end -print """\\input{custlib.ind} % Index -\\end{document}""" +print("""\\input{custlib.ind} % Index +\\end{document}""") Modified: python/branches/p3yk/Doc/tools/getversioninfo ============================================================================== --- python/branches/p3yk/Doc/tools/getversioninfo (original) +++ python/branches/p3yk/Doc/tools/getversioninfo Wed Mar 21 03:11:39 2007 @@ -68,4 +68,4 @@ "\\setshortversion{%s}\n" % (release, releaseinfo, shortversion)) -print release + releaseinfo +print(release + releaseinfo) Modified: python/branches/p3yk/Doc/tools/keywords.py ============================================================================== --- python/branches/p3yk/Doc/tools/keywords.py (original) +++ python/branches/p3yk/Doc/tools/keywords.py Wed Mar 21 03:11:39 2007 @@ -21,5 +21,5 @@ nrows = (len(l)+ncols-1)/ncols for i in range(nrows): for j in range(i, len(l), nrows): - print l[j].ljust(10), - print + print(l[j].ljust(10), end=' ') + print() Modified: python/branches/p3yk/Doc/tools/listmodules.py ============================================================================== --- python/branches/p3yk/Doc/tools/listmodules.py (original) +++ python/branches/p3yk/Doc/tools/listmodules.py Wed Mar 21 03:11:39 2007 @@ -40,8 +40,7 @@ for p in path: modules.update(getmodules(p)) - keys = modules.keys() - keys.sort() + keys = sorted(modules.keys()) # filter out known test packages def cb(m): @@ -79,7 +78,7 @@ if out is not sys.stdout: out.close() - print out.name, "ok (%d modules)" % len(modules) + print(out.name, "ok (%d modules)" % len(modules)) def getmodules(p): # get modules in a given directory Modified: python/branches/p3yk/Doc/tools/mkackshtml ============================================================================== --- python/branches/p3yk/Doc/tools/mkackshtml (original) +++ python/branches/p3yk/Doc/tools/mkackshtml Wed Mar 21 03:11:39 2007 @@ -26,7 +26,7 @@ options.variables["title"] = "Acknowledgements" options.parse(sys.argv[1:]) names = collect(sys.stdin) - percol = (len(names) + options.columns - 1) / options.columns + percol = (len(names) + options.columns - 1) // options.columns colnums = [] for i in range(options.columns): colnums.append(percol*i) Modified: python/branches/p3yk/Doc/tools/mkhowto ============================================================================== --- python/branches/p3yk/Doc/tools/mkhowto (original) +++ python/branches/p3yk/Doc/tools/mkhowto Wed Mar 21 03:11:39 2007 @@ -65,11 +65,11 @@ def usage(options, file): - print >>file, __doc__ % options + print(__doc__ % options, file=file) def error(options, message, err=2): - print >>sys.stderr, message - print >>sys.stderr + print(message, file=sys.stderr) + print(file=sys.stderr) usage(options, sys.stderr) sys.exit(2) @@ -132,7 +132,7 @@ try: return getattr(self, key) except AttributeError: - raise KeyError, key + raise KeyError(key) def parse(self, args): opts, args = getopt.getopt(args, "Hi:a:s:lDkqr:", @@ -289,7 +289,7 @@ if not imgs: self.warning( "Could not locate support images of type %s." - % `self.options.image_type`) + % repr(self.options.image_type)) for fn in imgs: new_fn = os.path.join(self.builddir, os.path.basename(fn)) shutil.copyfile(fn, new_fn) @@ -534,7 +534,7 @@ def message(self, msg): msg = "+++ " + msg if not self.options.quiet: - print msg + print(msg) self.log(msg + "\n") def warning(self, msg): Modified: python/branches/p3yk/Doc/tools/mkmodindex ============================================================================== --- python/branches/p3yk/Doc/tools/mkmodindex (original) +++ python/branches/p3yk/Doc/tools/mkmodindex Wed Mar 21 03:11:39 2007 @@ -49,7 +49,7 @@ def usage(self): program = os.path.basename(sys.argv[0]) - print __doc__ % {"program": program} + print(__doc__ % {"program": program}) links = [ ('author', 'acks.html', 'Acknowledgements'), @@ -143,8 +143,8 @@ if options.outputfile == "-": sys.stderr.write("%s: %d index nodes\n" % (program, num_nodes)) else: - print - print "%s: %d index nodes" % (program, num_nodes) + print() + print("%s: %d index nodes" % (program, num_nodes)) PLAT_DISCUSS = """ Modified: python/branches/p3yk/Doc/tools/prechm.py ============================================================================== --- python/branches/p3yk/Doc/tools/prechm.py (original) +++ python/branches/p3yk/Doc/tools/prechm.py Wed Mar 21 03:11:39 2007 @@ -413,7 +413,7 @@ def do_index(library, output): output.write('
    \n') for book in library: - print '\t', book.title, '-', book.indexpage + print('\t', book.title, '-', book.indexpage) if book.indexpage: index(book.directory, book.indexpage, output) output.write('
\n') @@ -421,7 +421,7 @@ def do_content(library, version, output): output.write(contents_header) for book in library: - print '\t', book.title, '-', book.firstpage + print('\t', book.title, '-', book.firstpage) path = book.directory + "/" + book.firstpage output.write('
  • ') output.write(object_sitemap % (book.title, path)) @@ -449,12 +449,12 @@ try: p = open(file, "w") except IOError as msg: - print file, ":", msg + print(file, ":", msg) sys.exit(1) return p def usage(): - print usage_mode + print(usage_mode) sys.exit(0) def do_it(args = None): @@ -467,7 +467,7 @@ try: optlist, args = getopt.getopt(args, 'ckpv:') except getopt.error as msg: - print msg + print(msg) usage() if not args or len(args) > 1: @@ -487,15 +487,15 @@ if not (('-p','') in optlist): fname = arch + '.stp' f = openfile(fname) - print "Building stoplist", fname, "..." + print("Building stoplist", fname, "...") words = stop_list.split() words.sort() for word in words: - print >> f, word + print(word, file=f) f.close() f = openfile(arch + '.hhp') - print "Building Project..." + print("Building Project...") do_project(library, f, arch, version) if version == '2.0.0': for image in os.listdir('icons'): @@ -505,13 +505,13 @@ if not (('-c','') in optlist): f = openfile(arch + '.hhc') - print "Building Table of Content..." + print("Building Table of Content...") do_content(library, version, f) f.close() if not (('-k','') in optlist): f = openfile(arch + '.hhk') - print "Building Index..." + print("Building Index...") do_index(library, f) f.close() Modified: python/branches/p3yk/Doc/tools/refcounts.py ============================================================================== --- python/branches/p3yk/Doc/tools/refcounts.py (original) +++ python/branches/p3yk/Doc/tools/refcounts.py Wed Mar 21 03:11:39 2007 @@ -69,24 +69,23 @@ def dump(d): """Dump the data in the 'canonical' format, with functions in sorted order.""" - items = d.items() - items.sort() + items = sorted(d.items()) first = 1 for k, entry in items: if first: first = 0 else: - print + print() s = entry.name + ":%s:%s:%s:" if entry.result_refs is None: r = "" else: r = entry.result_refs - print s % (entry.result_type, "", r) + print(s % (entry.result_type, "", r)) for t, n, r in entry.args: if r is None: r = "" - print s % (t, n, r) + print(s % (t, n, r)) def main(): Modified: python/branches/p3yk/Doc/tools/sgmlconv/docfixer.py ============================================================================== --- python/branches/p3yk/Doc/tools/sgmlconv/docfixer.py (original) +++ python/branches/p3yk/Doc/tools/sgmlconv/docfixer.py Wed Mar 21 03:11:39 2007 @@ -210,8 +210,7 @@ # 2a. if descriptor.hasAttribute("var"): if descname != "opcodedesc": - raise RuntimeError, \ - "got 'var' attribute on descriptor other than opcodedesc" + raise RuntimeError("got 'var' attribute on descriptor other than opcodedesc") variable = descriptor.getAttribute("var") if variable: args = doc.createElement("args") @@ -241,7 +240,7 @@ try: sig = methodline_to_signature(doc, children[pos]) except KeyError: - print oldchild.toxml() + print(oldchild.toxml()) raise newchildren.append(sig) else: @@ -347,7 +346,7 @@ while queue: node = queue[0] del queue[0] - if wsmap.has_key(node.nodeName): + if node.nodeName in wsmap: fixups.append(node) for child in node.childNodes: if child.nodeType == ELEMENT: @@ -962,8 +961,7 @@ gi = node.tagName if knownempty(gi): if node.hasChildNodes(): - raise ValueError, \ - "declared-empty node <%s> has children" % gi + raise ValueError("declared-empty node <%s> has children" % gi) ofp.write("e\n") for k, value in node.attributes.items(): if _token_rx.match(value): @@ -979,7 +977,7 @@ elif nodeType == ENTITY_REFERENCE: ofp.write("&%s\n" % node.nodeName) else: - raise RuntimeError, "unsupported node type: %s" % nodeType + raise RuntimeError("unsupported node type: %s" % nodeType) def convert(ifp, ofp): @@ -1033,7 +1031,7 @@ for gi in events.parser.get_empties(): d[gi] = gi for key in ("author", "pep", "rfc"): - if d.has_key(key): + if key in d: del d[key] knownempty = d.has_key # Modified: python/branches/p3yk/Doc/tools/sgmlconv/esis2sgml.py ============================================================================== --- python/branches/p3yk/Doc/tools/sgmlconv/esis2sgml.py (original) +++ python/branches/p3yk/Doc/tools/sgmlconv/esis2sgml.py Wed Mar 21 03:11:39 2007 @@ -44,8 +44,7 @@ def format_attrs(attrs, xml=0): - attrs = attrs.items() - attrs.sort() + attrs = sorted(attrs.items()) parts = [] append = parts.append for name, value in attrs: @@ -149,7 +148,7 @@ ofp.write("&%s;" % data) knownempty = 0 else: - raise RuntimeError, "unrecognized ESIS event type: '%s'" % type + raise RuntimeError("unrecognized ESIS event type: '%s'" % type) if LIST_EMPTIES: dump_empty_element_names(knownempties) @@ -170,8 +169,7 @@ if gi: d[gi] = gi fp = open(EMPTIES_FILENAME, "w") - gilist = d.keys() - gilist.sort() + gilist = sorted(d.keys()) fp.write("\n".join(gilist)) fp.write("\n") fp.close() Modified: python/branches/p3yk/Doc/tools/sgmlconv/esistools.py ============================================================================== --- python/branches/p3yk/Doc/tools/sgmlconv/esistools.py (original) +++ python/branches/p3yk/Doc/tools/sgmlconv/esistools.py Wed Mar 21 03:11:39 2007 @@ -29,7 +29,7 @@ n, s = s.split(";", 1) r = r + unichr(int(n)) else: - raise ValueError, "can't handle %r" % s + raise ValueError("can't handle %r" % s) return r @@ -80,7 +80,7 @@ self.setErrorHandler(errorHandler) def get_empties(self): - return self._empties.keys() + return list(self._empties.keys()) # # XMLReader interface @@ -270,7 +270,7 @@ return self._attrs[name][0] def get(self, name, default=None): - if self._attrs.has_key(name): + if name in self._attrs: return self._attrs[name][0] return default @@ -282,7 +282,7 @@ def values(self): L = [] - for value, type in self._attrs.values(): + for value, type in list(self._attrs.values()): L.append(value) return L Modified: python/branches/p3yk/Doc/tools/sgmlconv/latex2esis.py ============================================================================== --- python/branches/p3yk/Doc/tools/sgmlconv/latex2esis.py (original) +++ python/branches/p3yk/Doc/tools/sgmlconv/latex2esis.py Wed Mar 21 03:11:39 2007 @@ -472,7 +472,7 @@ name = attrs["name"] self.__current = TableEntry(name, environment=1) self.__current.verbatim = attrs.get("verbatim") == "yes" - if attrs.has_key("outputname"): + if "outputname" in attrs: self.__current.outputname = attrs.get("outputname") self.__current.endcloses = attrs.get("endcloses", "").split() def end_environment(self): @@ -482,11 +482,11 @@ name = attrs["name"] self.__current = TableEntry(name) self.__current.closes = attrs.get("closes", "").split() - if attrs.has_key("outputname"): + if "outputname" in attrs: self.__current.outputname = attrs.get("outputname") def end_macro(self): name = self.__current.name - if self.__table.has_key(name): + if name in self.__table: raise ValueError("name %r already in use" % (name,)) self.__table[name] = self.__current self.__current = None Modified: python/branches/p3yk/Doc/tools/undoc_symbols.py ============================================================================== --- python/branches/p3yk/Doc/tools/undoc_symbols.py (original) +++ python/branches/p3yk/Doc/tools/undoc_symbols.py Wed Mar 21 03:11:39 2007 @@ -80,11 +80,10 @@ fp = os.popen("ctags -IPyAPI_FUNC -IPy_GCC_ATTRIBUTE --c-types=%s -f - %s" % (TAG_KINDS, incfiles)) dict = findnames(fp, prefix) - names = dict.keys() - names.sort() + names = sorted(dict.keys()) for name in names: if not re.search("%s\\W" % name, docs): - print dict[name], name + print(dict[name], name) if __name__ == '__main__': srcdir = os.path.dirname(sys.argv[0]) From python-3000-checkins at python.org Wed Mar 21 03:14:14 2007 From: python-3000-checkins at python.org (collin.winter) Date: Wed, 21 Mar 2007 03:14:14 +0100 (CET) Subject: [Python-3000-checkins] r54470 - python/branches/p3yk/Doc/Makefile Message-ID: <20070321021414.BBB291E4006@bag.python.org> Author: collin.winter Date: Wed Mar 21 03:14:12 2007 New Revision: 54470 Modified: python/branches/p3yk/Doc/Makefile Log: Use the local python binary to build the docs, not whatever 'python' is on the PATH (which is probably Python 2.x, and we need 3.x). Modified: python/branches/p3yk/Doc/Makefile ============================================================================== --- python/branches/p3yk/Doc/Makefile (original) +++ python/branches/p3yk/Doc/Makefile Wed Mar 21 03:14:12 2007 @@ -73,7 +73,7 @@ # commontex/patchlevel.tex in their dependencies. RELEASE=$(shell $(PYTHON) tools/getversioninfo) -PYTHON= python +PYTHON= $(PWD)/../python DVIPS= dvips -N0 -t $(PAPER) # This is ugly! The issue here is that there are two different levels From python-3000-checkins at python.org Wed Mar 21 03:57:28 2007 From: python-3000-checkins at python.org (collin.winter) Date: Wed, 21 Mar 2007 03:57:28 +0100 (CET) Subject: [Python-3000-checkins] r54472 - in python/branches/p3yk: Doc/lib/libatexit.tex Doc/lib/libsys.tex Include/pythonrun.h Lib/atexit.py Lib/test/test___all__.py Lib/test/test_atexit.py Misc/NEWS Modules/Setup.dist Modules/atexitmodule.c Python/import.c Python/pythonrun.c Python/sysmodule.c setup.py Message-ID: <20070321025728.94DCB1E4006@bag.python.org> Author: collin.winter Date: Wed Mar 21 03:57:17 2007 New Revision: 54472 Added: python/branches/p3yk/Modules/atexitmodule.c (contents, props changed) Removed: python/branches/p3yk/Lib/atexit.py Modified: python/branches/p3yk/Doc/lib/libatexit.tex python/branches/p3yk/Doc/lib/libsys.tex python/branches/p3yk/Include/pythonrun.h python/branches/p3yk/Lib/test/test___all__.py python/branches/p3yk/Lib/test/test_atexit.py python/branches/p3yk/Misc/NEWS python/branches/p3yk/Modules/Setup.dist python/branches/p3yk/Python/import.c python/branches/p3yk/Python/pythonrun.c python/branches/p3yk/Python/sysmodule.c python/branches/p3yk/setup.py Log: Patch #1680961: remove sys.exitfunc and replace it with a private C API. Also, reimplement atexit in C so it can take advantage of this private API. Modified: python/branches/p3yk/Doc/lib/libatexit.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libatexit.tex (original) +++ python/branches/p3yk/Doc/lib/libatexit.tex Wed Mar 21 03:57:17 2007 @@ -1,32 +1,21 @@ \section{\module{atexit} --- Exit handlers} -\declaremodule{standard}{atexit} +\declaremodule{builtin}{atexit} \moduleauthor{Skip Montanaro}{skip at mojam.com} \sectionauthor{Skip Montanaro}{skip at mojam.com} \modulesynopsis{Register and execute cleanup functions.} \versionadded{2.0} -The \module{atexit} module defines a single function to register -cleanup functions. Functions thus registered are automatically -executed upon normal interpreter termination. - -Note: the functions registered via this module are not called when the program is killed by a -signal, when a Python fatal internal error is detected, or when -\function{os._exit()} is called. - -This is an alternate interface to the functionality provided by the -\code{sys.exitfunc} variable. -\withsubitem{(in sys)}{\ttindex{exitfunc}} - -Note: This module is unlikely to work correctly when used with other code -that sets \code{sys.exitfunc}. In particular, other core Python modules are -free to use \module{atexit} without the programmer's knowledge. Authors who -use \code{sys.exitfunc} should convert their code to use -\module{atexit} instead. The simplest way to convert code that sets -\code{sys.exitfunc} is to import \module{atexit} and register the function -that had been bound to \code{sys.exitfunc}. + +The \module{atexit} module defines functions to register and +unregister cleanup functions. Functions thus registered are +automatically executed upon normal interpreter termination. + +Note: the functions registered via this module are not called when +the program is killed by a signal, when a Python fatal internal +error is detected, or when \function{os._exit()} is called. \begin{funcdesc}{register}{func\optional{, *args\optional{, **kargs}}} Register \var{func} as a function to be executed at termination. Any @@ -47,7 +36,16 @@ \versionchanged[This function now returns \var{func} which makes it possible to use it as a decorator without binding the - original name to \code{None}]{2.6} + original name to \code{None}]{2.6} +\end{funcdesc} + +\begin{funcdesc}{unregister}{func} +Remove a function \var{func} from the list of functions to be run at +interpreter-shutdown. After calling \function{unregister()}, +\var{func} is guaranteed not to be called when the interpreter +shuts down. + +\versionadded{3.0} \end{funcdesc} Modified: python/branches/p3yk/Doc/lib/libsys.tex ============================================================================== --- python/branches/p3yk/Doc/lib/libsys.tex (original) +++ python/branches/p3yk/Doc/lib/libsys.tex Wed Mar 21 03:57:17 2007 @@ -218,19 +218,6 @@ program when an error occurs. \end{funcdesc} -\begin{datadesc}{exitfunc} - This value is not actually defined by the module, but can be set by - the user (or by a program) to specify a clean-up action at program - exit. When set, it should be a parameterless function. This - function will be called when the interpreter exits. Only one - function may be installed in this way; to allow multiple functions - which will be called at termination, use the \refmodule{atexit} - module. \note{The exit function is not called when the program is - killed by a signal, when a Python fatal internal error is detected, - or when \code{os._exit()} is called.} - \deprecated{2.4}{Use \refmodule{atexit} instead.} -\end{datadesc} - \begin{funcdesc}{getcheckinterval}{} Return the interpreter's ``check interval''; see \function{setcheckinterval()}. Modified: python/branches/p3yk/Include/pythonrun.h ============================================================================== --- python/branches/p3yk/Include/pythonrun.h (original) +++ python/branches/p3yk/Include/pythonrun.h Wed Mar 21 03:57:17 2007 @@ -69,6 +69,10 @@ PyAPI_FUNC(void) PyErr_PrintEx(int); PyAPI_FUNC(void) PyErr_Display(PyObject *, PyObject *, PyObject *); +/* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level + * exit functions. + */ +PyAPI_FUNC(void) _Py_PyAtExit(void (*func)(void)); PyAPI_FUNC(int) Py_AtExit(void (*func)(void)); PyAPI_FUNC(void) Py_Exit(int); Deleted: /python/branches/p3yk/Lib/atexit.py ============================================================================== --- /python/branches/p3yk/Lib/atexit.py Wed Mar 21 03:57:17 2007 +++ (empty file) @@ -1,65 +0,0 @@ -""" -atexit.py - allow programmer to define multiple exit functions to be executed -upon normal program termination. - -One public function, register, is defined. -""" - -__all__ = ["register"] - -import sys - -_exithandlers = [] -def _run_exitfuncs(): - """run any registered exit functions - - _exithandlers is traversed in reverse order so functions are executed - last in, first out. - """ - - exc_info = None - while _exithandlers: - func, targs, kargs = _exithandlers.pop() - try: - func(*targs, **kargs) - except SystemExit: - exc_info = sys.exc_info() - except: - import traceback - print("Error in atexit._run_exitfuncs:", file=sys.stderr) - traceback.print_exc() - exc_info = sys.exc_info() - - if exc_info is not None: - raise exc_info[0], exc_info[1], exc_info[2] - - -def register(func, *targs, **kargs): - """register a function to be executed upon normal program termination - - func - function to be called at exit - targs - optional arguments to pass to func - kargs - optional keyword arguments to pass to func - - func is returned to facilitate usage as a decorator. - """ - _exithandlers.append((func, targs, kargs)) - return func - -if hasattr(sys, "exitfunc"): - # Assume it's another registered exit function - append it to our list - register(sys.exitfunc) -sys.exitfunc = _run_exitfuncs - -if __name__ == "__main__": - def x1(): - print("running x1") - def x2(n): - print("running x2(%r)" % (n,)) - def x3(n, kwd=None): - print("running x3(%r, kwd=%r)" % (n, kwd)) - - register(x1) - register(x2, 12) - register(x3, 5, "bar") - register(x3, "no kwd args") Modified: python/branches/p3yk/Lib/test/test___all__.py ============================================================================== --- python/branches/p3yk/Lib/test/test___all__.py (original) +++ python/branches/p3yk/Lib/test/test___all__.py Wed Mar 21 03:57:17 2007 @@ -48,7 +48,6 @@ self.check_all("StringIO") self.check_all("UserString") self.check_all("aifc") - self.check_all("atexit") self.check_all("audiodev") self.check_all("base64") self.check_all("bdb") Modified: python/branches/p3yk/Lib/test/test_atexit.py ============================================================================== --- python/branches/p3yk/Lib/test/test_atexit.py (original) +++ python/branches/p3yk/Lib/test/test_atexit.py Wed Mar 21 03:57:17 2007 @@ -4,97 +4,112 @@ import atexit from test import test_support +### helpers +def h1(): + print("h1") + +def h2(): + print("h2") + +def h3(): + print("h3") + +def h4(*args, **kwargs): + print("h4", args, kwargs) + +def raise1(): + raise TypeError + +def raise2(): + raise SystemError + class TestCase(unittest.TestCase): + def setUp(self): + self.stream = StringIO.StringIO() + sys.stdout = sys.stderr = self.stream + atexit._clear() + + def tearDown(self): + sys.stdout = sys.__stdout__ + sys.stderr = sys.__stderr__ + atexit._clear() + def test_args(self): # be sure args are handled properly - s = StringIO.StringIO() - sys.stdout = sys.stderr = s - save_handlers = atexit._exithandlers - atexit._exithandlers = [] - try: - atexit.register(self.h1) - atexit.register(self.h4) - atexit.register(self.h4, 4, kw="abc") - atexit._run_exitfuncs() - finally: - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - atexit._exithandlers = save_handlers - self.assertEqual(s.getvalue(), "h4 (4,) {'kw': 'abc'}\nh4 () {}\nh1\n") + atexit.register(h1) + atexit.register(h4) + atexit.register(h4, 4, kw="abc") + atexit._run_exitfuncs() + + self.assertEqual(self.stream.getvalue(), + "h4 (4,) {'kw': 'abc'}\nh4 () {}\nh1\n") def test_order(self): # be sure handlers are executed in reverse order - s = StringIO.StringIO() - sys.stdout = sys.stderr = s - save_handlers = atexit._exithandlers - atexit._exithandlers = [] - try: - atexit.register(self.h1) - atexit.register(self.h2) - atexit.register(self.h3) - atexit._run_exitfuncs() - finally: - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - atexit._exithandlers = save_handlers - self.assertEqual(s.getvalue(), "h3\nh2\nh1\n") - - def test_sys_override(self): - # be sure a preset sys.exitfunc is handled properly - s = StringIO.StringIO() - sys.stdout = sys.stderr = s - save_handlers = atexit._exithandlers - atexit._exithandlers = [] - exfunc = sys.exitfunc - sys.exitfunc = self.h1 - reload(atexit) - try: - atexit.register(self.h2) - atexit._run_exitfuncs() - finally: - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - atexit._exithandlers = save_handlers - sys.exitfunc = exfunc - self.assertEqual(s.getvalue(), "h2\nh1\n") + atexit.register(h1) + atexit.register(h2) + atexit.register(h3) + atexit._run_exitfuncs() + + self.assertEqual(self.stream.getvalue(), "h3\nh2\nh1\n") def test_raise(self): # be sure raises are handled properly - s = StringIO.StringIO() - sys.stdout = sys.stderr = s - save_handlers = atexit._exithandlers - atexit._exithandlers = [] - try: - atexit.register(self.raise1) - atexit.register(self.raise2) - self.assertRaises(TypeError, atexit._run_exitfuncs) - finally: - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - atexit._exithandlers = save_handlers - - ### helpers - def h1(self): - print("h1") - - def h2(self): - print("h2") - - def h3(self): - print("h3") - - def h4(self, *args, **kwargs): - print("h4", args, kwargs) - - def raise1(self): - raise TypeError - - def raise2(self): - raise SystemError + atexit.register(raise1) + atexit.register(raise2) + + self.assertRaises(TypeError, atexit._run_exitfuncs) + + def test_stress(self): + a = [0] + def inc(): + a[0] += 1 + + for i in range(128): + atexit.register(inc) + atexit._run_exitfuncs() + + self.assertEqual(a[0], 128) + + def test_clear(self): + a = [0] + def inc(): + a[0] += 1 + + atexit.register(inc) + atexit._clear() + atexit._run_exitfuncs() + + self.assertEqual(a[0], 0) + + def test_unregister(self): + a = [0] + def inc(): + a[0] += 1 + def dec(): + a[0] -= 1 + + for i in range(4): + atexit.register(inc) + atexit.register(dec) + atexit.unregister(inc) + atexit._run_exitfuncs() + + self.assertEqual(a[0], -1) + + def test_bound_methods(self): + l = [] + atexit.register(l.append, 5) + atexit._run_exitfuncs() + self.assertEqual(l, [5]) + + atexit.unregister(l.append) + atexit._run_exitfuncs() + self.assertEqual(l, [5]) + def test_main(): test_support.run_unittest(TestCase) - if __name__ == "__main__": test_main() Modified: python/branches/p3yk/Misc/NEWS ============================================================================== --- python/branches/p3yk/Misc/NEWS (original) +++ python/branches/p3yk/Misc/NEWS Wed Mar 21 03:57:17 2007 @@ -28,6 +28,9 @@ Core and Builtins ----------------- +- Patch #1680961: sys.exitfunc has been removed and replaced with a private + C-level API. + - PEP 3115: new metaclasses: the metaclass is now specified as a keyword arg in the class statement, which can now use the full syntax of a parameter list. Also, the metaclass can implement a __prepare__ function @@ -156,6 +159,8 @@ Library ------- +- Patch #1680961: atexit has been reimplemented in C. + - Removed all traces of the sets module. Build Modified: python/branches/p3yk/Modules/Setup.dist ============================================================================== --- python/branches/p3yk/Modules/Setup.dist (original) +++ python/branches/p3yk/Modules/Setup.dist Wed Mar 21 03:57:17 2007 @@ -176,6 +176,7 @@ #collections collectionsmodule.c # Container types #itertools itertoolsmodule.c # Functions creating iterators for efficient looping #strop stropmodule.c # String manipulations +#atexit atexitmodule.c # Register functions to be run at interpreter-shutdown #unicodedata unicodedata.c # static Unicode character database Added: python/branches/p3yk/Modules/atexitmodule.c ============================================================================== --- (empty file) +++ python/branches/p3yk/Modules/atexitmodule.c Wed Mar 21 03:57:17 2007 @@ -0,0 +1,217 @@ +/* + * atexit - allow programmer to define multiple exit functions to be executed + * upon normal program termination. + * + * Translated from atexit.py by Collin Winter. + + Copyright 2007 Python Software Foundation. + */ + +#include "Python.h" + +/* ===================================================================== */ +/* Callback machinery. */ + +typedef struct { + PyObject *func; + PyObject *args; + PyObject *kwargs; +} atexit_callback; + +atexit_callback **atexit_callbacks; +int ncallbacks = 0; +int callback_len = 32; + +/* Installed into pythonrun.c's atexit mechanism */ + +void +atexit_callfuncs(void) +{ + PyObject *exc_type = NULL, *exc_value, *exc_tb, *r; + atexit_callback *cb; + int i; + + if (ncallbacks == 0) + return; + + for(i = ncallbacks - 1; i >= 0; i--) + { + cb = atexit_callbacks[i]; + if (cb == NULL) + continue; + + r = PyObject_Call(cb->func, cb->args, cb->kwargs); + Py_XDECREF(r); + if (r == NULL) { + if (exc_type) { + Py_DECREF(exc_type); + Py_DECREF(exc_value); + Py_DECREF(exc_tb); + } + PyErr_Fetch(&exc_type, &exc_value, &exc_tb); + if (!PyErr_ExceptionMatches(PyExc_SystemExit)) { + PySys_WriteStderr("Error in atexit._run_exitfuncs:\n"); + PyErr_Display(exc_type, exc_value, exc_tb); + } + } + } + + if (exc_type) + PyErr_Restore(exc_type, exc_value, exc_tb); +} + +void +atexit_delete_cb(int i) +{ + atexit_callback *cb = atexit_callbacks[i]; + atexit_callbacks[i] = NULL; + Py_DECREF(cb->func); + Py_DECREF(cb->args); + Py_XDECREF(cb->kwargs); + PyMem_Free(cb); +} + +/* ===================================================================== */ +/* Module methods. */ + +PyDoc_STRVAR(atexit_register__doc__, +"register(func, *args, **kwargs) -> func\n\ +\n\ +Register a function to be executed upon normal program termination\n\ +\n\ + func - function to be called at exit\n\ + args - optional arguments to pass to func\n\ + kwargs - optional keyword arguments to pass to func\n\ +\n\ + func is returned to facilitate usage as a decorator."); + +static PyObject * +atexit_register(PyObject *self, PyObject *args, PyObject *kwargs) +{ + atexit_callback *new_callback; + PyObject *func = NULL; + + if (ncallbacks >= callback_len) { + callback_len += 16; + atexit_callbacks = PyMem_Realloc(atexit_callbacks, + sizeof(atexit_callback*) * callback_len); + + } + + if (PyTuple_GET_SIZE(args) == 0) { + PyErr_SetString(PyExc_TypeError, + "register() takes at least 1 argument (0 given)"); + return NULL; + } + + func = PyTuple_GET_ITEM(args, 0); + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "the first argument must be callable"); + return NULL; + } + + new_callback = PyMem_Malloc(sizeof(atexit_callback)); + if (new_callback == NULL) + return PyErr_NoMemory(); + + new_callback->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args)); + if (new_callback->args == NULL) { + PyMem_Free(new_callback); + return NULL; + } + new_callback->func = func; + new_callback->kwargs = kwargs; + Py_INCREF(func); + Py_XINCREF(kwargs); + + atexit_callbacks[ncallbacks++] = new_callback; + + Py_INCREF(func); + return func; +} + +static PyObject * +atexit_run_exitfuncs(PyObject *self) +{ + atexit_callfuncs(); + if (PyErr_Occurred()) + return NULL; + Py_RETURN_NONE; +} + +static PyObject * +atexit_clear(PyObject *self) +{ + atexit_callback *cb; + int i; + + for(i = 0; i < ncallbacks; i++) + { + cb = atexit_callbacks[i]; + if (cb == NULL) + continue; + + atexit_delete_cb(i); + } + ncallbacks = 0; + Py_RETURN_NONE; +} + +static PyObject * +atexit_unregister(PyObject *self, PyObject *func) +{ + atexit_callback *cb; + int i, eq; + + for(i = 0; i < ncallbacks; i++) + { + cb = atexit_callbacks[i]; + if (cb == NULL) + continue; + + eq = PyObject_RichCompareBool(cb->func, func, Py_EQ); + if (eq < 0) + return NULL; + if (eq) + atexit_delete_cb(i); + } + Py_RETURN_NONE; +} + +static PyMethodDef atexit_methods[] = { + {"register", (PyCFunction) atexit_register, METH_VARARGS|METH_KEYWORDS, + atexit_register__doc__}, + {"_clear", (PyCFunction) atexit_clear, METH_NOARGS, + NULL}, + {"unregister", (PyCFunction) atexit_unregister, METH_O, + NULL}, + {"_run_exitfuncs", (PyCFunction) atexit_run_exitfuncs, METH_NOARGS, + NULL}, + {NULL, NULL} /* sentinel */ +}; + +/* ===================================================================== */ +/* Initialization function. */ + +PyDoc_STRVAR(atexit__doc__, +"atexit.py - allow programmer to define multiple exit functions to be executed\ +upon normal program termination.\n\ +\n\ +One public function, register, is defined.\n\ +"); + +PyMODINIT_FUNC +initatexit(void) +{ + PyObject *m; + + atexit_callbacks = PyMem_New(atexit_callback*, callback_len); + if (atexit_callbacks == NULL) + return; + + m = Py_InitModule3("atexit", atexit_methods, atexit__doc__); + if (m == NULL) + return; + + _Py_PyAtExit(atexit_callfuncs); +} Modified: python/branches/p3yk/Python/import.c ============================================================================== --- python/branches/p3yk/Python/import.c (original) +++ python/branches/p3yk/Python/import.c Wed Mar 21 03:57:17 2007 @@ -361,7 +361,7 @@ /* List of names to clear in sys */ static char* sys_deletes[] = { - "path", "argv", "ps1", "ps2", "exitfunc", + "path", "argv", "ps1", "ps2", "exc_type", "exc_value", "exc_traceback", "last_type", "last_value", "last_traceback", "path_hooks", "path_importer_cache", "meta_path", Modified: python/branches/p3yk/Python/pythonrun.c ============================================================================== --- python/branches/p3yk/Python/pythonrun.c (original) +++ python/branches/p3yk/Python/pythonrun.c Wed Mar 21 03:57:17 2007 @@ -56,7 +56,7 @@ PyCompilerFlags *); static void err_input(perrdetail *); static void initsigs(void); -static void call_sys_exitfunc(void); +static void call_py_exitfuncs(void); static void call_ll_exitfuncs(void); extern void _PyUnicode_Init(void); extern void _PyUnicode_Fini(void); @@ -355,7 +355,7 @@ * threads created thru it, so this also protects pending imports in * the threads created via Threading. */ - call_sys_exitfunc(); + call_py_exitfuncs(); initialized = 0; /* Get current thread state and interpreter pointer */ @@ -1557,6 +1557,23 @@ #include "pythread.h" #endif +static void (*pyexitfunc)(void) = NULL; +/* For the atexit module. */ +void _Py_PyAtExit(void (*func)(void)) +{ + pyexitfunc = func; +} + +static void +call_py_exitfuncs(void) +{ + if (pyexitfunc == NULL) + return; + + (*pyexitfunc)(); + PyErr_Clear(); +} + #define NEXITFUNCS 32 static void (*exitfuncs[NEXITFUNCS])(void); static int nexitfuncs = 0; @@ -1570,27 +1587,6 @@ } static void -call_sys_exitfunc(void) -{ - PyObject *exitfunc = PySys_GetObject("exitfunc"); - - if (exitfunc) { - PyObject *res; - Py_INCREF(exitfunc); - PySys_SetObject("exitfunc", (PyObject *)NULL); - res = PyEval_CallObject(exitfunc, (PyObject *)NULL); - if (res == NULL) { - if (!PyErr_ExceptionMatches(PyExc_SystemExit)) { - PySys_WriteStderr("Error in sys.exitfunc:\n"); - } - PyErr_Print(); - } - Py_DECREF(exitfunc); - } - -} - -static void call_ll_exitfuncs(void) { while (nexitfuncs > 0) Modified: python/branches/p3yk/Python/sysmodule.c ============================================================================== --- python/branches/p3yk/Python/sysmodule.c (original) +++ python/branches/p3yk/Python/sysmodule.c Wed Mar 21 03:57:17 2007 @@ -897,9 +897,6 @@ To customize printing in an interactive session or to install a custom\n\ top-level exception handler, assign other functions to replace these.\n\ \n\ -exitfunc -- if sys.exitfunc exists, this routine is called when Python exits\n\ - Assigning to sys.exitfunc is deprecated; use the atexit module instead.\n\ -\n\ stdin -- standard input file object; used by raw_input() and input()\n\ stdout -- standard output file object; used by print()\n\ stderr -- standard error object; used for error messages\n\ Modified: python/branches/p3yk/setup.py ============================================================================== --- python/branches/p3yk/setup.py (original) +++ python/branches/p3yk/setup.py Wed Mar 21 03:57:17 2007 @@ -379,6 +379,8 @@ exts.append( Extension('operator', ['operator.c']) ) # _functools exts.append( Extension("_functools", ["_functoolsmodule.c"]) ) + # atexit + exts.append( Extension("atexit", ["atexitmodule.c"]) ) # Python C API test module exts.append( Extension('_testcapi', ['_testcapimodule.c']) ) # profilers (_lsprof is for cProfile.py) From python-3000-checkins at python.org Wed Mar 21 05:45:14 2007 From: python-3000-checkins at python.org (neal.norwitz) Date: Wed, 21 Mar 2007 05:45:14 +0100 (CET) Subject: [Python-3000-checkins] r54478 - in python/branches/p3yk: Modules/atexitmodule.c PC/config.c Message-ID: <20070321044514.0AADA1E4006@bag.python.org> Author: neal.norwitz Date: Wed Mar 21 05:45:04 2007 New Revision: 54478 Modified: python/branches/p3yk/Modules/atexitmodule.c python/branches/p3yk/PC/config.c Log: Little fixes: * make some module variables static to prevent name pollution * Add some comments to clarify what's going on and some XXXs to address * Add a space after "for" before ( * exc_value and tb can be NULL in some cases * Get working on Windows (I think) Modified: python/branches/p3yk/Modules/atexitmodule.c ============================================================================== --- python/branches/p3yk/Modules/atexitmodule.c (original) +++ python/branches/p3yk/Modules/atexitmodule.c Wed Mar 21 05:45:04 2007 @@ -17,9 +17,9 @@ PyObject *kwargs; } atexit_callback; -atexit_callback **atexit_callbacks; -int ncallbacks = 0; -int callback_len = 32; +static atexit_callback **atexit_callbacks; +static int ncallbacks = 0; +static int callback_len = 32; /* Installed into pythonrun.c's atexit mechanism */ @@ -33,7 +33,7 @@ if (ncallbacks == 0) return; - for(i = ncallbacks - 1; i >= 0; i--) + for (i = ncallbacks - 1; i >= 0; i--) { cb = atexit_callbacks[i]; if (cb == NULL) @@ -42,10 +42,12 @@ r = PyObject_Call(cb->func, cb->args, cb->kwargs); Py_XDECREF(r); if (r == NULL) { + /* Maintain the last exception, but don't leak if there are + multiple exceptions. */ if (exc_type) { Py_DECREF(exc_type); - Py_DECREF(exc_value); - Py_DECREF(exc_tb); + Py_XDECREF(exc_value); + Py_XDECREF(exc_tb); } PyErr_Fetch(&exc_type, &exc_value, &exc_tb); if (!PyErr_ExceptionMatches(PyExc_SystemExit)) { @@ -92,6 +94,8 @@ if (ncallbacks >= callback_len) { callback_len += 16; + /* XXX(nnorwitz): this leaks if realloc() fails. It also + doesn't verify realloc() returns a valid (non-NULL) pointer. */ atexit_callbacks = PyMem_Realloc(atexit_callbacks, sizeof(atexit_callback*) * callback_len); @@ -145,7 +149,7 @@ atexit_callback *cb; int i; - for(i = 0; i < ncallbacks; i++) + for (i = 0; i < ncallbacks; i++) { cb = atexit_callbacks[i]; if (cb == NULL) @@ -163,7 +167,7 @@ atexit_callback *cb; int i, eq; - for(i = 0; i < ncallbacks; i++) + for (i = 0; i < ncallbacks; i++) { cb = atexit_callbacks[i]; if (cb == NULL) @@ -213,5 +217,8 @@ if (m == NULL) return; + /* XXX(nnorwitz): probably best to register a callback that will free + atexit_callbacks, otherwise valgrind will report memory leaks. + Need to call atexit_clear() first. */ _Py_PyAtExit(atexit_callfuncs); } Modified: python/branches/p3yk/PC/config.c ============================================================================== --- python/branches/p3yk/PC/config.c (original) +++ python/branches/p3yk/PC/config.c Wed Mar 21 05:45:04 2007 @@ -68,6 +68,7 @@ extern void init_lsprof(void); extern void init_ast(void); extern void init_types(void); +extern void initatexit(void); /* tools/freeze/makeconfig.py marker for additional "extern" */ /* -- ADDMODULE MARKER 1 -- */ @@ -79,6 +80,7 @@ {"array", initarray}, {"_ast", init_ast}, + {"atexit", initatexit}, #ifdef MS_WINDOWS #ifndef MS_WIN64 {"audioop", initaudioop}, From thomas at python.org Wed Mar 21 14:32:44 2007 From: thomas at python.org (Thomas Wouters) Date: Wed, 21 Mar 2007 14:32:44 +0100 Subject: [Python-3000-checkins] r54433 - in python/branches/p3yk: Doc/api/concrete.tex Doc/api/refcounts.dat Include/floatobject.h Misc/NEWS Objects/abstract.c Objects/floatobject.c In-Reply-To: <20070318183520.70D471E400A@bag.python.org> References: <20070318183520.70D471E400A@bag.python.org> Message-ID: <9e804ac0703210632s218e7720o34c3b3937a268085@mail.gmail.com> On 3/18/07, georg.brandl wrote: > > Author: georg.brandl > Date: Sun Mar 18 19:35:15 2007 > New Revision: 54433 > > Modified: > python/branches/p3yk/Doc/api/concrete.tex > python/branches/p3yk/Doc/api/refcounts.dat > python/branches/p3yk/Include/floatobject.h > python/branches/p3yk/Misc/NEWS > python/branches/p3yk/Objects/abstract.c > python/branches/p3yk/Objects/floatobject.c > Log: > Remove the deprecated and useless "pend" argument from > PyFloat_FromString. (fixes bug #1650903) > FWIW, I don't believe this is congruent with what Guido promised about C API stability. (On the other hand, *I* see no problem with cleanly breaking some of the backward compatiblity API cruft :) -- Thomas Wouters Hi! I'm a .signature virus! copy me into your .signature file to help me spread! -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/python-3000-checkins/attachments/20070321/c4ef7b0d/attachment.htm From g.brandl at gmx.net Wed Mar 21 14:49:56 2007 From: g.brandl at gmx.net (Georg Brandl) Date: Wed, 21 Mar 2007 14:49:56 +0100 Subject: [Python-3000-checkins] r54433 - in python/branches/p3yk: Doc/api/concrete.tex Doc/api/refcounts.dat Include/floatobject.h Misc/NEWS Objects/abstract.c Objects/floatobject.c In-Reply-To: <9e804ac0703210632s218e7720o34c3b3937a268085@mail.gmail.com> References: <20070318183520.70D471E400A@bag.python.org> <9e804ac0703210632s218e7720o34c3b3937a268085@mail.gmail.com> Message-ID: Thomas Wouters schrieb: > > > On 3/18/07, *georg.brandl* > wrote: > > Author: georg.brandl > Date: Sun Mar 18 19:35:15 2007 > New Revision: 54433 > > Modified: > python/branches/p3yk/Doc/api/concrete.tex > python/branches/p3yk/Doc/api/refcounts.dat > python/branches/p3yk/Include/floatobject.h > python/branches/p3yk/Misc/NEWS > python/branches/p3yk/Objects/abstract.c > python/branches/p3yk/Objects/floatobject.c > Log: > Remove the deprecated and useless "pend" argument from > PyFloat_FromString. (fixes bug #1650903) > > > FWIW, I don't believe this is congruent with what Guido promised about C > API stability. (On the other hand, *I* see no problem with cleanly > breaking some of the backward compatiblity API cruft :) I know, and I had these objections myself, but look what Guido himself said: """IMO it's OK to change the signature (for Py3k) since the compiler will report an error if you call it with the old signature. What's *not* OK is to keep the signature (or to keep it compatible anyway) but change the *behavior*, as that would cause bugs that are only caught (if at all) at runtime, and will hence be hard to debug. """ Georg From python-3000-checkins at python.org Wed Mar 21 21:10:59 2007 From: python-3000-checkins at python.org (collin.winter) Date: Wed, 21 Mar 2007 21:10:59 +0100 (CET) Subject: [Python-3000-checkins] r54493 - in python/branches/p3yk: Lib/test/test_bool.py Lib/test/test_operator.py Misc/NEWS Modules/operator.c Message-ID: <20070321201059.D1A111E4007@bag.python.org> Author: collin.winter Date: Wed Mar 21 21:10:51 2007 New Revision: 54493 Modified: python/branches/p3yk/Lib/test/test_bool.py python/branches/p3yk/Lib/test/test_operator.py python/branches/p3yk/Misc/NEWS python/branches/p3yk/Modules/operator.c Log: Remove isCallable() and sequenceIncludes() from the operator module. Modified: python/branches/p3yk/Lib/test/test_bool.py ============================================================================== --- python/branches/p3yk/Lib/test/test_bool.py (original) +++ python/branches/p3yk/Lib/test/test_bool.py Wed Mar 21 21:10:51 2007 @@ -257,8 +257,6 @@ import operator self.assertIs(operator.truth(0), False) self.assertIs(operator.truth(1), True) - self.assertIs(operator.isCallable(0), False) - self.assertIs(operator.isCallable(len), True) self.assertIs(operator.isNumberType(None), False) self.assertIs(operator.isNumberType(0), True) self.assertIs(operator.not_(1), False) Modified: python/branches/p3yk/Lib/test/test_operator.py ============================================================================== --- python/branches/p3yk/Lib/test/test_operator.py (original) +++ python/branches/p3yk/Lib/test/test_operator.py Wed Mar 21 21:10:51 2007 @@ -177,17 +177,6 @@ self.failUnlessRaises(TypeError, operator.invert, None) self.failUnless(operator.inv(4) == -5) - def test_isCallable(self): - self.failUnlessRaises(TypeError, operator.isCallable) - class C: - pass - def check(self, o, v): - self.assert_(operator.isCallable(o) == callable(o) == v) - check(self, 4, 0) - check(self, operator.isCallable, 1) - check(self, C, 1) - check(self, C(), 0) - def test_isMappingType(self): self.failUnlessRaises(TypeError, operator.isMappingType) self.failIf(operator.isMappingType(1)) @@ -296,8 +285,6 @@ self.failUnlessRaises(TypeError, operator.contains, None, None) self.failUnless(operator.contains(range(4), 2)) self.failIf(operator.contains(range(4), 5)) - self.failUnless(operator.sequenceIncludes(range(4), 2)) - self.failIf(operator.sequenceIncludes(range(4), 5)) def test_setitem(self): a = range(3) Modified: python/branches/p3yk/Misc/NEWS ============================================================================== --- python/branches/p3yk/Misc/NEWS (original) +++ python/branches/p3yk/Misc/NEWS Wed Mar 21 21:10:51 2007 @@ -156,6 +156,10 @@ Extension Modules ----------------- +- isCallable() and sequenceIncludes() have been removed from the operator + module. + + Library ------- Modified: python/branches/p3yk/Modules/operator.c ============================================================================== --- python/branches/p3yk/Modules/operator.c (original) +++ python/branches/p3yk/Modules/operator.c Wed Mar 21 21:10:51 2007 @@ -65,7 +65,6 @@ if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \ return PyObject_RichCompare(a1,a2,A); } -spami(isCallable , PyCallable_Check) spami(isNumberType , PyNumber_Check) spami(truth , PyObject_IsTrue) spam2(op_add , PyNumber_Add) @@ -102,7 +101,6 @@ spam2(op_iconcat , PySequence_InPlaceConcat) spamoi(op_irepeat , PySequence_InPlaceRepeat) spami2b(op_contains , PySequence_Contains) -spami2b(sequenceIncludes, PySequence_Contains) spamn2(indexOf , PySequence_Index) spamn2(countOf , PySequence_Count) spami(isMappingType , PyMapping_Check) @@ -218,8 +216,6 @@ static struct PyMethodDef operator_methods[] = { -spam1o(isCallable, - "isCallable(a) -- Same as callable(a).") spam1o(isNumberType, "isNumberType(a) -- Return True if a has a numeric type, False otherwise.") spam1o(isSequenceType, @@ -228,8 +224,6 @@ "truth(a) -- Return True if a is true, False otherwise.") spam2(contains,__contains__, "contains(a, b) -- Same as b in a (note reversed operands).") -spam1(sequenceIncludes, - "sequenceIncludes(a, b) -- Same as b in a (note reversed operands; deprecated).") spam1(indexOf, "indexOf(a, b) -- Return the first index of b in a.") spam1(countOf, From python-3000-checkins at python.org Wed Mar 21 22:27:03 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 21 Mar 2007 22:27:03 +0100 (CET) Subject: [Python-3000-checkins] r54502 - python/branches/p3yk/Python/compile.c Message-ID: <20070321212703.247C71E4007@bag.python.org> Author: guido.van.rossum Date: Wed Mar 21 22:26:58 2007 New Revision: 54502 Modified: python/branches/p3yk/Python/compile.c Log: Fix refleak in compiler. (A symbol table entry was leaked every time a class was compiled.) Modified: python/branches/p3yk/Python/compile.c ============================================================================== --- python/branches/p3yk/Python/compile.c (original) +++ python/branches/p3yk/Python/compile.c Wed Mar 21 22:26:58 2007 @@ -1519,6 +1519,7 @@ PyCodeObject *co; PyObject *str; PySTEntryObject *ste; + int err; /* initialize statics */ if (build_class == NULL) { @@ -1547,7 +1548,9 @@ if (ste == NULL) return 0; assert(PyList_Check(ste->ste_varnames)); - if (PyList_Append(ste->ste_varnames, locals) < 0) + err = PyList_Append(ste->ste_varnames, locals); + Py_DECREF(ste); + if (err < 0) return 0; /* 1. compile the class body into a code object */ From python-3000-checkins at python.org Wed Mar 21 23:26:26 2007 From: python-3000-checkins at python.org (brett.cannon) Date: Wed, 21 Mar 2007 23:26:26 +0100 (CET) Subject: [Python-3000-checkins] r54510 - in python/branches/p3yk/Lib: ConfigParser.py test/test_file.py Message-ID: <20070321222626.83B4E1E400F@bag.python.org> Author: brett.cannon Date: Wed Mar 21 23:26:20 2007 New Revision: 54510 Modified: python/branches/p3yk/Lib/ConfigParser.py python/branches/p3yk/Lib/test/test_file.py Log: When removing indexing/slicing on exceptions some places were changed inappropriately from ``e[0]`` to ``e.message`` instead of ``e.args[0]``. The reason it needs to be the last option is the dichotomy of 'message' and 'args': 'message' can be the empty string but args[0] can have a value if more than one argument was passed. Modified: python/branches/p3yk/Lib/ConfigParser.py ============================================================================== --- python/branches/p3yk/Lib/ConfigParser.py (original) +++ python/branches/p3yk/Lib/ConfigParser.py Wed Mar 21 23:26:20 2007 @@ -569,7 +569,7 @@ value = value % vars except KeyError as e: raise InterpolationMissingOptionError( - option, section, rawval, e.message) + option, section, rawval, e.args[0]) else: break if "%(" in value: Modified: python/branches/p3yk/Lib/test/test_file.py ============================================================================== --- python/branches/p3yk/Lib/test/test_file.py (original) +++ python/branches/p3yk/Lib/test/test_file.py Wed Mar 21 23:26:20 2007 @@ -156,7 +156,7 @@ try: f = open(TESTFN, bad_mode) except ValueError as msg: - if msg.message != 0: + if msg.args[0] != 0: s = str(msg) if s.find(TESTFN) != -1 or s.find(bad_mode) == -1: self.fail("bad error message for invalid mode: %s" % s) From python-3000-checkins at python.org Fri Mar 23 23:46:49 2007 From: python-3000-checkins at python.org (collin.winter) Date: Fri, 23 Mar 2007 23:46:49 +0100 (CET) Subject: [Python-3000-checkins] r54557 - python/branches/p3yk/Modules/atexitmodule.c Message-ID: <20070323224649.A85251E4008@bag.python.org> Author: collin.winter Date: Fri Mar 23 23:46:49 2007 New Revision: 54557 Modified: python/branches/p3yk/Modules/atexitmodule.c Log: Address some XXXs from Neal Norwitz. Modified: python/branches/p3yk/Modules/atexitmodule.c ============================================================================== --- python/branches/p3yk/Modules/atexitmodule.c (original) +++ python/branches/p3yk/Modules/atexitmodule.c Fri Mar 23 23:46:49 2007 @@ -8,6 +8,9 @@ #include "Python.h" +/* Forward declaration (for atexit_cleanup) */ +static PyObject *atexit_clear(PyObject*); + /* ===================================================================== */ /* Callback machinery. */ @@ -72,6 +75,13 @@ PyMem_Free(cb); } +void +atexit_cleanup(void) +{ + PyObject *r = atexit_clear(NULL); + Py_DECREF(r); +} + /* ===================================================================== */ /* Module methods. */ @@ -93,12 +103,13 @@ PyObject *func = NULL; if (ncallbacks >= callback_len) { + atexit_callback **r; callback_len += 16; - /* XXX(nnorwitz): this leaks if realloc() fails. It also - doesn't verify realloc() returns a valid (non-NULL) pointer. */ - atexit_callbacks = PyMem_Realloc(atexit_callbacks, - sizeof(atexit_callback*) * callback_len); - + r = (atexit_callback**)PyMem_Realloc(atexit_callbacks, + sizeof(atexit_callback*) * callback_len); + if (r == NULL) + return PyErr_NoMemory(); + atexit_callbacks = r; } if (PyTuple_GET_SIZE(args) == 0) { @@ -217,8 +228,8 @@ if (m == NULL) return; - /* XXX(nnorwitz): probably best to register a callback that will free - atexit_callbacks, otherwise valgrind will report memory leaks. - Need to call atexit_clear() first. */ _Py_PyAtExit(atexit_callfuncs); + /* Register a callback that will free + atexit_callbacks, otherwise valgrind will report memory leaks. */ + Py_AtExit(atexit_cleanup); } From python-3000-checkins at python.org Tue Mar 27 06:55:27 2007 From: python-3000-checkins at python.org (collin.winter) Date: Tue, 27 Mar 2007 06:55:27 +0200 (CEST) Subject: [Python-3000-checkins] r54583 - python/branches/p3yk/Lib/test/test_linuxaudiodev.py python/branches/p3yk/Lib/test/test_ossaudiodev.py Message-ID: <20070327045527.B44F51E4011@bag.python.org> Author: collin.winter Date: Tue Mar 27 06:55:27 2007 New Revision: 54583 Modified: python/branches/p3yk/Lib/test/test_linuxaudiodev.py python/branches/p3yk/Lib/test/test_ossaudiodev.py Log: Fix two bugs related to the remove of exception subscripting. Modified: python/branches/p3yk/Lib/test/test_linuxaudiodev.py ============================================================================== --- python/branches/p3yk/Lib/test/test_linuxaudiodev.py (original) +++ python/branches/p3yk/Lib/test/test_linuxaudiodev.py Tue Mar 27 06:55:27 2007 @@ -28,7 +28,7 @@ try: a = linuxaudiodev.open('w') except linuxaudiodev.error as msg: - if msg[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): + if msg.args[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): raise TestSkipped, msg raise TestFailed, msg Modified: python/branches/p3yk/Lib/test/test_ossaudiodev.py ============================================================================== --- python/branches/p3yk/Lib/test/test_ossaudiodev.py (original) +++ python/branches/p3yk/Lib/test/test_ossaudiodev.py Tue Mar 27 06:55:27 2007 @@ -49,7 +49,7 @@ try: dsp = ossaudiodev.open('w') except IOError as msg: - if msg[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): + if msg.args[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): raise TestSkipped, msg raise TestFailed, msg From python-3000-checkins at python.org Wed Mar 28 00:34:36 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 28 Mar 2007 00:34:36 +0200 (CEST) Subject: [Python-3000-checkins] r54587 - python/branches/p3yk/Python/graminit.c Message-ID: <20070327223436.BA1331E4006@bag.python.org> Author: guido.van.rossum Date: Wed Mar 28 00:34:34 2007 New Revision: 54587 Modified: python/branches/p3yk/Python/graminit.c Log: Looks like this file wasn't checked in. Modified: python/branches/p3yk/Python/graminit.c ============================================================================== --- python/branches/p3yk/Python/graminit.c (original) +++ python/branches/p3yk/Python/graminit.c Wed Mar 28 00:34:34 2007 @@ -616,12 +616,14 @@ static arc arcs_30_0[1] = { {77, 1}, }; -static arc arcs_30_1[2] = { +static arc arcs_30_1[3] = { {78, 2}, + {79, 2}, {12, 3}, }; -static arc arcs_30_2[3] = { +static arc arcs_30_2[4] = { {78, 2}, + {79, 2}, {12, 3}, {75, 4}, }; @@ -631,21 +633,21 @@ static arc arcs_30_4[3] = { {29, 5}, {13, 6}, - {79, 5}, + {80, 5}, }; static arc arcs_30_5[1] = { {0, 5}, }; static arc arcs_30_6[1] = { - {79, 7}, + {80, 7}, }; static arc arcs_30_7[1] = { {15, 5}, }; static state states_30[8] = { {1, arcs_30_0}, - {2, arcs_30_1}, - {3, arcs_30_2}, + {3, arcs_30_1}, + {4, arcs_30_2}, {1, arcs_30_3}, {3, arcs_30_4}, {1, arcs_30_5}, @@ -656,7 +658,7 @@ {19, 1}, }; static arc arcs_31_1[2] = { - {81, 2}, + {82, 2}, {0, 1}, }; static arc arcs_31_2[1] = { @@ -675,7 +677,7 @@ {12, 1}, }; static arc arcs_32_1[2] = { - {81, 2}, + {82, 2}, {0, 1}, }; static arc arcs_32_2[1] = { @@ -691,14 +693,14 @@ {1, arcs_32_3}, }; static arc arcs_33_0[1] = { - {80, 1}, + {81, 1}, }; static arc arcs_33_1[2] = { {28, 2}, {0, 1}, }; static arc arcs_33_2[2] = { - {80, 1}, + {81, 1}, {0, 2}, }; static state states_33[3] = { @@ -707,7 +709,7 @@ {2, arcs_33_2}, }; static arc arcs_34_0[1] = { - {82, 1}, + {83, 1}, }; static arc arcs_34_1[2] = { {28, 0}, @@ -729,7 +731,7 @@ {2, arcs_35_1}, }; static arc arcs_36_0[1] = { - {83, 1}, + {84, 1}, }; static arc arcs_36_1[1] = { {19, 2}, @@ -744,7 +746,7 @@ {2, arcs_36_2}, }; static arc arcs_37_0[1] = { - {84, 1}, + {85, 1}, }; static arc arcs_37_1[1] = { {19, 2}, @@ -759,7 +761,7 @@ {2, arcs_37_2}, }; static arc arcs_38_0[1] = { - {85, 1}, + {86, 1}, }; static arc arcs_38_1[1] = { {22, 2}, @@ -782,13 +784,13 @@ {1, arcs_38_4}, }; static arc arcs_39_0[7] = { - {86, 1}, {87, 1}, {88, 1}, {89, 1}, {90, 1}, - {17, 1}, {91, 1}, + {17, 1}, + {92, 1}, }; static arc arcs_39_1[1] = { {0, 1}, @@ -798,7 +800,7 @@ {1, arcs_39_1}, }; static arc arcs_40_0[1] = { - {92, 1}, + {93, 1}, }; static arc arcs_40_1[1] = { {22, 2}, @@ -810,8 +812,8 @@ {24, 4}, }; static arc arcs_40_4[3] = { - {93, 1}, - {94, 5}, + {94, 1}, + {95, 5}, {0, 4}, }; static arc arcs_40_5[1] = { @@ -834,7 +836,7 @@ {1, arcs_40_7}, }; static arc arcs_41_0[1] = { - {95, 1}, + {96, 1}, }; static arc arcs_41_1[1] = { {22, 2}, @@ -846,7 +848,7 @@ {24, 4}, }; static arc arcs_41_4[2] = { - {94, 5}, + {95, 5}, {0, 4}, }; static arc arcs_41_5[1] = { @@ -869,13 +871,13 @@ {1, arcs_41_7}, }; static arc arcs_42_0[1] = { - {96, 1}, + {97, 1}, }; static arc arcs_42_1[1] = { {62, 2}, }; static arc arcs_42_2[1] = { - {97, 3}, + {98, 3}, }; static arc arcs_42_3[1] = { {9, 4}, @@ -887,7 +889,7 @@ {24, 6}, }; static arc arcs_42_6[2] = { - {94, 7}, + {95, 7}, {0, 6}, }; static arc arcs_42_7[1] = { @@ -912,7 +914,7 @@ {1, arcs_42_9}, }; static arc arcs_43_0[1] = { - {98, 1}, + {99, 1}, }; static arc arcs_43_1[1] = { {23, 2}, @@ -921,8 +923,8 @@ {24, 3}, }; static arc arcs_43_3[2] = { - {99, 4}, - {100, 5}, + {100, 4}, + {101, 5}, }; static arc arcs_43_4[1] = { {23, 6}, @@ -937,9 +939,9 @@ {24, 9}, }; static arc arcs_43_8[4] = { - {99, 4}, - {94, 10}, - {100, 5}, + {100, 4}, + {95, 10}, + {101, 5}, {0, 8}, }; static arc arcs_43_9[1] = { @@ -952,7 +954,7 @@ {24, 12}, }; static arc arcs_43_12[2] = { - {100, 5}, + {101, 5}, {0, 12}, }; static state states_43[13] = { @@ -971,13 +973,13 @@ {2, arcs_43_12}, }; static arc arcs_44_0[1] = { - {101, 1}, + {102, 1}, }; static arc arcs_44_1[1] = { {22, 2}, }; static arc arcs_44_2[2] = { - {102, 3}, + {103, 3}, {23, 4}, }; static arc arcs_44_3[1] = { @@ -998,10 +1000,10 @@ {1, arcs_44_5}, }; static arc arcs_45_0[1] = { - {81, 1}, + {82, 1}, }; static arc arcs_45_1[1] = { - {103, 2}, + {104, 2}, }; static arc arcs_45_2[1] = { {0, 2}, @@ -1012,14 +1014,14 @@ {1, arcs_45_2}, }; static arc arcs_46_0[1] = { - {104, 1}, + {105, 1}, }; static arc arcs_46_1[2] = { {22, 2}, {0, 1}, }; static arc arcs_46_2[2] = { - {81, 3}, + {82, 3}, {0, 2}, }; static arc arcs_46_3[1] = { @@ -1043,14 +1045,14 @@ {0, 1}, }; static arc arcs_47_2[1] = { - {105, 3}, + {106, 3}, }; static arc arcs_47_3[1] = { {6, 4}, }; static arc arcs_47_4[2] = { {6, 4}, - {106, 1}, + {107, 1}, }; static state states_47[5] = { {2, arcs_47_0}, @@ -1060,21 +1062,21 @@ {2, arcs_47_4}, }; static arc arcs_48_0[1] = { - {108, 1}, + {109, 1}, }; static arc arcs_48_1[2] = { {28, 2}, {0, 1}, }; static arc arcs_48_2[1] = { - {108, 3}, + {109, 3}, }; static arc arcs_48_3[2] = { {28, 4}, {0, 3}, }; static arc arcs_48_4[2] = { - {108, 3}, + {109, 3}, {0, 4}, }; static state states_48[5] = { @@ -1085,8 +1087,8 @@ {2, arcs_48_4}, }; static arc arcs_49_0[2] = { - {109, 1}, {110, 1}, + {111, 1}, }; static arc arcs_49_1[1] = { {0, 1}, @@ -1096,7 +1098,7 @@ {1, arcs_49_1}, }; static arc arcs_50_0[1] = { - {111, 1}, + {112, 1}, }; static arc arcs_50_1[2] = { {33, 2}, @@ -1106,7 +1108,7 @@ {23, 3}, }; static arc arcs_50_3[1] = { - {108, 4}, + {109, 4}, }; static arc arcs_50_4[1] = { {0, 4}, @@ -1119,21 +1121,21 @@ {1, arcs_50_4}, }; static arc arcs_51_0[2] = { - {109, 1}, - {112, 2}, + {110, 1}, + {113, 2}, }; static arc arcs_51_1[2] = { - {92, 3}, + {93, 3}, {0, 1}, }; static arc arcs_51_2[1] = { {0, 2}, }; static arc arcs_51_3[1] = { - {109, 4}, + {110, 4}, }; static arc arcs_51_4[1] = { - {94, 5}, + {95, 5}, }; static arc arcs_51_5[1] = { {22, 2}, @@ -1147,10 +1149,10 @@ {1, arcs_51_5}, }; static arc arcs_52_0[1] = { - {113, 1}, + {114, 1}, }; static arc arcs_52_1[2] = { - {114, 0}, + {115, 0}, {0, 1}, }; static state states_52[2] = { @@ -1158,10 +1160,10 @@ {2, arcs_52_1}, }; static arc arcs_53_0[1] = { - {115, 1}, + {116, 1}, }; static arc arcs_53_1[2] = { - {116, 0}, + {117, 0}, {0, 1}, }; static state states_53[2] = { @@ -1169,11 +1171,11 @@ {2, arcs_53_1}, }; static arc arcs_54_0[2] = { - {117, 1}, - {118, 2}, + {118, 1}, + {119, 2}, }; static arc arcs_54_1[1] = { - {115, 2}, + {116, 2}, }; static arc arcs_54_2[1] = { {0, 2}, @@ -1184,10 +1186,10 @@ {1, arcs_54_2}, }; static arc arcs_55_0[1] = { - {103, 1}, + {104, 1}, }; static arc arcs_55_1[2] = { - {119, 0}, + {120, 0}, {0, 1}, }; static state states_55[2] = { @@ -1195,24 +1197,24 @@ {2, arcs_55_1}, }; static arc arcs_56_0[9] = { - {120, 1}, {121, 1}, {122, 1}, {123, 1}, {124, 1}, {125, 1}, - {97, 1}, - {117, 2}, - {126, 3}, + {126, 1}, + {98, 1}, + {118, 2}, + {127, 3}, }; static arc arcs_56_1[1] = { {0, 1}, }; static arc arcs_56_2[1] = { - {97, 1}, + {98, 1}, }; static arc arcs_56_3[2] = { - {117, 1}, + {118, 1}, {0, 3}, }; static state states_56[4] = { @@ -1222,10 +1224,10 @@ {2, arcs_56_3}, }; static arc arcs_57_0[1] = { - {127, 1}, + {128, 1}, }; static arc arcs_57_1[2] = { - {128, 0}, + {129, 0}, {0, 1}, }; static state states_57[2] = { @@ -1233,10 +1235,10 @@ {2, arcs_57_1}, }; static arc arcs_58_0[1] = { - {129, 1}, + {130, 1}, }; static arc arcs_58_1[2] = { - {130, 0}, + {131, 0}, {0, 1}, }; static state states_58[2] = { @@ -1244,10 +1246,10 @@ {2, arcs_58_1}, }; static arc arcs_59_0[1] = { - {131, 1}, + {132, 1}, }; static arc arcs_59_1[2] = { - {132, 0}, + {133, 0}, {0, 1}, }; static state states_59[2] = { @@ -1255,11 +1257,11 @@ {2, arcs_59_1}, }; static arc arcs_60_0[1] = { - {133, 1}, + {134, 1}, }; static arc arcs_60_1[3] = { - {134, 0}, {135, 0}, + {136, 0}, {0, 1}, }; static state states_60[2] = { @@ -1267,11 +1269,11 @@ {3, arcs_60_1}, }; static arc arcs_61_0[1] = { - {136, 1}, + {137, 1}, }; static arc arcs_61_1[3] = { - {137, 0}, {138, 0}, + {139, 0}, {0, 1}, }; static state states_61[2] = { @@ -1279,13 +1281,13 @@ {3, arcs_61_1}, }; static arc arcs_62_0[1] = { - {139, 1}, + {140, 1}, }; static arc arcs_62_1[5] = { {29, 0}, - {140, 0}, {141, 0}, {142, 0}, + {143, 0}, {0, 1}, }; static state states_62[2] = { @@ -1293,13 +1295,13 @@ {5, arcs_62_1}, }; static arc arcs_63_0[4] = { - {137, 1}, {138, 1}, - {143, 1}, - {144, 2}, + {139, 1}, + {144, 1}, + {145, 2}, }; static arc arcs_63_1[1] = { - {139, 2}, + {140, 2}, }; static arc arcs_63_2[1] = { {0, 2}, @@ -1310,15 +1312,15 @@ {1, arcs_63_2}, }; static arc arcs_64_0[1] = { - {145, 1}, + {146, 1}, }; static arc arcs_64_1[3] = { - {146, 1}, + {147, 1}, {31, 2}, {0, 1}, }; static arc arcs_64_2[1] = { - {139, 3}, + {140, 3}, }; static arc arcs_64_3[1] = { {0, 3}, @@ -1331,41 +1333,41 @@ }; static arc arcs_65_0[7] = { {13, 1}, - {148, 2}, - {151, 3}, + {149, 2}, + {152, 3}, {19, 4}, - {154, 4}, - {155, 5}, - {156, 4}, + {155, 4}, + {156, 5}, + {79, 4}, }; static arc arcs_65_1[3] = { {48, 6}, - {147, 6}, + {148, 6}, {15, 4}, }; static arc arcs_65_2[2] = { - {149, 7}, - {150, 4}, + {150, 7}, + {151, 4}, }; static arc arcs_65_3[2] = { - {152, 8}, - {153, 4}, + {153, 8}, + {154, 4}, }; static arc arcs_65_4[1] = { {0, 4}, }; static arc arcs_65_5[2] = { - {155, 5}, + {156, 5}, {0, 5}, }; static arc arcs_65_6[1] = { {15, 4}, }; static arc arcs_65_7[1] = { - {150, 4}, + {151, 4}, }; static arc arcs_65_8[1] = { - {153, 4}, + {154, 4}, }; static state states_65[9] = { {7, arcs_65_0}, @@ -1431,7 +1433,7 @@ {2, arcs_67_4}, }; static arc arcs_68_0[1] = { - {111, 1}, + {112, 1}, }; static arc arcs_68_1[2] = { {33, 2}, @@ -1455,7 +1457,7 @@ }; static arc arcs_69_0[3] = { {13, 1}, - {148, 2}, + {149, 2}, {78, 3}, }; static arc arcs_69_1[2] = { @@ -1475,7 +1477,7 @@ {0, 5}, }; static arc arcs_69_6[1] = { - {150, 5}, + {151, 5}, }; static state states_69[7] = { {3, arcs_69_0}, @@ -1545,14 +1547,14 @@ {1, arcs_72_2}, }; static arc arcs_73_0[1] = { - {103, 1}, + {104, 1}, }; static arc arcs_73_1[2] = { {28, 2}, {0, 1}, }; static arc arcs_73_2[2] = { - {103, 1}, + {104, 1}, {0, 2}, }; static state states_73[3] = { @@ -1725,16 +1727,16 @@ {1, arcs_79_1}, }; static arc arcs_80_0[1] = { - {96, 1}, + {97, 1}, }; static arc arcs_80_1[1] = { {62, 2}, }; static arc arcs_80_2[1] = { - {97, 3}, + {98, 3}, }; static arc arcs_80_3[1] = { - {107, 4}, + {108, 4}, }; static arc arcs_80_4[2] = { {164, 5}, @@ -1752,10 +1754,10 @@ {1, arcs_80_5}, }; static arc arcs_81_0[1] = { - {92, 1}, + {93, 1}, }; static arc arcs_81_1[1] = { - {108, 2}, + {109, 2}, }; static arc arcs_81_2[2] = { {164, 3}, @@ -1782,16 +1784,16 @@ {1, arcs_82_1}, }; static arc arcs_83_0[1] = { - {96, 1}, + {97, 1}, }; static arc arcs_83_1[1] = { {62, 2}, }; static arc arcs_83_2[1] = { - {97, 3}, + {98, 3}, }; static arc arcs_83_3[1] = { - {109, 4}, + {110, 4}, }; static arc arcs_83_4[2] = { {166, 5}, @@ -1809,10 +1811,10 @@ {1, arcs_83_5}, }; static arc arcs_84_0[1] = { - {92, 1}, + {93, 1}, }; static arc arcs_84_1[1] = { - {108, 2}, + {109, 2}, }; static arc arcs_84_2[2] = { {166, 3}, @@ -1865,11 +1867,11 @@ }; static dfa dfas[88] = { {256, "single_input", 0, 3, states_0, - "\004\050\014\000\000\000\000\240\340\051\070\220\045\200\040\000\000\206\220\034\004\004"}, + "\004\050\014\000\000\000\000\240\340\251\160\040\113\000\101\000\000\014\041\031\004\004"}, {257, "file_input", 0, 2, states_1, - "\204\050\014\000\000\000\000\240\340\051\070\220\045\200\040\000\000\206\220\034\004\004"}, + "\204\050\014\000\000\000\000\240\340\251\160\040\113\000\101\000\000\014\041\031\004\004"}, {258, "eval_input", 0, 3, states_2, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {259, "decorator", 0, 7, states_3, "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {260, "decorators", 0, 2, states_4, @@ -1895,13 +1897,13 @@ {270, "vfplist", 0, 3, states_14, "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {271, "stmt", 0, 2, states_15, - "\000\050\014\000\000\000\000\240\340\051\070\220\045\200\040\000\000\206\220\034\004\004"}, + "\000\050\014\000\000\000\000\240\340\251\160\040\113\000\101\000\000\014\041\031\004\004"}, {272, "simple_stmt", 0, 4, states_16, - "\000\040\010\000\000\000\000\240\340\051\070\000\000\200\040\000\000\206\220\034\000\004"}, + "\000\040\010\000\000\000\000\240\340\251\160\000\000\000\101\000\000\014\041\031\000\004"}, {273, "small_stmt", 0, 2, states_17, - "\000\040\010\000\000\000\000\240\340\051\070\000\000\200\040\000\000\206\220\034\000\004"}, + "\000\040\010\000\000\000\000\240\340\251\160\000\000\000\101\000\000\014\041\031\000\004"}, {274, "expr_stmt", 0, 6, states_18, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {275, "augassign", 0, 2, states_19, "\000\000\000\000\000\000\376\037\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {276, "del_stmt", 0, 3, states_20, @@ -1937,105 +1939,105 @@ {291, "dotted_name", 0, 2, states_35, "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {292, "global_stmt", 0, 3, states_36, - "\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000"}, - {293, "nonlocal_stmt", 0, 3, states_37, "\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000"}, - {294, "assert_stmt", 0, 5, states_38, + {293, "nonlocal_stmt", 0, 3, states_37, "\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000"}, + {294, "assert_stmt", 0, 5, states_38, + "\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000"}, {295, "compound_stmt", 0, 2, states_39, - "\000\010\004\000\000\000\000\000\000\000\000\220\045\000\000\000\000\000\000\000\004\000"}, + "\000\010\004\000\000\000\000\000\000\000\000\040\113\000\000\000\000\000\000\000\004\000"}, {296, "if_stmt", 0, 8, states_40, - "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"}, {297, "while_stmt", 0, 8, states_41, - "\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000"}, - {298, "for_stmt", 0, 10, states_42, "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000"}, + {298, "for_stmt", 0, 10, states_42, + "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"}, {299, "try_stmt", 0, 13, states_43, - "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000"}, {300, "with_stmt", 0, 6, states_44, - "\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"}, {301, "with_var", 0, 3, states_45, - "\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000"}, {302, "except_clause", 0, 5, states_46, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"}, {303, "suite", 0, 5, states_47, - "\004\040\010\000\000\000\000\240\340\051\070\000\000\200\040\000\000\206\220\034\000\004"}, + "\004\040\010\000\000\000\000\240\340\251\160\000\000\000\101\000\000\014\041\031\000\004"}, {304, "testlist_safe", 0, 5, states_48, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {305, "old_test", 0, 2, states_49, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {306, "old_lambdef", 0, 5, states_50, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"}, {307, "test", 0, 6, states_51, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {308, "or_test", 0, 2, states_52, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\100\000\000\014\041\031\000\000"}, {309, "and_test", 0, 2, states_53, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\100\000\000\014\041\031\000\000"}, {310, "not_test", 0, 3, states_54, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\100\000\000\014\041\031\000\000"}, {311, "comparison", 0, 2, states_55, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"}, {312, "comp_op", 0, 4, states_56, - "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\040\177\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\100\376\000\000\000\000\000\000"}, {313, "expr", 0, 2, states_57, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"}, {314, "xor_expr", 0, 2, states_58, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"}, {315, "and_expr", 0, 2, states_59, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"}, {316, "shift_expr", 0, 2, states_60, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"}, {317, "arith_expr", 0, 2, states_61, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"}, {318, "term", 0, 2, states_62, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"}, {319, "factor", 0, 3, states_63, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"}, {320, "power", 0, 4, states_64, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\040\031\000\000"}, {321, "atom", 0, 9, states_65, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\040\031\000\000"}, {322, "listmaker", 0, 5, states_66, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {323, "testlist_gexp", 0, 5, states_67, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {324, "lambdef", 0, 5, states_68, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"}, {325, "trailer", 0, 7, states_69, - "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\020\000\000\000"}, + "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\040\000\000\000"}, {326, "subscriptlist", 0, 3, states_70, - "\000\040\210\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\210\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {327, "subscript", 0, 5, states_71, - "\000\040\210\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\210\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {328, "sliceop", 0, 3, states_72, "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {329, "exprlist", 0, 3, states_73, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"}, {330, "testlist", 0, 3, states_74, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {331, "dictsetmaker", 0, 8, states_75, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {332, "classdef", 0, 8, states_76, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000"}, {333, "arglist", 0, 8, states_77, - "\000\040\010\240\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\240\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {334, "argument", 0, 4, states_78, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {335, "list_iter", 0, 2, states_79, - "\000\000\000\000\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\040\002\000\000\000\000\000\000\000\000\000"}, {336, "list_for", 0, 6, states_80, - "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"}, {337, "list_if", 0, 4, states_81, - "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"}, {338, "gen_iter", 0, 2, states_82, - "\000\000\000\000\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\040\002\000\000\000\000\000\000\000\000\000"}, {339, "gen_for", 0, 6, states_83, - "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"}, {340, "gen_if", 0, 4, states_84, - "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"}, {341, "testlist1", 0, 2, states_85, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\200\040\000\000\206\220\034\000\000"}, + "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"}, {342, "encoding_decl", 0, 2, states_86, "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {343, "yield_expr", 0, 3, states_87, @@ -2121,6 +2123,7 @@ {290, 0}, {1, "from"}, {23, 0}, + {52, 0}, {289, 0}, {287, 0}, {1, "as"}, @@ -2198,7 +2201,6 @@ {27, 0}, {2, 0}, {3, 0}, - {52, 0}, {336, 0}, {339, 0}, {326, 0}, From python-3000-checkins at python.org Wed Mar 28 00:37:39 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 28 Mar 2007 00:37:39 +0200 (CEST) Subject: [Python-3000-checkins] r54588 - in python/branches/p3yk: Lib/test/test_compare.py Misc/NEWS Objects/typeobject.c Message-ID: <20070327223739.976DC1E400B@bag.python.org> Author: guido.van.rossum Date: Wed Mar 28 00:37:34 2007 New Revision: 54588 Modified: python/branches/p3yk/Lib/test/test_compare.py python/branches/p3yk/Misc/NEWS python/branches/p3yk/Objects/typeobject.c Log: By default, != returns the opposite of ==, unless the latter returns NotImplemented. (Is this worth backporting to 2.6? It seems so useful...!) Modified: python/branches/p3yk/Lib/test/test_compare.py ============================================================================== --- python/branches/p3yk/Lib/test/test_compare.py (original) +++ python/branches/p3yk/Lib/test/test_compare.py Wed Mar 28 00:37:34 2007 @@ -39,6 +39,12 @@ self.assertEqual(a == b, id(a) == id(b), 'a=%r, b=%r' % (a, b)) + def test_ne_defaults_to_not_eq(self): + a = Cmp(1) + b = Cmp(1) + self.assertTrue(a == b) + self.assertFalse(a != b) + def test_main(): test_support.run_unittest(ComparisonTest) Modified: python/branches/p3yk/Misc/NEWS ============================================================================== --- python/branches/p3yk/Misc/NEWS (original) +++ python/branches/p3yk/Misc/NEWS Wed Mar 28 00:37:34 2007 @@ -28,6 +28,9 @@ Core and Builtins ----------------- +- By default, != returns the opposite of ==, unless the latter returns + NotImplemented. + - Patch #1680961: sys.exitfunc has been removed and replaced with a private C-level API. Modified: python/branches/p3yk/Objects/typeobject.c ============================================================================== --- python/branches/p3yk/Objects/typeobject.c (original) +++ python/branches/p3yk/Objects/typeobject.c Wed Mar 28 00:37:34 2007 @@ -2314,7 +2314,22 @@ break; case Py_NE: - res = (self != other) ? Py_True : Py_False; + /* By default, != returns the opposite of ==, + unless the latter returns NotImplemented. */ + res = PyObject_RichCompare(self, other, Py_EQ); + if (res != NULL && res != Py_NotImplemented) { + int ok = PyObject_IsTrue(res); + Py_DECREF(res); + if (ok < 0) + res = NULL; + else { + if (ok) + res = Py_False; + else + res = Py_True; + Py_INCREF(res); + } + } break; default: From python-3000-checkins at python.org Wed Mar 28 02:30:16 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 28 Mar 2007 02:30:16 +0200 (CEST) Subject: [Python-3000-checkins] r54592 - in python/branches/p3yk/Lib: test/test_xreload.py xreload.py Message-ID: <20070328003016.1B8DB1E4006@bag.python.org> Author: guido.van.rossum Date: Wed Mar 28 02:30:15 2007 New Revision: 54592 Removed: python/branches/p3yk/Lib/test/test_xreload.py python/branches/p3yk/Lib/xreload.py Log: Moving xreload to the sandbox for now. Deleted: /python/branches/p3yk/Lib/test/test_xreload.py ============================================================================== --- /python/branches/p3yk/Lib/test/test_xreload.py Wed Mar 28 02:30:15 2007 +++ (empty file) @@ -1,103 +0,0 @@ -"""Doctests for module reloading. - ->>> from xreload import xreload ->>> from test.test_xreload import make_mod ->>> make_mod() ->>> import x ->>> C = x.C ->>> Cfoo = C.foo ->>> Cbar = C.bar ->>> Cstomp = C.stomp ->>> b = C() ->>> bfoo = b.foo ->>> b.foo() -42 ->>> bfoo() -42 ->>> Cfoo(b) -42 ->>> Cbar() -42 42 ->>> Cstomp() -42 42 42 ->>> make_mod(repl="42", subst="24") ->>> xreload(x) - ->>> b.foo() -24 ->>> bfoo() -24 ->>> Cfoo(b) -24 ->>> Cbar() -24 24 ->>> Cstomp() -24 24 24 - -""" - -SAMPLE_CODE = """ -class C: - def foo(self): - print(42) - @classmethod - def bar(cls): - print(42, 42) - @staticmethod - def stomp(): - print (42, 42, 42) -""" - -import os -import sys -import shutil -import doctest -import xreload -import tempfile -from test.test_support import run_unittest - -tempdir = None -save_path = None - - -def setUp(unused=None): - global tempdir, save_path - tempdir = tempfile.mkdtemp() - save_path = list(sys.path) - sys.path.append(tempdir) - - -def tearDown(unused=None): - global tempdir, save_path - if save_path is not None: - sys.path = save_path - save_path = None - if tempdir is not None: - shutil.rmtree(tempdir) - tempdir = None - - -def make_mod(name="x", repl=None, subst=None): - if not tempdir: - setUp() - assert tempdir - fn = os.path.join(tempdir, name + ".py") - f = open(fn, "w") - sample = SAMPLE_CODE - if repl is not None and subst is not None: - sample = sample.replace(repl, subst) - try: - f.write(sample) - finally: - f.close() - - -def test_suite(): - return doctest.DocTestSuite(setUp=setUp, tearDown=tearDown) - - -def test_main(): - run_unittest(test_suite()) - -if __name__ == "__main__": - test_main() Deleted: /python/branches/p3yk/Lib/xreload.py ============================================================================== --- /python/branches/p3yk/Lib/xreload.py Wed Mar 28 02:30:15 2007 +++ (empty file) @@ -1,190 +0,0 @@ -"""Alternative to reload(). - -This works by executing the module in a scratch namespace, and then -patching classes, methods and functions in place. This avoids the -need to patch instances. New objects are copied into the target -namespace. - -Some of the many limitiations include: - -- Global mutable objects other than classes are simply replaced, not patched - -- Code using metaclasses is not handled correctly - -- Code creating global singletons is not handled correctly - -- Functions and methods using decorators (other than classmethod and - staticmethod) is not handled correctly - -- Renamings are not handled correctly - -- Dependent modules are not reloaded - -- When a dependent module contains 'from foo import bar', and - reloading foo deletes foo.bar, the dependent module continues to use - the old foo.bar object rather than failing - -- Frozen modules and modules loaded from zip files aren't handled - correctly - -- Classes involving __slots__ are not handled correctly -""" - -import imp -import sys -import types - - -def xreload(mod): - """Reload a module in place, updating classes, methods and functions. - - Args: - mod: a module object - - Returns: - The (updated) input object itself. - """ - # Get the module name, e.g. 'foo.bar.whatever' - modname = mod.__name__ - # Get the module namespace (dict) early; this is part of the type check - modns = mod.__dict__ - # Parse it into package name and module name, e.g. 'foo.bar' and 'whatever' - i = modname.rfind(".") - if i >= 0: - pkgname, modname = modname[:i], modname[i+1:] - else: - pkgname = None - # Compute the search path - if pkgname: - # We're not reloading the package, only the module in it - pkg = sys.modules[pkgname] - path = pkg.__path__ # Search inside the package - else: - # Search the top-level module path - pkg = None - path = None # Make find_module() uses the default search path - # Find the module; may raise ImportError - (stream, filename, (suffix, mode, kind)) = imp.find_module(modname, path) - # Turn it into a code object - try: - # Is it Python source code or byte code read from a file? - if kind not in (imp.PY_COMPILED, imp.PY_SOURCE): - # Fall back to built-in reload() - return reload(mod) - if kind == imp.PY_SOURCE: - source = stream.read() - code = compile(source, filename, "exec") - else: - code = marshal.load(stream) - finally: - if stream: - stream.close() - # Execute the code. We copy the module dict to a temporary; then - # clear the module dict; then execute the new code in the module - # dict; then swap things back and around. This trick (due to - # Glyph Lefkowitz) ensures that the (readonly) __globals__ - # attribute of methods and functions is set to the correct dict - # object. - tmpns = modns.copy() - modns.clear() - modns["__name__"] = tmpns["__name__"] - exec(code, modns) - # Now we get to the hard part - oldnames = set(tmpns) - newnames = set(modns) - # Update attributes in place - for name in oldnames & newnames: - modns[name] = _update(tmpns[name], modns[name]) - # Done! - return mod - - -def _update(oldobj, newobj): - """Update oldobj, if possible in place, with newobj. - - If oldobj is immutable, this simply returns newobj. - - Args: - oldobj: the object to be updated - newobj: the object used as the source for the update - - Returns: - either oldobj, updated in place, or newobj. - """ - if oldobj is newobj: - # Probably something imported - return newobj - if type(oldobj) is not type(newobj): - # Cop-out: if the type changed, give up - return newobj - if hasattr(newobj, "__reload_update__"): - # Provide a hook for updating - return newobj.__reload_update__(oldobj) - if isinstance(newobj, types.ClassType): - return _update_class(oldobj, newobj) - if isinstance(newobj, types.FunctionType): - return _update_function(oldobj, newobj) - if isinstance(newobj, types.MethodType): - return _update_method(oldobj, newobj) - if isinstance(newobj, classmethod): - return _update_classmethod(oldobj, newobj) - if isinstance(newobj, staticmethod): - return _update_staticmethod(oldobj, newobj) - # Not something we recognize, just give up - return newobj - - -# All of the following functions have the same signature as _update() - - -def _update_function(oldfunc, newfunc): - """Update a function object.""" - oldfunc.__doc__ = newfunc.__doc__ - oldfunc.__dict__.update(newfunc.__dict__) - oldfunc.__code__ = newfunc.__code__ - oldfunc.__defaults__ = newfunc.__defaults__ - return oldfunc - - -def _update_method(oldmeth, newmeth): - """Update a method object.""" - # XXX What if im_func is not a function? - _update(oldmeth.im_func, newmeth.im_func) - return oldmeth - - -def _update_class(oldclass, newclass): - """Update a class object.""" - olddict = oldclass.__dict__ - newdict = newclass.__dict__ - oldnames = set(olddict) - newnames = set(newdict) - for name in newnames - oldnames: - setattr(oldclass, name, newdict[name]) - for name in oldnames - newnames: - delattr(oldclass, name) - for name in oldnames & newnames - {"__dict__", "__doc__"}: - setattr(oldclass, name, _update(olddict[name], newdict[name])) - return oldclass - - -def _update_classmethod(oldcm, newcm): - """Update a classmethod update.""" - # While we can't modify the classmethod object itself (it has no - # mutable attributes), we *can* extract the underlying function - # (by calling __get__(), which returns a method object) and update - # it in-place. We don't have the class available to pass to - # __get__() but any object except None will do. - _update(oldcm.__get__(0), newcm.__get__(0)) - return newcm - - -def _update_staticmethod(oldsm, newsm): - """Update a staticmethod update.""" - # While we can't modify the staticmethod object itself (it has no - # mutable attributes), we *can* extract the underlying function - # (by calling __get__(), which returns it) and update it in-place. - # We don't have the class available to pass to __get__() but any - # object except None will do. - _update(oldsm.__get__(0), newsm.__get__(0)) - return newsm From python-3000-checkins at python.org Wed Mar 28 23:02:46 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 28 Mar 2007 23:02:46 +0200 (CEST) Subject: [Python-3000-checkins] r54600 - python/branches/p3yk/Lib/bsddb/test/test_basics.py python/branches/p3yk/Lib/bsddb/test/test_recno.py Message-ID: <20070328210246.B2F651E4002@bag.python.org> Author: guido.van.rossum Date: Wed Mar 28 23:02:43 2007 New Revision: 54600 Modified: python/branches/p3yk/Lib/bsddb/test/test_basics.py python/branches/p3yk/Lib/bsddb/test/test_recno.py Log: Fix errors in bsddb3 tests due to removal of exception slicing. (There was also a segfault but it disappeared when the tests stopped erroring out; I presume the segfault is a pre-existing problem somewhere in a destructor.) Modified: python/branches/p3yk/Lib/bsddb/test/test_basics.py ============================================================================== --- python/branches/p3yk/Lib/bsddb/test/test_basics.py (original) +++ python/branches/p3yk/Lib/bsddb/test/test_basics.py Wed Mar 28 23:02:43 2007 @@ -163,7 +163,7 @@ try: d.delete('abcd') except db.DBNotFoundError as val: - assert val[0] == db.DB_NOTFOUND + assert val.args[0] == db.DB_NOTFOUND if verbose: print(val) else: self.fail("expected exception") @@ -182,7 +182,7 @@ try: d.put('abcd', 'this should fail', flags=db.DB_NOOVERWRITE) except db.DBKeyExistError as val: - assert val[0] == db.DB_KEYEXIST + assert val.args[0] == db.DB_KEYEXIST if verbose: print(val) else: self.fail("expected exception") @@ -315,7 +315,7 @@ rec = c.next() except db.DBNotFoundError as val: if get_raises_error: - assert val[0] == db.DB_NOTFOUND + assert val.args[0] == db.DB_NOTFOUND if verbose: print(val) rec = None else: @@ -335,7 +335,7 @@ rec = c.prev() except db.DBNotFoundError as val: if get_raises_error: - assert val[0] == db.DB_NOTFOUND + assert val.args[0] == db.DB_NOTFOUND if verbose: print(val) rec = None else: @@ -358,7 +358,7 @@ try: n = c.set('bad key') except db.DBNotFoundError as val: - assert val[0] == db.DB_NOTFOUND + assert val.args[0] == db.DB_NOTFOUND if verbose: print(val) else: if set_raises_error: @@ -372,7 +372,7 @@ try: n = c.get_both('0404', 'bad data') except db.DBNotFoundError as val: - assert val[0] == db.DB_NOTFOUND + assert val.args[0] == db.DB_NOTFOUND if verbose: print(val) else: if get_raises_error: @@ -401,7 +401,7 @@ rec = c.current() except db.DBKeyEmptyError as val: if get_raises_error: - assert val[0] == db.DB_KEYEMPTY + assert val.args[0] == db.DB_KEYEMPTY if verbose: print(val) else: self.fail("unexpected DBKeyEmptyError") @@ -446,7 +446,7 @@ # a bug may cause a NULL pointer dereference... getattr(c, method)(*args) except db.DBError as val: - assert val[0] == 0 + assert val.args[0] == 0 if verbose: print(val) else: self.fail("no exception raised when using a buggy cursor's" Modified: python/branches/p3yk/Lib/bsddb/test/test_recno.py ============================================================================== --- python/branches/p3yk/Lib/bsddb/test/test_recno.py (original) +++ python/branches/p3yk/Lib/bsddb/test/test_recno.py Wed Mar 28 23:02:43 2007 @@ -64,7 +64,7 @@ try: data = d[0] # This should raise a KeyError!?!?! except db.DBInvalidArgError as val: - assert val[0] == db.EINVAL + assert val.args[0] == db.EINVAL if verbose: print(val) else: self.fail("expected exception") @@ -181,7 +181,7 @@ if get_returns_none: self.fail("unexpected DBKeyEmptyError exception") else: - assert val[0] == db.DB_KEYEMPTY + assert val.args[0] == db.DB_KEYEMPTY if verbose: print(val) else: if not get_returns_none: @@ -268,7 +268,7 @@ try: # this one will fail d.append('bad' * 20) except db.DBInvalidArgError as val: - assert val[0] == db.EINVAL + assert val.args[0] == db.EINVAL if verbose: print(val) else: self.fail("expected exception") From python-3000-checkins at python.org Wed Mar 28 23:03:50 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 28 Mar 2007 23:03:50 +0200 (CEST) Subject: [Python-3000-checkins] r54601 - python/branches/p3yk/Lib/bsddb/dbtables.py Message-ID: <20070328210350.1F56D1E4002@bag.python.org> Author: guido.van.rossum Date: Wed Mar 28 23:03:48 2007 New Revision: 54601 Modified: python/branches/p3yk/Lib/bsddb/dbtables.py Log: More fixes related to removal of exception slicing. Modified: python/branches/p3yk/Lib/bsddb/dbtables.py ============================================================================== --- python/branches/p3yk/Lib/bsddb/dbtables.py (original) +++ python/branches/p3yk/Lib/bsddb/dbtables.py Wed Mar 28 23:03:48 2007 @@ -263,7 +263,7 @@ except DBError as dberror: if txn: txn.abort() - raise TableDBError, dberror[1] + raise TableDBError, dberror.args[1] def ListTableColumns(self, table): @@ -341,7 +341,7 @@ except DBError as dberror: if txn: txn.abort() - raise TableDBError, dberror[1] + raise TableDBError, dberror.args[1] def __load_column_info(self, table) : @@ -416,7 +416,7 @@ if txn: txn.abort() self.db.delete(_rowid_key(table, rowid)) - raise TableDBError, dberror[1], info[2] + raise TableDBError, dberror.args[1], info[2] def Modify(self, table, conditions={}, mappings={}): @@ -467,7 +467,7 @@ raise except DBError as dberror: - raise TableDBError, dberror[1] + raise TableDBError, dberror.args[1] def Delete(self, table, conditions={}): """Delete(table, conditions) - Delete items matching the given @@ -507,7 +507,7 @@ txn.abort() raise except DBError as dberror: - raise TableDBError, dberror[1] + raise TableDBError, dberror.args[1] def Select(self, table, columns, conditions={}): @@ -527,7 +527,7 @@ columns = self.__tablecolumns[table] matching_rowids = self.__Select(table, columns, conditions) except DBError as dberror: - raise TableDBError, dberror[1] + raise TableDBError, dberror.args[1] # return the matches as a list of dictionaries return matching_rowids.values() @@ -617,7 +617,7 @@ key, data = cur.next() except DBError as dberror: - if dberror[0] != DB_NOTFOUND: + if dberror.args[0] != DB_NOTFOUND: raise continue @@ -637,7 +637,7 @@ rowdata[column] = self.db.get( _data_key(table, column, rowid)) except DBError as dberror: - if dberror[0] != DB_NOTFOUND: + if dberror.args[0] != DB_NOTFOUND: raise rowdata[column] = None @@ -703,4 +703,4 @@ except DBError as dberror: if txn: txn.abort() - raise TableDBError, dberror[1] + raise TableDBError, dberror.args[1] From python-3000-checkins at python.org Wed Mar 28 23:44:57 2007 From: python-3000-checkins at python.org (collin.winter) Date: Wed, 28 Mar 2007 23:44:57 +0200 (CEST) Subject: [Python-3000-checkins] r54602 - in python/branches/p3yk: Lib/test/test_csv.py Lib/test/test_descr.py Lib/test/test_generators.py Lib/test/test_os.py Python/structmember.c Message-ID: <20070328214457.7E8AC1E4018@bag.python.org> Author: collin.winter Date: Wed Mar 28 23:44:53 2007 New Revision: 54602 Modified: python/branches/p3yk/Lib/test/test_csv.py python/branches/p3yk/Lib/test/test_descr.py python/branches/p3yk/Lib/test/test_generators.py python/branches/p3yk/Lib/test/test_os.py python/branches/p3yk/Python/structmember.c Log: Make readonly members defined in C throw an AttributeError on modification. This brings them into sync with Python-level attributes. Fixes bug #1687163. Modified: python/branches/p3yk/Lib/test/test_csv.py ============================================================================== --- python/branches/p3yk/Lib/test/test_csv.py (original) +++ python/branches/p3yk/Lib/test/test_csv.py Wed Mar 28 23:44:53 2007 @@ -53,8 +53,8 @@ self.assertEqual(obj.dialect.skipinitialspace, False) self.assertEqual(obj.dialect.strict, False) # Try deleting or changing attributes (they are read-only) - self.assertRaises(TypeError, delattr, obj.dialect, 'delimiter') - self.assertRaises(TypeError, setattr, obj.dialect, 'delimiter', ':') + self.assertRaises(AttributeError, delattr, obj.dialect, 'delimiter') + self.assertRaises(AttributeError, setattr, obj.dialect, 'delimiter', ':') self.assertRaises(AttributeError, delattr, obj.dialect, 'quoting') self.assertRaises(AttributeError, setattr, obj.dialect, 'quoting', None) Modified: python/branches/p3yk/Lib/test/test_descr.py ============================================================================== --- python/branches/p3yk/Lib/test/test_descr.py (original) +++ python/branches/p3yk/Lib/test/test_descr.py Wed Mar 28 23:44:53 2007 @@ -1857,13 +1857,13 @@ for attr in "__doc__", "fget", "fset", "fdel": try: setattr(raw, attr, 42) - except TypeError as msg: + except AttributeError as msg: if str(msg).find('readonly') < 0: raise TestFailed("when setting readonly attr %r on a " - "property, got unexpected TypeError " + "property, got unexpected AttributeError " "msg %r" % (attr, str(msg))) else: - raise TestFailed("expected TypeError from trying to set " + raise TestFailed("expected AttributeError from trying to set " "readonly %r attr on a property" % attr) class D(object): Modified: python/branches/p3yk/Lib/test/test_generators.py ============================================================================== --- python/branches/p3yk/Lib/test/test_generators.py (original) +++ python/branches/p3yk/Lib/test/test_generators.py Wed Mar 28 23:44:53 2007 @@ -400,7 +400,7 @@ >>> i.gi_running = 42 Traceback (most recent call last): ... -TypeError: readonly attribute +AttributeError: readonly attribute >>> def g(): ... yield me.gi_running >>> me = g() Modified: python/branches/p3yk/Lib/test/test_os.py ============================================================================== --- python/branches/p3yk/Lib/test/test_os.py (original) +++ python/branches/p3yk/Lib/test/test_os.py Wed Mar 28 23:44:53 2007 @@ -143,7 +143,7 @@ try: result.st_mode = 1 self.fail("No exception thrown") - except TypeError: + except AttributeError: pass try: @@ -201,7 +201,7 @@ try: result.f_bfree = 1 self.fail("No exception thrown") - except TypeError: + except AttributeError: pass try: Modified: python/branches/p3yk/Python/structmember.c ============================================================================== --- python/branches/p3yk/Python/structmember.c (original) +++ python/branches/p3yk/Python/structmember.c Wed Mar 28 23:44:53 2007 @@ -164,7 +164,7 @@ if ((l->flags & READONLY) || l->type == T_STRING) { - PyErr_SetString(PyExc_TypeError, "readonly attribute"); + PyErr_SetString(PyExc_AttributeError, "readonly attribute"); return -1; } if ((l->flags & WRITE_RESTRICTED) && PyEval_GetRestricted()) { From python-3000-checkins at python.org Thu Mar 29 22:49:58 2007 From: python-3000-checkins at python.org (guido.van.rossum) Date: Thu, 29 Mar 2007 22:49:58 +0200 (CEST) Subject: [Python-3000-checkins] r54609 - python/branches/p3yk/Objects/typeobject.c Message-ID: <20070329204958.DCF131E4014@bag.python.org> Author: guido.van.rossum Date: Thu Mar 29 22:49:57 2007 New Revision: 54609 Modified: python/branches/p3yk/Objects/typeobject.c Log: Fix refcounting bug reported by Amaury Forgeot d'Arc. Modified: python/branches/p3yk/Objects/typeobject.c ============================================================================== --- python/branches/p3yk/Objects/typeobject.c (original) +++ python/branches/p3yk/Objects/typeobject.c Thu Mar 29 22:49:57 2007 @@ -2311,6 +2311,7 @@ case Py_EQ: res = (self == other) ? Py_True : Py_False; + Py_INCREF(res); break; case Py_NE: @@ -2334,10 +2335,10 @@ default: res = Py_NotImplemented; + Py_INCREF(res); break; } - Py_INCREF(res); return res; } From python-3000-checkins at python.org Fri Mar 30 01:11:29 2007 From: python-3000-checkins at python.org (fred.drake) Date: Fri, 30 Mar 2007 01:11:29 +0200 (CEST) Subject: [Python-3000-checkins] r54610 - python/branches/p3yk/Doc/lib/liburlparse.tex Message-ID: <20070329231129.D45701E4002@bag.python.org> Author: fred.drake Date: Fri Mar 30 01:11:24 2007 New Revision: 54610 Modified: python/branches/p3yk/Doc/lib/liburlparse.tex Log: make the markup match that of the trunk to avoid insane spread of mystery italics Modified: python/branches/p3yk/Doc/lib/liburlparse.tex ============================================================================== --- python/branches/p3yk/Doc/lib/liburlparse.tex (original) +++ python/branches/p3yk/Doc/lib/liburlparse.tex Fri Mar 30 01:11:24 2007 @@ -168,7 +168,7 @@ If you do not want that behavior, preprocess the \var{url} with \function{urlsplit()} and \function{urlunsplit()}, -removing possible \em{scheme} and \em{netloc} parts. +removing possible \emph{scheme} and \emph{netloc} parts. \end{funcdesc} \begin{funcdesc}{urldefrag}{url}